/* ══════════════════════════════════════════════════════════════════════════
   ARMAZÓN MÓVIL sobre el rediseño · solo la cabecera y la barra de abajo
   ──────────────────────────────────────────────────────────────────────────
   Esto es un RECORTE de `movil/estilos.css` de la rama `movil/armazon-nativo`.
   Allí el fichero son 2.177 líneas porque además rehace cada vista para móvil;
   aquí las vistas son las del rediseño y no se tocan.

   Lo que queda: la cabecera compacta, la barra de pestañas, sus dos hojas
   —«Más» y «Registrar»— y el mínimo táctil, que es accesibilidad y no diseño.

   Lo que se quitó, y dónde está si hace falta:
     · los ocho arquetipos de vista        → estilos.css:1122-1609 de esa rama
     · las piezas que comparten            → 803-1121
     · los modales convertidos en hojas    → 1610-1894
     · Cartera (#projGate) y Acceso        → 1895-2177
   Los tres últimos porque el rediseño ya los tiene hechos: convertir sus
   modales en hojas o repintar su pantalla de acceso sería deshacer su trabajo.

   Sigue sin necesitar un solo !important para ganar: el <link> va al final
   del <body>, después de los bloques <style> de index.html, y a igual
   especificidad decide el orden.
   ══════════════════════════════════════════════════════════════════════════ */

@media (max-width: 900px) {

  :root {
    --mv-tabs-h: 58px;
    --mv-seguro: env(safe-area-inset-bottom, 0px);
    --mv-barra: calc(var(--mv-tabs-h) + var(--mv-seguro));
    /* Alias, no copias. Antes eran seis hex literales de los siete colores
       base: si cambiaba el azul corporativo, el móvil no se enteraba. El
       segundo valor es el respaldo por si el token no existe. */
    --mv-tinta: var(--text, #1A2B3C);
    --mv-apagado: var(--text-muted, #5A7A96);
    --mv-borde: var(--border, #EDF1F6);
    --mv-papel: var(--bg-card, #FFFFFF);
    --mv-fondo: var(--bg, #EEF5FA);
    --mv-sombra: 0 2px 10px rgba(0, 0, 0, .06);
  }

  :root[data-theme="dark"] {
    --mv-tinta: #E6EDF5;
    --mv-apagado: #7E93AB;
    --mv-borde: #223044;
    --mv-papel: #141A24;
    --mv-fondo: #0E131B;
    --mv-sombra: 0 2px 12px rgba(0, 0, 0, .5);
  }

  /* index.html:9418 pone zoom:.90 y descuadra las @media un 11 %. */
  html.mv .app {
    zoom: 1 !important;
    height: 100dvh !important;
    padding: 0 !important;
    gap: 0 !important;
  }

  html.mv .app {
    display: grid !important;
    grid-template-areas: "topbar" "content" "tabs" !important;
    grid-template-rows: auto minmax(0, 1fr) auto !important;
    grid-template-columns: minmax(0, 1fr) !important;
  }
  html.mv .content-area { grid-area: content !important; min-width: 0 !important; }
  html.mv .mv-tabs { grid-area: tabs; }

  /* Una sola navegación: la barra inferior. Vale para las DOS aplicaciones —
     index.html y central.html—, así que el ☰ sobra en ambas. Hubo un paso
     intermedio en el que Central montaba sin barra y había que devolverle el
     ☰; se descartó porque contradecía la regla. Ahora Central construye su
     propia barra leyendo su lateral, y el botón vuelve a sobrar. */
  /* NINGÚN CAJÓN CERRADO EMPUJA LA PÁGINA.
     Medido en el Panel Fotográfico: la página se desplazaba 33 px DE VERDAD
     —`scrollLeft` respondía y volvía con contenido— y no era la vista. Era
     `.help-panel`, un cajón `fixed` aparcado en `left:390px` con
     `visibility:visible` aunque esté cerrado. Un elemento fijo fuera de
     pantalla y visible alarga el área desplazable.

     Se probó antes `overflow-x: clip` en la raíz y NO lo corta: el cajón es
     `fixed`, se posiciona contra la ventana y recortar el documento no lo
     quita del área desplazable. Lo que funciona es que, cerrado, no esté.
     Se abre con `toggleHelp()`, que le pone `.open`. */
  html.mv .help-panel:not(.open) { display: none !important; }

  html.mv .mobile-toggle,
  html.mv .sb-toggle { display: none !important; }
  html.mv #sidebar,
  html.mv .sidebar { z-index: 120 !important; }

  /* EL LATERAL SIN DESENFOQUE: era lo que hacía el scroll pastoso.
     En el teléfono el lateral no se usa —la navegación es la barra de abajo—
     pero sigue en el documento porque `armazon.js` lo LEE para construir las
     pestañas. Está aparcado fuera de pantalla, en -260→0… y aun así el
     navegador lo compone en cada fotograma, porque lleva
     `backdrop-filter: blur(24px) saturate(1.5)` sobre 260×844 y es `fixed`.
     Un desenfoque fijo se rehace cada vez que algo se mueve por debajo, esté
     o no a la vista.

     Medido en RFI / SIG: de los 33 elementos del documento con
     `backdrop-filter`, sólo UNO estaba visible, y era éste. El coste no sale
     en el hilo principal —el diseño tarda 0,2 ms— porque lo paga el
     compositor, que es justo lo que se nota al arrastrar el dedo.

     Se le quita el efecto y NO se oculta: con `display:none` el armazón
     dejaría de leer sus destinos y la barra de pestañas se quedaría vacía. */
  html.mv #sidebar,
  html.mv .sidebar {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
  }

  /* Cabecera en dos filas en vez de tres. */
  /* La cabecera gastaba ~132 px en dos filas antes del primer dato. Apretarla
     devuelve alto a TODAS las pantallas, no solo a Resumen. La versión de una
     sola franja (obra · semana · corte) necesita tocar el marcado y va aparte. */
  html.mv .top-header {
    display: flex !important;
    flex-wrap: wrap !important;
    align-items: center !important;
    gap: 8px !important;

    /* TARJETA FLOTANTE, el mismo lenguaje que la cabecera del gate.
       Antes nacía pegada al borde con solo las esquinas de abajo redondeadas,
       porque un radio arriba dejaba ver el fondo en dos muescas. Con margen a
       los cuatro lados esa razón desaparece: el azul se lee como una pieza y
       no como una banda cortada por la pantalla. */
    /* 8 y no 10: la tarjeta cuesta margen, y entre cabecera y barra el cromo
       fijo se iba al 21 % de la pantalla —nuestro propio umbral es el 20—.
       Bajando margen y relleno vuelve a 20 sin que se note en el dibujo. */
    margin: 8px 12px 0 !important;
    border-radius: 24px !important;
    padding: 8px 14px !important;

    /* Degradado, no color plano: es lo que separa una pieza de una franja.
       Los dos tonos y sus paradas salen de `.pg-head` del gate, para que las
       dos cabeceras se lean como la misma familia. */
    background: linear-gradient(90deg, #2985D3 13%, #367EDC 84%) !important;

    /* Sin filete blanco (observación de Lili, 01/10/2026): solo la sombra
       suave de debajo, que la despega del fondo. */
    box-shadow: 0 6px 18px rgba(0, 40, 70, .16) !important;
  }
  /* SEMANA PARALIZADA (R-10, 28-sep). El aviso de «paralizada» es una capa
     fija que empieza a 80 px (`.paraliz-overlay`, z-index 50), medida para
     la cabecera de escritorio de una fila. En el teléfono la píldora de
     semana cae en su segunda fila (69–105 px) y la capa la tapaba: quedaba
     vacía y no se podía salir de la semana, aunque el aviso dice «selecciona
     otra semana en el header». La cabecera sube por encima de la capa (y por
     debajo del velo y las hojas, 190 y 200).
     `!important` porque `html.mv .top-header` ya fija su posición con
     `!important` más arriba. */
  html.mv body.is-paralizada .top-header {
    position: relative !important;
    z-index: 60 !important;
  }
  /* El chip de obra era `flex: 1 1 auto` y se llevaba 269 de 426 px, lo que
     empujaba la semana a una fila propia. Encogido a su contenido, obra +
     semana + botones caben en una franja: 102 px → ~58. Son ~44 px devueltos
     a TODAS las pantallas de la aplicación, no solo a una. */
  html.mv .th-left {
    flex: 0 1 auto !important;
    min-width: 0 !important;
    gap: 6px !important;
  }
  /* Los botones van ANTES que la semana en el orden flex, aunque visualmente
     queden a la derecha. Es lo que decide QUÉ baja de fila cuando no cabe todo:
     con la semana en medio, a 390 px los botones se iban solos a una segunda
     fila y la cabecera subía a 110 px — peor que los 102 de partida. Así el que
     baja es el selector de semana, que es ancho y tolera una fila propia. */
  html.mv .th-right {
    order: 1 !important;
    flex: 0 0 auto !important;
    gap: 8px !important;
    margin-left: auto !important;
  }
  html.mv .th-crumb,
  html.mv .th-inicio,
  html.mv .th-brand,
  html.mv .th-date,
  html.mv .hdr-user { display: none !important; }

  /* VOLVER ─────────────────────────────────────────────────────────────────
     La aplicación no escribe historial (cero `pushState`, medido), así que el
     gesto de volver del teléfono salía de la plataforma y en la PWA instalada
     la cerraba. `movil/vuelta.js` le da historial; este es su botón, y los dos
     entran por el mismo sitio.

     Lleva el rótulo del control de escritorio al que delega —«Volver a
     registros», «Semanas», «SAME»—, porque decir a dónde vuelves es más útil
     que un chevrón suelto. */
  html.mv .mv-atras {
    display: flex !important;
    align-items: center;
    gap: 4px;
    flex: 1 1 auto;
    min-width: 0;
    /* 44 de alto sin engordar la cabecera: el relleno lateral es el que da el
       área, y el alto lo pone la franja, que ya mide 44 con el chip de obra. */
    min-height: 44px;
    margin: 0 0 0 -8px;
    padding: 0 8px;
    background: transparent;
    border: 0;
    border-radius: 12px;
    color: #FFFFFF;
    font: 600 15px/1.25 'Inter', sans-serif;
    text-align: left;
    cursor: pointer;
  }
  /* `display:flex` de una clase gana al atributo `hidden` del marcado: sin
     esto el botón se vería también en las vistas raíz, donde no hay a dónde
     volver. Es la misma trampa que ya nos comió con `.week-selector`. */
  html.mv .mv-atras[hidden] { display: none !important; }
  html.mv .mv-atras svg { width: 22px; height: 22px; flex: none; }
  html.mv .mv-atras-txt {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* Con la vuelta a la vista, el nombre de la obra sobra: es el mismo en toda
     la aplicación y «Volver a registros» dice mucho más. Cediéndole su sitio
     el botón no cuesta ni un píxel de alto. */
  html.mv .top-header:has(> .mv-atras:not([hidden]):not(.solo-flecha)) .th-left { display: none !important; }
  /* ENTRE VISTAS, solo la flecha (R-09, 28-sep): 44 × 44 a la izquierda del
     chip de la obra, que se queda, porque aquí no hay rótulo que lo sustituya. */
  html.mv .mv-atras.solo-flecha {
    flex: none;
    width: 44px;
    justify-content: center;
    padding: 0;
    margin: 0 -4px 0 -10px;
  }
  html.mv .mv-atras.solo-flecha .mv-atras-txt { display: none; }
  /* El nombre de la obra se ve entero cuando cabe; si no, se corta con puntos
     suspensivos y no a secas («ESPARQ 14(»). La flecha le quita 44 px a la
     franja, así que se recupera lo que sobra alrededor: la flecha se monta
     sobre el relleno del chip (su área táctil sigue siendo de 44 px) y el chip
     pierde relleno lateral solo mientras la flecha está puesta. */
  html.mv .th-obra b {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  html.mv .th-obra svg { flex: none; }
  html.mv .top-header:has(> .mv-atras.solo-flecha:not([hidden])) .th-obra {
    padding-left: 6px !important;
    padding-right: 4px !important;
    margin-left: 0 !important;
  }
  html.mv .top-header:has(> .mv-atras.solo-flecha:not([hidden])) .mv-atras.solo-flecha {
    margin-right: -10px;
  }
  /* Y los huecos entre piezas bajan en toda vista, Resumen incluido (8 → 4 en la
     franja, 16 → 4 entre campana y avatar): son los ~20 px que le faltaban al
     nombre a 390 px. */
  html.mv .top-header { gap: 4px !important; }
  html.mv .top-header .th-right { gap: 4px !important; }
  html.mv .top-header:not(:has(> .mv-atras.solo-flecha:not([hidden]))) .th-obra { margin-left: 8px !important; }

  /* Y el control de escritorio al que delegamos se retira mientras el nuestro
     esté puesto: dos botones idénticos en la misma pantalla es peor que
     ninguno. Se oculta sólo el BOTÓN; el número del registro que va a su lado
     se queda, que es lo que dice cuál tienes abierto. */
  html.mv:has(.mv-atras:not([hidden]):not(.solo-flecha)) :is(#sec-calidad-nc, #sec-calidad-sig,
    #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig,
    #sec-calidad-equipos, #sec-sames).active :is(.rfi-back, .rfi-btn.dos-volver) {
    display: none !important;
  }

  /* `flex: 1 1 130px` y no un ancho fijo: a 426 px entra en la franja junto a
     la obra y los botones; a 320 no cabe y baja sola a su fila. Responsive por
     construcción, sin un breakpoint que adivinar. */
  html.mv .top-header > .week-selector {
    order: 2 !important;
    flex: 1 1 128px !important;
    min-width: 0 !important;
    margin: 0 !important;
    /* CAPSULA, como el segmentado de la cabecera del gate: blanco translucido
       sobre el azul con un filete claro por dentro. Sin esto el <select> se
       pinta con el gris del sistema y rompe la pieza. */
    padding: 3px !important;
    background: rgba(255, 255, 255, .10) !important;
    border-radius: 50px !important;
    box-shadow: none !important;   /* sin el filete claro (Lili, 01/10/2026) */
  }
  html.mv .top-header > .week-selector label { display: none !important; }
  /* Y con el rótulo oculto, una cápsula sin opciones no dice NADA.
     Medido en Registro de Inspecciones: `WEEKS_ORDER` vacío y
     `populateWeekSelector()` sin llegar a correr —ni siquiera pone su propia
     opción «Sin semanas cargadas»—, así que el `<select>` se queda con CERO
     opciones y queda una cápsula de 331×34 muda. En escritorio se lee «Semana»
     al lado y se entiende que el dato no ha llegado; aquí el rótulo está oculto
     por la regla de arriba, así que el hueco es obra nuestra.

     SE DEVUELVE EL RÓTULO, NO SE OCULTA LA CÁPSULA. Ocultarla fue el primer
     intento y estaba mal: la cabecera existe desde el arranque y el `<select>`
     se llena después, así que la cápsula pasaría de ausente a presente al
     llegar los datos y el contenido entero saltaría 55 px (cabecera 62 → 117).
     Cambiar una cápsula vacía por un salto de maquetación en cada carga es peor
     negocio. Así la caja mide igual siempre y mientras carga se lee «Semana».

     `:has(select)` delante NO sobra: la cápsula de Central no lleva `<select>`
     sino un `<span class="cen-sem-val">`, y sin ese primer filtro esta regla
     tocaría también a Central, que ya tiene su propio trato más abajo. */
  html.mv .top-header > .week-selector:has(select):not(:has(select option)) > label {
    display: inline !important;
    font-size: 11px !important;
    color: rgba(255, 255, 255, .75) !important;
  }
  html.mv .top-header > .week-selector select {
    width: 100% !important;
    min-height: 34px !important;
    height: 34px !important;
    padding-block: 0 !important;
    font-size: 12.5px !important;
    /* El campo desaparece: la capsula de arriba ES el control. El texto en
       blanco porque el fondo es el azul de la cabecera.
       Las OPCIONES del desplegable no heredan esto —las pinta el sistema— asi
       que no hay riesgo de blanco sobre blanco al abrirlo. */
    background: transparent !important;
    border: 0 !important;
    border-radius: 50px !important;
    color: #FFFFFF !important;
  }
  html.mv .th-obra { padding: 6px 10px !important; }

  /* B-04 (29/09): semana en la MISMA fila que la obra, corta («S58 ▾»).
     El <select> queda encima, transparente, y es el que recibe el toque. */
  html.mv .top-header > .week-selector.mv-sem-compacta {
    order: 0 !important;
    flex: 0 0 auto !important;
    position: relative !important;
    min-width: 64px !important;
    padding: 0 !important;
  }
  html.mv .top-header > .week-selector.mv-sem-compacta select {
    position: absolute !important;
    inset: 0 !important;
    width: 100% !important;
    height: 100% !important;
    min-height: 0 !important;
    opacity: 0 !important;
    cursor: pointer !important;
    z-index: 1 !important;
  }
  html.mv .mv-sem-corta {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    min-height: 34px;
    padding: 0 12px;
    color: #FFFFFF;
    font: 700 13px/1 'Inter', sans-serif;
    white-space: nowrap;
  }
  /* «Sin semanas» (obra sin cortes) mide 121 px y dejaba el campo de búsqueda en 20 px
     y el nombre de la obra en 3 letras. La píldora cede primero: su texto se corta con
     puntos suspensivos, con un piso de 66 px (lo que mide «S42 ⌄»). */
  html.mv .top-header > .week-selector.mv-sem-compacta { flex: 0 3 auto !important; min-width: 44px !important; }
  html.mv .mv-sem-corta { min-width: 0; max-width: 100%; padding: 0 8px; }
  html.mv .mv-sem-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  html.mv .mv-sem-corta svg {
    width: 12px; height: 12px;
    fill: none; stroke: currentColor; stroke-width: 1.6;
    stroke-linecap: round; stroke-linejoin: round;
  }
  /* Obra · semana · botones, en UNA sola franja y en ese orden. Otra regla
     le da `order:1` y margen automático a .th-left (la empujaba a la derecha
     y la semana salía primero); aquí se fija el orden completo. A 360 px no
     caben los tres enteros por ~10 px: cede el nombre de la obra. */
  html.mv .top-header:has(> .mv-sem-compacta) { flex-wrap: nowrap !important; }
  html.mv .top-header:has(> .mv-sem-compacta) > .th-left {
    order: 1 !important;
    margin-left: 0 !important;
    flex: 0 1 auto !important;
    min-width: 0 !important;
  }
  html.mv .top-header > .week-selector.mv-sem-compacta { order: 2 !important; }
  html.mv .top-header:has(> .mv-sem-compacta) > .th-right {
    order: 3 !important;
    margin-left: auto !important;
    gap: 6px !important;
  }
  html.mv .top-header:has(> .mv-sem-compacta) .th-obra {
    flex: 0 1 auto !important;
    min-width: 0 !important;
    overflow: hidden !important;
    white-space: nowrap !important;
  }

  /* CENTRAL · la semana es un dato, no un mando ──────────────────────────
     Central no lleva `<select>` dentro de la cápsula: pone un
     `<label>Semana</label>` y un `<span class="cen-sem-val">`, porque a nivel
     de cartera la semana INFORMA y no filtra. Dos consecuencias, medidas:

       · la cápsula salía aunque el marcado la mande ocultar —`.week-selector`
         trae su propio `display:flex`, que gana al atributo `hidden`—, y sin
         corte leído quedaba una cápsula entera con un «—» dentro;
       · el valor hereda el gris oscuro del escritorio (#16243A) y sobre el
         azul de la tarjeta no se lee. */
  html.mv .top-header > .week-selector[hidden] { display: none !important; }
  html.mv .top-header > .week-selector:has(> .cen-sem-val) {
    justify-content: center !important;
    gap: 7px !important;
    padding: 0 12px !important;
    min-height: 34px !important;
  }
  /* Aquí el rótulo SÍ hace falta: sin él la cápsula diría sólo «S42». */
  html.mv .top-header > .week-selector:has(> .cen-sem-val) > label {
    display: inline !important;
    font-size: 11px !important;
    color: rgba(255, 255, 255, .75) !important;
  }
  html.mv .top-header .cen-sem-val {
    font-size: 12.5px !important;
    font-weight: 600 !important;
    color: #FFFFFF !important;
  }

  html.mv .top-header button,
  html.mv .top-header .th-avatar { flex: 0 0 auto !important; }

  html.mv .top-header .hdr-btn,
  html.mv .top-header .notif-bell-btn,
  html.mv .top-header .th-avatar {
    width: 36px !important;
    height: 36px !important;
    min-height: 36px !important;
    min-width: 36px !important;
    padding: 0 !important;
    border-radius: 999px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    overflow: hidden !important;
  }
  html.mv .top-header .th-avatar img {
    width: 100% !important;
    height: 100% !important;
    object-fit: cover !important;
    border-radius: 999px !important;
  }

  /* `1fr` es `minmax(auto,1fr)`: su mínimo es min-content y desborda. */
  html.mv .kpi-strip,
  html.mv .r-kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  html.mv .r-frentes { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  html.mv .rep-resumen-grid,
  html.mv .rep-kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }

  /* Mismo caso en 76 rejillas. :where() da especificidad cero, así que un
     min-width explícito —las tablas anchas— sigue ganando. */
  :where(html.mv .scroll-area *) { min-width: 0; }
  html.mv .scroll-area { overflow-x: hidden !important; }

  /* En escritorio la zona de scroll se BLOQUEA cuando hay un iframe activo
     —`.scroll-area:has(> #sec-progmeta.active) { overflow:hidden }`— porque
     el que desplazaba era el iframe. En móvil el iframe crece hasta su
     contenido y ya no desplaza, así que ese candado dejaba sin scroll a los
     dos: ni la página ni el marco se movían. */
  html.mv .scroll-area:has(> #sec-progmeta.active),
  html.mv .scroll-area:has(> #sec-dimensionamiento.active),
  html.mv .scroll-area:has(> .section.active iframe) {
    overflow-y: auto !important;
    overflow-x: hidden !important;
    padding-bottom: 32px !important;
  }

  html.mv .scroll-area [class*="-wrap"],
  html.mv .scroll-area [class*="-scroll"] {
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
  }

  /* Una columna. Con minmax(150px) entraban dos a 390 px y el texto se partía
     cada dos palabras. Las tarjetas de cifra vuelven a dos más abajo. */
  /* Estos comodines reparan el marcado de ESCRITORIO. El :not(mv-) los aparta
     del marcado COMPUESTO, que define su propia maqueta y no necesita rescate.
     Sin él, «mv-res-kpi» caía en [class*="kpi"] y recibía dos columnas con
     !important: la etiqueta a la izquierda y la cifra a la derecha. */
  html.mv .scroll-area [class*="grid"]:not([class*="mv-"]),
  html.mv .scroll-area [class*="cols"]:not([class*="mv-"]),
  html.mv .scroll-area [class*="split"]:not([class*="mv-"]) {
    grid-template-columns: minmax(0, 1fr) !important;
  }

  html.mv .scroll-area [class*="kpi"]:not([class*="mv-"]),
  html.mv .scroll-area [class*="stats"]:not([class*="mv-"]) {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
  }

  /* Bajo 16 px, iOS hace zoom al enfocar un campo. */
  /* LOS CAMPOS: 16 px para que iOS no haga zoom al enfocarlos, y la caja que
     esos 16 px necesitan.
     Poner solo la fuente era medio arreglo y se vio: el gate de multiproyectos
     da a sus selects `height:36px` con `padding:10px/10px` y `border-box`, o
     sea 16 px de caja para una linea de ~19 — el texto salia cortado por
     arriba y por abajo. Con `height:auto` la caja la pide el contenido, y el
     minimo tactil la sube a 44.
     `max-width:none` porque un ancho tope de escritorio —240 px dentro de un
     contenedor de 334— deja el campo a media asta en un telefono.
     Las casillas y los radios quedan fuera: ahi 44 de alto los deformaria,
     igual que a los botones redondos. Su area de toque la amplia tactil.js. */
  html.mv input:not([type="checkbox"]):not([type="radio"]),
  html.mv textarea,
  html.mv select {
    font-size: 16px !important;
    line-height: 1.25 !important;
    height: auto !important;
    min-height: 44px !important;
    max-width: none !important;
  }

  /* UN <select> RESERVA EL ANCHO DE SU OPCIÓN MÁS LARGA, aunque su caja se
     vea pequeña. Y ese ancho intrínseco empuja el documento: el desborde del
     Panel Fotográfico —33 px reales, `scrollLeft` respondía— venía de
     `.foto-f-sel`, cuya caja medía 16→220 mientras su opción más larga es
     «S30 · 07/03/2026 · sin fotos». Costó encontrarlo porque NINGÚN elemento
     se salía por la derecha al medir rectángulos; salió apagando ramas una a
     una hasta que el ancho caía a 390.

     `min-width: 0` le quita ese suelo. Va a todos los desplegables: cualquiera
     con opciones largas hace lo mismo. */
  html.mv select {
    min-width: 0 !important;
    max-width: 100% !important;
    text-overflow: ellipsis;
  }

  /* CUANDO EL CAMPO NO ES EL INPUT, SINO SU ENVOLTURA.
     El buscador del gate se dibuja en un `.pgf-buscar` con su borde, su fondo
     y su radio de 999; el <input> de dentro va sin borde y transparente. Al
     darle 44 px de minimo al input, crecia 44 dentro de una envoltura de 36 y
     SE SALIA del dibujo: se veian dos marcos al enfocar, el de la capsula y
     el del input asomando por arriba y por abajo.

     El minimo tactil le toca a lo que SE VE como campo. Asi que crece la
     envoltura —que ademas a 36 se veia delgada para un dedo— y el input de
     dentro la llena en vez de imponer su alto.

     Lista cerrada a proposito. Un `*:has(> input)` generico le pondria 44 de
     alto a cualquier div que contenga un campo —formularios, celdas de tabla,
     etiquetas— y romperia mas de lo que arregla. En esta pantalla solo hay
     tres envolturas de este tipo y solo esta se salia; las otras dos
     —`.week-selector` y `.nova-entrada`— ya son mas altas que su campo. */
  html.mv .pgf-buscar { min-height: 44px !important; }
  html.mv .pgf-buscar > input {
    min-height: 0 !important;
    height: 100% !important;
  }

  html.mv button,
  html.mv .btn,
  html.mv .hdr-btn,
  html.mv .sb-item { min-height: 44px; }

  /* Excepciones al mínimo táctil, y hacen falta las dos veces: index.html
     tiene su propia regla de 44 px y esta capa la suya. Exceptuar solo allí
     no bastaba porque `html.mv button` puntúa más alto que `.pgm-seg > *`.
     De ahí el !important: no es pereza, es que la excepción tiene que ganarle
     a una regla propia más específica.
       · avatares  → deben ser círculos, no elipses
       · segmentos → el contenedor mide 44 con 3 de padding, o sea 38 de
                     hueco; a 44 el botón salía más alto que su propia caja */
  html.mv .pgc-av,
  html.mv .th-avatar,
  html.mv .pgm-seg > *,
  html.mv .nova-cab-x { min-height: 0 !important; }

  /* El paginado sí quiere los 44, pero CUADRADOS. Con el mínimo aplicado solo
     al alto salían de 34 de ancho por 44 de alto: rectángulos verticales. */
  html.mv .pager button {
    min-width: 44px !important;
    width: auto !important;
    height: 44px !important;
    border-radius: 11px !important;
  }
  html.mv .pager { gap: 7px !important; padding: 12px 14px !important }
  html.mv .pager .de { flex: 1 0 100% !important; margin: 0 0 8px !important }

  /* ── El mínimo táctil no deforma ·  movil/tactil.js ──────────────
     La regla de arriba usa `min-height`, que gana SIEMPRE sobre `height`: un
     avatar de 34 px o una ✕ de 27 salían estirados a 44 de alto, convertidos
     en elipses. El objetivo de 44 px es del ÁREA DE TOQUE, no del dibujo.
     Aquí se separan: el círculo recupera su medida y un pseudo-elemento
     invisible extiende la zona sensible. Accesible y sin deformar. */
  html.mv [data-mv-icono="1"] {
    min-height: 0 !important;
    min-width: 0 !important;
    height: var(--mv-lado) !important;
    width: var(--mv-lado) !important;
    aspect-ratio: 1 !important;
    flex: 0 0 var(--mv-lado) !important;
    padding: 0 !important;
    position: relative;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    align-self: center !important;
  }
  html.mv [data-mv-icono="1"]::after {
    content: '';
    position: absolute;
    /* Caja de 44 px centrada sobre el círculo, invisible pero sensible. */
    top: 50%;
    left: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
    border-radius: 50%;
  }

  html.mv .r-banner { gap: 14px !important; padding: 16px 14px !important; }

  /* Jerarquía en la entrada: la obra manda, el resto acompaña. */
  html.mv .r-banner-sub {
    font-size: 10px !important;
    font-weight: 600 !important;
    letter-spacing: .07em !important;
    color: #5A7A96 !important;
  }
  html.mv .r-banner-title {
    font-size: 30px !important;
    line-height: 1.05 !important;
    letter-spacing: -.025em !important;
    margin: 4px 0 0 !important;
  }
  html.mv .r-hero-clientrow { margin-top: 8px !important; }
  html.mv .r-banner-meta {
    font-size: 12.5px !important;
    line-height: 1.5 !important;
    color: #5A7A96 !important;
  }

  /* CORTE era un bloque centrado suelto; pasa a franja con separación real. */
  html.mv .r-hero-side {
    border-top: 1px solid var(--mv-borde) !important;
    padding-top: 14px !important;
    text-align: left !important;
  }
  html.mv .r-hero-corte { text-align: left !important; }

  html.mv .r-hero-curva {
    border-top: 1px solid var(--mv-borde) !important;
    padding-top: 14px !important;
  }

  /* La curva recibía 118 px y es lo que más se mira. */
  html.mv .rhc-svg,
  html.mv .rhc-svg svg { height: 200px !important; min-height: 200px !important; }

  html.mv .r-banner-meta {
    white-space: normal !important;
    overflow-x: visible !important;
    display: flex !important;
    flex-wrap: wrap !important;
    gap: 4px 14px !important;
  }

  /* FALLO: toggleSidebar() (index.html:23670) crea este velo sin CSS ninguno. */
  .velo-menu {
    position: fixed;
    inset: 0;
    z-index: 110;
    background: rgba(10, 22, 38, .46);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    opacity: 0;
    visibility: hidden;
    transition: opacity .2s ease, visibility .2s ease;
  }
  .velo-menu.on { opacity: 1; visibility: visible; }

  html.mv .mv-tabs {
    display: flex;
    align-items: stretch;
    height: var(--mv-barra);
    padding-bottom: var(--mv-seguro);
    background: var(--mv-papel);
    border-top: 1px solid var(--mv-borde);
    box-shadow: 0 -2px 14px rgba(16, 24, 40, .06);
    z-index: 130;
  }

  html.mv .mv-tab {
    flex: 1 1 0;
    min-width: 0;
    min-height: 44px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    padding: 0 2px;
    background: none;
    border: 0;
    font-family: inherit;
    color: var(--mv-apagado);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: color .16s ease;
  }
  html.mv .mv-tab:disabled { opacity: .38; pointer-events: none; }
  html.mv .mv-tab.on { color: #0070B4; }
  html.mv .mv-tab:active .mv-tab-ic { transform: scale(.9); }

  html.mv .mv-tab-ic {
    display: flex;
    align-items: center;
    justify-content: center;
    transition: transform .14s ease;
  }
  html.mv .mv-tab-ic svg { width: 23px; height: 23px; stroke-width: 1.85; }
  html.mv .mv-tab.on .mv-tab-ic svg { stroke-width: 2.2; }

  html.mv .mv-tab-tx {
    font-size: 10px;
    font-weight: 500;
    letter-spacing: -.01em;
    line-height: 1;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  html.mv .mv-tab.on .mv-tab-tx { font-weight: 700; }

  /* attr() lee el elemento del pseudo, no su padre: el dato va en el icono. */
  html.mv .mv-tab-ic[data-mv-badge]:not([data-mv-badge=""])::after {
    content: attr(data-mv-badge);
    position: absolute;
    transform: translate(13px, -11px);
    /* El contador común, el de la Bandeja del lateral (--cnt-*, en
       assets/shell-blanco.css). Solo el sitio es propio: la esquina del icono. */
    box-sizing: border-box;
    min-width: var(--cnt-min, 20px);
    padding: var(--cnt-pad, 2px 7px);
    border-radius: var(--cnt-radius, 999px);
    background: var(--cnt-bg, #DC2626);
    color: var(--cnt-fg, #fff);
    font: var(--cnt-font, 600 10px/normal 'Inter', system-ui, sans-serif);
    letter-spacing: var(--cnt-ls, .02em);
    text-align: center;
  }
  html.mv .mv-tab-ic { position: relative; }

  html.mv .mv-tab[data-mv-id="registrar"] .mv-tab-ic {
    width: 38px;
    height: 38px;
    border-radius: 12px;
    background: #0070B4;
    color: #fff;
    box-shadow: 0 4px 12px rgba(0, 112, 180, .34);
    margin-top: -3px;
  }
  html.mv .mv-tab[data-mv-id="registrar"] .mv-tab-ic svg { stroke-width: 2.4; }
  html.mv .mv-tab[data-mv-id="registrar"].on .mv-tab-ic { background: #005a91; }

  /* Hojas inferiores, patrón de Nova (index.html:64779). */
  html.mv .mv-velo {
    position: fixed;
    inset: 0;
    z-index: 190;
    background: rgba(10, 22, 38, .46);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    opacity: 0;
    visibility: hidden;
    transition: opacity .22s ease, visibility .22s ease;
  }
  html.mv .mv-velo.on { opacity: 1; visibility: visible; }

  html.mv .mv-hoja {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 200;
    max-height: 82dvh;
    display: flex;
    flex-direction: column;
    background: var(--mv-fondo);
    /* Las medidas del componente de hoja (más abajo): una sola familia. */
    border-radius: var(--hoja-radio, 22px) var(--hoja-radio, 22px) 0 0;
    box-shadow: var(--hoja-sombra, 0 -12px 40px rgba(15, 30, 55, .18));
    transform: translateY(100%);
    visibility: hidden;
    transition: transform .26s cubic-bezier(.32, .72, 0, 1), visibility .26s;
  }
  html.mv .mv-hoja.on { transform: translateY(0); visibility: visible; }

  html.mv .mv-hoja-asa {
    width: 36px;
    height: 5px;
    border-radius: 3px;
    background: var(--hoja-asa, #D3DCE6);
    margin: 8px auto 2px;
    flex: 0 0 auto;
  }

  html.mv .mv-hoja-cab {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 14px 12px;
    flex: 0 0 auto;
  }
  html.mv .mv-hoja-cab h2 {
    flex: 1 1 auto;
    margin: 0;
    font-size: 16px;
    font-weight: 700;
    letter-spacing: -.01em;
    color: var(--mv-tinta);
  }
  html.mv .mv-hoja-x {
    width: 44px;
    height: 44px;
    margin: -8px -4px -8px 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--hoja-x-fondo, #F1F4F8);
    border: 0;
    color: var(--hoja-x-tinta, #3B4452);
    cursor: pointer;
  }
  html.mv .mv-hoja-x svg { width: 20px; height: 20px; }

  html.mv .mv-hoja-cuerpo {
    flex: 1 1 auto;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 0 14px calc(18px + var(--mv-seguro));
  }

  html.mv .mv-grupo { margin-bottom: 16px; }
  html.mv .mv-grupo h3 {
    margin: 0 0 8px 2px;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: #5A7A96;
  }
  html.mv .mv-lista {
    background: var(--mv-papel);
    border-radius: 14px;
    box-shadow: var(--mv-sombra);
    overflow: hidden;
  }

  html.mv .mv-fila {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    min-height: 52px;
    padding: 12px 13px;
    background: none;
    border: 0;
    border-bottom: 1px solid var(--mv-borde);
    font-family: inherit;
    text-align: left;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  html.mv .mv-fila:last-child { border-bottom: 0; }
  html.mv .mv-fila:active { background: var(--mv-fondo); }

  html.mv .mv-fila-ic {
    flex: 0 0 30px;
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 9px;
    background: var(--mv-fondo);
    color: #0070B4;
  }
  /* Los SVG del lateral vienen desnudos: su trazo lo da .sb-item .sb-icon svg,
     que aquí no aplica. Sin esto caen al relleno negro por defecto. */
  html.mv .mv-fila-ic svg {
    width: 16px;
    height: 16px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
  }
  html.mv .mv-fila-ic svg [fill]:not([fill="none"]) { fill: currentColor; }
  html.mv .mv-fila-tx {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 14px;
    font-weight: 500;
    color: var(--mv-tinta);
  }
  html.mv .mv-fila-ch { flex: 0 0 auto; color: #B4C6D6; display: flex; }
  html.mv .mv-fila-ch svg { width: 17px; height: 17px; }

  /* La vista abierta, marcada con el mismo azul que la pestaña encendida. */
  html.mv .mv-fila-on { background: #EAF3FB; }
  html.mv .mv-fila-on .mv-fila-tx { color: #0070B4; font-weight: 700; }
  html.mv .mv-fila-on .mv-fila-ic { background: #fff; }
  /* Pendientes de la Bandeja: el mismo globo que la pestaña de abajo. */
  /* El contador común, el de la Bandeja del lateral (--cnt-*). */
  html.mv .mv-fila-n {
    flex: 0 0 auto;
    box-sizing: border-box;
    min-width: var(--cnt-min, 20px);
    padding: var(--cnt-pad, 2px 7px);
    border-radius: var(--cnt-radius, 999px);
    background: var(--cnt-bg, #DC2626);
    color: var(--cnt-fg, #fff);
    font: var(--cnt-font, 600 10px/normal 'Inter', system-ui, sans-serif);
    letter-spacing: var(--cnt-ls, .02em);
    text-align: center;
  }
  /* El del área va en el título de su grupo («GESTIÓN · CALIDAD»), que es
     texto y no flex: sin inline-block no respetaría min-width. */
  html.mv .mv-grupo h3 .mv-fila-n {
    display: inline-block;
    margin-left: 6px;
    vertical-align: 1px;
    text-transform: none;
  }

  html.mv .mv-accs { display: flex; flex-direction: column; gap: 8px; }
  html.mv .mv-acc {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    min-height: 64px;
    padding: 13px;
    background: var(--mv-papel);
    border: 0;
    border-radius: 14px;
    box-shadow: var(--mv-sombra);
    font-family: inherit;
    text-align: left;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  html.mv .mv-acc:active { transform: scale(.985); }
  html.mv .mv-acc-ic {
    flex: 0 0 40px;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 11px;
  }
  html.mv .mv-acc-ic svg { width: 20px; height: 20px; }
  html.mv .mv-acc-metrado   { background: #EEF5FA; color: #0070B4; }
  html.mv .mv-acc-foto      { background: #F3EFFE; color: #8b5cf6; }
  html.mv .mv-acc-tareo     { background: #FEF3E2; color: #f59e0b; }
  html.mv .mv-acc-incidente { background: #E8F7ED; color: #16a34a; }

  html.mv .mv-acc-tx { flex: 1 1 auto; min-width: 0; display: block; }
  html.mv .mv-acc-tx b {
    display: block;
    font-size: 14px;
    font-weight: 600;
    color: var(--mv-tinta);
  }
  html.mv .mv-acc-tx i {
    display: block;
    margin-top: 2px;
    font-size: 11.5px;
    font-style: normal;
    color: #5A7A96;
  }

  html.mv .mv-vacio {
    margin: 10px 2px;
    font-size: 13px;
    line-height: 1.5;
    color: #5A7A96;
  }


  html.mv .mv-tab,
  html.mv .mv-fila,
  html.mv .mv-acc,
  html.mv .mv-hoja-x { min-height: 44px; }

  html.mv.mv-hoja-abierta .scroll-area { overflow: hidden !important; }

  @media (prefers-reduced-motion: reduce) {
    html.mv .mv-hoja,
    html.mv .mv-velo,
    html.mv .velo-menu,
    html.mv .mv-tab,
    html.mv .mv-tab-ic,
    html.mv .mv-acc { transition: none !important; }
    html.mv .mv-hoja { transform: none; }
    html.mv .mv-hoja:not(.on) { display: none; }
  }

  /* ═══════════════════════════════════════════════════════════════
     MODALES → HOJAS INFERIORES  ·  movil/modales.js
     Un rectángulo flotando en el centro con márgenes por los cuatro
     lados es una forma de escritorio. En móvil el contenido llega
     desde abajo, al alcance del pulgar, y tapa la barra de pestañas
     en vez de dejarla asomar.
     ═══════════════════════════════════════════════════════════════ */

  /* ── El componente: HOJA INFERIOR ───────────────────────────────
     Una sola hoja para toda la aplicación: las ventanas de escritorio que
     etiqueta modales.js y las que crea la capa (Más, Registrar) comparten
     medidas, asa, cabecera, ✕ y pie. Las piezas se reconocen POR CLASE y
     no con una marca puesta desde JS: varias ventanas rehacen su contenido
     con innerHTML en cada apertura y una marca se perdería.

       asa ········ 36 × 5, arriba al centro
       cabecera ··· título a 18, hueco a la derecha para la ✕
       ✕ ·········· 44 × 44, redonda, siempre DENTRO de la hoja
       cuerpo ····· lo único que desplaza
       pie ········ fijo abajo, principal a todo el ancho

     Antes cada familia traía su radio, su sombra y su ✕ (flotando fuera de
     la tarjeta en Notificaciones, 12 px en otras): se leían como ventanas
     de aplicaciones distintas. */
  html.mv {
    --hoja-fondo: #FFFFFF;
    --hoja-radio: 22px;
    --hoja-sombra: 0 -12px 40px rgba(15, 30, 55, .18);
    --hoja-velo: rgba(15, 30, 55, .45);
    --hoja-asa: #D3DCE6;
    --hoja-linea: #EDF1F6;
    --hoja-x-fondo: #F1F4F8;
    --hoja-x-tinta: #3B4452;
    --hoja-tinta: #111827;
    --hoja-suave: #6B7280;
    --hoja-lado: 18px;
    --hoja-azul: #0B6FB8;
    --hoja-azul-suave: #E8F2FC;
    --hoja-borde: #D8E1EB;
  }
  /* El oscuro lo decide la plataforma con `data-theme`, no el sistema: con
     la preferencia del teléfono la hoja salía oscura sobre una app clara. */
  html.mv[data-theme="dark"] {
    --hoja-fondo: #151B24; --hoja-asa: #3A4555; --hoja-linea: #232C38;
    --hoja-x-fondo: #222B37; --hoja-x-tinta: #C9D3DF; --hoja-tinta: #E6EDF5;
    --hoja-suave: #93A3B6; --hoja-azul: #5AA2F0; --hoja-azul-suave: #17304A; --hoja-borde: #2E3A4A;
  }

  @keyframes mv-hoja-sube { from { transform: translateY(100%); } to { transform: none; } }

  html.mv [data-mv-velo="1"] {
    align-items: flex-end !important;
    justify-content: stretch !important;
    padding: 0 !important;
    background: var(--hoja-velo) !important;
  }

  html.mv [data-mv-hoja-inf="1"] {
    position: fixed !important;
    inset: auto 0 0 0 !important;
    width: 100% !important;
    max-width: none !important;
    min-width: 0 !important;
    height: auto !important;
    margin: 0 !important;
    max-height: min(88dvh, calc(100dvh - 24px)) !important;
    /* OJO: aquí NO se fuerza `display`. La plataforma muestra y esconde varios
       de estos con display —`.notif-dropdown` se oculta al quitarle `.show`—,
       y un `display:flex !important` los dejaba visibles para siempre. Solo se
       fija la DIRECCIÓN, que no interfiere con mostrar u ocultar. */
    flex-direction: column !important;
    overflow: hidden !important;
    padding: 0 !important;
    border: 0 !important;
    background: var(--hoja-fondo) !important;
    color: var(--hoja-tinta);
    border-radius: var(--hoja-radio) var(--hoja-radio) 0 0 !important;
    box-shadow: var(--hoja-sombra) !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    transform: none;
    /* Sube desde abajo. Si una regla global apaga las animaciones, la hoja
       se queda donde tiene que estar: `both` no la deja fuera de pantalla
       porque sin animación no hay primer fotograma que aplicar. */
    animation: mv-hoja-sube .28s cubic-bezier(.32, .72, 0, 1);
  }

  /* Los paneles que viven DENTRO de un velo sí pueden forzar display: quien
     decide si se ven es el velo, no ellos. */
  html.mv [data-mv-velo="1"] > [data-mv-hoja-inf="1"] {
    display: flex !important;
  }

  /* El asa: dice «esto viene de abajo», la convención que ya se conoce. */
  html.mv [data-mv-hoja-inf="1"]::before {
    content: '';
    position: absolute;
    top: 8px;
    left: 50%;
    transform: translateX(-50%);
    width: 36px;
    height: 5px;
    border-radius: 3px;
    background: var(--hoja-asa);
    z-index: 5;
    pointer-events: none;
  }

  /* Envolturas de escritorio (la tarjeta blanca dentro del cristal de
     Notificaciones): sus piezas pasan a ser piezas de la hoja. */
  html.mv [data-mv-hoja-inf="1"] :is(.notif-card, .notif-top) {
    display: contents !important;
  }

  /* Cabecera: el hueco de la derecha es para la ✕. */
  html.mv [data-mv-hoja-inf="1"] :is(.modal-head, .kpi-edit-head, .rfi-modal-h, .docctrl-modal-head, .notif-head, .cap-edit-head, .help-head, .rz-evo-head, .rg3-modal-cab) {
    flex: 0 0 auto !important;
    display: flex !important;
    align-items: center !important;
    gap: 10px !important;
    height: auto !important;
    min-height: 0 !important;
    padding: 26px 66px 12px var(--hoja-lado) !important;
    margin: 0 !important;
    background: none !important;
    border: 0 !important;
    color: var(--hoja-tinta) !important;
    font-size: 18px !important;
    font-weight: 700 !important;
    line-height: 1.25 !important;
  }

  /* El título y su bajada. En escritorio van en blanco sobre una banda de
     color (a veces en línea, `style="background:…"`); sobre la hoja blanca
     el título desaparecía y solo quedaba el emoji. */
  html.mv [data-mv-hoja-inf="1"] :is(.modal-head, .kpi-edit-head, .rfi-modal-h, .docctrl-modal-head, .cap-edit-head, .help-head, .rz-evo-head, .rg3-modal-cab) :is(h1, h2, h3, h4, [class*="title"], [class*="tit"]) {
    margin: 0 !important;
    color: var(--hoja-tinta) !important;
    font-size: 18px !important;
    line-height: 1.3 !important;
    font-weight: 700 !important;
    letter-spacing: 0 !important;
  }
  html.mv [data-mv-hoja-inf="1"] :is(.modal-head, .kpi-edit-head, .rfi-modal-h, .docctrl-modal-head, .cap-edit-head, .help-head) :is(p, .sub) {
    margin: 3px 0 0 !important;
    color: var(--hoja-suave) !important;
    font-size: 13.5px !important;
    line-height: 1.4 !important;
    letter-spacing: 0 !important;
    text-transform: none !important;
  }

  /* Cabecera de una ventana que no está en la lista: la fila de arriba que
     lleva la ✕. Su título, con el mismo peso y tamaño que el resto (en el SPI
     salía a 400 y se leía como un párrafo). */
  html.mv [data-mv-hoja-inf="1"] > :has(> [data-mv-x="1"]) :is(h1, h2, h3, h4, [class*="tit"]),
  html.mv [data-mv-hoja-inf="1"] > :has(> [data-mv-x="1"]) > :first-child:not([data-mv-x]) {
    margin: 0 !important;
    color: var(--hoja-tinta) !important;
    font-size: 18px !important;
    line-height: 1.3 !important;
    font-weight: 700 !important;
    letter-spacing: 0 !important;
  }

  /* La ✕: dentro de la hoja, arriba a la derecha, 44 × 44 y redonda.
     `min-*` a 44 y no más: el mínimo táctil general la estiraba a elipse. */
  html.mv [data-mv-hoja-inf="1"] :is(.modal-close, .rfi-x, .rg3-modal-x, .mc-x, .chart-max-close, .notif-close, .cap-edit-close, .rz-evo-x, .sigf-toolbar .x, [data-mv-x="1"]) {
    position: absolute !important;
    top: 12px !important;
    right: 12px !important;
    left: auto !important;
    width: 44px !important;
    height: 44px !important;
    min-width: 44px !important;
    min-height: 44px !important;
    max-width: 44px !important;
    max-height: 44px !important;
    box-sizing: border-box !important;
    padding: 0 !important;
    margin: 0 !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    border: 0 !important;
    border-radius: 50% !important;
    background: var(--hoja-x-fondo) !important;
    color: var(--hoja-x-tinta) !important;
    box-shadow: none !important;
    font-size: 18px !important;
    z-index: 6 !important;
  }
  /* El dibujo de la ✕ es SIEMPRE el mismo trazo, no el carácter «✕» o «X»
     de cada ventana: cada fuente lo pinta distinto (en el SPI salía una X
     fina de letra) y no se leía como un botón. El texto y el svg de origen
     se apagan y el icono va en un ::before con máscara. El círculo visible
     mide 36; los 44 de toque los da el relleno transparente. */
  html.mv [data-mv-hoja-inf="1"] :is(.modal-close, .rfi-x, .rg3-modal-x, .mc-x, .chart-max-close, .notif-close, .cap-edit-close, .rz-evo-x, .sigf-toolbar .x, [data-mv-x="1"]):not(.mc-x) {
    padding: 4px !important;
    background-clip: content-box !important;
    font-size: 0 !important;
    color: transparent !important;
  }
  html.mv [data-mv-hoja-inf="1"] :is(.modal-close, .rfi-x, .rg3-modal-x, .mc-x, .chart-max-close, .notif-close, .cap-edit-close, .rz-evo-x, .sigf-toolbar .x, [data-mv-x="1"]):not(.mc-x) > * {
    display: none !important;
  }
  html.mv [data-mv-hoja-inf="1"] :is(.modal-close, .rfi-x, .rg3-modal-x, .mc-x, .chart-max-close, .notif-close, .cap-edit-close, .rz-evo-x, .sigf-toolbar .x, [data-mv-x="1"]):not(.mc-x)::before {
    content: '';
    width: 14px;
    height: 14px;
    background: var(--hoja-x-tinta);
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cpath d='M1.5 1.5l11 11M12.5 1.5l-11 11' stroke='%23000' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
            mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cpath d='M1.5 1.5l11 11M12.5 1.5l-11 11' stroke='%23000' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
  }
  html.mv [data-mv-hoja-inf="1"] :is(.modal-close, .rfi-x, .rg3-modal-x, .mc-x, .chart-max-close, .notif-close, .cap-edit-close, .rz-evo-x, .sigf-toolbar .x, [data-mv-x="1"]):not(.mc-x):active {
    background-color: var(--hoja-borde) !important;
  }

  /* El cuerpo desplaza; cabecera y pie se quedan quietos. */
  html.mv [data-mv-hoja-inf="1"] :is(.modal-body, .kpi-edit-body, .mc-cuerpo, .docctrl-form-grid, .notif-list, .cap-edit-body, .help-body) {
    flex: 1 1 auto !important;
    min-height: 0 !important;
    max-height: none !important;
    overflow-y: auto !important;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    padding: 4px var(--hoja-lado) calc(20px + env(safe-area-inset-bottom, 0px)) !important;
  }
  /* Una ventana que no sigue la anatomía conocida (la detectó modales.js por
     su forma, no por su clase): sin cuerpo reconocible, desplaza la hoja
     entera, con el hueco del asa arriba y el seguro abajo. */
  html.mv [data-mv-hoja-inf="1"]:not(#notifDropdown):not(:has(:is(.modal-body, .kpi-edit-body, .mc-cuerpo, .docctrl-form-grid, .notif-list, .cap-edit-body, .help-body))) {
    overflow-y: auto !important;
    overscroll-behavior: contain;
    padding: 26px var(--hoja-lado) calc(20px + env(safe-area-inset-bottom, 0px)) !important;
  }

  html.mv [data-mv-hoja-inf="1"]:not(#notifDropdown):not(:has(:is(.modal-body, .kpi-edit-body, .mc-cuerpo, .docctrl-form-grid, .notif-list, .cap-edit-body, .help-body))) > :first-child:not([data-mv-x]) {
    padding-right: 52px !important;
  }

  /* Sin cuerpo reconocible pero CON pie (Editar foto): el pie se pega al
     fondo de la hoja que desplaza. El relleno inferior va en el pie y no en
     la hoja; con él en la hoja, `sticky` se pegaba al borde del relleno y el
     contenido asomaba por debajo de los botones. */
  html.mv [data-mv-hoja-inf="1"]:not(:has(:is(.modal-body, .kpi-edit-body, .mc-cuerpo, .docctrl-form-grid, .notif-list, .cap-edit-body, .help-body))):has(> :is(.foto-edit-actions, .modal-actions)) {
    padding-bottom: 0 !important;
  }
  html.mv [data-mv-hoja-inf="1"] > :is(.foto-edit-actions, .modal-actions) {
    position: sticky !important;
    bottom: 0 !important;
    margin: 16px calc(-1 * var(--hoja-lado)) 0 !important;
    z-index: 2;
  }

  /* Pies con los botones dentro de una envoltura y una nota al lado
     (Reporte SST, Gestión Ambiental): la nota arriba a todo el ancho, los
     botones debajo repartiendo la fila. Y como ese pie vive DENTRO del cuerpo,
     se pega al fondo de lo que desplaza. */
  html.mv [data-mv-hoja-inf="1"] :is(.modal-foot, .kpi-edit-actions, .rfi-modal-f, .docctrl-modal-actions, .cap-edit-foot, .foto-edit-actions, .modal-actions) > :is(div, span):has(button) {
    display: flex !important;
    flex: 1 1 100% !important;
    gap: 10px !important;
  }
  html.mv [data-mv-hoja-inf="1"] :is(.modal-foot, .kpi-edit-actions, .rfi-modal-f, .docctrl-modal-actions, .cap-edit-foot, .foto-edit-actions, .modal-actions) > span:not(:has(button)) {
    flex: 1 1 100% !important;
    font-size: 13px !important;
    line-height: 1.4 !important;
    color: var(--hoja-suave) !important;
  }
  html.mv [data-mv-hoja-inf="1"] .kpi-edit-body:has(> .kpi-edit-actions) { padding-bottom: 0 !important; }
  html.mv [data-mv-hoja-inf="1"] .kpi-edit-body > .kpi-edit-actions {
    position: sticky !important;
    bottom: 0 !important;
    margin: 18px calc(-1 * var(--hoja-lado)) 0 !important;
    z-index: 2;
  }

  /* La barra de título de los diálogos del motor (Confirmar, pedir nombre,
     alta de adicional): en escritorio es una tarjeta con borde y sombra; en
     la hoja se leía como una caja metida dentro de otra. Pasa a ser la
     cabecera, con hueco para la ✕. */
  html.mv [data-mv-hoja-inf="1"] > .sigf-toolbar {
    border: 0 !important;
    box-shadow: none !important;
    background: none !important;
    border-radius: 0 !important;
    margin: 0 0 6px !important;
    padding: 6px 52px 8px 0 !important;
    min-height: 44px;
  }
  html.mv [data-mv-hoja-inf="1"] > .sigf-toolbar .sigf-tt {
    color: var(--hoja-tinta) !important;
    font-size: 18px !important;
    line-height: 1.3 !important;
    font-weight: 700 !important;
  }

  /* Cabecera con título y bajada sin envoltura (Reporte SST, Editar avance):
     uno debajo del otro, no la bajada al costado del título. */
  html.mv [data-mv-hoja-inf="1"] .kpi-edit-head {
    flex-direction: column !important;
    align-items: flex-start !important;
    gap: 3px !important;
  }

  /* Títulos sueltos de ventanas sin cabecera (Editar foto, el aviso de error):
     el mismo 18/700 en tinta, no azul ni 24 espaciado en mayúsculas. */
  html.mv [data-mv-hoja-inf="1"] :is(.foto-edit-title, .modal-title) {
    margin: 0 0 14px !important;
    padding-right: 52px !important;
    color: var(--hoja-tinta) !important;
    font-size: 19px !important;
    line-height: 1.3 !important;
    font-weight: 700 !important;
    letter-spacing: 0 !important;
  }

  /* Los campos de las ventanas de edición: blancos, con borde, texto a la
     izquierda y 16 px. En escritorio van grises y centrados; en la hoja se
     leían como cajas deshabilitadas. */
  html.mv [data-mv-hoja-inf="1"] :is(.kpi-edit-input, .cap-edit-input, .cap-edit-select) {
    min-height: 48px !important;
    padding: 0 14px !important;
    border: 1px solid var(--hoja-borde) !important;
    border-radius: 12px !important;
    background-color: var(--hoja-fondo) !important;
    color: var(--hoja-tinta) !important;
    font-size: 16px !important;
    text-align: left !important;
  }

  /* Con pie, el relleno seguro lo lleva el pie. */
  html.mv [data-mv-hoja-inf="1"]:has(:is(.modal-foot, .kpi-edit-actions, .rfi-modal-f, .docctrl-modal-actions, .cap-edit-foot, .foto-edit-actions, .modal-actions)) :is(.modal-body, .kpi-edit-body, .mc-cuerpo, .docctrl-form-grid, .cap-edit-body) {
    padding-bottom: 16px !important;
  }

  /* Pie: fijo abajo, principal primero y a todo el ancho, el resto debajo
     a partes iguales. 48 de alto y letra de 15: se pulsa con el pulgar. */
  html.mv [data-mv-hoja-inf="1"] :is(.modal-foot, .kpi-edit-actions, .rfi-modal-f, .docctrl-modal-actions, .cap-edit-foot, .foto-edit-actions, .modal-actions) {
    flex: 0 0 auto !important;
    display: flex !important;
    flex-wrap: wrap !important;
    justify-content: stretch !important;
    gap: 10px !important;
    margin: 0 !important;
    padding: 12px var(--hoja-lado) calc(12px + env(safe-area-inset-bottom, 0px)) !important;
    border-top: 1px solid var(--hoja-linea) !important;
    background: var(--hoja-fondo) !important;
  }
  html.mv [data-mv-hoja-inf="1"] :is(.modal-foot, .kpi-edit-actions, .rfi-modal-f, .docctrl-modal-actions, .cap-edit-foot, .foto-edit-actions, .modal-actions) :is(button, .btn) {
    flex: 1 1 0 !important;
    min-width: 0 !important;
    min-height: 48px !important;
    justify-content: center !important;
    border-radius: 12px !important;
    font-size: 15px !important;
    font-weight: 700 !important;
  }
  /* Principal a la derecha y un poco más ancha, en la misma fila que
     Cancelar: apiladas, dos botones gastaban 131 px de pie. Con tres o más,
     la fila parte sola. */
  html.mv [data-mv-hoja-inf="1"] :is(.modal-foot, .kpi-edit-actions, .rfi-modal-f, .docctrl-modal-actions, .cap-edit-foot, .foto-edit-actions, .modal-actions) :is(.btn-primary, .primary, [class*="-primary"], [type="submit"], .btn-save, [class*="-save"], [class*="guardar"]) {
    order: 2 !important;
    flex-grow: 1.6 !important;
  }

  /* Pestañas internas («Perfil · Firma · Seguridad · Sesión» en Mi cuenta)
     se salían del ancho sin poder alcanzarlas. */
  html.mv [data-mv-hoja-inf="1"] [class*="tabs"],
  html.mv [data-mv-hoja-inf="1"] [class*="-tab-bar"] {
    display: flex !important;
    overflow-x: auto !important;
    flex-wrap: nowrap !important;
    gap: 6px !important;
    scrollbar-width: none;
  }
  html.mv [data-mv-hoja-inf="1"] [class*="tabs"]::-webkit-scrollbar { width: 0; height: 0 }
  html.mv [data-mv-hoja-inf="1"] [class*="tabs"] > * {
    flex: 0 0 auto !important;
    min-height: 40px !important;
    white-space: nowrap !important;
  }

  /* ── Notificaciones sobre el componente ─────────────────────────
     El rediseño la dibuja por ID (`#notifDropdown …`, con !important): a
     igual !important el id gana a `[data-mv-hoja-inf]`. Medido a 390: salía
     flotando con el marco de cristal, la ✕ fuera de la tarjeta, filtros de
     38 de alto y 24 rótulos por debajo de 12,5 px. Aquí se repite lo
     necesario con el id delante. */
  html.mv #notifDropdown[data-mv-hoja-inf="1"] {
    position: fixed !important;
    inset: auto 0 0 0 !important;
    width: 100% !important;
    max-width: none !important;
    height: auto !important;
    max-height: min(88dvh, calc(100dvh - 24px)) !important;
    padding: 0 !important;
    border-radius: var(--hoja-radio) var(--hoja-radio) 0 0 !important;
    background: var(--hoja-fondo) !important;
    box-shadow: var(--hoja-sombra) !important;
    overflow: hidden !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
  }
  html.mv #notifDropdown[data-mv-hoja-inf="1"].show {
    display: flex !important;
    animation: mv-hoja-sube .28s cubic-bezier(.32, .72, 0, 1);
  }
  html.mv .notif-backdrop.show { background: var(--hoja-velo) !important; }

  html.mv #notifDropdown .notif-head {
    padding: 26px 66px 10px var(--hoja-lado) !important;
    height: auto !important;
    align-items: center !important;
  }
  html.mv #notifDropdown .notif-title {
    flex: 1 1 auto;
    font-size: 20px !important;
    line-height: 26px !important;
    font-weight: 700 !important;
    color: var(--hoja-tinta) !important;
  }
  /* «Marcar leídas» es una acción secundaria: texto azul, no una píldora
     con borde que compite con el título. */
  html.mv #notifDropdown .notif-mark {
    height: 44px !important;
    padding: 0 10px !important;
    margin-right: -6px !important;
    border: 0 !important;
    border-radius: 10px !important;
    background: none !important;
    color: var(--hoja-azul) !important;
    font-size: 15px !important;
    font-weight: 600 !important;
  }
  html.mv #notifDropdown .notif-close {
    top: 16px !important;
    right: 12px !important;
  }

  /* Filtros como chips: tres estados con su número y el área en su propia
     chip, en un carril que se desliza —el mismo gesto que el resto de la
     capa— en vez de recortarse dentro de una cápsula gris. A 360 no caben
     los tres y partir a dos filas dejaba «Leídas» sola abajo. */
  html.mv #notifDropdown .notif-filters {
    flex: 0 0 auto !important;
    display: flex !important;
    flex-wrap: nowrap !important;
    align-items: center !important;
    gap: 8px !important;
    height: auto !important;
    padding: 6px var(--hoja-lado) 14px !important;
    margin: 0 !important;
    background: none !important;
    border-radius: 0 !important;
    border-bottom: 1px solid var(--hoja-linea) !important;
    overflow-x: auto !important;
    overflow-y: hidden !important;
    scrollbar-width: none;
    overscroll-behavior-x: contain;
  }
  html.mv #notifDropdown .notif-filters::-webkit-scrollbar { width: 0; height: 0; }
  html.mv #notifDropdown .notif-filters > * { flex: 0 0 auto !important; }
  html.mv #notifDropdown .notif-filter {
    position: relative;
    height: 36px !important;
    padding: 0 12px !important;
    gap: 6px !important;
    border: 1px solid var(--hoja-borde) !important;
    border-radius: 999px !important;
    background: var(--hoja-fondo) !important;
    color: var(--hoja-x-tinta) !important;
    font-size: 14px !important;
    font-weight: 500 !important;
  }
  /* 36 de dibujo, 44 de toque: el área crece sin engordar la chip. Con 38 y
     letra de 15, a 390 «Leídas» bajaba sola a una segunda fila. */
  html.mv #notifDropdown .notif-filter::after { content: ''; position: absolute; inset: -4px 0; }
  html.mv #notifDropdown .notif-filter.active {
    padding: 0 12px !important;
    border-color: var(--hoja-azul) !important;
    background: var(--hoja-azul-suave) !important;
    color: var(--hoja-azul) !important;
    font-weight: 600 !important;
  }
  html.mv #notifDropdown .notif-filter-count,
  html.mv #notifDropdown .notif-filter.active .notif-filter-count {
    display: inline-flex !important;
    min-width: 22px !important;
    height: 22px !important;
    padding: 0 6px !important;
    border-radius: 11px !important;
    background: var(--hoja-x-fondo) !important;
    color: var(--hoja-x-tinta) !important;
    font: 600 13px/22px Inter, system-ui, sans-serif !important;
  }
  html.mv #notifDropdown .notif-filter.active .notif-filter-count {
    background: var(--hoja-azul) !important;
    color: #fff !important;
  }
  html.mv #notifDropdown .notif-area-wrap {
    position: relative;
    margin: 0 !important;
    padding: 0 !important;
    flex: 0 0 auto !important;
  }
  /* 16 px: con menos, iOS amplía la página al tocar el desplegable. */
  html.mv #notifDropdown .notif-area {
    height: 36px !important;
    padding: 0 34px 0 38px !important;
    border: 1px solid var(--hoja-borde) !important;
    border-radius: 999px !important;
    background: var(--hoja-fondo) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='%236B7280'%3E%3Cpath d='M5.2 7.2a.75.75 0 0 1 1.06 0L10 10.94l3.74-3.74a.75.75 0 1 1 1.06 1.06l-4.27 4.27a.75.75 0 0 1-1.06 0L5.2 8.26a.75.75 0 0 1 0-1.06'/%3E%3C/svg%3E") no-repeat right 10px center / 18px !important;
    color: var(--hoja-x-tinta) !important;
    font-size: 16px !important;
    line-height: 34px !important;
  }
  html.mv #notifDropdown .notif-area-ico {
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    width: 17px !important;
    height: 17px !important;
    color: var(--hoja-suave) !important;
    pointer-events: none;
  }

  /* La lista: filas planas con filete FINO entre ellas —no punteado, no
     después de la última— que empieza donde empieza el texto, no bajo el
     disco. Título a 15 y descripción a 14: a 12 no se leía. */
  html.mv #notifDropdown .notif-list {
    gap: 0 !important;
    padding: 0 var(--hoja-lado) calc(16px + env(safe-area-inset-bottom, 0px)) !important;
  }
  html.mv #notifDropdown .notif-item {
    gap: 12px !important;
    padding: 14px 0 !important;
    border-radius: 0 !important;
  }
  html.mv #notifDropdown .notif-item:hover { background: none !important; border-radius: 0; }
  html.mv #notifDropdown .notif-item:active { background: var(--hoja-x-fondo) !important; }
  html.mv #notifDropdown .notif-item::after {
    left: 48px !important;
    background: var(--hoja-linea) !important;
  }
  html.mv #notifDropdown .notif-item-icon {
    width: 36px !important;
    height: 36px !important;
    margin-top: 1px;
  }
  html.mv #notifDropdown .notif-item-icon svg { width: 18px !important; height: 18px !important; }
  html.mv #notifDropdown .notif-item-content { gap: 3px !important; }
  html.mv #notifDropdown .notif-item-head { align-items: flex-start !important; gap: 10px !important; }
  html.mv #notifDropdown .notif-item-title {
    font-size: 15px !important;
    line-height: 20px !important;
    font-weight: 600 !important;
    color: var(--hoja-tinta) !important;
  }
  html.mv #notifDropdown .notif-item.unread .notif-item-title { font-weight: 700 !important; }
  html.mv #notifDropdown .notif-item.read .notif-item-title { color: var(--hoja-suave) !important; }
  html.mv #notifDropdown .notif-item-time {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 1px;
    font-size: 13px !important;
    line-height: 18px !important;
    color: var(--hoja-suave) !important;
  }
  /* Sin leer: un punto azul junto a la hora, como en cualquier bandeja. */
  html.mv #notifDropdown .notif-item.unread .notif-item-time::before {
    content: '';
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--hoja-azul);
  }
  html.mv #notifDropdown .notif-item-desc {
    font-size: 14px !important;
    line-height: 19px !important;
    color: var(--hoja-suave) !important;
  }
  /* Lo que main añade a cada aviso y al pie: quién lo manda, «TE TOCA» y
     el aviso de push. Medido: 9 textos entre 11 y 12 px. */
  html.mv #notifDropdown .notif-item-author { font-size: 13px !important; color: var(--hoja-suave) !important; }
  html.mv #notifDropdown .notif-item-yo {
    font-size: 12.5px !important;
    line-height: 20px !important;
    padding: 0 8px !important;
    font-weight: 700 !important;
  }
  html.mv #notifDropdown .notif-foot {
    flex: 0 0 auto !important;
    display: flex !important;
    align-items: center !important;
    justify-content: space-between !important;
    gap: 10px !important;
    padding: 10px var(--hoja-lado) calc(10px + env(safe-area-inset-bottom, 0px)) !important;
    border-top: 1px solid var(--hoja-linea) !important;
    background: var(--hoja-fondo) !important;
  }
  html.mv #notifDropdown .notif-foot-info { font-size: 13px !important; color: var(--hoja-suave) !important; }
  html.mv #notifDropdown .notif-push {
    height: 44px !important;
    padding: 0 16px !important;
    border-radius: 12px !important;
    font-size: 14px !important;
    font-weight: 600 !important;
  }
  /* Con pie, el relleno seguro lo lleva el pie y no la lista. */
  html.mv #notifDropdown:has(.notif-foot) .notif-list { padding-bottom: 8px !important; }

  html.mv #notifDropdown .notif-empty {
    padding: 48px 16px !important;
    text-align: center;
    font-size: 15px !important;
    color: var(--hoja-suave) !important;
  }

  /* ── Bandeja · adjuntos (B-05, 28-sep) ─────────────────────────────
     «E140_Reporte_Gerencial_SEM48.pdf» es una sola palabra de 33 letras: en
     el chip no cabía y el peso («· 775 KB») se partía en tres líneas. El
     nombre puede cortarse donde haga falta; el peso, nunca. */
  html.mv #sec-central .oc-files a {
    flex-wrap: wrap;
    overflow-wrap: anywhere;
    row-gap: 2px;
    line-height: 1.35;
    max-width: 100%;
  }
  html.mv #sec-central .oc-files a > span:last-child { white-space: nowrap; }

  /* ── Buscador ────────────────────────────────────────────────────
     El ÚNICO que no se convierte en hoja inferior, y es a propósito: al
     enfocar el campo se abre el teclado, que ocupa la mitad de abajo y
     taparía justo donde se escribe. Un buscador va anclado ARRIBA, que es
     donde queda visible con el teclado desplegado. */
  html.mv .th-search {
    left: 10px !important;
    right: 10px !important;
    width: auto !important;
    min-height: 48px !important;
    border-radius: 13px !important;
    gap: 9px !important;
    padding: 0 12px !important;
    box-shadow: 0 6px 22px rgba(0, 0, 0, .14) !important;
  }
  /* 16 px o iOS hace zoom al enfocar y descuadra toda la maqueta. */
  html.mv .th-search .th-buscar {
    font-size: 16px !important;
    min-height: 46px !important;
    flex: 1 1 auto !important;
    min-width: 0 !important;
  }
  /* El atajo de teclado no significa nada sin teclado físico. */
  html.mv .th-search .th-kbd { display: none !important }
  /* DENTRO DE LA CABECERA, DE CRISTAL (N-03, 28-sep). Al buscar salía una
     caja blanca fija ENCIMA de la cabecera azul, montada sobre la píldora de
     semana, y no se parecía al buscador de escritorio. Ahora el campo toma el
     sitio del chip de la obra, en la primera fila, con el mismo cristal que
     en escritorio (blanco al 10–14 %, canto celeste de 1 px, texto claro). La
     lupa que lo abrió sobra mientras se busca. Sigue arriba, que es lo que
     pedía el comentario de arriba: el teclado no lo tapa.
     Los `!important` de este bloque le ganan a los de `assets/shell-blanco.css`
     (`.top-header .th-search{…!important}` y `.top-header.busca-movil
     .th-search{position:fixed!important…}`), que son todos `!important`. */
  /* El campo vive DENTRO de `.th-left`, junto al chip: se ocultan sus
     hermanos (el chip) y el bloque se estira. */
  html.mv .top-header.busca-movil .th-left > :not(.th-search),
  html.mv .top-header.busca-movil .th-busca-btn { display: none !important; }
  html.mv .top-header.busca-movil .th-left {
    flex: 1 1 0 !important;
    min-width: 0 !important;
  }
  /* Mientras se busca, la semana y los botones se ocultan y el campo ocupa toda la
     fila, como en main (370 px). Con `flex-basis: 100%` en la semana el campo
     quedaba en 20 px; con la semana visible, en 75–130 px. */
  html.mv .top-header.busca-movil .week-selector,
  html.mv .top-header.busca-movil .th-right { display: none !important; }
  /* El desplegable usa el ancho de la pantalla, no el del campo: con el campo a la
     mitad los nombres salían «Op… / Pan… / Per…». */
  html.mv .bs-menu { left: 8px !important; right: 8px !important; width: auto !important; }
  html.mv .top-header.busca-movil .th-search {
    display: flex !important;
    position: static !important;
    flex: 1 1 0 !important;
    min-width: 0 !important;
    height: 44px !important;
    min-height: 44px !important;
    margin: 0 !important;
    padding: 0 6px 0 14px !important;
    background: rgba(255, 255, 255, .14) !important;
    box-shadow: inset 0 0 0 1px rgba(160, 224, 255, .72) !important;
    border-radius: 22px !important;
    color: #FFFFFF !important;
  }
  html.mv .top-header.busca-movil .th-search .th-buscar {
    min-height: 42px !important;
    background: transparent !important;
    border: 0 !important;
    color: #FFFFFF !important;
  }
  html.mv .top-header.busca-movil .th-search .th-buscar::placeholder { color: rgba(236, 244, 255, .82) !important; }
  /* Un solo anillo de foco (guía §4): el del cristal, no otro dentro. */
  html.mv .top-header.busca-movil .th-search .th-buscar:focus {
    outline: none !important;
    box-shadow: none !important;
    background: transparent !important;
  }
  html.mv .top-header.busca-movil .th-search:focus-within {
    box-shadow: inset 0 0 0 2px #FFFFFF !important;
  }
  html.mv .top-header.busca-movil .th-search svg { color: #D4E0F9 !important; }
  html.mv .top-header.busca-movil .th-search .th-busca-x { color: #FFFFFF !important; }
  html.mv .th-search .th-busca-x {
    min-width: 40px !important;
    min-height: 40px !important;
    flex: 0 0 auto !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    border-radius: 10px !important;
  }

  /* ── Botones sueltos que se quedaron sin formato móvil ───────────
     Barras de acción de las vistas: en escritorio caben en una fila a la
     derecha; a 390 px se apelotonan o se salen. Ancho compartido y altura
     táctil. */
  html.mv .scroll-area .rfi-btn,
  html.mv .scroll-area .apu-tools .rfi-btn,
  html.mv .scroll-area [class*="-tools"] > button,
  html.mv .scroll-area [class*="-toolbar"] > button {
    min-height: 44px !important;
    border-radius: 11px !important;
    white-space: nowrap !important;
  }
  html.mv .scroll-area [class*="-tools"],
  html.mv .scroll-area [class*="-toolbar"] {
    display: flex !important;
    flex-wrap: wrap !important;
    gap: 8px !important;
  }

  /* ── Bandeja · el filtro deja de colgar de una pestaña ───────────
     `.oc-cab` es flex-wrap con dos pestañas y un <select>. El select caía a
     la segunda fila pero alineado a la derecha, justo debajo del subrayado de
     «Solicitudes», y se leía como si perteneciera a esa pestaña. Fila propia,
     ancho completo: filtra la lista entera, no una pestaña. */
  html.mv .oc-cab {
    display: flex !important;
    flex-wrap: wrap !important;
    gap: 8px !important;
    align-items: center !important;
  }
  html.mv .oc-cab .oc-tab {
    flex: 1 1 auto !important;
    min-height: 44px !important;
    white-space: nowrap !important;
  }
  html.mv .oc-cab .oc-filtro {
    flex: 1 0 100% !important;
    width: 100% !important;
    margin: 4px 0 0 !important;
    min-height: 44px !important;
    border-radius: 11px !important;
  }

  /* ── Tarjetas anidadas ·  movil/marcos.js ────────────────────────
     Una tarjeta que contiene tarjetas no es una tarjeta: es un contenedor.
     En Programación meta se perdían 58 px POR LADO —32 % del ancho— en
     marcos que solo contenían otros marcos. */
  html.mv [data-mv-contenedor="1"] {
    background: transparent !important;
    border: 0 !important;
    box-shadow: none !important;
    border-radius: 0 !important;
    padding-left: 0 !important;
    padding-right: 0 !important;
  }
  html.mv [data-mv-anidada="1"] {
    padding: 13px 14px !important;
    border-radius: 13px !important;
  }

  /* La caja que envuelve al iframe desaparece. En móvil no aporta nada: ni
     agrupa —solo contiene una cosa— ni separa, y lo que sí hacía era imponer
     un alto fijo con scroll propio. Título y contenido pasan a fluir en la
     página, con el scroll nativo de la aplicación y ninguno más. */
  html.mv .pm-marco,
  html.mv #sec-dimensionamiento > div:has(> iframe) {
    border: 0 !important;
    box-shadow: none !important;
    border-radius: 0 !important;
    background: transparent !important;
    height: auto !important;
    max-height: none !important;
    overflow: visible !important;
    padding: 0 !important;
  }
  /* La sección deja de ser flex. Con `display:flex` el iframe llevaba
     `flex: 1 1 0%`, y un flex-basis de 0 gana sobre `height`: por mucho que
     marcos.js le pusiera 1156 px, seguía renderizando 528. En flujo normal el
     alto que se le asigna es el que manda.

     OJO CON `.active`. La aplicación esconde lo que no toca con
     `.section{display:none}` y lo enseña con `.section.active`. Sin pedir
     `.active` aquí, este `!important` ganaba SIEMPRE y las dos secciones se
     quedaban visibles en TODAS las vistas: medido en el Panel Fotográfico,
     una banda de 120 px con el iframe vacío de Programación meta encima del
     contenido. */
  html.mv #sec-progmeta.section.active,
  html.mv #sec-dimensionamiento.section.active {
    display: block !important;
  }
  html.mv #sec-progmeta iframe,
  html.mv #sec-dimensionamiento iframe {
    display: block !important;
    width: 100% !important;
    border: 0 !important;
    flex: 0 0 auto !important;
    min-height: 0 !important;
    /* El alto lo fija movil/marcos.js midiendo el contenido real. */
  }

  /* ═══════════════════════════════════════════════════════════════
     «Mi cuenta», que pelea por ID
     ───────────────────────────────────────────────────────────────
     Las reglas de la hoja inferior cuelgan de `[data-mv-hoja-inf]`,
     que puntúa (0,2,0). El bloque del Figma usa `#perfilOv .rfi-modal`
     —(1,1,0)— y con `!important` en las dos, gana el id: la hoja salía
     con las cuatro esquinas a 12 en vez de redondeada solo arriba.
     Estas repiten lo mismo con el id delante para puntuar por encima.

     Y el relleno baja de 48 a 18: 48 por lado en una pantalla de 414
     deja 318 para el contenido, y los campos ya no caben en dos
     columnas. En escritorio se queda como está. */
  html.mv #perfilOv [data-mv-hoja-inf="1"] {
    border-radius: 18px 18px 0 0 !important;
    padding: 18px !important;
    gap: 14px !important;
  }
  /* La cápsula de pestañas a lo ancho: con cinco pestañas en 414 px no
     caben en una fila y el `flex-wrap` las parte; que se desplacen. */
  html.mv #perfilOv .mc-tabs {
    flex-wrap: nowrap !important;
    overflow-x: auto !important;
    scrollbar-width: none;
    align-self: stretch !important;
  }
  html.mv #perfilOv .mc-tabs::-webkit-scrollbar { display: none; }
  /* Y la ✕ dentro de la hoja sigue siendo cuadrada: el mínimo táctil de
     44 la estiraría, que es justo el fallo que se acaba de arreglar. */
  html.mv #perfilOv .mc-x {
    /* `min-width` Y `min-height` a cero: las dos ganan a `width`/`height`, asi
       que con el minimo tactil puesto la ✕ salia 40×36 — el mismo fallo que se
       acaba de arreglar en escritorio, por el otro eje. El area de toque la
       amplia tactil.js sin deformar el dibujo. */
    min-width: 0 !important;
    min-height: 0 !important;
    width: 36px !important;
    height: 36px !important;
    padding: 0 !important;
  }

  /* ═══════════════════════════════════════════════════════════════
     Etiquetas cortas que se recortan al apretar
     ───────────────────────────────────────────────────────────────
     A 360 px se cortaban dos: el distintivo «Editado» de las tarjetas
     KPI (9 px de más) y el porcentaje en negrita de la comparativa de
     avances (12 px). Las dos viven en filas flex y llevaban
     `flex:0 1 auto`, así que la fila las encogía cuando el ancho no
     daba, y con `white-space:normal` ni siquiera podían partir: el
     texto quedaba tapado dentro de su propia caja.

     Con `flex:none` salen del reparto —miden lo que miden, que son
     siete letras y cinco cifras— y lo que cede es el rótulo largo de
     al lado, que sí puede envolver. */
  html.mv .rk-override-badge,
  html.mv .rz-len-r b {
    flex: none !important;
    white-space: nowrap !important;
  }

  /* ══════════════════════════════════════════════════════════════════════
     LAS VISTAS, RECOMPUESTAS PARA MÓVIL
     ──────────────────────────────────────────────────────────────────────
     Hasta aquí esta hoja era solo el armazón. Esto es lo otro: el Resumen
     compuesto, las piezas que comparten los ocho arquetipos, y los ocho.

     Viene entero de `movil/armazon-nativo`, donde ya estaba probado. Se
     había dejado fuera mientras el rediseño estaba en marcha —recomponer
     una pantalla que alguien acaba de dibujar es deshacer su trabajo— y
     entra ahora que está terminado.

     Lo que NO entra: Cartera y Acceso. Esas dos el rediseño ya las tiene
     hechas para móvil.
     ══════════════════════════════════════════════════════════════════════ */

  /* ── Resumen compuesto ─────────────────────────────────────────────────── */
  /* «Estado general» es UNA tarjeta, como en escritorio (R-11, 28-sep): el
     bloque lleva `.rz-card` y aquí solo se le da el relleno de las otras
     secciones del Resumen (16 × 14). Sus partes —anillo, avance, curva,
     proyección— ya no son tarjetas: van una debajo de otra, con un filete. */
  html.mv #sec-resumen .mv-res {
    display: flex;
    flex-direction: column;
    gap: 0;
    padding: 16px 14px;
  }
  html.mv #sec-resumen .mv-res > .rz-sec-h { margin-bottom: 12px; }
  html.mv .mv-res > .rz-estado + .mv-res-parte,
  html.mv .mv-res-parte + .mv-res-parte {
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px solid var(--mv-borde);
  }

  html.mv .mv-res-card {
    background: var(--mv-papel);
    border-radius: 14px;
    padding: 16px;
    box-shadow: var(--mv-sombra);
  }

  html.mv .mv-res-cab {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
  }
  html.mv .mv-res-eyebrow {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: #5A7A96;
  }
  html.mv .mv-res-sem { font-size: 11px; font-weight: 600; color: #5A7A96; }

  html.mv .mv-res-cifra { display: flex; align-items: flex-end; gap: 10px; margin-top: 6px; }
  html.mv .mv-res-cifra b {
    font-size: 44px;
    line-height: 1;
    font-weight: 800;
    letter-spacing: -.025em;
    color: var(--mv-tinta);
  }
  html.mv .mv-res-cifra b i { font-size: 22px; font-style: normal; font-weight: 700; }

  html.mv .mv-res-delta {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 5px 9px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 700;
    margin-bottom: 5px;
  }
  html.mv .mv-res-delta.mal  { background: #FBEAEA; color: #A8293B; }
  html.mv .mv-res-delta.bien { background: #E8F7ED; color: #1F7A43; }
  html.mv .mv-res-delta svg { width: 13px; height: 13px; stroke-width: 2.6; }

  html.mv .mv-res-sub { margin: 6px 0 0; font-size: 12.5px; color: #5A7A96; }
  html.mv .mv-res-sub b { color: var(--mv-tinta); font-weight: 700; }

  /* Avance físico (R-08): real y programado en la misma línea, con el mismo
     tamaño de cifra para compararlos de un vistazo; el programado en el tono
     secundario. Debajo, la variación y su frase juntas. */
  html.mv .mv-res-par {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 12px;
    margin-top: 8px;
  }
  html.mv .mv-res-dato span {
    display: block;
    font-size: 12.5px;
    font-weight: 600;
    color: #5A7A96;
  }
  html.mv .mv-res-dato b {
    display: block;
    margin-top: 2px;
    font-size: 36px;
    line-height: 1.05;
    font-weight: 800;
    letter-spacing: -.025em;
    color: var(--mv-tinta);
    font-variant-numeric: tabular-nums;
  }
  html.mv .mv-res-dato b i { font-size: 18px; font-style: normal; font-weight: 700; }
  html.mv .mv-res-dato.prog b { color: #5A7A96; }
  html.mv .mv-res-var {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin: 10px 0 0;
    font-size: 12.5px;
    color: #5A7A96;
  }
  html.mv .mv-res-var .mv-res-delta { margin-bottom: 0; }

  /* UN DATO DE OTRA SEMANA NO SE LEE COMO EL ESTADO DE HOY. Cuando el último punto de la curva no es la
     semana abierta (la semana en curso aún no tiene medición), las cifras van en su propio recuadro,
     aparte del anillo del plazo que las precede; el rótulo con su semana y la fecha del corte es su
     encabezado y pesa lo que ellas (mismo color de texto, negrita, 17 px sobre cifras de 30); la
     diferencia va sin color de semáforo y sin frase en presente. */
  html.mv .mv-res > .mv-res-parte.mv-res-previo {
    margin-top: 14px;
    padding: 12px;
    border: 1px dashed var(--mv-apagado);
    border-radius: 10px;
    background: var(--mv-fondo);
  }
  html.mv .mv-res-rotulo {
    margin: 8px 0 0;
    font-size: 17px;
    line-height: 1.25;
    font-weight: 700;
    letter-spacing: -.01em;
    color: var(--mv-tinta);
    text-wrap: balance;
  }
  html.mv .mv-res-rotulo span { display: block; }
  html.mv .mv-res-rotulo i { display: none; }
  html.mv .mv-res-previo .mv-res-dato b { font-size: 30px; }
  html.mv .mv-res-previo .mv-res-dato b i { font-size: 16px; }
  html.mv .mv-res-delta.neutro { background: var(--mv-borde); color: var(--mv-tinta); }
  html.mv .mv-res-aviso { margin: 8px 0 0; font-size: 12.5px; color: var(--mv-apagado); }

  /* EL BLOQUE «AVANCE FÍSICO» VA SOBRE LA TARJETA BLANCA EN LOS DOS TEMAS. `#sec-resumen .rz-card { background:#fff }` no
     cambia con el tema, pero los textos de aquí abajo usaban los tokens de móvil, que en oscuro pasan a casi blanco:
     «Real 22.3 %» quedaba casi invisible (idéntico en main). En oscuro se vuelven a poner, SOLO para este bloque, los
     valores de la paleta clara que ya traen el resto de sus textos fijos (#5A7A96 …); los demás bloques de la caja
     (la curva, el carril de proyección con sus tarjetas oscuras) no se tocan. */
  html.mv[data-theme="dark"] .mv-res-hero {
    --mv-tinta: #1A2B3C;
    --mv-apagado: #5C5E64;
    --mv-borde: #EDF1F6;
    --mv-fondo: #EEF5FA;
  }

  html.mv .mv-res-sep { height: 1px; background: var(--mv-borde); margin: 14px 0 12px; }

  html.mv .mv-res-plazo {
    display: flex;
    justify-content: space-between;
    font-size: 11.5px;
    color: #5A7A96;
    margin-bottom: 7px;
  }
  html.mv .mv-res-plazo b { color: var(--mv-tinta); font-weight: 700; }
  /* pasado el plazo contractual: «N días de atraso» en rojo, como en escritorio (.rz-corte-p b) */
  html.mv .mv-res-plazo .mv-res-atraso, html.mv .mv-res-plazo .mv-res-atraso b { color: #EF4444; }

  html.mv .mv-res-barra {
    height: 7px;
    border-radius: 999px;
    background: var(--mv-borde);
    overflow: hidden;
  }
  html.mv .mv-res-barra i { display: block; height: 100%; background: #0070B4; }

  html.mv .mv-res-curva .mv-res-cab { align-items: center; }
  html.mv .mv-res-lienzo { margin-top: 10px; }
  html.mv .mv-res-lienzo .rhc-svg,
  html.mv .mv-res-lienzo svg { width: 100% !important; height: 200px !important; display: block; }

  html.mv .mv-res-leyenda { display: flex; gap: 16px; padding: 8px 4px 0; }
  html.mv .mv-res-leyenda span {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 11.5px;
    color: #5A7A96;
  }
  html.mv .mv-res-leyenda i { width: 14px; height: 3px; border-radius: 2px; }
  html.mv .mv-l-real { background: #B9831C; }
  html.mv .mv-l-prog { background: #0070B4; }

  html.mv .mv-res-tit { padding: 4px 2px 0; }

  /* El carril SIEMPRE tuvo overflow-x. Lo que faltaba era que se notara:
     sin encaje paraba a media tarjeta, y sin asomo el corte del borde parecía
     un fallo en vez de una invitación a deslizar. */
  html.mv .mv-res-carril {
    display: flex;
    gap: 10px;
    overflow-x: auto;
    scrollbar-width: none;
    padding: 0 14px 4px;
    margin: 0 -14px;
    align-items: stretch;             /* pies alineados aunque la nota mida distinto */
    scroll-snap-type: x mandatory;
    scroll-padding-inline: 14px;
    overscroll-behavior-x: contain;   /* no arrastra la página al llegar al final */
    -webkit-overflow-scrolling: touch;
  }
  html.mv .mv-res-carril::-webkit-scrollbar { width: 0; height: 0; }

  html.mv .mv-res-kpi {
    flex: 0 0 78%;                    /* el 22 % restante ASOMA: esa es la señal */
    max-width: 320px;                 /* tope para tabletas; a 390 px no muerde */
    scroll-snap-align: start;
    /* EL MISMO LENGUAJE QUE LAS TARJETAS DE ESCRITORIO, en formato de
       teléfono. Llevaban una raya de color de 3 px arriba, que es el
       lenguaje viejo; las modernas tiñen con un radial anclado SOBRE el
       borde superior y se van a nada hacia abajo. Los valores —posición,
       tamaño y alfa— son los mismos de `.r-kpi` en index.html, para que
       las dos pantallas se lean como la misma familia. */
    background: radial-gradient(120% 85% at 50% -12%, rgba(0,112,180,.10), transparent 58%), var(--mv-papel);
    border-radius: 20px;
    padding: 16px;
    border: 1.5px solid rgba(255, 255, 255, .9);
    box-shadow: 0 1px 2px rgba(16,24,40,.02), 0 9px 20px -24px rgba(16,24,40,.07);
    display: grid;
    grid-template-columns: minmax(0, 1fr);  /* explícito: una sola columna */
    grid-template-rows: auto 1fr auto;      /* etiqueta · cifra · nota */
    min-height: 124px;
  }
  /* El estado tiñe el radial, no una raya. Mismos tonos que `.rk-red` y
     `.rk-green` de escritorio. */
  html.mv .mv-res-kpi.mal {
    background: radial-gradient(120% 85% at 50% -12%, rgba(220,38,38,.10), transparent 58%), var(--mv-papel);
  }
  html.mv .mv-res-kpi.bien {
    background: radial-gradient(120% 85% at 50% -12%, rgba(22,163,110,.10), transparent 58%), var(--mv-papel);
  }

  /* La cifra se parte en número y unidad. «12.8% del CD» envolvía a dos líneas
     porque eran 24 px metidos en 158: no era falta de sitio, era forma del dato.
     ACOTADO a .mv-res-kpi: la clase .mv-res-cifra ya la usa el número grande del
     hero (línea 553, 44 px) y sin acotar estas reglas le ganaban la cascada. */
  html.mv .mv-res-kpi .mv-res-cifra {
    display: flex;
    align-items: baseline;
    gap: 4px;
    margin-top: 8px;
    white-space: nowrap;
    min-width: 0;
  }
  html.mv .mv-res-kpi .mv-res-cifra b {
    font-size: 28px;
    font-weight: 800;
    letter-spacing: -.025em;
    line-height: 1.05;
    color: var(--mv-tinta);
  }
  html.mv .mv-res-kpi .mv-res-cifra u {
    text-decoration: none;
    font-size: 13px;
    font-weight: 700;
    color: var(--mv-apagado);
  }
  html.mv .mv-res-nota {
    display: block;
    align-self: end;
    margin-top: 9px;
    font-size: 11px;
    line-height: 1.4;
    color: var(--mv-apagado);
  }
  html.mv .mv-res-kpi.mal .mv-res-nota  { color: #A8293B; }
  html.mv .mv-res-kpi.bien .mv-res-nota { color: #1F7A43; }
  /* Fin del proyecto (R-03): la fecha contractual y la proyectada, una por
     línea, debajo de la nota. Su diferencia es la cifra de arriba. */
  html.mv .mv-res-fechas {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-top: 8px;
    font-size: 12.5px;
    line-height: 1.35;
    color: var(--mv-apagado);
  }
  html.mv .mv-res-fechas b { color: var(--mv-tinta); font-weight: 700; }

  /* Puntos: cuántas tarjetas hay y en cuál estás. */
  html.mv .mv-res-puntos {
    display: flex;
    gap: 5px;
    justify-content: center;
    margin: 11px 0 2px;
  }
  html.mv .mv-res-puntos i {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--mv-borde);
    transition: width .18s ease, background .18s ease;
  }
  html.mv .mv-res-puntos i.on { width: 15px; border-radius: 3px; background: #0070B4; }

  @media (prefers-reduced-motion: reduce) {
    html.mv .mv-res-carril { scroll-behavior: auto; }
    html.mv .mv-res-puntos i { transition: none; }
  }

  html.mv .mv-res-zoom .rk-zoom { position: static !important; margin: 0 !important; }

  /* ═══════════════════════════════════════════════════════════════
     PIEZAS COMPARTIDAS  ·  movil/piezas.js
     Vocabulario común de los arquetipos. Todo con prefijo mv-, que es
     lo que mantiene fuera a los comodines de la capa de parches.
     ═══════════════════════════════════════════════════════════════ */

  /* Tonos. Tres, no cuatro: el amarillo no alcanza 3:1 contra fondo claro. */
  html.mv .mv-t-mal    { --t: #A8293B; --t-suave: rgba(168, 41, 59, .11); }
  html.mv .mv-t-aten   { --t: #B9831C; --t-suave: rgba(185, 131, 28, .13); }
  html.mv .mv-t-bien   { --t: #1F7A43; --t-suave: rgba(31, 122, 67, .11); }
  html.mv .mv-t-neutro { --t: #0070B4; --t-suave: rgba(0, 112, 180, .10); }
  :root[data-theme="dark"] html.mv .mv-t-mal,
  html.mv[data-theme="dark"] .mv-t-mal { --t: #C94257; }

  html.mv .mv-eyebrow {
    display: block;
    font: 700 10px/1.35 'Inter', sans-serif;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--mv-apagado);
  }

  html.mv .mv-tit-sec {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 16px 2px 9px;
    font: 700 10px/1.35 'Inter', sans-serif;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--mv-apagado);
  }
  html.mv .mv-tit-sec s { flex: 1; height: 1px; background: var(--mv-borde); }
  html.mv .mv-tit-sec i {
    font-style: normal;
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
    font-size: 11px;
  }

  html.mv .mv-cifra {
    display: flex;
    align-items: baseline;
    gap: 4px;
    margin-top: 6px;
    white-space: nowrap;
    min-width: 0;
  }
  html.mv .mv-cifra b {
    font-size: 27px;
    font-weight: 800;
    letter-spacing: -.025em;
    line-height: 1.05;
    color: var(--mv-tinta);
  }
  html.mv .mv-cifra u {
    text-decoration: none;
    font-size: 13px;
    font-weight: 700;
    color: var(--mv-apagado);
  }

  html.mv .mv-senal {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font: 700 9.5px/1 'Inter', sans-serif;
    letter-spacing: .05em;
    text-transform: uppercase;
    padding: 5px 9px;
    border-radius: 999px;
    white-space: nowrap;
    background: var(--t-suave);
    color: var(--t);
  }

  html.mv .mv-medidor {
    height: 5px;
    border-radius: 3px;
    background: var(--mv-borde);
    margin-top: 10px;
    overflow: hidden;
  }
  html.mv .mv-medidor i { display: block; height: 100%; border-radius: 3px; background: var(--t); }

  /* Fila de estadística — Panel de área */
  html.mv .mv-stat {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 11px;
    background: var(--mv-papel);
    border-radius: 14px;
    padding: 13px 14px;
    margin-bottom: 10px;
    box-shadow: var(--mv-sombra);
  }
  html.mv .mv-stat .mv-eyebrow { grid-column: 1; grid-row: 1; }
  html.mv .mv-stat .mv-cifra   { grid-column: 1; grid-row: 2; }
  html.mv .mv-stat .mv-senal   { grid-column: 2; grid-row: 1 / span 2; align-self: start; }
  html.mv .mv-stat-meta {
    grid-column: 1 / -1;
    grid-row: 3;
    margin-top: 6px;
    font-size: 11.5px;
    line-height: 1.45;
    color: var(--mv-apagado);
  }
  html.mv .mv-stat .mv-medidor { grid-column: 1 / -1; grid-row: 4; }

  /* Fila de registro — las 24 vistas de lista */
  html.mv .mv-reg {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 10px;
    width: 100%;
    text-align: left;
    border: 0;
    font: inherit;
    color: inherit;
    background: var(--mv-papel);
    border-radius: 13px;
    padding: 12px 13px;
    margin-bottom: 9px;
    box-shadow: var(--mv-sombra);
    position: relative;
    overflow: hidden;
    min-height: 44px;
  }
  html.mv .mv-reg::before {
    content: '';
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 3px;
    background: var(--t, transparent);
  }
  html.mv .mv-reg-cod {
    grid-column: 1;
    font: 700 10.5px/1 'Inter', sans-serif;
    letter-spacing: .05em;
    color: var(--mv-apagado);
  }
  html.mv .mv-reg .mv-senal { grid-column: 2; grid-row: 1; }
  html.mv .mv-reg-tit {
    grid-column: 1 / -1;
    margin-top: 6px;
    font-size: 14px;
    font-weight: 700;
    line-height: 1.35;
    letter-spacing: -.005em;
    color: var(--mv-tinta);
  }
  html.mv .mv-reg-meta {
    grid-column: 1 / -1;
    margin-top: 7px;
    font-size: 11.5px;
    line-height: 1.45;
    color: var(--mv-apagado);
  }

  /* Fila de enlace — apilada, nunca dos columnas a 390 px */
  html.mv .mv-link {
    display: flex;
    align-items: center;
    gap: 11px;
    width: 100%;
    text-align: left;
    border: 0;
    font: inherit;
    color: inherit;
    background: var(--mv-papel);
    border-radius: 13px;
    padding: 12px 13px;
    margin-bottom: 9px;
    box-shadow: var(--mv-sombra);
    min-height: 44px;
  }
  html.mv .mv-link-ic {
    width: 32px; height: 32px;
    border-radius: 9px;
    background: rgba(0, 112, 180, .1);
    flex: 0 0 auto;
    display: flex; align-items: center; justify-content: center;
  }
  html.mv .mv-link-ic svg { width: 17px; height: 17px; }
  html.mv .mv-link-tx { min-width: 0; flex: 1 }
  html.mv .mv-link-tx b {
    display: block;
    font-size: 14px;
    font-weight: 700;
    line-height: 1.3;
    letter-spacing: -.005em;
    color: var(--mv-tinta);
  }
  html.mv .mv-link-tx span {
    display: block;
    font-size: 11.5px;
    line-height: 1.4;
    color: var(--mv-apagado);
    margin-top: 2px;
  }
  html.mv .mv-link-ch { margin-left: auto; color: var(--mv-apagado); font-size: 19px; line-height: 1 }

  /* Segmentos de filtro */
  html.mv .mv-segm {
    display: flex;
    gap: 7px;
    overflow-x: auto;
    margin: 0 -14px 11px;
    padding: 0 14px 2px;
    scrollbar-width: none;
  }
  html.mv .mv-segm::-webkit-scrollbar { width: 0; height: 0 }
  html.mv .mv-segm-b {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 6px;
    font: 700 11.5px/1 'Inter', sans-serif;
    padding: 9px 13px;
    border-radius: 999px;
    background: var(--mv-papel);
    color: var(--mv-apagado);
    border: 1px solid var(--mv-borde);
    min-height: 34px;
  }
  html.mv .mv-segm-b.on { background: #0070B4; color: #fff; border-color: #0070B4 }
  html.mv .mv-segm-b i { font-style: normal; font-size: 10px; opacity: .75 }

  /* Buscador */
  html.mv .mv-buscar {
    display: flex;
    align-items: center;
    gap: 9px;
    background: var(--mv-papel);
    border-radius: 11px;
    padding: 0 12px;
    box-shadow: var(--mv-sombra);
    margin-bottom: 11px;
    min-height: 42px;
  }
  html.mv .mv-buscar-ic {
    width: 14px; height: 14px;
    border: 2px solid var(--mv-apagado);
    border-radius: 50%;
    flex: 0 0 auto;
  }
  html.mv .mv-buscar input {
    flex: 1;
    min-width: 0;
    border: 0;
    background: none;
    font: 400 16px/1 'Inter', sans-serif;  /* 16 px: bajo eso iOS hace zoom */
    color: var(--mv-tinta);
    padding: 11px 0;
  }
  html.mv .mv-buscar input:focus { outline: none }

  html.mv .mv-vacio {
    margin: 22px 4px;
    font-size: 13px;
    line-height: 1.55;
    color: var(--mv-apagado);
    text-align: center;
  }

  /* Carril genérico — mismas reglas que el de Resumen */
  html.mv .mv-carril {
    display: flex;
    gap: 10px;
    overflow-x: auto;
    scrollbar-width: none;
    padding: 0 14px 4px;
    margin: 0 -14px;
    align-items: stretch;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: 14px;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
  }
  html.mv .mv-carril::-webkit-scrollbar { width: 0; height: 0 }
  html.mv .mv-carril-t {
    flex: 0 0 78%;
    max-width: 320px;
    scroll-snap-align: start;
    background: var(--mv-papel);
    border-radius: 14px;
    padding: 13px 14px;
    box-shadow: var(--mv-sombra);
    border-top: 3px solid var(--t, #0070B4);
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto 1fr auto;
    min-height: 124px;
  }
  html.mv .mv-carril-nota {
    align-self: end;
    margin-top: 9px;
    font-size: 11px;
    line-height: 1.4;
    color: var(--t, var(--mv-apagado));
  }
  html.mv .mv-carril-t.mv-t-neutro .mv-carril-nota { color: var(--mv-apagado) }

  html.mv .mv-puntos { display: flex; gap: 5px; justify-content: center; margin: 11px 0 2px }
  html.mv .mv-puntos i {
    width: 5px; height: 5px;
    border-radius: 50%;
    background: var(--mv-borde);
    transition: width .18s ease, background .18s ease;
  }
  html.mv .mv-puntos i.on { width: 15px; border-radius: 3px; background: #0070B4 }

  /* Bordes de tono para tarjetas y filas */
  html.mv .mv-t-borde-mal    { --t: #A8293B }
  html.mv .mv-t-borde-aten   { --t: #B9831C }
  html.mv .mv-t-borde-bien   { --t: #1F7A43 }
  html.mv .mv-t-borde-neutro { --t: #0070B4 }

  /* ═══════════════════════════════════════════════════════════════
     ARQUETIPO A · Panel de área  ·  movil/panel.js
     ═══════════════════════════════════════════════════════════════ */

  html.mv .mv-panel { padding-top: 2px }

  /* El área manda: es lo que cambia al navegar. La obra ya está arriba. */
  html.mv .mv-panel-cab { margin: 0 2px 14px }
  html.mv .mv-panel-cab h2 {
    margin: 0;
    font-size: 20px;
    font-weight: 800;
    letter-spacing: -.02em;
    line-height: 1.2;
    color: var(--mv-tinta);
  }
  html.mv .mv-panel-cab p {
    margin: 5px 0 0;
    font-size: 12px;
    line-height: 1.45;
    color: var(--mv-apagado);
  }
  html.mv .mv-panel-corte { margin-top: 2px !important; font-size: 11.5px }

  html.mv .mv-panel-hero {
    background: var(--mv-papel);
    border-radius: 15px;
    padding: 15px 16px;
    margin-bottom: 11px;
    box-shadow: var(--mv-sombra);
  }
  html.mv .mv-cifra-xl b { font-size: 40px; letter-spacing: -.03em }
  html.mv .mv-cifra-xl u { font-size: 16px }
  html.mv .mv-panel-hero-sub {
    margin: 8px 0 0;
    font-size: 12px;
    line-height: 1.45;
    color: var(--mv-apagado);
  }
  html.mv .mv-panel-hero-meta {
    display: flex;
    gap: 22px;
    margin-top: 13px;
    padding-top: 12px;
    border-top: 1px solid var(--mv-borde);
  }
  html.mv .mv-panel-hero-meta span {
    font-size: 11.5px;
    line-height: 1.35;
    color: var(--mv-apagado);
  }
  html.mv .mv-panel-hero-meta b {
    display: block;
    font-size: 19px;
    font-weight: 800;
    letter-spacing: -.02em;
    color: var(--mv-tinta);
    margin-bottom: 2px;
  }

  /* ═══════════════════════════════════════════════════════════════
     ARQUETIPO B · Lista de registros  ·  movil/listas.js
     ═══════════════════════════════════════════════════════════════ */

  html.mv .mv-registros { padding-top: 2px }
  html.mv .mv-registros-cuenta {
    margin: 0 2px 10px;
    font-size: 11.5px;
    color: var(--mv-apagado);
  }
  html.mv .mv-registros-cuenta b { color: var(--mv-tinta); font-weight: 700 }

  /* La fila entera es el objetivo táctil. Antes había que acertar en un
     enlace de 11 px dentro de una celda de 28 de alto. */
  html.mv .mv-registros .mv-reg { cursor: pointer; -webkit-tap-highlight-color: transparent }
  html.mv .mv-registros .mv-reg:active { transform: scale(.994) }

  /* ═══════════════════════════════════════════════════════════════
     ARQUETIPO F · Documentación referencial  ·  movil/docs.js
     No se reconstruye el árbol: se le da medida táctil y se distingue
     el tipo de archivo, que es lo que de verdad fallaba en móvil.
     ═══════════════════════════════════════════════════════════════ */

  /* En escritorio el árbol es una columna que llena el alto de la ventana y
     desplaza por dentro. En móvil eso deja un scroll DENTRO de otro scroll:
     el árbol se quedaba en 282 px con 551 de contenido y las últimas carpetas
     no se veían. Aquí crece y desplaza la página, que es lo natural. */
  html.mv .mv-docref .dref-grid,
  html.mv .mv-docref .dref-arbol-col,
  html.mv .mv-docref .dref-arbol {
    height: auto !important;
    max-height: none !important;
    min-height: 0 !important;
    overflow: visible !important;
  }

  /* Filas de 29 px: por debajo del mínimo táctil. Ahora 48. */
  html.mv .mv-docref .dref-nodo {
    min-height: 48px !important;
    align-items: center !important;
    gap: 10px !important;
    padding: 8px 10px !important;
    border-radius: 11px !important;
  }
  html.mv .mv-docref .dref-nodo + .dref-nodo,
  html.mv .mv-docref .dref-hijos .dref-nodo { margin-top: 4px !important }

  html.mv .mv-docref .dref-nom {
    font-size: 14px !important;
    font-weight: 600 !important;
    line-height: 1.35 !important;
    color: var(--mv-tinta) !important;
    white-space: normal !important;
    overflow: visible !important;
  }
  html.mv .mv-docref .dref-nodo[data-mv-tipo="carpeta"] .dref-nom { font-weight: 700 !important }

  /* El tipo deja de ser un icono igual para todos y pasa a ser un bloque
     reconocible. attr() lee el dato del propio nodo, que docs.js le puso. */
  html.mv .mv-docref .dref-nodo[data-mv-ext] > svg { display: none !important }
  html.mv .mv-docref .dref-nodo[data-mv-ext]::before {
    content: attr(data-mv-ext);
    flex: 0 0 auto;
    width: 34px;
    height: 34px;
    border-radius: 9px;
    display: flex;
    align-items: center;
    justify-content: center;
    font: 700 8.5px/1 'Inter', sans-serif;
    letter-spacing: .03em;
    text-transform: uppercase;
    color: #fff;
    background: #5A7A96;
  }
  html.mv .mv-docref .dref-nodo[data-mv-ext="pdf"]::before { background: #A8293B }
  html.mv .mv-docref .dref-nodo[data-mv-ext="xls"]::before { background: #1F7A43 }
  html.mv .mv-docref .dref-nodo[data-mv-ext="cad"]::before { background: #0070B4 }
  html.mv .mv-docref .dref-nodo[data-mv-ext="doc"]::before { background: #3A91C5 }
  html.mv .mv-docref .dref-nodo[data-mv-ext="img"]::before { background: #B9831C }
  html.mv .mv-docref .dref-nodo[data-mv-ext="ppt"]::before { background: #B9831C }
  html.mv .mv-docref .dref-nodo[data-mv-ext="zip"]::before { background: #5A7A96 }

  html.mv .mv-docref .dref-nodo[data-mv-tipo="carpeta"] > svg {
    width: 21px !important; height: 21px !important; flex: 0 0 auto;
  }
  html.mv .mv-docref .dref-chev { font-size: 11px !important; opacity: .55 }

  /* El contador de la carpeta, en píldora legible */
  html.mv .mv-docref .dref-nodo > .dref-cont {
    margin-left: auto !important;
    font: 700 10.5px/1 'Inter', sans-serif !important;
    padding: 4px 8px !important;
    border-radius: 999px !important;
    background: var(--mv-borde) !important;
    color: var(--mv-apagado) !important;
  }

  /* Acciones: objetivos reales, no iconos de 15 px */
  html.mv .mv-docref .dref-acc { gap: 4px !important }
  html.mv .mv-docref .dref-a {
    min-width: 40px !important; min-height: 40px !important;
    display: inline-flex !important; align-items: center !important;
    justify-content: center !important;
    border-radius: 9px !important;
  }

  html.mv .mv-docref .dref-chip-demo {
    font-size: 9.5px !important;
    padding: 3px 7px !important;
    border-radius: 999px !important;
  }

  /* Barra de acciones: dos botones de ancho completo, a rango del pulgar */
  html.mv .mv-docref .dref-tb { gap: 8px !important; flex-wrap: wrap !important }
  html.mv .mv-docref .dref-btn {
    flex: 1 1 0 !important;
    min-width: 0 !important;
    min-height: 44px !important;
    justify-content: center !important;
    border-radius: 11px !important;
    white-space: nowrap !important;   /* «Nueva carpeta» partía en dos líneas */
    font-size: 13px !important;
    padding-inline: 10px !important;
  }
  html.mv .mv-docref .dref-buscar { min-height: 42px !important }
  html.mv .mv-docref .dref-buscar input { font-size: 16px !important }

  /* ═══════════════════════════════════════════════════════════════
     ARQUETIPO G · Galería fotográfica  ·  movil/galeria.js
     ═══════════════════════════════════════════════════════════════ */

  /* Tres columnas. El comodín de los parches la había dejado en UNA —caza a
     `.foto-grid-in` por contener «grid»— y en una rejilla de fotos eso es al
     revés de lo que hace falta: 18 miniaturas donde antes cabían dos. */
  /* `.scroll-area` en el selector no es decorativo: sin él esta regla PIERDE
     contra el comodín de los parches. Su `:not([class*="mv-"])` suma
     especificidad —un :not() vale lo que su argumento—, así que el comodín
     puntúa (0,4,1) y esto sin `.scroll-area` se quedaba en (0,3,1). */
  /* DOS Y NO TRES. Con tres, la miniatura se queda en 115 px de lado y la foto
     dentro en 93×69: a ese tamaño una foto de obra no se distingue de otra, que
     es justo para lo que se abre esta vista. Con dos sube a ~175 y se reconoce
     el frente. */
  html.mv .scroll-area .mv-galeria .foto-grid-in {
    display: grid !important;
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    gap: 8px !important;
  }
  /* La rejilla de fotos de los RFI lleva su ancho EN EL MARCADO
     —`minmax(200px,1fr)` en un atributo `style`—, así que ninguna hoja la
     alcanza sin `!important`. Es la que empujaba la vista fuera de pantalla. */
  html.mv .scroll-area .mv-galeria #fotoRfiGrid {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    gap: 8px !important;
  }
  html.mv .mv-galeria .foto-card {
    aspect-ratio: 1 !important;
    height: auto !important;
    min-height: 0 !important;
    border-radius: 9px !important;
    overflow: hidden !important;
    padding: 0 !important;
    position: relative;
  }
  /* EL REDISEÑO METIÓ UNA ENVOLTURA. Entre la tarjeta y la foto hay ahora un
     `.foto-card-m`, y es ÉL quien manda el alto: medía 79 de los 115 de la
     tarjeta, así que la foto se quedaba en 93×69 y sobraban 36 px de blanco
     debajo. Dar 100 % a la imagen no servía de nada: el 100 % era de los 79.
     La envoltura pasa a ocupar la tarjeta entera. */
  html.mv .mv-galeria .foto-card-m {
    position: absolute !important;
    inset: 0 !important;
    width: 100% !important;
    height: 100% !important;
    padding: 0 !important;
    margin: 0 !important;
  }
  html.mv .mv-galeria .foto-img,
  html.mv .mv-galeria .foto-card img {
    width: 100% !important;
    height: 100% !important;
    object-fit: cover !important;
    border-radius: 0 !important;
  }
  /* La fase, encima de la foto y no ocupando su propia franja. */
  html.mv .mv-galeria .foto-card-fase {
    position: absolute !important;
    left: 5px; bottom: 5px; z-index: 2;
    max-width: calc(100% - 10px) !important;
  }


  /* La metadata baja al detalle: en la miniatura compite con la foto, que es
     lo único que se distingue de un vistazo. Sigue accesible al tocar. */
  html.mv .mv-galeria .foto-card-b,
  html.mv .mv-galeria .foto-card-d,
  html.mv .mv-galeria .foto-card-p { display: none !important }
  html.mv .mv-galeria .foto-card-ed {
    position: absolute !important;
    right: 3px; top: 3px;
    z-index: 2;
    min-width: 30px; min-height: 30px;
    display: flex !important; align-items: center; justify-content: center;
    border-radius: 8px;
    background: rgba(0, 0, 0, .45);
    color: #fff;
  }

  /* Agrupada por fase/semana: así es como se piensa el avance de obra. */
  html.mv .mv-galeria .foto-grupo-h {
    margin: 15px 2px 8px !important;
    display: flex !important;
    align-items: center !important;
    gap: 8px !important;
  }
  html.mv .mv-galeria .foto-grupo-t {
    font: 700 11px/1.3 'Inter', sans-serif !important;
    letter-spacing: .08em !important;
    text-transform: uppercase !important;
    color: var(--mv-apagado) !important;
  }
  html.mv .mv-galeria .foto-grupo-n {
    font: 700 10.5px/1 'Inter', sans-serif !important;
    padding: 4px 8px !important;
    border-radius: 999px !important;
    background: var(--mv-borde) !important;
    color: var(--mv-apagado) !important;
  }

  /* LOS FILTROS SE ENGRILLAN, NO SE DESLIZAN. Estaban en una fila con
     `overflow-x: auto` para no robar alto, pero tres de 168 son 520 en una
     caja de 358: el tercero quedaba cortado por el borde, y un filtro que no
     se ve es un filtro que no se usa. En rejilla caben dos por línea y el
     tercero ocupa las dos columnas. Cuesta 48 px de alto y no esconde nada.

     De paso se retira el `margin: 0 -14px` que llevaba para sangrar a los
     bordes: daba por hecho que el padre pone 14 de relleno, y ya no los pone
     —el aplanado de tarjetas se los quita—, así que esos 28 px se salían de
     la pantalla. */
  /* LOS FILTROS SE ENGRILLAN, NO SE DESLIZAN. Estaban en una fila con
     `overflow-x: auto`, y tres de 168 son 520 en una caja de 358: el tercero
     quedaba cortado por el borde. Un filtro que no se ve es un filtro que no
     se usa.

     UNO POR FILA, y es una rendición honesta. Se intentó a dos columnas con el
     tercero abarcando las dos —queda en 97 px de alto en vez de 149, medido
     poniéndolo en línea: 175 / 175 / 358—, pero desde la hoja no hay manera:
     con `!important` y subiendo la especificidad con `.scroll-area`, como en
     la rejilla de fotos, el contenedor sigue resolviendo a UNA pista de 358.
     Algo del comodín de rejillas la fija y no se localizó. A todo el ancho
     tampoco se pierde nada: el rótulo del desplegable se lee entero y el
     objetivo —que no se corte— se cumple. Los 52 px de más están medidos y
     ahí queda dicho por si alguien quiere perseguirlo.

     De paso se retira el `margin: 0 -14px` que llevaba para sangrar a los
     bordes: daba por hecho que el padre pone 14 de relleno, y ya no los pone
     —el aplanado se los quita—, así que esos 28 px se salían de la pantalla. */
  html.mv .scroll-area .mv-galeria .foto-filtros {
    display: grid !important;
    gap: 8px !important;
    overflow: visible !important;
    margin: 0 0 4px !important;
    padding: 0 !important;
  }
  /* BASE FIJA, no «auto». Con `flex: 0 0 auto` el filtro se dimensiona al
     CONTENIDO, y el contenido de un `<select>` es su opción más larga: «S30 ·
     07/03/2026 · sin fotos». Ese ancho intrínseco se propagaba hasta la raíz y
     era el desborde de 33 px de esta vista —comprobado: forzando el ancho del
     desplegable o vaciándole las opciones, el documento volvía a 390—.
     Con una base definida el contenido ya no manda, y la fila sigue
     deslizándose porque son tres de 168 en 358. */
  html.mv .mv-galeria .foto-f {
    min-width: 0 !important;
    width: auto !important;
  }

  /* UN SCROLL DENTRO DE OTRO SCROLL. La rejilla de fotos cuelga de un `div`
     sin clase con `flex: 1 1 0` y `overflow-y: auto`: se quedaba en 424 px de
     alto con 532 de contenido y se desplazaba POR SU CUENTA dentro de una
     página que ya se desplaza. Con el pulgar no se sabe cuál de los dos se
     mueve. Que crezca y que desplace la vista entera, que es el único scroll
     que el usuario reconoce. */
  html.mv .mv-galeria .chart-card > div:has(> .foto-grid-in) {
    flex: 0 0 auto !important;
    height: auto !important;
    max-height: none !important;
    overflow-y: visible !important;
  }
  html.mv .mv-galeria .foto-f-sel,
  html.mv .mv-galeria .foto-f select {
    min-height: 44px !important;   /* 40 se quedaba por debajo del mínimo táctil */
    font-size: 13px !important;
    width: 100% !important;
  }

  /* Tomar y cargar, lado a lado y de ancho completo: son las dos acciones de
     la vista y en móvil van a rango del pulgar, no encajadas en la cabecera. */
  html.mv .mv-galeria .mv-galeria-acciones {
    display: flex;
    gap: 8px;
    width: 100%;
    margin-top: 4px;
  }
  html.mv .mv-galeria .mv-galeria-acciones .fotos-upload-btn,
  html.mv .mv-galeria .mv-galeria-acciones .mv-camara {
    flex: 1 1 0 !important;
    min-width: 0 !important;
    min-height: 44px !important;
    justify-content: center !important;
    border-radius: 11px !important;
    font-weight: 700 !important;
  }

  /* ═══════════════════════════════════════════════════════════════
     ARQUETIPO E · Cronograma  ·  movil/crono.js
     ═══════════════════════════════════════════════════════════════ */

  /* El plazo primero: es el marco de todo lo demás, no un pie de tabla. */
  html.mv .mv-crono-plazo {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 9px;
    margin-bottom: 13px;
  }
  html.mv .mv-crono-p {
    background: var(--mv-papel);
    border-radius: 13px;
    padding: 12px 13px;
    box-shadow: var(--mv-sombra);
    min-width: 0;
  }
  html.mv .mv-crono-p b {
    display: block;
    margin-top: 5px;
    font-size: 19px;
    font-weight: 800;
    letter-spacing: -.02em;
    line-height: 1.15;
    color: var(--mv-tinta);
  }
  html.mv .mv-crono-p span {
    display: block;
    margin-top: 4px;
    font-size: 10.5px;
    line-height: 1.4;
    color: var(--mv-apagado);
  }

  /* 24 columnas de semana: desplazar para llegar a la S18 hacía perder de
     vista a qué frente pertenece la fila. La primera celda se queda fija. */
  html.mv .mv-crono table[data-mv-fija] { border-collapse: separate !important; border-spacing: 0 }
  html.mv .mv-crono [data-mv-fija="1"] > td:first-child,
  html.mv .mv-crono [data-mv-fija="1"] > th:first-child,
  html.mv .mv-crono td[data-mv-fija="1"],
  html.mv .mv-crono th[data-mv-fija="1"] {
    position: sticky !important;
    left: 0;
    z-index: 3;
    background: var(--mv-papel) !important;
    box-shadow: 1px 0 0 var(--mv-borde), 3px 0 7px rgba(0, 0, 0, .06);
    max-width: 128px;
    min-width: 96px;
    white-space: normal !important;
  }
  html.mv .mv-crono thead th[data-mv-fija="1"] { z-index: 4 }

  /* Subpestañas: objetivos reales y en fila deslizable */
  /* SIN SANGRADO: las pestañas al mismo ancho que lo que abren. Llevaban
     `margin: 0 -14px` y quedaban en 386 sobre un contenido de 358, así que la
     franja de pestañas sobresalía por los dos lados y la vista no se leía como
     una pieza. */
  html.mv .mv-crono .presup-subtabs {
    display: flex !important;
    gap: 7px !important;
    overflow-x: auto !important;
    margin: 0 0 11px !important;
    padding: 0 0 3px !important;
    scrollbar-width: none;
  }
  html.mv .mv-crono .presup-subtabs::-webkit-scrollbar { width: 0; height: 0 }

  /* UN SOLO LENGUAJE DE PESTAÑAS, Y ES EL QUE YA ESTÁ VALIDADO.
     `.presup-subtab` es el MISMO componente en Presupuesto, Mano de Obra y
     Cronograma. En Mano de Obra se ve como toca —subrayado, sin caja, 44 de
     alto— y en Cronograma salía como cápsula de 40 px. La cápsula la imponía
     esta misma regla, escrita para un diseño anterior, peleando con el
     `box-shadow: inset 0 -2px 0` que el rediseño ya le da en index.html.

     Se retira la cápsula y se deja el subrayado suyo. Y se quita el ámbito
     `.mv-crono`: si el componente es el mismo, la regla también.

     `flex: 1 0 auto` reparte el ancho cuando son dos o tres —el caso de estas
     vistas— y las deja deslizarse cuando sean muchas, sin un número mágico. */
  html.mv .presup-subtab {
    flex: 1 0 auto !important;
    min-height: 44px !important;
    border-radius: 0 !important;
    white-space: nowrap !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
  }

  /* ═══════════════════════════════════════════════════════════════
     ARQUETIPO C · Hoja de cálculo  ·  movil/hojas.js
     Manda la CIFRA, no el título: se abre para comparar importes.
     ═══════════════════════════════════════════════════════════════ */

  html.mv .mv-calc-cuenta {
    margin: 0 2px 10px;
    font-size: 11.5px;
    color: var(--mv-apagado);
  }
  html.mv .mv-calc-cuenta b { color: var(--mv-tinta); font-weight: 700 }

  html.mv .mv-calc-l {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    width: 100%;
    text-align: left;
    border: 0;
    font: inherit;
    color: inherit;
    background: var(--mv-papel);
    border-radius: 13px;
    padding: 12px 14px;
    margin-bottom: 9px;
    box-shadow: var(--mv-sombra);
    min-height: 44px;
  }
  html.mv .mv-calc-tit {
    font-size: 12.5px;
    font-weight: 600;
    line-height: 1.35;
    color: var(--mv-apagado);
  }
  html.mv .mv-calc-cifra { display: block; margin-top: 5px }
  html.mv .mv-calc-cifra b {
    display: block;
    font-size: 23px;
    font-weight: 800;
    letter-spacing: -.025em;
    line-height: 1.1;
    color: var(--mv-tinta);
    white-space: nowrap;
  }
  html.mv .mv-calc-cifra .mv-eyebrow { font-size: 9.5px }
  html.mv .mv-calc-meta {
    display: block;
    margin-top: 7px;
    font-size: 11.5px;
    line-height: 1.45;
    color: var(--mv-apagado);
  }
  html.mv .mv-calc-barra {
    display: block;
    height: 5px;
    border-radius: 3px;
    background: var(--mv-borde);
    margin-top: 10px;
    overflow: hidden;
  }
  html.mv .mv-calc-barra i { display: block; height: 100%; border-radius: 3px; background: #0070B4 }

  /* ═══════════════════════════════════════════════════════════════
     ARQUETIPO H · Administración  ·  movil/admin.js
     ═══════════════════════════════════════════════════════════════ */

  html.mv .mv-admin-sel {
    display: block;
    background: var(--mv-papel);
    border-radius: 13px;
    padding: 12px 14px;
    margin-bottom: 12px;
    box-shadow: var(--mv-sombra);
  }
  html.mv .mv-admin-sel select {
    width: 100%;
    margin-top: 7px;
    min-height: 44px;
    border: 1px solid var(--mv-borde);
    border-radius: 10px;
    padding: 0 10px;
    background: var(--mv-fondo);
    color: var(--mv-tinta);
    font-weight: 700;
  }

  html.mv .mv-admin-fila {
    display: flex;
    align-items: center;
    gap: 11px;
    background: var(--mv-papel);
    border-radius: 12px;
    padding: 12px 14px;
    margin-bottom: 8px;
    box-shadow: var(--mv-sombra);
    min-height: 44px;
  }
  html.mv .mv-admin-tx { min-width: 0; flex: 1 }
  html.mv .mv-admin-tx b {
    display: block;
    font-size: 14px;
    font-weight: 700;
    color: var(--mv-tinta);
  }
  /* «E·V» no se explica en ninguna parte de la interfaz. Aquí sí. */
  html.mv .mv-admin-tx span {
    display: block;
    margin-top: 2px;
    font-size: 11.5px;
    line-height: 1.4;
    color: var(--mv-apagado);
  }
  html.mv .mv-admin-fila .mv-senal { flex: 0 0 auto }

  html.mv .mv-admin-aviso {
    margin: 14px 2px 0;
    padding: 12px 14px;
    border-radius: 11px;
    background: rgba(0, 112, 180, .06);
    border: 1px solid rgba(0, 112, 180, .18);
    font-size: 11.5px;
    line-height: 1.55;
    color: var(--mv-apagado);
  }

  /* ═══════════════════════════════════════════════════════════════
     Las cabeceras de sección, apiladas
     ───────────────────────────────────────────────────────────────
     `.rz-sec-h` pone el título y su bajada en DOS COLUMNAS. A 390 px el
     título se queda con 123 y la bajada con el resto, así que los dos
     parten: «Proyección a fin de / obra» al lado de «PLAZO · COSTO ·
     UTILIDAD AL / CIERRE». Dos textos rotos uno junto al otro es lo que
     se veía raro.

     En vertical no hay sitio para dos columnas: se apilan. El título
     entero en su línea y la bajada debajo, sin versalita apretada —a
     este tamaño las mayúsculas con espaciado cuestan ancho y no aportan
     jerarquía, que ya la da el peso. */
  html.mv #sec-resumen .rz-sec-h {
    flex-direction: column !important;
    align-items: flex-start !important;
    gap: 2px !important;
  }
  html.mv #sec-resumen .rz-sec-h > * {
    width: auto !important;
    max-width: 100% !important;
    text-align: left !important;
  }
  html.mv #sec-resumen .rz-sec-h span {
    text-transform: none !important;
    letter-spacing: 0 !important;
  }

  /* ═══════════════════════════════════════════════════════════════
     La ficha de la obra, en dos columnas fijas
     ───────────────────────────────────────────────────────────────
     `.rz-meta` es un flex con `wrap`, así que a 390 px caía en filas de
     1, luego 2, luego 3 columnas según lo que midiera cada dato. Ese
     ritmo irregular es lo que se leía como desordenado: el ojo no
     encuentra una retícula porque no la hay.

     Pasa a rejilla de DOS columnas fijas. La dirección ocupa las dos
     —es la más larga y partida no se lee—, y el resto cae de dos en dos
     en el orden en que ya venían.

     Y el botón de descargar a lo ancho: es la única acción de este
     bloque, y a media asta parece deshabilitado. */
  html.mv #sec-resumen .rz-meta {
    display: grid !important;
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    gap: 14px 16px !important;
  }
  html.mv #sec-resumen .rz-meta > .rz-m {
    width: auto !important;
    min-width: 0 !important;
    flex: none !important;
  }
  html.mv #sec-resumen .rz-meta > .rz-m-dir { grid-column: 1 / -1 !important; }
  html.mv #sec-resumen .rz-dl {
    width: 100% !important;
    justify-content: center !important;
  }

  /* ═══════════════════════════════════════════════════════════════
     El anillo de avance, en su propia tarjeta
     ───────────────────────────────────────────────────────────────
     `movil/resumen.js` lo sube a la cabecera desde su tarjeta original.
     El primer intento lo ancló con posición absoluta arriba a la derecha
     del título, y salió mal por dos cosas MEDIDAS:

       · el `<svg>` mide 149×149 por dentro y no lo encoge darle 108 a su
         caja: se salía 39 px de la pantalla, cortado por la derecha;
       · el rótulo del corte, absoluto a 112 px del borde, caía encima de
         la rejilla de metadatos.

     Así que deja de flotar: es una TARJETA en el flujo, con el anillo a
     la izquierda y el corte a la derecha. Mismo lenguaje que el resto de
     tarjetas de esta vista —tinte radial anclado arriba, radio 20, filete
     blanco— para que se lea como de la misma familia. */
  /* Columna, NO bloque: `.rz-cab` trae un `gap:16px` que sólo existe si
     sigue siendo caja flexible. Al ponerlo en bloque se perdió y el botón
     de descargar quedó pegado a «Fin 471 d», con 0 px entre medias. */
  html.mv #sec-resumen .rz-cab {
    display: flex !important;
    flex-direction: column !important;
    /* En horizontal centraba título y anillo; en columna eso centra el texto. */
    align-items: stretch !important;
  }
  html.mv #sec-resumen .rz-cab > .rz-id {
    padding-right: 0 !important;
    min-height: 0 !important;
  }
  /* EL ANILLO, DENTRO DE «ESTADO GENERAL» (R-11, 28-sep). Vivía como tarjeta
     propia junto al título de la obra; ahora abre el bloque «Estado general»,
     como en escritorio, y ahí es una parte más: sin fondo, borde ni sombra
     propios, porque ya está dentro de una tarjeta.
     `!important` como en las reglas de Anderson que reemplaza: le gana al
     `#sec-resumen .rz-estado` de escritorio (posición, ancho y columna). */
  html.mv #sec-resumen .mv-res > .rz-estado {
    position: static !important;
    width: auto !important;
    margin: 0 !important;
    padding: 0 !important;
    display: flex !important;
    flex-direction: row !important;
    align-items: center !important;
    gap: 14px !important;
    background: none !important;
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
  }
  /* «Estado General» sobra: el bloque ya lleva ese título. */
  html.mv #sec-resumen .mv-res > .rz-estado > .rz-h2 { display: none !important; }
  html.mv #sec-resumen .mv-res > .rz-estado > .rz-ring {
    position: relative !important;
    width: 104px !important;
    height: 104px !important;
    flex: none !important;
  }
  /* AL DIBUJO HAY QUE DECÍRSELO APARTE. Encoger la caja no encoge el
     `<svg>`: conserva sus 149 de atributo y asoma por los cuatro lados. */
  html.mv #sec-resumen .mv-res > .rz-estado > .rz-ring > svg,
  html.mv #sec-resumen .mv-res > .rz-estado > .rz-ring > .rz-ring-c {
    width: 104px !important;
    height: 104px !important;
  }
  /* El corte ocupa lo que queda, alineado con el anillo y sin partirse. */
  html.mv #sec-resumen .mv-res > .rz-estado > .rz-corte {
    position: static !important;
    flex: 1 1 auto !important;
    min-width: 0 !important;
    width: auto !important;
    white-space: normal !important;
    /* Venía como columna centrada; en la tarjeta se alinea con el anillo. */
    align-items: flex-start !important;
    text-align: left !important;
    font-size: 12px !important;
    line-height: 1.45 !important;
  }
  /* Las dos líneas traen su propio centrado del bloque original. */
  html.mv #sec-resumen .mv-res > .rz-estado > .rz-corte > * { text-align: left !important; }

  /* ══════════════════════════════════════════════════════════════════════
     LAS CUATRO SECCIONES DEL RESUMEN, EN FORMATO DE TELÉFONO
     ──────────────────────────────────────────────────────────────────────
     El rediseño añadió «Estado por área», «Control de operaciones»,
     «Valorización» y «Frentes de obra». Las cuatro llegaban a móvil como la
     rejilla de escritorio reflowada: 761 + 1.072 + 581 + 828 px. Tres
     pantallas y media para cuatro bloques.

     NO SE QUITA NADA: cada dato sigue en pantalla. Cambia la FORMA —tabla a
     fichas, rejilla de tres a carril que se desliza, columnas con filete
     vertical a filas con filete horizontal—, que es lo que un teléfono sabe
     leer. Apagar la capa devuelve las cuatro al estado de Emanuel.
     ══════════════════════════════════════════════════════════════════════ */

  /* ── 1 · Estado por área ───────────────────────────────────────────────
     Emanuel ya la apila por debajo de 820 px (index.html), así que la
     estructura está: lo que faltaba es la lectura. Las métricas eran prosa
     corrida con viñetas —cuatro líneas por área, 187 px de fila— y pasan a
     CÁPSULAS: el ojo las cuenta en vez de leerlas. */
  html.mv #sec-resumen .rz-areas { padding: 16px 14px; gap: 12px; }
  html.mv #sec-resumen .rz-t-r { padding: 10px 0; align-items: start; row-gap: 8px; }
  /* El `grid-column: 1 / -1` que trae index.html para la barra y las métricas
     NO abarca: medido, las dos se quedan en los 208 px de la primera columna
     en vez de los 322 de la fila. Se colocan por número de línea, que no
     depende de resolver `-1`, y la barra y las cápsulas recuperan el ancho. */
  html.mv #sec-resumen .rz-t-r > .rz-t-a { grid-area: 1 / 1 / 2 / 2; }
  html.mv #sec-resumen .rz-t-r > .rz-t-s { grid-area: 1 / 2 / 2 / 3; }
  html.mv #sec-resumen .rz-t-r > .rz-t-p { grid-area: 2 / 1 / 3 / 3; }
  html.mv #sec-resumen .rz-t-r > .rz-t-m { grid-area: 3 / 1 / 4 / 3; }
  html.mv #sec-resumen .rz-t-a { align-items: center; }
  html.mv #sec-resumen .rz-t-a b { font-size: 13px; line-height: 16px; }
  html.mv #sec-resumen .rz-dot { width: 9px; height: 9px; }
  html.mv #sec-resumen .rz-t-p .rz-bar { height: 8px; }
  html.mv #sec-resumen .rz-t-pct { font-size: 13px; line-height: 16px; }
  html.mv #sec-resumen .rz-t-m { gap: 6px; }
  /* La viñeta «•» separaba prosa; entre cápsulas sobra. */
  html.mv #sec-resumen .rz-t-m .rz-sep { display: none; }
  html.mv #sec-resumen .rz-t-m .rz-mi {
    padding: 3px 8px;
    border-radius: 7px;
    background: #F4F7FA;
    font-size: 11px;
    line-height: 15px;
    color: #42526B;
  }
  /* El enlace al panel no es un dato, es una acción: se pinta como tal y
     cumple el mínimo táctil sin deformar la cápsula. */
  html.mv #sec-resumen .rz-t-m .rz-mi:has(.rz-mi-link) {
    flex: 1 1 100%;                 /* línea propia: mezclada con las cortas partía en dos */
    padding: 9px 10px;
    background: #E9F4FC;
    color: #0B6FB8;
    font-weight: 600;
  }

  /* ── 2 · Control de operaciones ────────────────────────────────────────
     Tres KPI de 356 px apilados son 1.072: pantalla y pico para tres cifras.
     En móvil se deslizan, con el MISMO carril, el mismo asomo y el mismo
     encaje que el de proyección de arriba — la vista entera se recorre con
     un solo gesto.
     Ojo con la cascada: `#rKpiGrid` se pinta desde index.html con `!important`
     en cada declaración, así que aquí hay que ganar por especificidad Y por
     `!important`; el orden del documento solo desempata a igual peso. */
  html.mv #sec-resumen .rz-ctrl { padding: 12px 16px 10px; }
  html.mv #sec-resumen #rKpiGrid {
    display: flex !important;
    grid-template-columns: none !important;
    gap: 10px !important;
    align-items: stretch;
    overflow-x: auto;
    scrollbar-width: none;
    padding: 2px 16px 8px !important;
    margin: 0 -16px !important;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: 16px;
    overscroll-behavior-x: contain;   /* no arrastra la página al llegar al final */
    -webkit-overflow-scrolling: touch;
  }
  html.mv #sec-resumen #rKpiGrid::-webkit-scrollbar { width: 0; height: 0; }
  html.mv #sec-resumen #rKpiGrid .r-kpi {
    flex: 0 0 78% !important;         /* el 22 % que asoma ES la señal de deslizar */
    max-width: 320px;
    scroll-snap-align: start;
    padding: 16px !important;
  }
  /* El evolutivo de 66 px era para una tarjeta de escritorio; en la mano
     manda la cifra. La lupa sigue abriendo el gráfico grande. */
  html.mv #sec-resumen #rKpiGrid .r-kpi-spark { height: 44px !important; margin-top: 10px !important; }
  html.mv #sec-resumen #rKpiGrid .r-kpi-label { margin-bottom: 10px !important; }
  /* 1,05 de interlineado deja la caja 2 px más baja que el propio glifo y,
     con `overflow:hidden`, el navegador recorta sin avisar. Medido en «88 pax»:
     alto real 31, caja 29. */
  html.mv #sec-resumen #rKpiGrid .r-kpi .r-kpi-value { line-height: 1.2 !important; }
  html.mv #sec-resumen #rKpiGrid .kpi-meta-footer {
    margin-top: 12px !important; padding-top: 10px !important; flex-wrap: wrap !important; row-gap: 6px !important;
  }
  /* La meta se cortaba con «…»: «▲ Meta: ≤ 91 pax (dimensionado)» pedía 184
     px en 142. Desde que «Control de operaciones» conserva su marco (R-11)
     las tarjetas miden un poco menos y también se cortaba «≤ 25% costo
     directo». En el teléfono la meta envuelve a dos líneas: se lee entera. */
  html.mv #sec-resumen #rKpiGrid .kpi-meta-target {
    white-space: normal !important;   /* gana al nowrap + ellipsis de escritorio */
    overflow: visible !important;
    text-overflow: clip !important;
  }
  /* Las lupas de los KPI y la de la curva medían 41 × 36: bajo el mínimo de
     toque de la guía. El dibujo no cambia; crece la caja. */
  html.mv #sec-resumen .rk-zoom {
    min-width: 44px;
    min-height: 44px;
    justify-content: center;
  }

  /* ── 3 · Valorización y rentabilidad ───────────────────────────────────
     Cuatro columnas con filete vertical no caben en 318 px: se apilaban
     dejando los tres filetes flotando de canto. El filete se tumba y cada
     cifra ocupa una fila —rótulo a la izquierda, cifra a la derecha, la
     explicación debajo a todo el ancho—, que es como se lee una cuenta. */
  html.mv #sec-resumen .rz-valo { padding: 16px 14px; gap: 14px; }
  html.mv #sec-resumen .rz-v-row { display: block; }
  html.mv #sec-resumen .rz-v-vl { display: none; }
  html.mv #sec-resumen .rz-v-c {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: baseline;
    column-gap: 10px;
    row-gap: 2px;
    padding: 12px 0;
  }
  /* Los filetes verticales siguen en el marcado entre columna y columna, así
     que `+` no las alcanza: `~` es «toda .rz-v-c que tenga otra delante». */
  html.mv #sec-resumen .rz-v-row > .rz-v-c ~ .rz-v-c { border-top: 1px solid #EDF1F6; }
  html.mv #sec-resumen .rz-v-l { grid-column: 1; font-size: 11px; line-height: 14px; }
  html.mv #sec-resumen .rz-v-b { grid-column: 2; grid-row: 1; font-size: 22px; line-height: 26px; }
  html.mv #sec-resumen .rz-v-s { grid-column: 1 / -1; font-size: 12px; line-height: 16px; }
  /* La comparativa no es una cifra: vuelve a bloque, y sus tres barras se
     estiran en vez de quedarse en los 120 px fijos del escritorio. */
  html.mv #sec-resumen .rz-v-cmp { display: block; padding: 14px 0 2px; }
  html.mv #sec-resumen .rz-v-cmp .rz-v-l { margin-bottom: 10px; }
  html.mv #sec-resumen .rz-lens { gap: 10px; }
  html.mv #sec-resumen .rz-len { gap: 10px; }
  html.mv #sec-resumen .rz-len-l { flex: 0 1 auto; min-width: 0; font-size: 12px; line-height: 15px; }
  html.mv #sec-resumen .rz-len-r { flex: 1 1 auto; min-width: 0; }
  html.mv #sec-resumen .rz-len-r .rz-bar { flex: 1 1 auto; width: auto; min-width: 0; }
  html.mv #sec-resumen .rz-len-r b { width: 48px; font-size: 12px; line-height: 15px; }
  /* 10 px es tamaño de pie de escritorio; en la mano no se lee. */
  html.mv #sec-resumen .rz-alert { align-items: flex-start; padding: 12px; font-size: 12px; line-height: 17px; }
  html.mv #sec-resumen .rz-alert img { margin-top: 1px; }

  /* ── 4 · Frentes de obra ───────────────────────────────────────────────
     Las dos flechas se comían 72 de los 318 px para paginar una rejilla que
     en móvil cabe en un carril.
     Cuándo sobran, sin preguntárselo al JS: con una sola página el render
     deja las dos en `aria-disabled` y a ninguna le pone `fin` —esa clase
     solo aparece si hay más de una—. Ese par exacto es la firma de «no hay
     nada que paginar». Con varias páginas, las flechas siguen ahí. */
  html.mv #sec-resumen .rz-frentes { padding: 12px 16px; }
  html.mv #sec-resumen .rz-fr-nav[aria-disabled="true"]:not(.fin) { display: none !important; }
  /* El sangrado a los bordes, solo cuando las flechas se han ido. */
  html.mv #sec-resumen .rz-fr-row:has(> .rz-fr-nav[aria-disabled="true"]:not(.fin)) { margin: 0 -16px; }
  html.mv #sec-resumen .rz-fr-cards {
    display: flex;
    gap: 10px;
    overflow-x: auto;
    scrollbar-width: none;
    padding: 2px 16px 6px;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: 16px;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
  }
  html.mv #sec-resumen .rz-fr-cards::-webkit-scrollbar { width: 0; height: 0; }
  html.mv #sec-resumen .rz-fr {
    flex: 0 0 72%;
    max-width: 280px;
    scroll-snap-align: start;
    min-height: 0;
    gap: 8px;
    padding: 14px;
  }
  html.mv #sec-resumen .rz-fr-pct { font-size: 26px; line-height: 30px; }
  html.mv #sec-resumen .rz-fr-nota { font-size: 11px; line-height: 15px; }
  html.mv #sec-resumen .rz-fr-stat { gap: 6px; font-size: 11.5px; line-height: 16px; }
  /* «1/5, 2/5…» (R-17). El paginador de escritorio cuenta páginas de cinco
     y decía «1/1» con cinco frentes; en el teléfono lo reemplaza el
     contador de `resumen.js`, que dice en qué frente estás de cuántos. */
  html.mv #sec-resumen #rFrPager { display: none; }
  html.mv #sec-resumen .mv-fr-cont {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    margin-top: 8px;
  }
  html.mv #sec-resumen .mv-fr-cont[hidden] { display: none; }
  html.mv #sec-resumen .mv-fr-puntos { display: flex; gap: 5px; }
  html.mv #sec-resumen .mv-fr-puntos i {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--mv-borde);
    transition: width .18s ease, background .18s ease;
  }
  html.mv #sec-resumen .mv-fr-puntos i.on { width: 15px; border-radius: 3px; background: #0070B4; }
  html.mv #sec-resumen .mv-fr-n {
    font-size: 12.5px;
    font-weight: 600;
    color: #5A7A96;
    font-variant-numeric: tabular-nums;
  }

  /* ── Arquetipo F · formato llenado ─────────────────────────────────────
     La hoja no se clona ni se aprieta: se queda donde está y cambia de forma.
     Filas y celdas pasan a bloque, y como el par etiqueta/valor ya viene
     consecutivo en el DOM, se lee como campo apilado sin tocar el marcado ni
     los <input>, que siguen con su data-campo y sus manejadores.
     Apretar la hoja con table-layout:fixed se probó el 22-sep y se descartó:
     a 400 px las columnas del SIG.009-F01 quedan en 11px y sin aire. */
  html.mv .mv-fmt-cab {
    margin: 0 0 12px;
    padding: 14px 16px;
    background: #fff;
    border: 1px solid #E6F2FA;
    border-radius: 14px;
  }
  html.mv .mv-fmt-cab h3 {
    margin: 6px 0 0;
    font-size: 16px;
    line-height: 21px;
    font-weight: 800;
    color: #16243A;
  }
  html.mv .mv-fmt-cab .mv-fmt-cor {
    margin: 6px 0 0;
    font-size: 13px;
    line-height: 18px;
    font-weight: 700;
    color: #077FCF;
  }

  /* La tabla deja de ser tabla: cada fila es una tarjeta y cada celda, un
     bloque. `colgroup` se apaga o sigue imponiendo los anchos del papel. */
  html.mv .mv-fmt table.mv-fmt-hoja,
  html.mv .mv-fmt table.mv-fmt-hoja tbody,
  html.mv .mv-fmt table.mv-fmt-hoja thead,
  html.mv .mv-fmt table.mv-fmt-hoja tr,
  html.mv .mv-fmt table.mv-fmt-hoja td,
  html.mv .mv-fmt table.mv-fmt-hoja th {
    display: block !important;
    width: auto !important;
    max-width: 100% !important;
    height: auto !important;
  }
  html.mv .mv-fmt table.mv-fmt-hoja { border: 0 !important; border-collapse: separate !important; }
  /* El envoltorio de escritorio le impone min-width:940 a la hoja para poder
     desplazarla de lado. Aquí ya no hace falta: la hoja es una pila de campos.
     Sin esto la pila mide 940 en una ventana de 400 y todo se sale. */
  html.mv .mv-fmt .sigf-scroll,
  html.mv .mv-fmt .dos-sheet-wrap { overflow: visible !important; }
  html.mv .mv-fmt .sigf-scroll table.mv-fmt-hoja,
  html.mv .mv-fmt .dos-sheet-wrap table.mv-fmt-hoja { min-width: 0 !important; width: 100% !important; }
  html.mv .mv-fmt table.mv-fmt-hoja colgroup,
  html.mv .mv-fmt table.mv-fmt-hoja col { display: none !important; }

  html.mv .mv-fmt table.mv-fmt-hoja tr {
    margin: 0 0 8px;
    padding: 12px 14px;
    background: #fff;
    border: 1px solid #E6F2FA !important;
    border-radius: 14px;
  }
  html.mv .mv-fmt table.mv-fmt-hoja td,
  html.mv .mv-fmt table.mv-fmt-hoja th {
    padding: 0 !important;
    border: 0 !important;
    text-align: left !important;
    white-space: normal !important;
    overflow-wrap: anywhere;
  }

  /* La banda de sección es el título de su grupo: su fila deja de ser tarjeta
     y se convierte en encabezado, para que se vea dónde empieza cada parte
     del formato. */
  html.mv .mv-fmt table.mv-fmt-hoja tr:has(> td.sigf-bar),
  html.mv .mv-fmt table.mv-fmt-hoja tr:has(> td.dos-gr) {
    margin: 18px 0 8px;
    padding: 0;
    background: transparent;
    border: 0 !important;
  }
  html.mv .mv-fmt table.mv-fmt-hoja td.sigf-bar,
  html.mv .mv-fmt table.mv-fmt-hoja td.dos-gr {
    padding: 8px 14px !important;
    background: #E6F2FA !important;
    border-radius: 10px;
    font-size: 12px !important;
    line-height: 16px;
    font-weight: 800;
    letter-spacing: .02em;
    text-transform: uppercase;
    color: #0B4E7C !important;
  }

  /* Etiqueta arriba, valor abajo, los dos a todo el ancho. */
  html.mv .mv-fmt table.mv-fmt-hoja td.sigf-lbl,
  html.mv .mv-fmt table.mv-fmt-hoja td.dos-cj-lbl {
    margin: 10px 0 2px;
    font-size: 11px !important;
    line-height: 15px;
    font-weight: 800;
    letter-spacing: .03em;
    text-transform: uppercase;
    color: #64748B !important;
    background: transparent !important;
  }
  html.mv .mv-fmt table.mv-fmt-hoja tr > td.sigf-lbl:first-child,
  html.mv .mv-fmt table.mv-fmt-hoja tr > td.dos-cj-lbl:first-child { margin-top: 0; }
  html.mv .mv-fmt table.mv-fmt-hoja td.sigf-val,
  html.mv .mv-fmt table.mv-fmt-hoja td.dos-cj-pv {
    font-size: 14px !important;
    line-height: 20px;
    color: #16243A !important;
    background: transparent !important;
  }

  /* Los campos se pulsan con el dedo: 44 de alto y 16 de letra, que es el piso
     por debajo del cual iOS hace zoom al enfocar y descuadra la vista. */
  html.mv .mv-fmt table.mv-fmt-hoja input:not([type=checkbox]):not([type=radio]),
  html.mv .mv-fmt table.mv-fmt-hoja select,
  html.mv .mv-fmt table.mv-fmt-hoja textarea {
    width: 100% !important;
    min-width: 0 !important;
    max-width: 100% !important;
    min-height: 44px;
    padding: 10px 12px !important;
    background: #F8FAFC;
    border: 1px solid #E2E8F0 !important;
    border-radius: 10px;
    font-size: 16px !important;
    line-height: 22px;
    color: #16243A;
  }
  html.mv .mv-fmt table.mv-fmt-hoja textarea { min-height: 88px; }
  html.mv .mv-fmt table.mv-fmt-hoja input:focus,
  html.mv .mv-fmt table.mv-fmt-hoja select:focus,
  html.mv .mv-fmt table.mv-fmt-hoja textarea:focus {
    outline: 0;
    border-color: #077FCF !important;
    background: #fff;
  }
  /* Las casillas conservan su tamaño de dibujo y ganan área con relleno en su
     etiqueta: un min-height de 44 sobre la casilla la deformaría. */
  html.mv .mv-fmt table.mv-fmt-hoja input[type=checkbox],
  html.mv .mv-fmt table.mv-fmt-hoja input[type=radio] {
    width: 20px !important;
    height: 20px !important;
    min-height: 0;
  }
  /* El boton de comentario de cada seccion mide 13x13: se le amplia el area
     con un pseudo-elemento, sin tocar el dibujo. */
  html.mv .mv-fmt .rc-bar-btn { position: relative; }
  html.mv .mv-fmt .rc-bar-btn::after {
    content: '';
    position: absolute;
    inset: -15px;
  }
  html.mv .mv-fmt table.mv-fmt-hoja label {
    display: inline-flex !important;
    align-items: center;
    gap: 8px;
    min-height: 44px;
    padding: 4px 0;
    font-size: 14px !important;
  }

  /* ── Reporte Gerencial · las tres dimensiones se deslizan ──────────────
     772 px en escritorio y 2.258 en un teléfono: las tres tarjetas de 512
     apiladas son 2,7 pantallas para tres cifras. Mismo carril que el
     Resumen —asomo, encaje, sin barra— para que toda la aplicación se
     recorra con un solo gesto y no con dos lenguajes distintos. */
  html.mv #sec-reporte .rg3-dims {
    display: flex !important;
    gap: 12px !important;
    align-items: stretch;
    overflow-x: auto;
    scrollbar-width: none;
    padding: 2px 13px 8px !important;
    margin: 0 -13px !important;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: 13px;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
  }
  html.mv #sec-reporte .rg3-dims::-webkit-scrollbar { width: 0; height: 0; }
  html.mv #sec-reporte .rg3-card {
    flex: 0 0 82%;                  /* el 18 % que asoma es la señal */
    max-width: 330px;               /* tope para tabletas; a 390 no muerde */
    scroll-snap-align: start;
  }
  /* LA GRÁFICA DE CADA DIMENSIÓN (G-02, 28-sep). En escritorio la franja del
     gráfico se queda con el alto que SOBRA en la tarjeta (`flex: 1 1 0`); en
     el teléfono la tarjeta mide lo que mide su contenido, así que no sobraba
     nada, la franja medía ~0 px y `montarSpark` la retiraba por debajo de
     86 (`.sin-sitio`). Aquí la franja lleva su propio alto, con sitio para el
     rótulo del eje arriba y «Semana» abajo. */
  html.mv #sec-reporte .rg3-card > .rg3-spark {
    flex: none;
    height: 168px;
  }
  /* «Descargar PDF» es la única acción de la vista y ya cae en su propia
     línea al envolverse la fila; a media asta parece deshabilitada. */
  html.mv #sec-reporte .rg3-btn {
    width: 100% !important;
    justify-content: center !important;
  }

  /* ── Registro de NC · el SIG.009-F01 en la mano ─────────────────────────
     Solo presentación: ningún manejador, ningún dato ni permiso cambia. Lo
     que cambia es el orden de lectura, que en el teléfono va así: qué
     registro es, a quién le toca, qué falta, y el botón de guardar siempre
     al alcance del pulgar. Colores y píldoras son los del Figma de Calidad
     (684:8954/8956 botones, 684:8972 estados); los bordes de campo suben a
     #7F8FA4 porque #E2E8F0 da 1,2:1 sobre blanco y un campo que no se ve
     no se encuentra (WCAG 1.4.11 pide 3:1; este da 3,3:1).

     LOS !important DE ESTE BLOQUE (§8 de responsive-movil.md). Se midieron
     el 23-sep: se le quitó la prioridad a cada uno y se comparó el estilo
     calculado de los ~3.500 elementos de la vista en seis estados (formato,
     lista, comentarios abiertos, horizontal, iPhone SE). Los 128 que no
     cambiaban nada se quitaron; quedan los que ganan a:
       · la capa F de arriba (`html.mv .mv-fmt table.mv-fmt-hoja tr / td /
         label / input…`), que declara display, padding, borde, margen y
         letra con !important;
       · el armazón: `html.mv input…, html.mv textarea, html.mv select
         {min-height:44px !important}` y `html.mv .scroll-area
         [class*="-toolbar"]`;
       · index.html: `.sigf-bar` y `.sigf-chk` (padding con !important) y
         el estilo en línea del título del registro (15 px, peso 800);
       · reglas de este mismo bloque que ya ganan con !important (anotado
         en cada caso: banda de sección, campo de solo lectura, opción
         marcada).
     Los de foco y la ✕ de anular firma no se pudieron medir en el banco
     (no hay foco ni firma propia) y se conservan. */
  html.mv #sec-calidad-nc.mv-fmt {
    --nc-azul: #077FCF;
    --nc-azul-suave: #E6F2FA;
    --nc-azul-tinta: #0B4E7C;
    /* Borde de la tarjeta de registro de Yary (833:981): el formato y la
       lista del teléfono comparten la misma tarjeta. */
    --nc-tarjeta: #D9DADB;
    --nc-tinta: #1E2229;
    --nc-apagado: #6B7280;
    --nc-linea: #E5E7EB;
    --nc-campo: #7F8FA4;
    --nc-acc-h: 58px;
  }

  /* Cabecera del registro: volver, título, formato y estado, y las acciones
     raras (plantilla, eliminar) en una fila. Comentarios y Guardar bajan a
     la barra fija, que es donde llega el pulgar. */
  html.mv #sec-calidad-nc.mv-fmt .insp-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin: 0 0 12px;
    padding: 0;
  }
  html.mv #sec-calidad-nc.mv-fmt .insp-toolbar .rfi-back {
    height: 44px;
    margin: 0 0 0 -8px;
    padding: 0 10px;
    background: transparent;
    border: 0;
    box-shadow: none;
    font: 600 15px/1 'Inter', sans-serif;
    color: var(--nc-azul);
  }
  html.mv #sec-calidad-nc.mv-fmt .insp-toolbar > .rfi-back + span {
    flex: 1 1 100%;
    font: 700 18px/24px 'Inter', sans-serif !important;
    color: var(--nc-tinta);
    overflow-wrap: anywhere;
  }
  html.mv #sec-calidad-nc.mv-fmt .insp-toolbar .insp-cat,
  html.mv #sec-calidad-nc.mv-fmt .insp-toolbar .insp-est { flex: 0 0 auto; }
  /* Rótulos a 12,5 como mínimo (§4 de responsive-movil.md). Medidos en
     el iPhone 14: el formato a 10, el estado a 11, los números de la tira
     de firmas a 10, el antetítulo del membrete a 10 y el aviso de NC
     recibida a 12. */
  html.mv #sec-calidad-nc.mv-fmt .insp-toolbar .insp-cat,
  html.mv #sec-calidad-nc.mv-fmt .insp-toolbar .insp-est,
  html.mv #sec-calidad-nc.mv-fmt #inspFlujo .insp-paso .n,
  html.mv #sec-calidad-nc.mv-fmt .mv-fmt-cab .mv-eyebrow,
  html.mv #sec-calidad-nc.mv-fmt .nc-recibida { font-size: 12.5px; }
  html.mv #sec-calidad-nc.mv-fmt #inspFlujo .insp-paso .n { min-width: 22px; height: 22px; }
  html.mv #sec-calidad-nc.mv-fmt .insp-toolbar .sp { flex: 1 1 100%; height: 0; }
  html.mv #sec-calidad-nc.mv-fmt .insp-toolbar #inspTplBtn,
  html.mv #sec-calidad-nc.mv-fmt .insp-toolbar .insp-btn-del,
  html.mv #sec-calidad-nc.mv-fmt .insp-toolbar #inspLevBtn {
    flex: 1 1 0;
    min-width: 0;
    height: 44px;
    padding: 0 12px;
    font-size: 14px;
  }
  /* Eliminar es la única acción que no se deshace: se distingue de las
     demás por el color, no por el tamaño. */
  html.mv #sec-calidad-nc.mv-fmt .insp-toolbar .insp-btn-del {
    background: #fff;
    border-color: #F92F2F;
    color: #D92D20;
  }

  /* La barra de acción. Los botones siguen siendo los mismos nodos, con su
     onclick: solo cambian de sitio en la pantalla. Mientras se ve el
     formato no hay barra de pestañas (una pantalla de detalle no la
     necesita y juntas comían un 27 % del alto); se vuelve con «Volver». */
  html.mv:has(#sec-calidad-nc.mv-fmt.active) .mv-tabs { display: none; }
  html.mv:has(#sec-calidad-nc.mv-fmt.active) #novaFab { display: none; }
  html.mv:has(#sec-calidad-nc.mv-fmt.active) .scroll-area {
    padding-bottom: calc(var(--nc-acc-h, 58px) + var(--mv-seguro, 0px) + 20px);
    /* El campo con foco no puede quedar debajo de la barra (WCAG 2.4.11). */
    scroll-padding-bottom: calc(var(--nc-acc-h, 58px) + 24px);
    scroll-padding-top: 64px;
  }
  html.mv #sec-calidad-nc.mv-fmt .insp-toolbar::after {
    content: '';
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    height: calc(var(--nc-acc-h) + var(--mv-seguro, 0px));
    background: rgba(255, 255, 255, .97);
    border-top: 1px solid var(--nc-linea);
    box-shadow: 0 -2px 14px rgba(16, 24, 40, .06);
    z-index: 139;
  }
  html.mv #sec-calidad-nc.mv-fmt #regComentToggle,
  html.mv #sec-calidad-nc.mv-fmt #inspSaveBtn {
    position: fixed;
    bottom: calc(7px + var(--mv-seguro, 0px));
    z-index: 140;
    height: 48px;
    margin: 0;
    justify-content: center;
    font-size: 15px;
  }
  html.mv #sec-calidad-nc.mv-fmt #regComentToggle {
    left: 16px;
    width: calc((100vw - 40px) * .42);
  }
  html.mv #sec-calidad-nc.mv-fmt #inspSaveBtn {
    right: 16px;
    width: calc((100vw - 40px) * .58);
    font-weight: 600;
  }
  /* Sin Guardar (quien solo mira), Comentarios ocupa la barra entera. */
  html.mv #sec-calidad-nc.mv-fmt .insp-toolbar:not(:has(#inspSaveBtn:not([style*="none"]))) #regComentToggle {
    width: calc(100vw - 32px);
  }
  /* Con el teclado arriba la barra estorba: se aparta mientras se escribe
     y vuelve al soltar el campo. */
  html.mv #sec-calidad-nc.mv-fmt:has(:is(input:not([type=checkbox]):not([type=radio]), textarea, select):focus) :is(#regComentToggle, #inspSaveBtn),
  html.mv #sec-calidad-nc.mv-fmt:has(:is(input:not([type=checkbox]):not([type=radio]), textarea, select):focus) .insp-toolbar::after {
    display: none !important;
  }

  /* Adjunto recibido, cadena y firmas: tres franjas cortas antes del
     formato, no tres bloques. La cadena es un carril que se desliza. */
  html.mv #sec-calidad-nc.mv-fmt .nc-recibida {
    flex-wrap: wrap;
    min-height: 44px;
    margin: 0 0 10px;
  }
  html.mv #sec-calidad-nc.mv-fmt .nc-recibida .rfi-btn { flex: 1 1 100%; height: 44px; }
  /* El dato del adjunto («47 KB · subido por … el …») iba a 11 px, en el
     registro y en el alta al elegir archivo. */
  html.mv:has(#sec-calidad-nc.active) .nc-file-tx small { font-size: 12.5px; line-height: 17px; }
  html.mv #sec-calidad-nc.mv-fmt #inspCadena {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    scroll-snap-type: x proximity;
    margin: 0 0 10px;
    padding: 2px 0 4px;
  }
  html.mv #sec-calidad-nc.mv-fmt #inspCadena:empty { display: none; }

  /* En el registro ya se sabe dónde se está: «Volver a registros» y el N°
     lo dicen. El título de la sección y sus pestañas son de la lista y
     costaban 110 px antes del primer dato. */
  html.mv #sec-calidad-nc.mv-fmt > .section-header,
  html.mv #sec-calidad-nc.mv-fmt > .rfi-tabs { display: none; }
  html.mv #sec-calidad-nc.mv-fmt #inspCadena::-webkit-scrollbar { display: none; }
  html.mv #sec-calidad-nc.mv-fmt #inspCadena > * { flex: 0 0 auto; scroll-snap-align: start; white-space: nowrap; }

  /* La tira de firmas se lee de arriba abajo: número, paso y, debajo,
     quién y en qué está. El paso en turno conserva su color. */
  html.mv #sec-calidad-nc.mv-fmt #inspFlujo {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 6px;
    margin: 0 0 14px;
    padding: 12px;
  }
  html.mv #sec-calidad-nc.mv-fmt #inspFlujo .insp-sep { display: none; }
  html.mv #sec-calidad-nc.mv-fmt #inspFlujo .insp-paso {
    display: grid;
    grid-template-columns: 26px minmax(0, 1fr);
    align-items: center;
    column-gap: 10px;
    width: 100%;
    min-height: 48px;
    padding: 7px 12px;
    border-radius: 12px;
    font: 700 14px/18px 'Inter', sans-serif;
    text-align: left;
  }
  html.mv #sec-calidad-nc.mv-fmt #inspFlujo .insp-paso .n { grid-row: span 2; }
  html.mv #sec-calidad-nc.mv-fmt #inspFlujo .insp-paso small {
    grid-column: 2;
    font: 500 12.5px/17px 'Inter', sans-serif;
    white-space: normal;
  }
  html.mv #sec-calidad-nc.mv-fmt #inspFlujo .insp-vis {
    justify-self: start;
    margin: 2px 0 0;
    font-size: 12.5px;
  }

  /* El membrete ya dice el N° arriba, en la cabecera: aquí sobra. Y el
     nombre del documento en mayúsculas cuesta tres líneas; en frase, dos. */
  html.mv #sec-calidad-nc.mv-fmt .mv-fmt-cab { padding: 12px 16px; }
  html.mv #sec-calidad-nc.mv-fmt .mv-fmt-cab .mv-fmt-cor { display: none; }
  html.mv #sec-calidad-nc.mv-fmt .mv-fmt-cab h3 {
    font-size: 15px;
    line-height: 20px;
    font-weight: 700;
    color: var(--nc-tinta);
    text-transform: lowercase;
  }
  html.mv #sec-calidad-nc.mv-fmt .mv-fmt-cab h3::first-letter { text-transform: uppercase; }

  /* Una sección, una tarjeta. En escritorio cada fila de la tabla junta dos
     campos del papel («Cliente» con «Fecha»); en el teléfono esa pareja no
     significa nada y partía cada sección en tres o cuatro tarjetas. Las
     filas se unen: la primera tras la banda abre la tarjeta y la última
     antes de la siguiente banda la cierra. */
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja > tbody {
    display: flex !important;
    flex-direction: column;
  }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja tr {
    margin: 0;
    padding: 6px 16px;
    border: 0 !important;
    border-left: 1px solid var(--nc-tarjeta) !important;
    border-right: 1px solid var(--nc-tarjeta) !important;
    border-radius: 0;
    background: #fff;
  }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja tr:has(> td.sigf-bar) + tr {
    margin-top: 8px;
    padding-top: 14px;
    border-top: 1px solid var(--nc-tarjeta) !important;
    border-radius: 12px 12px 0 0;
  }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja tr:has(+ tr > td.sigf-bar),
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja tr:last-child {
    padding-bottom: 14px;
    border-bottom: 1px solid var(--nc-tarjeta) !important;
    border-bottom-left-radius: 12px;
    border-bottom-right-radius: 12px;
  }

  /* La banda de sección se queda arriba mientras dura su sección: en la 5 o
     la 8 se escribe varias pantallas por debajo de su título. */
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja tr:has(> td.sigf-bar) {
    position: sticky;
    top: 0;
    z-index: 3;
    /* !important: gana a la fila genérica de arriba (margin/padding/borde
       con !important, que a su vez gana a `html.mv .mv-fmt table.mv-fmt-hoja
       tr` de la capa F). Sin él la banda sale con bordes laterales y 2 px
       más angosta. */
    margin: 18px 0 0 !important;
    padding: 6px 0 !important;
    border: 0 !important;
    border-radius: 0 !important;
    background: rgba(255, 255, 255, .96);
  }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja td.sigf-bar {
    min-height: 40px;
    padding-top: 12px !important;
    padding-bottom: 12px !important;
    font-size: 12.5px !important;
  }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja td.sigf-bar .rc-bar-btn { margin-left: 8px; vertical-align: -2px; }
  /* 13 + 2 × 16 = 45: el -15 de arriba dejaba 43, un píxel bajo el mínimo. */
  html.mv #sec-calidad-nc.mv-fmt .rc-bar-btn::after { inset: -16px; }
  /* `#inspForm` desplaza de lado en escritorio (overflow:auto). En el
     teléfono la hoja ya es una pila y ese overflow solo conseguía que las
     bandas se pegaran a un contenedor que no se mueve: nunca se pegaban. */
  html.mv #sec-calidad-nc.mv-fmt #inspForm { overflow: visible; }

  /* «2 · Tipo de hallazgo» y «3 · Fuente de detección» comparten fila en el
     papel: las dos bandas arriba y las dos listas debajo. Apiladas tal cual,
     las siete opciones salían juntas bajo dos títulos y no se sabía cuál era
     de cuál. Se reordenan sin mover nodos: banda 2, lista 2, banda 3, lista 3. */
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja tr:has(> td.sigf-bar + td.sigf-bar),
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja tr:has(> td.sigf-bar + td.sigf-bar) + tr {
    display: contents !important;
  }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja tr:has(> td.sigf-bar + td.sigf-bar) > td:nth-child(1) { order: 1; }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja tr:has(> td.sigf-bar + td.sigf-bar) + tr > td:nth-child(1) { order: 2; }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja tr:has(> td.sigf-bar + td.sigf-bar) > td:nth-child(2) { order: 3; }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja tr:has(> td.sigf-bar + td.sigf-bar) + tr > td:nth-child(2) { order: 4; }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja tr:has(> td.sigf-bar + td.sigf-bar) + tr ~ tr { order: 5; }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja tr:has(> td.sigf-bar + td.sigf-bar) > td.sigf-bar {
    position: sticky;
    top: 6px;
    z-index: 3;
    margin: 18px 0 0;
    box-shadow: 0 -6px 0 #fff, 0 6px 0 #fff;
  }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja tr:has(> td.sigf-bar + td.sigf-bar) + tr > td {
    margin: 8px 0 0;
    padding: 14px 16px !important;
    background: #fff;
    border: 1px solid var(--nc-tarjeta) !important;
    border-radius: 12px;
  }

  /* Etiquetas en frase y a 12 px, no en mayúsculas a 11: se leen de corrido
     y no bajan del mínimo de la plataforma. */
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja td.sigf-lbl {
    margin: 12px 0 6px;
    font-size: 12.5px !important;
    line-height: 16px;
    font-weight: 700;
    letter-spacing: 0;
    text-transform: lowercase;
    color: var(--nc-apagado) !important;
  }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja td.sigf-lbl::first-letter { text-transform: uppercase; }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja tr > td.sigf-lbl:first-child { margin-top: 4px; }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja td.sigf-lbl .req { color: #D92D20; }

  /* Campo que se llena: caja blanca de 48 con borde que se ve. */
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja input:not([type=checkbox]):not([type=radio]),
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja select,
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja textarea {
    /* !important porque el armazón fija `html.mv textarea{min-height:44px
       !important}` para todo campo, y eso pisaba también el 88 de arriba y
       el min-height en línea del motor: los cuadros salían de una línea. */
    min-height: 48px !important;
    background: #fff !important;
    border: 1px solid var(--nc-campo) !important;
    border-radius: 10px !important;
    color: var(--nc-tinta) !important;
  }
  /* El textarea crece con lo escrito: la descripción se lee entera, no por
     una ventanita de tres líneas con su propio scroll. */
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja textarea {
    min-height: 96px !important;
    field-sizing: content;
    resize: none;
  }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja :is(input, select, textarea):focus {
    /* Un solo anillo: el borde cambia de color y nada más. Un halo encima
       son dos marcos (sonda del §4 de responsive-movil.md). */
    border-color: var(--nc-azul) !important;
    box-shadow: none !important;
  }
  /* Campo que ya no se toca (fijo de la plantilla, o de un paso ya firmado):
     se lee como dato, no como caja vacía para llenar. Así se ve de un golpe
     qué te toca a ti y qué ya está. */
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja input[readonly]:not([type=checkbox]):not([type=radio]),
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja textarea[readonly] {
    /* !important en todo: gana a «Campo que se llena» de arriba (fondo,
       borde y radio con !important), que existe para ganarle al
       `html.mv textarea{min-height:44px !important}` del armazón. */
    min-height: 0 !important;
    padding: 2px 0 6px !important;
    background: transparent !important;
    border: 0 !important;
    border-bottom: 1px dashed #CBD5E1 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    font-weight: 600;
  }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja textarea[readonly] { min-height: 0 !important; line-height: 22px; }

  /* Opciones: una por renglón, toda la fila es la zona de toque y la
     elegida se ve en azul. Las de dos o tres palabras cortas (AC/OM/NA,
     Cumple/No cumple, Sí/No) van como selector segmentado. */
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja td.sigf-chk {
    display: flex !important;
    flex-direction: column;
    gap: 8px;
    margin: 4px 0;
  }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja td.sigf-chk label {
    display: flex !important;
    align-items: center;
    gap: 12px;
    width: 100%;
    min-height: 48px;
    margin: 0;
    padding: 12px 14px;
    background: #fff;
    border: 1px solid var(--nc-campo);
    border-radius: 12px;
    font: 500 15px/20px 'Inter', sans-serif !important;
    color: var(--nc-tinta);
    cursor: pointer;
  }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja td.sigf-chk label:has(input:checked) {
    background: var(--nc-azul-suave);
    border-color: var(--nc-azul);
    color: var(--nc-azul-tinta);
    /* Gana al `font: 500 …!important` de la opción sin marcar, que a su vez
       gana al `label{font-size:14px !important}` de la capa F. */
    font-weight: 600 !important;
  }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja td.sigf-chk label:has(input:disabled) { opacity: .62; cursor: default; }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja td.sigf-chk input {
    flex: 0 0 auto;
    width: 22px !important;
    height: 22px !important;
    margin: 0;
    accent-color: var(--nc-azul);
  }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja td.sigf-chk:is([data-campo="tipoAccion"], [data-campo="resultadoVerif"], [data-campo="costosAsociados"]) {
    display: grid !important;
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
  }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja td.sigf-chk:is([data-campo="tipoAccion"], [data-campo="resultadoVerif"], [data-campo="costosAsociados"]) label {
    justify-content: center;
    padding: 12px 8px;
  }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja td.sigf-note {
    margin: 8px 0 0;
    font-size: 13px;
    color: var(--nc-apagado);
  }

  /* La firma: una zona de 72 que se ve como sitio para firmar, con su aviso
     a 13 px (en escritorio va a 8, ilegible en la mano). Anular la firma es
     un botón de 17: su área crece a 44 sin tocar el dibujo. */
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja td.sigf-firma { height: auto; }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja td.sigf-firma .fmz {
    min-height: 72px;
    border: 1.5px dashed #B6C3D3;
    border-radius: 12px;
    background: #F8FAFC;
    font-size: 14px;
  }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja td.sigf-firma .fmz-turno {
    border-color: #F2B366;
    background: #FFF4E6;
    color: #B46504;
    font-weight: 700;
  }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja td.sigf-firma .fmz-ok { border-style: solid; background: #fff; }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja td.sigf-firma .fmz-ok img { max-height: 52px; }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja td.sigf-firma .fmz small {
    font-size: 13px !important;
    line-height: 18px;
  }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja td.sigf-firma .fmz-x {
    top: 8px !important;
    right: 8px !important;
    width: 28px !important;
    height: 28px !important;
  }
  html.mv #sec-calidad-nc.mv-fmt table.mv-fmt-hoja td.sigf-firma .fmz-x::after {
    content: '';
    position: absolute;
    inset: -8px;
  }

  /* Comentarios como hoja desde abajo, no como cajón lateral: en 390 px el
     cajón tapaba el 85 % y no dejaba ver la sección que se comenta. En el
     teléfono no se abre solo al entrar (lo decide `formato.js`, sin tocar la
     preferencia guardada): se abre con «Comentarios» o con el globo de
     cada sección. */
  html.mv #sec-calidad-nc.mv-fmt .reg-det.mv-coment-oculto .reg-coment { display: none; }
  /* Entre que se pinta el registro y que `formato.js` actúa pasan ~250 ms:
     sin esto el panel asoma y se va. Si el compositor no llegara a actuar,
     el panel aparece igual a los 1,5 s: nunca queda escondido para siempre. */
  html.mv #sec-calidad-nc:not(.mv-fmt) .reg-det:not(.coment-cerrado) .reg-coment {
    visibility: hidden;
    animation: mv-coment-respaldo 0s linear 1.5s forwards;
  }
  @keyframes mv-coment-respaldo { to { visibility: visible; } }
  html.mv #sec-calidad-nc.mv-fmt .reg-det .reg-coment {
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    width: auto;
    height: auto;
    max-height: 82dvh;
    min-height: 0;
    padding-bottom: var(--mv-seguro, 0px);
    border-radius: 18px 18px 0 0;
    /* Opaca: el vidrio del cajón de escritorio dejaba ver la barra de
       acción difuminada a través de la hoja. */
    background: #fff;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    box-shadow: 0 -8px 30px rgba(15, 23, 42, .18);
    z-index: 160;
  }
  html.mv #sec-calidad-nc.mv-fmt .reg-det:not(.coment-cerrado):not(.mv-coment-oculto)::before {
    content: '';
    position: fixed;
    inset: 0;
    z-index: 159;
    background: rgba(15, 23, 42, .32);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
  }
  html.mv #sec-calidad-nc.mv-fmt .reg-coment label { min-height: 0; }
  html.mv #sec-calidad-nc.mv-fmt .reg-coment .rc-x { min-width: 44px; min-height: 44px; }

  /* En horizontal quedan ~280 px útiles: una barra fija más la cabecera
     dejarían media pantalla. Los botones vuelven a su fila. */
  @media (max-height: 500px) {
    html.mv #sec-calidad-nc.mv-fmt #regComentToggle,
    html.mv #sec-calidad-nc.mv-fmt #inspSaveBtn {
      position: static;
      flex: 1 1 0;
      width: auto;
      height: 44px;
    }
    html.mv #sec-calidad-nc.mv-fmt .insp-toolbar::after { display: none; }
    html.mv:has(#sec-calidad-nc.mv-fmt.active) .scroll-area { padding-bottom: 24px; }
  }

  /* ── Arquetipo R · lista de Control de NC (Figma 833:946, Yary) ─────────
     Estructura, colores y jerarquía son los del frame. Se apartan del
     Figma, a propósito, solo las medidas que en un teléfono impiden operar
     o leer:
       · botones de 31 px de alto → 44 (mínimo de toque);
       · buscador de 32 px con letra de 13 → 44 y 16 (bajo 16 iOS hace zoom
         al enfocar);
       · paginación de 40 → 44;
       · textos de 10 y 11 px → 12 (mínimo de la plataforma);
       · grises #8E9093 (3,2:1) → #5C5E64, el neutro/8 del mismo Figma
         (6,5:1); el rojo del retraso #D93838 sobre celeste (4,0:1) →
         #B42318 (5,8:1); el texto de «Eliminar» #F92F2F (3,8:1) → #D92D20.
     El rojo del retraso sale de la clase de la plataforma (`tarde`), no del
     texto: el Figma pinta «Sin guardar» de rojo y en escritorio el rojo está
     reservado al retraso de verdad.

     Los !important que quedan aquí ganan a `.section-header` de index.html
     (letra y mayúsculas con !important), a la regla general del armazón
     para campos (min-height 44 !important) y a `html.mv .scroll-area
     [class*="-tools"]`. La etiqueta de estado y las pestañas ganan por
     especificidad (#sec-calidad-nc), sin !important. */
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-ncr-on {
    --ncr-borde: #D9DADB;
    --ncr-tinta: #2A2D34;
    --ncr-gris: #5C5E64;
    --ncr-celeste: #E6F2FA;
    --ncr-azul: #077FCF;
  }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-ncr-on :is(#ncBody, #inspBody, #capregBody, #dossierRoot, #calFormRoot) .rfi-table-wrap { display: none; }
  /* En escritorio la lista vive en una tarjeta blanca; en el frame todo va
     sobre la página y la tarjeta es cada registro. */
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-ncr-on :is(#ncPane-registro, #inspPane-registro, #capregPane-registro, #gsigPane-formato),
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-ncr-on :is(#ncBody, #inspBody, #capregBody, #dossierRoot, #calFormRoot) {
    padding: 0;
    background: transparent;
    border: 0;
    box-shadow: none;
  }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-ncr-on :is(#ncBody, #inspBody, #capregBody, #dossierRoot, #calFormRoot) .rfi-list-title { display: none; }

  /* Título de la vista (833:971): 24/28 bold, sin la barrita de escritorio. */
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig):is(.mv-ncr-on, .mv-nci-on) > .section-header {
    margin: 4px 0 8px;
    font: 700 24px/28px 'Inter', sans-serif !important;
    letter-spacing: -.01em !important;
    text-transform: none;
    color: #111827;
  }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig):is(.mv-ncr-on, .mv-nci-on) > .section-header::before { display: none; }

  /* Pestañas (833:962): subrayado de 2 px, activa en azul 600, inactiva en
     gris 400. 10 px arriba y abajo para llegar a 44 de toque. */
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig):is(.mv-ncr-on, .mv-nci-on) > .rfi-tabs {
    display: flex;
    gap: 0;
    margin: 0 0 14px;
    padding: 0;
    background: transparent;
    border: 0;
    border-bottom: 2px solid var(--ncr-celeste);
    border-radius: 0;
    box-shadow: none;
  }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig):is(.mv-ncr-on, .mv-nci-on) > .rfi-tabs .rfi-tab {
    min-height: 44px;
    margin: 0 0 -2px;
    padding: 10px 12px;
    background: transparent;
    border: 0;
    border-bottom: 2px solid #ECEEF2;
    border-radius: 0;
    box-shadow: none;
    font: 400 16px/24px 'Inter', sans-serif;
    color: #677790;
  }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig):is(.mv-ncr-on, .mv-nci-on) > .rfi-tabs .rfi-tab.active {
    border-bottom-color: var(--ncr-azul);
    font-weight: 600;
    color: var(--ncr-azul);
  }

  /* Buscador y filtro en una fila (833:972); Publicar y «+ Agregar
     registro», que el frame no dibuja pero la vista necesita, en la de
     abajo. Son los controles originales: filtran con su propia lógica. */
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-ncr-on :is(#ncBody, #inspBody, #capregBody, #dossierRoot, #calFormRoot) .rfi-list-head {
    margin: 0 0 12px;
    padding: 0;
    background: transparent;
    border: 0;
    box-shadow: none;
  }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-ncr-on :is(#ncBody, #inspBody, #capregBody, #dossierRoot, #calFormRoot) .rfi-list-tools {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 12px !important;
    width: 100%;
  }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-ncr-on :is(#ncBody, #inspBody, #capregBody, #dossierRoot, #calFormRoot) .rfi-search {
    flex: 1 1 0;
    min-width: 0;
    width: auto;
    height: 44px;
    min-height: 44px;
    border-color: #7F8FA4;
    font-size: 16px;
  }
  /* Un anillo al enfocar: el borde pasa a azul y hace de anillo. El
     !important gana al anillo global de index.html
     (`input:focus-visible{box-shadow:var(--focus-ring) !important}`), que
     sumado al borde daba dos marcos. El foco no se quita: se sustituye. */
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-ncr-on :is(#ncBody, #inspBody, #capregBody, #dossierRoot, #calFormRoot) .rfi-search:focus {
    outline: 0;
    border-color: var(--ncr-azul);
    box-shadow: none !important;
  }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-ncr-on :is(#ncBody, #inspBody, #capregBody, #dossierRoot, #calFormRoot) .insp-sel {
    flex: 0 0 auto;
    width: auto;
    max-width: 46%;
    height: 44px;
    min-height: 44px;
    padding: 0 24px 0 4px;
    background: transparent url("data:image/svg+xml,%3Csvg%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cg%20id%3D%22heroicons-mini%2Fadjustments-horizontal%22%3E%3Cg%20id%3D%22Union%22%3E%3Cpath%20d%3D%22M8%203C8%202.11634%207.28366%201.4%206.4%201.4C5.51634%201.4%204.8%202.11634%204.8%203C4.8%203.88366%205.51634%204.6%206.4%204.6C7.28366%204.6%208%203.88366%208%203Z%22%20fill%3D%22%230D0F1F%22%2F%3E%3Cpath%20d%3D%22M13.8%203.6C14.1314%203.6%2014.4%203.33137%2014.4%203C14.4%202.66863%2014.1314%202.4%2013.8%202.4L9.4%202.4C9.06863%202.4%208.8%202.66863%208.8%203C8.8%203.33137%209.06863%203.6%209.4%203.6L13.8%203.6Z%22%20fill%3D%22%230D0F1F%22%2F%3E%3Cpath%20d%3D%22M4%203C4%203.33137%203.73137%203.6%203.4%203.6H2.2C1.86863%203.6%201.6%203.33137%201.6%203C1.6%202.66863%201.86863%202.4%202.2%202.4L3.4%202.4C3.73137%202.4%204%202.66863%204%203Z%22%20fill%3D%22%230D0F1F%22%2F%3E%3Cpath%20d%3D%22M3.4%2013.6C3.73137%2013.6%204%2013.3314%204%2013C4%2012.6686%203.73137%2012.4%203.4%2012.4H2.2C1.86863%2012.4%201.6%2012.6686%201.6%2013C1.6%2013.3314%201.86863%2013.6%202.2%2013.6H3.4Z%22%20fill%3D%22%230D0F1F%22%2F%3E%3Cpath%20d%3D%22M13.8%2013.6C14.1314%2013.6%2014.4%2013.3314%2014.4%2013C14.4%2012.6686%2014.1314%2012.4%2013.8%2012.4H9.4C9.06863%2012.4%208.8%2012.6686%208.8%2013C8.8%2013.3314%209.06863%2013.6%209.4%2013.6H13.8Z%22%20fill%3D%22%230D0F1F%22%2F%3E%3Cpath%20d%3D%22M7.2%208C7.2%208.33137%206.93137%208.6%206.6%208.6H2.2C1.86863%208.6%201.6%208.33137%201.6%208C1.6%207.66863%201.86863%207.4%202.2%207.4L6.6%207.4C6.93137%207.4%207.2%207.66863%207.2%208Z%22%20fill%3D%22%230D0F1F%22%2F%3E%3Cpath%20d%3D%22M13.8%208.6C14.1314%208.6%2014.4%208.33137%2014.4%208C14.4%207.66863%2014.1314%207.4%2013.8%207.4H12.6C12.2686%207.4%2012%207.66863%2012%208C12%208.33137%2012.2686%208.6%2012.6%208.6H13.8Z%22%20fill%3D%22%230D0F1F%22%2F%3E%3Cpath%20d%3D%22M11.2%208C11.2%207.11634%2010.4837%206.4%209.6%206.4C8.71634%206.4%208%207.11634%208%208C8%208.88366%208.71634%209.6%209.6%209.6C10.4837%209.6%2011.2%208.88366%2011.2%208Z%22%20fill%3D%22%230D0F1F%22%2F%3E%3Cpath%20d%3D%22M8%2013C8%2012.1163%207.28366%2011.4%206.4%2011.4C5.51634%2011.4%204.8%2012.1163%204.8%2013C4.8%2013.8837%205.51634%2014.6%206.4%2014.6C7.28366%2014.6%208%2013.8837%208%2013Z%22%20fill%3D%22%230D0F1F%22%2F%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E") no-repeat right 2px center / 16px;
    border: 0;
    box-shadow: none;
    font: 400 16px/24px 'Inter', sans-serif !important;
    color: var(--ncr-tinta);
    text-align: right;
  }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-ncr-on :is(#ncBody, #inspBody, #capregBody, #dossierRoot, #calFormRoot) .rfi-list-tools .rfi-btn {
    flex: 1 1 40%;
    height: 44px;
  }

  /* La tarjeta (833:981): blanca, borde #D9DADB, radio 12, relleno 16. */
  html.mv .mv-ncr-caja-lista { padding: 0 0 8px; }
  html.mv .mv-ncr-lista { display: flex; flex-direction: column; gap: 10px; }
  html.mv .mv-ncr {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 16px;
    background: #fff;
    border: 1px solid var(--ncr-borde);
    border-radius: 12px;
    font-family: 'Inter', sans-serif;
  }
  html.mv .mv-ncr p { margin: 0; }
  /* Dos columnas (actividad | responsable, tiempo | retraso) mientras el
     interior de la tarjeta dé para ellas. A 360 px el interior mide 296 y
     cada columna quedaría en ~130: ahí se apilan, un dato por línea
     (§4 de responsive-movil.md). */
  html.mv .mv-ncr { container-type: inline-size; }
  /* `.mv-ncr` delante: estas reglas van antes que las de base en el
     archivo y, a igual especificidad, ganaría la de base. */
  @container (max-width: 300px) {
    html.mv .mv-ncr .mv-ncr-pend { flex-direction: column; gap: 8px; }
    html.mv .mv-ncr .mv-ncr-quien { padding: 8px 0 0; border-left: 0; border-top: 1px dashed var(--ncr-borde); }
    html.mv .mv-ncr .mv-ncr-caja { grid-template-columns: minmax(0, 1fr); }
  }
  html.mv .mv-ncr-cab {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding-bottom: 10px;
    border-bottom: 1px dashed var(--ncr-borde);
  }
  html.mv .mv-ncr-id { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
  /* El título manda: 14 en vez de 12 y en varias líneas si hace falta. El
     frame lo deja en una línea porque su ejemplo es «asdasd». */
  html.mv .mv-ncr-nom { font-weight: 600; line-height: 19px; overflow-wrap: anywhere; }
  html.mv .mv-ncr-num { font-size: 13px; color: var(--ncr-gris); white-space: nowrap; }
  html.mv .mv-ncr-tit { font-size: 14px; color: var(--ncr-tinta); }
  html.mv .mv-ncr-nom .reg-coment-n { vertical-align: 1px; }
  html.mv .mv-ncr-fecha { font-size: 12.5px; line-height: 16px; color: var(--ncr-gris); }
  /* El estado (833:989): etiqueta de radio 4 en mayúsculas. El borrador en
     el naranja del frame; los demás estados, con el color de escritorio. */
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig) .mv-ncr .insp-est {
    flex: 0 0 auto;
    padding: 3px 8px;
    border-radius: 4px;
    font: 700 12.5px/17px 'Inter', sans-serif;
    text-transform: uppercase;
  }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig) .mv-ncr .insp-e-borrador { background: #FFF4E6; color: #B46504; }

  /* Qué falta | a quién le toca, con el filete punteado entre los dos. */
  html.mv .mv-ncr-pend { display: flex; align-items: flex-start; gap: 16px; font-size: 13px; line-height: 18px; }
  html.mv .mv-ncr-que { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 4px; color: var(--ncr-tinta); }
  html.mv .mv-ncr-lbl { font-size: 12.5px; font-weight: 600; color: var(--ncr-gris); }
  html.mv .mv-ncr-quien {
    flex: 1 1 0;
    min-width: 0;
    align-self: stretch;
    padding-left: 16px;
    border-left: 1px dashed var(--ncr-borde);
    color: var(--ncr-gris);
  }
  html.mv .mv-ncr-quien b { color: var(--ncr-tinta); font-weight: 600; }

  /* Tiempo y retraso en su caja celeste (833:1000). */
  html.mv .mv-ncr-caja {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 12px;
    padding: 10px 12px;
    background: var(--ncr-celeste);
    border-radius: 8px;
  }
  html.mv .mv-ncr-caja > div { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
  html.mv .mv-ncr-lbl2 { font-size: 12.5px; font-weight: 500; color: var(--ncr-gris); }
  html.mv .mv-ncr-caja b { font-size: 13px; line-height: 18px; font-weight: 600; color: var(--ncr-tinta); }
  html.mv .mv-ncr-caja small { font-size: 12.5px; line-height: 16px; color: var(--ncr-gris); }
  html.mv .mv-ncr-caja .mv-ncr-p-tarde { color: #B42318; }
  html.mv .mv-ncr-caja .mv-ncr-p-pronto { color: #B46504; }

  html.mv .mv-ncr-rec {
    padding-bottom: 10px;
    border-bottom: 1px solid var(--ncr-borde);
    font-size: 12.5px;
    line-height: 16px;
    text-align: center;
    color: var(--ncr-gris);
  }
  html.mv .mv-ncr-rec span { margin-left: 6px; }

  /* Acciones (833:1010): las dos a partes iguales, en píldora. */
  html.mv .mv-ncr-acc { display: flex; gap: 12px; }
  html.mv .mv-ncr-acc button {
    flex: 1 1 0;
    min-width: 0;
    height: 44px;
    padding: 0 16px;
    border-radius: 50px;
    font: 500 14px/1 'Inter', sans-serif;
    cursor: pointer;
  }
  html.mv .mv-ncr-ver { background: var(--ncr-azul); border: 0; color: #fff; }
  html.mv .mv-ncr-del { background: #fff; border: 1px solid #F92F2F; color: #D92D20; }
  /* G05 · icono + texto, como los botones de la casa (Heroicon de 18, trazo 2). */
  html.mv .mv-ncr-acc button { display: inline-flex; align-items: center; justify-content: center; gap: 8px; }
  html.mv .mv-ncr-acc button svg { width: 18px; height: 18px; flex: none; }

  /* Paginación (833:949): cuadros de radio 10, la activa con el degradé. */
  html.mv .mv-ncr-pag {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 10px;
    margin: 18px 0 4px;
  }
  html.mv .mv-ncr-pb {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    padding: 0;
    background: #F8FAFC;
    border: 1.25px solid #E2E8F0;
    border-radius: 10px;
    font: 600 16px/1 'Inter', sans-serif;
    color: #64748B;
    cursor: pointer;
  }
  html.mv .mv-ncr-pb.on {
    background: linear-gradient(90deg, #2985D3 13%, #367EDC 84%);
    border: 0;
    font-weight: 700;
    color: #fff;
  }
  html.mv .mv-ncr-pb:disabled { border-color: transparent; cursor: default; }
  html.mv .mv-ncr-pb svg { width: 15px; height: 15px; fill: none; stroke: #64748B; stroke-width: 2.5; stroke-linecap: round; }
  html.mv .mv-ncr-pb:disabled svg { stroke: #CBD5E1; }
  html.mv .mv-ncr-pe { color: #64748B; font-weight: 600; }
  html.mv .mv-ncr-vacio { margin: 8px 0; padding: 24px 16px; text-align: center; color: var(--ncr-gris); background: #fff; border: 1px dashed var(--ncr-borde); border-radius: 12px; }

  /* ── Control de NC · Indicadores ────────────────────────────────────
     Tres KPI, una nota y el detalle de NC. El detalle es una tabla de solo
     lectura: pasa a la misma tarjeta de la lista, sin acciones, en su sitio
     dentro de su tarjeta. Los rótulos de los KPI y de la nota iban a 12 px. */
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-nci-on {
    --ncr-borde: #D9DADB;
    --ncr-tinta: #2A2D34;
    --ncr-gris: #5C5E64;
    --ncr-celeste: #E6F2FA;
    --ncr-azul: #077FCF;
  }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-nci-on :is(#ncPane-indicadores, #inspPane-indicadores, #capregPane-indicadores, #capregPane-mios, #gsigPane-indicadores) .table-wrap:has(:is(#calTblDetalle, #inspIndTabla, #calCapTblHistorico, #calSIGTblDetalle)) { display: none !important; }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-nci-on :is(#ncPane-indicadores, #inspPane-indicadores, #capregPane-indicadores, #capregPane-mios, #gsigPane-indicadores) :is(.section-subheader, .kpi-label, .kpi-sublabel,
    .kpi-meta-target, .kpi-meta-status, .chart-subtitle) { font-size: 12.5px !important; }
  /* El título de la tarjeta de detalle salía a 30 px en mayúsculas y
     partido en dos líneas: pasa al título de tarjeta de la vista (16/700). */
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-nci-on :is(#ncPane-indicadores, #inspPane-indicadores, #capregPane-indicadores, #capregPane-mios, #gsigPane-indicadores) .chart-card .chart-title {
    font: 700 16px/22px 'Inter', sans-serif !important;
    letter-spacing: 0 !important;
    /* En frase, como los rótulos de los KPI de arriba. */
    text-transform: none !important;
    gap: 8px;
  }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-nci-on :is(#ncPane-indicadores, #inspPane-indicadores, #capregPane-indicadores, #capregPane-mios, #gsigPane-indicadores) .chart-card .chart-title .num {
    min-width: 28px;
    height: 24px;
    font-size: 12.5px !important;
  }
  /* Fuente y nota. Medido a 390 × 844: la nota ocupaba 150 px con su icono en
     columna propia, y entre ella y el primer KPI no cabía nada más. Sin el
     icono y con menos relleno queda en ~85 px; el texto no cambia. */
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-nci-on :is(#ncPane-indicadores, #inspPane-indicadores, #capregPane-indicadores, #capregPane-mios, #gsigPane-indicadores) > .section-subheader {
    margin: 0 0 8px;
    padding: 0;
    text-align: left;
  }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-nci-on :is(#ncPane-indicadores, #inspPane-indicadores, #capregPane-indicadores, #capregPane-mios, #gsigPane-indicadores) .ssoma-note {
    gap: 0;
    margin: 0 0 12px;
    padding: 10px 12px;
    font-size: 13px;
    line-height: 1.45;
  }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-nci-on :is(#ncPane-indicadores, #inspPane-indicadores, #capregPane-indicadores, #capregPane-mios, #gsigPane-indicadores) .ssoma-note-icon { display: none; }

  /* Los tres KPI. En escritorio son tres tarjetas en fila; apiladas en el
     teléfono medían 205 px cada una (615 px): el detalle empezaba en la
     segunda pantalla. En una hoja de indicadores manda la cifra: una sola
     tarjeta con una fila por KPI; rótulo, explicación y meta a la izquierda y
     la cifra a la derecha, donde se alinea sola diga «6» o «16,7%».
     La tarjeta es flex y no grid a propósito: `unaColumna()` de armazon.js
     fuerza a una columna, en línea y con !important, toda rejilla de dos
     pistas con un hijo de más de 80 caracteres, y las tres filas juntas lo
     superan. La rejilla va en cada fila, cuyos hijos son cortos. */
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-nci-on :is(#ncPane-indicadores, #inspPane-indicadores, #capregPane-indicadores, #capregPane-mios, #gsigPane-indicadores) .kpi-strip {
    display: flex;
    flex-direction: column;
    /* Gana al margin-bottom:18px en línea. */
    margin: 0 0 14px !important;
    padding: 0 16px;
    background: #fff;
    border: 1px solid var(--ncr-borde);
    border-radius: 12px;
  }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-nci-on :is(#ncPane-indicadores, #inspPane-indicadores, #capregPane-indicadores, #capregPane-mios, #gsigPane-indicadores) .kpi-card {
    /* Gana a `:is(#inspPane-indicadores, #ncPane-indicadores, …) .kpi-card
       {display:flex !important; flex-direction:column !important}` del
       rediseño homogéneo de Calidad: con él la cifra caía debajo del rótulo
       en vez de ir a la derecha (medido en NC e Inspecciones, 24-sep). */
    display: grid !important;
    /* Gana al comodín `html.mv .scroll-area [class*="kpi"]{repeat(2,…) !important}`,
       que también atrapa a .kpi-card y partía la fila en dos mitades de 161 px. */
    grid-template-columns: minmax(0, 1fr) auto !important;
    column-gap: 16px;
    align-items: start;
    /* Gana a `:is(#inspPane-indicadores, …) .kpi-card{padding:20px !important}`
       del rediseño homogéneo de Calidad: sumaba 40 px de alto y 40 de ancho
       a cada fila (163 px por cifra) y metía el texto 20 px más adentro. */
    padding: 14px 0 !important;
    background: none;
    /* Los tres ganan a `.kpi-card{border, border-radius, box-shadow !important}`
       del rediseño de escritorio (T6). */
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
  }
  /* Gana al border-top:4px en línea de la primera y al border:0 de arriba. */
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-nci-on :is(#ncPane-indicadores, #inspPane-indicadores, #capregPane-indicadores, #capregPane-mios, #gsigPane-indicadores) .kpi-card + .kpi-card { border-top: 1px dashed var(--ncr-borde) !important; }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-nci-on :is(#ncPane-indicadores, #inspPane-indicadores, #capregPane-indicadores, #capregPane-mios, #gsigPane-indicadores) .kpi-card::before { display: none; }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-nci-on :is(#ncPane-indicadores, #inspPane-indicadores, #capregPane-indicadores, #capregPane-mios, #gsigPane-indicadores) .kpi-value {
    grid-column: 2;
    grid-row: 1 / span 2;
    justify-self: end;
    text-align: right;
    /* Los tres ganan a las variables del rediseño de escritorio (!important). */
    font-size: 28px !important;
    line-height: 32px !important;
    letter-spacing: 0 !important;
    color: var(--ncr-azul);
    font-variant-numeric: tabular-nums;
  }
  /* Sin valor: el mismo «—», en gris y más chico, para que no parezca una barra. */
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-nci-on :is(#ncPane-indicadores, #inspPane-indicadores, #capregPane-indicadores, #capregPane-mios, #gsigPane-indicadores) .kpi-value[data-mv-vacio="1"] {
    font-size: 22px !important;
    color: #A3A7AE;
  }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-nci-on :is(#ncPane-indicadores, #inspPane-indicadores, #capregPane-indicadores, #capregPane-mios, #gsigPane-indicadores) .kpi-label {
    grid-column: 1;
    grid-row: 1;
    margin: 0 0 2px;
    /* Gana a las variables del rediseño (10 px en mayúsculas). */
    font: 700 14px/20px 'Inter', sans-serif !important;
    letter-spacing: 0 !important;
    text-transform: none;
    color: var(--ncr-tinta);
  }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-nci-on :is(#ncPane-indicadores, #inspPane-indicadores, #capregPane-indicadores, #capregPane-mios, #gsigPane-indicadores) .kpi-sublabel {
    grid-column: 1;
    grid-row: 2;
    line-height: 17px;
    color: var(--ncr-gris);
  }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-nci-on :is(#ncPane-indicadores, #inspPane-indicadores, #capregPane-indicadores, #capregPane-mios, #gsigPane-indicadores) .kpi-meta-footer {
    grid-column: 1 / -1;
    grid-row: 3;
    justify-content: flex-start;
    gap: 6px 10px;
    /* Gana al margin-top:10px en línea. */
    margin: 8px 0 0 !important;
    /* Los dos ganan al pie del rediseño homogéneo (`padding:14px 0 0` y
       filete, con !important): era otra raya dentro de la fila. */
    padding: 0 !important;
    border: 0 !important;
    line-height: 17px;
  }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-nci-on :is(#ncPane-indicadores, #inspPane-indicadores, #capregPane-indicadores, #capregPane-mios, #gsigPane-indicadores) .kpi-meta-target {
    flex: 0 1 auto;
    white-space: normal;
    overflow: visible;
    color: var(--ncr-gris);
  }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig).mv-nci-on :is(#ncPane-indicadores, #inspPane-indicadores, #capregPane-indicadores, #capregPane-mios, #gsigPane-indicadores) .kpi-meta-status {
    padding: 2px 8px;
    border-radius: 6px;
  }

  /* Detalle: cada NC es una fila dentro de su tarjeta, no otra tarjeta (una
     tarjeta que contiene tarjetas es un contenedor). Sin caja celeste: la fila
     baja de ~275 a ~110 px y caben cinco por página. */
  html.mv .mv-ncr-caja-det { margin-top: 10px; }
  html.mv .mv-ncr-caja-det .mv-ncr-lista { gap: 0; }
  html.mv .mv-ncr-caja-det .mv-ncr {
    gap: 6px;
    padding: 12px 0;
    border: 0;
    border-top: 1px dashed var(--ncr-borde);
    border-radius: 0;
  }
  html.mv .mv-ncr-caja-det .mv-ncr:first-child { border-top: 0; padding-top: 2px; }
  html.mv .mv-ncr-caja-det .mv-ncr-cab { padding-bottom: 0; border-bottom: 0; }
  html.mv .mv-nci-dato {
    display: flex;
    flex-wrap: wrap;
    gap: 2px 14px;
    font-size: 13px;
    line-height: 18px;
    color: var(--ncr-tinta);
  }
  html.mv .mv-nci-dato .mv-ncr-lbl { margin-right: 4px; }
  /* El punto repite el texto de la acción correctiva: no informa solo. */
  html.mv .mv-nci-acc { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; }
  html.mv .mv-nci-acc::before {
    content: '';
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #E8A33D;
  }
  html.mv .mv-nci-acc-sin::before { background: #B4C2D2; }
  html.mv .mv-nci-acc-ok::before { background: #1F7A43; }

  /* ── Ventanas del motor de registros → hoja desde abajo ────────────────
     Alta de NC (.sigf-modal-ov), avisos del motor (.insp-dlg-ov) y firma y
     visor del adjunto (.sigp-ov). Hacen lo mismo que las familias de
     `modales.js`, pero por clase: estas ventanas rehacen su contenido con
     innerHTML en cada apertura y la marca data-mv-hoja-inf se perdería.
     Medido a 390 px antes: botones de 40, cierre ✕ de 27 de ancho, textos
     de 8,5 a 12 px, «✕ Cerrar» partido a una segunda línea.
     Solo con Control de NC a la vista: .sigf-modal-ov también es la ventana
     de avance, adicionales, fotos y documentos, e .insp-dlg-ov y .sigp-ov
     son del motor que usan los demás registros. */
  html.mv:has(#sec-calidad-nc.active) :is(.sigf-modal-ov, .insp-dlg-ov, .sigp-ov) {
    align-items: flex-end !important;
    justify-content: stretch !important;
    padding: 0 !important;
  }
  html.mv:has(#sec-calidad-nc.active) :is(.sigf-modal-ov > .sigf-modal-card, .insp-dlg-ov > .insp-dlg, .sigp-ov > .sigp-card) {
    position: relative;
    width: 100% !important;
    max-width: none !important;
    margin: 0 !important;
    max-height: 88dvh !important;
    overflow-y: auto !important;
    overscroll-behavior: contain;
    border-radius: 18px 18px 0 0 !important;
    padding-top: 20px !important;
    padding-bottom: calc(14px + env(safe-area-inset-bottom, 0px)) !important;
  }
  /* El asa, como en las demás hojas. */
  html.mv:has(#sec-calidad-nc.active) :is(.sigf-modal-ov > .sigf-modal-card, .insp-dlg-ov > .insp-dlg, .sigp-ov > .sigp-card)::before {
    content: '';
    position: absolute;
    top: 7px;
    left: 50%;
    transform: translateX(-50%);
    width: 38px;
    height: 4px;
    border-radius: 2px;
    background: rgba(127, 127, 127, .32);
    pointer-events: none;
  }

  /* El pie del alta es sticky (bottom:0) y se pega al borde del relleno,
     no al de la hoja: en horizontal, con la hoja desplazando, el formulario
     asomaba 14 px por debajo de los botones. El relleno inferior pasa al pie. */
  html.mv:has(#sec-calidad-nc.active) .sigf-modal-ov > .sigf-modal-card:has(.ncc-f) { padding-bottom: 0 !important; }
  html.mv:has(#sec-calidad-nc.active) .ncc-f {
    padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px)) !important;
    border-radius: 0 !important;
  }
  /* El pie del aviso no era sticky: en horizontal, con diez campos faltantes,
     «Aceptar» quedaba 180 px bajo el borde. Mismo trato que el del alta. */
  html.mv:has(#sec-calidad-nc.active) .insp-dlg-ov > .insp-dlg:has(> .insp-dlg-pie) { padding-bottom: 0 !important; }
  html.mv:has(#sec-calidad-nc.active) .insp-dlg-ov .insp-dlg-pie {
    position: sticky;
    bottom: 0;
    z-index: 1;
    background: #fff;
    /* A todo el ancho de la hoja (16 px de relleno a cada lado) para tapar
       también los bordes de la lista que pasa por debajo. */
    margin-left: -16px;
    margin-right: -16px;
    padding: 14px 16px calc(14px + env(safe-area-inset-bottom, 0px));
  }

  /* Cierres de 44 × 44. */
  html.mv:has(#sec-calidad-nc.active) :is(.ncc-x, .insp-dlg-x) { min-width: 44px !important; min-height: 44px !important; }

  /* Pies: la acción principal a todo el ancho y primero; las demás debajo,
     a partes iguales. Botones de 46 como el resto de las hojas. */
  html.mv:has(#sec-calidad-nc.active) :is(.ncc-f, .sigp-f, .insp-dlg-pie) {
    display: flex !important;
    flex-wrap: wrap !important;
    gap: 9px !important;
  }
  html.mv:has(#sec-calidad-nc.active) :is(.ncc-f, .sigp-f) > :is(span, .sp) { display: none !important; }
  html.mv:has(#sec-calidad-nc.active) :is(.ncc-f, .sigp-f) > .rfi-btn,
  html.mv:has(#sec-calidad-nc.active) .insp-dlg-pie > .insp-dlg-btn {
    flex: 1 1 0 !important;
    min-width: 0;
    min-height: 46px !important;
    white-space: nowrap;
    font-size: 14px !important;
  }
  html.mv:has(#sec-calidad-nc.active) :is(.ncc-x, .insp-dlg-x) { font-size: 13px !important; }
  html.mv:has(#sec-calidad-nc.active) :is(.ncc-f, .sigp-f) > .rfi-btn-primary,
  html.mv:has(#sec-calidad-nc.active) .insp-dlg-pie > .insp-dlg-btn.prim {
    order: -1;
    flex-basis: 100% !important;
  }

  /* Aviso del motor: título y conteo a la izquierda, «Cerrar» a la derecha,
     sin partirse. El membrete del formato (logo, título y código a 8,5 px)
     no ayuda en un aviso de teléfono: se esconde, como en el registro. */
  html.mv:has(#sec-calidad-nc.active) .insp-dlg-tb {
    display: grid !important;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 12px;
    row-gap: 6px;
    align-items: center;
  }
  html.mv:has(#sec-calidad-nc.active) .insp-dlg-tb > .insp-dlg-tt { grid-column: 1; }
  html.mv:has(#sec-calidad-nc.active) .insp-dlg-tb > .insp-dlg-badge { grid-column: 1; justify-self: start; }
  html.mv:has(#sec-calidad-nc.active) .insp-dlg-tb > .sp { display: none; }
  html.mv:has(#sec-calidad-nc.active) .insp-dlg-tb > .insp-dlg-x { grid-column: 2; grid-row: 1 / span 2; }
  html.mv:has(#sec-calidad-nc.active) .insp-dlg-cab { display: none !important; }

  /* Letra: 12,5 como mínimo en rótulos y 16 en campos. */
  html.mv:has(#sec-calidad-nc.active) :is(.insp-dlg-badge, .insp-dlg-bar, .nc-lbl, .nc-step-n, .sigp-h span) { font-size: 12.5px !important; }
  html.mv:has(#sec-calidad-nc.active) :is(.insp-dlg-aviso, .sigp-aviso, .sigp-hint, .ncc-b small) { font-size: 13px !important; line-height: 1.45 !important; }
  html.mv:has(#sec-calidad-nc.active) .nc-step-n { min-width: 24px; height: 24px; }
  html.mv:has(#sec-calidad-nc.active) :is(.sigf-modal-card, .insp-dlg, .sigp-card) :is(input:not([type=checkbox]):not([type=radio]), select, textarea) { font-size: 16px !important; }

  /* En horizontal la hoja tiene ~340 px: el pie va en una sola fila y el
     panel de firma baja su lienzo a 120 y esconde la indicación. Medido a
     844 × 390: Firmar, Limpiar y Cancelar quedaban por debajo del borde. */
  @media (max-height: 500px) {
    html.mv:has(#sec-calidad-nc.active) :is(.ncc-f, .sigp-f) > .rfi-btn-primary,
    html.mv:has(#sec-calidad-nc.active) .insp-dlg-pie > .insp-dlg-btn.prim { order: 0; flex-basis: 0 !important; }
    html.mv:has(#sec-calidad-nc.active) .sigp-ov .sigp-pad canvas { height: 120px !important; }
    html.mv:has(#sec-calidad-nc.active) .sigp-ov .sigp-hint { display: none !important; }
    html.mv:has(#sec-calidad-nc.active) .sigp-ov .sigp-aviso { margin: 6px 0 8px !important; padding: 8px 12px !important; }
  }

  /* ══════════════════════════════════════════════════════════════════════
     TRAÍDO DE `movil/armazon-nativo` TAL CUAL (estilos.css:2008-2160).
     Al injertar el armazón sobre el rediseño se dejó fuera el Acceso dando
     por hecho que el rediseño ya lo tenía resuelto. No lo tiene: medido a
     390 px, el overlay se pinta con `zoom: .82` y la tarjeta sale a 156 px
     de los 390 —el 40 % de la pantalla, con 117 px muertos a cada lado—,
     el titular parte en cuatro líneas y los campos se quedan en 36 de alto.
     Las clases no cambiaron con el rediseño, así que el bloque entra sin
     tocar una línea.
     ══════════════════════════════════════════════════════════════════════ */
  /* ═══════════════════════════════════════════════════════════════
     ACCESO  ·  la primera pantalla que ve cualquiera
     ───────────────────────────────────────────────────────────────
     Sin `html.mv` a propósito: el acceso se pinta ANTES de que exista
     el armazón, así que no puede depender de que este haya montado.
     Todo el archivo ya vive bajo @media(max-width:900px).
     ═══════════════════════════════════════════════════════════════ */

  /* EL ARREGLO DE FONDO. El acceso se encoge a sí mismo según el ALTO del
     viewport —`zoom: var(--fit)`, que baja hasta .52— para caber sin scroll
     en portátiles bajos. En un teléfono eso es exactamente lo contrario de
     lo que hace falta: encoge el texto hasta un 48 %, deja márgenes
     laterales enormes y baja los campos por debajo de 16 px, que es el
     umbral donde iOS hace zoom al enfocar y descuadra la maqueta.
     Un teléfono desplaza. No hay nada que encoger. */
  .login-overlay,
  .loading-overlay {
    /* SIN FUNDIDO. El overlay entra con `animation: loginFadeIn .35s`, que
       sube la opacidad de 0 a 1: durante ese tercio de segundo la aplicación
       que hay DETRÁS —cabecera de escritorio y Resumen— se lee a través del
       formulario, y en un teléfono, que pinta más lento, da tiempo de sobra a
       verlo. El acceso es la primera pantalla: tiene que estar opaca en el
       primer fotograma, no aparecer. */
    animation: none !important;

    --fit: 1 !important;
    zoom: 1 !important;
    width: 100% !important;
    height: auto !important;
    min-height: 100dvh !important;
    align-items: stretch !important;
    padding: 0 !important;
  }

  /* La foto de obra se va: en vertical roba el alto que necesita el
     formulario, y la marca ya está dentro de la tarjeta. */
  .login-overlay .login-right { display: none !important; }
  .login-overlay .login-left {
    width: 100% !important;
    max-width: none !important;
    flex: 1 1 auto !important;
    padding: 0 !important;
  }

  /* La tarjeta ES la pantalla: sin ancho máximo, sin sombra flotante y sin
     esquinas redondeadas contra el borde. Deja de parecer un recorte
     centrado en un fondo vacío. */
  .login-overlay .login-card {
    width: 100% !important;
    max-width: none !important;
    margin: 0 !important;
    min-height: 100dvh !important;
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    /* Arriba, 44 + la zona segura: con viewport-fit=cover la tarjeta llega a
       la muesca y a la barra de estado, y en un iPhone real el logo quedaba
       pegado al borde (en el emulador la zona segura es 0 y no se veía). */
    padding: calc(44px + env(safe-area-inset-top, 0px)) 20px calc(24px + env(safe-area-inset-bottom, 0px)) !important;
    display: flex !important;
    flex-direction: column !important;
  }

  /* El logo es un <img> sin ancho propio, así que se estiraba a los 350 px de
     la tarjeta: el doble de grande que el titular. Se acota por ancho y la
     altura sale de su proporción. */
  .login-overlay .login-brand-logo {
    display: block !important;
    width: auto !important;
    max-width: 178px !important;
    height: auto !important;
    margin: 0 0 26px !important;
  }

  /* «¡Bienvenido a ESPARQ NOVA!» partía en tres líneas a 28 px. */
  .login-overlay .login-title {
    font-size: 25px !important;
    line-height: 1.2 !important;
  }
  .login-overlay .login-sub { font-size: 14px !important; margin-top: 7px !important; }

  /* El subtítulo quedaba pegado a «USUARIO»: 4 px entre uno y otro. */
  .login-overlay .login-form { margin-top: 22px !important; }
  .login-overlay .login-field { margin-top: 17px !important; }
  .login-overlay .login-field:first-child { margin-top: 0 !important; }

  /* La etiqueta y «¿Olvidaste tu contraseña?» compartían línea y se
     apretaban. Con wrap, el enlace baja solo cuando no cabe. */
  .login-overlay .login-field-head {
    display: flex !important;
    flex-wrap: wrap !important;
    align-items: baseline !important;
    gap: 4px 12px !important;
  }
  .login-overlay .login-forgot { font-size: 13px !important; }

  /* 16 px o iOS hace zoom al enfocar. 52 de alto para el pulgar.
     Va a TODOS los controles del overlay, no solo a `.login-field input`: la
     misma tarjeta sirve tres pantallas —acceso, recuperar contraseña y
     solicitar acceso— y las otras dos usan `.rec-vista`, donde los campos se
     quedaban en 41 px. Se comprobó recorriendo el flujo entero. */
  .login-overlay input:not([type="checkbox"]):not([type="radio"]),
  .login-overlay select {
    font-size: 16px !important;
    min-height: 52px !important;
    border-radius: 13px !important;
  }
  .login-overlay textarea {
    font-size: 16px !important;
    min-height: 84px !important;
    border-radius: 13px !important;
  }
  .login-overlay .login-input-wrap { position: relative !important; }
  .login-overlay .login-eye {
    min-width: 44px !important;
    min-height: 44px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
  }

  /* «Mantener la sesión iniciada» salía en dos líneas. */
  .login-overlay .login-options { margin-top: 16px !important; }
  .login-overlay .login-remember {
    display: flex !important;
    align-items: center !important;
    gap: 10px !important;
    font-size: 14px !important;
    line-height: 1.35 !important;
    min-height: 44px !important;
  }
  .login-overlay .login-remember input[type="checkbox"] {
    width: 20px !important;
    height: 20px !important;
    min-height: 0 !important;
    flex: 0 0 20px !important;
  }

  /* El botón principal a ancho completo: es la acción de la pantalla. */
  .login-overlay .login-btn {
    width: 100% !important;
    min-height: 52px !important;
    border-radius: 13px !important;
    font-size: 15.5px !important;
    font-weight: 700 !important;
    margin-top: 20px !important;
  }

  .login-overlay .login-nota {
    margin-top: 18px !important;
    font-size: 13.5px !important;
    line-height: 1.5 !important;
  }

  /* El pie al final de verdad, no flotando en mitad del hueco. */
  .login-overlay .login-footer {
    margin-top: auto !important;
    padding-top: 26px !important;
    font-size: 12px !important;
    line-height: 1.5 !important;
  }

  /* ── R-445 · textos centrados (pedido del cliente, Telegram 25-sep) ──────
     Logo, bienvenida, subtítulo, «¿No tienes acceso?» y pie van al centro.
     El formulario ya ocupa todo el ancho: queda centrado como bloque y sus
     etiquetas siguen a la izquierda de cada campo, como en el Figma.
     Heredar no basta para el título y el subtítulo: la hoja de escritorio
     (index.html) les pone text-align:left propio con !important; esta capa
     carga después, así que a igual peso gana. */
  .login-overlay .login-card { text-align: center !important; }
  .login-overlay .login-title,
  .login-overlay .login-sub { text-align: center !important; }
  .login-overlay .login-brand-logo { margin: 0 auto 26px !important; }
  .login-overlay .login-form,
  .login-overlay .rec-vista { text-align: left !important; }
  .login-overlay .sol-pie,
  .login-overlay .login-footer { text-align: center !important; align-items: center !important; }

  /* ── Panel de Operaciones · las tablas de indicadores ──────────────────
     Dos rejillas de CINCO columnas fijas —200+160+220+180+140 = 900 px—
     metidas en una caja de 326 con `overflow-x: auto`. En el teléfono eso es
     un carril horizontal dentro de una página que ya se desplaza: el pulgar
     no sabe cuál mueve, y lo que se ve es «63.29» sin el signo y «16.90»
     cortado por el borde.

     LAS DOS TABLAS NO TIENEN LAS MISMAS CLASES, y el primer intento lo dio
     por hecho: colocaba `.pz-ind/.pz-res/.pz-ctx/.pz-meta-t`, que sólo existen
     en la de adquisiciones. En la de frentes —`.pz-fr-n`, `.pz-bar`, `.pz-det`
     y un chevrón— los trozos se auto-colocaban y salían unos encima de otros:
     la barra tapando el nombre y la cápsula de estado sobre el detalle.

     Así que la regla es al revés: TODO ocupa el ancho salvo lo que se nombra
     para la primera línea. Lo que venga nuevo cae apilado, que es lo correcto
     por defecto en un teléfono. */
  html.mv .pz-tabla {
    display: block !important;
    overflow-x: visible !important;
    width: auto !important;
  }
  /* La cabecera de columnas se retira: con una fila por indicador, «Resultado»
     o «Meta» delante de su valor sobran.
     `.pz-tr.pz-th` y no `.pz-th` a secas: la cabecera TAMBIÉN es `.pz-tr`, y
     con la misma puntuación ganaba la regla de abajo por ir después. Salió a
     la vista, con sus cuatro rótulos apilados sobre el contenido. */
  html.mv .pz-tabla > .pz-tr.pz-th { display: none !important; }
  html.mv .pz-tabla > .pz-tr {
    display: grid !important;
    grid-template-columns: minmax(0, 1fr) auto !important;
    gap: 6px 10px !important;
    /* 100 % y no `auto`. Con `auto` las filas no se estiraban y cada una
       medía lo suyo —303, 228 y 319 en la misma tabla de 326—, así que la
       cápsula de estado, aunque va pegada al borde DE SU FILA, caía a una
       altura distinta en cada una y la columna se veía en zigzag. Medido:
       con `width: 100%` las tres pasan a 326 y los estados quedan a plomo. */
    width: 100% !important;
    min-width: 0 !important;
    padding: 13px 0 !important;
    align-items: center !important;
  }
  html.mv .pz-tabla > .pz-tr + .pz-tr { border-top: 1px solid var(--mv-borde) !important; }
  /* Por defecto, cada trozo a todo el ancho y en su propia línea. */
  html.mv .pz-tabla > .pz-tr > * {
    grid-column: 1 / -1 !important;
    min-width: 0 !important;
    width: auto !important;
  }
  /* La excepción: el nombre y su estado comparten la primera línea. El estado
     es el único `span` sin clase de la fila, en las dos tablas. */
  html.mv .pz-tabla > .pz-tr > .pz-ind,
  html.mv .pz-tabla > .pz-tr > .pz-fr-n {
    grid-column: 1 !important;
    grid-row: 1 !important;
  }
  html.mv .pz-tabla > .pz-tr > span:not([class]) {
    grid-column: 2 !important;
    grid-row: 1 !important;
    justify-self: end !important;
  }
  /* El chevrón se va al final, a la derecha: apilado no señala una columna. */
  html.mv .pz-tabla > .pz-tr > img {
    grid-column: 2 !important;
    justify-self: end !important;
  }
  html.mv .pz-tabla .pz-ctx,
  html.mv .pz-tabla .pz-det,
  html.mv .pz-tabla .pz-meta-t { font-size: 12.5px !important; line-height: 1.45 !important; }

  /* ── La pantalla de carga NO es el acceso ──────────────────────────────
     El bloque de arriba trata a `.login-overlay` y a `.loading-overlay` por
     igual: la tarjeta ES la pantalla, a ras de borde y sin esquinas. Para el
     acceso está bien —se escribe en él—, pero la carga es un rótulo de paso,
     y así salía a 390 px pegada a los dos bordes CONSERVANDO su radio de 24 y
     sus 44 px de relleno lateral: una tarjeta con las esquinas cortadas por
     la pantalla, que es justo lo que se veía raro.

     Vuelve a ser tarjeta: centrada, con aire a los lados y su sombra. Y el
     relleno baja de 44 a 22, que en 390 px de ancho es casi una cuarta parte
     de la pantalla en margen interior. */
  html.mv .loading-overlay {
    align-items: center !important;
    justify-content: center !important;
    padding: 24px 16px !important;
  }
  html.mv .loading-overlay .loading-card {
    width: 100% !important;
    max-width: 360px !important;
    min-height: 0 !important;
    margin: 0 !important;
    padding: 32px 22px 26px !important;
    border-radius: 22px !important;
    box-shadow: 0 18px 40px -22px rgba(10, 25, 45, .35) !important;
  }

  /* ── «Cargar Panel Fotográfico» · los dos campos de la semana ───────────
     `.sem-input-row` pone «Semana del proyecto» y «Fecha de la semana» lado a
     lado: dos campos de 185 son 459 en una caja de 340, así que el segundo
     quedaba cortado por el borde y la hoja salía con barra horizontal.
     Medido: `.modal-body` con 483 de contenido en 388 de caja.
     En el teléfono se apilan; cada campo mantiene su rótulo y su ancho. */
  html.mv .sem-input-row {
    display: grid !important;
    grid-template-columns: minmax(0, 1fr) !important;
    gap: 12px !important;
    overflow: visible !important;
  }
  html.mv .sem-input {
    width: auto !important;
    min-width: 0 !important;
    max-width: none !important;
  }

  /* ── Cronograma meta · el contenido a la anchura de su pestaña ──────────
     Entre la tarjeta de pestañas y el contenido hay un `div` sin clase con
     16 px de margen a cada lado: las pestañas van de 16 a 374 y lo que abren,
     de 32 a 358. Treinta y dos píxeles de aire que sólo se ven como un
     escalón. El panel pasa a ocupar el ancho de su pestaña. */
  html.mv .mv-crono .crof-card-tabs > div {
    margin-left: 0 !important;
    margin-right: 0 !important;
  }

  /* El segmentado «Tabla / Gantt» medía 139 de 326 y quedaba encogido a la
     izquierda como si fuera un control suelto. Ocupa el ancho y reparte: dos
     mitades, que es lo que es. */
  html.mv .mv-crono .cm-toggle {
    display: flex !important;
    width: 100% !important;
  }
  html.mv .mv-crono .cm-toggle > * {
    flex: 1 1 0 !important;
    min-width: 0 !important;
    min-height: 44px !important;
    justify-content: center !important;
  }

  /* ── Los botones de exportar, homologados ──────────────────────────────
     Cada vista trae el suyo con su propia clase —`.mof-excel`, `.cm-excel`,
     el de Inspecciones— y su propio dibujo: uno verde sólido, otro con filete,
     otro flotando a la derecha de una cabecera. En el teléfono se leen como
     tres controles distintos que hacen lo mismo.

     Medido en Mano de Obra: 58 px de ancho colgando a la derecha de una
     cabecera de 326 en `space-between`, encima de una tabla que ya se
     desplaza sola. Un botón de 58 al lado de un título largo no es una
     acción, es un adorno.

     Pasan a línea propia y ancho completo, debajo de su cabecera. Se
     seleccionan por el trozo de clase, que es lo único que comparten. */
  html.mv *:has(> button[class*="excel"]),
  html.mv *:has(> a[class*="excel"]) {
    flex-wrap: wrap !important;
  }
  html.mv button[class*="excel"],
  html.mv a[class*="excel"] {
    flex: 1 0 100% !important;
    width: 100% !important;
    min-height: 44px !important;
    margin: 10px 0 0 !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
  }

  /* ── RFI / SIG · el resumen de seguimiento ─────────────────────────────
     Es una barra apilada de cuatro tramos proporcionales, y cada tramo lleva
     su rótulo DEBAJO DE SU TROZO. Medido: el primer tramo ocupa 153 px y los
     otros tres 51 cada uno, pero sus rótulos miden 87. Tres etiquetas de 87
     en tres huecos de 51 se montan unas sobre otras: «1 respondida», «1 de la
     obra» y «1 colaborador» salían encabalgadas e ilegibles.

     A 314 px de ancho una barra apilada de cuatro tramos ya no se lee como
     proporción —el 16,7 % son 51 px—, así que deja de intentarlo: cada tramo
     pasa a su propia casilla con su barra y su rótulo completo, dos por
     línea. El porcentaje sigue escrito en cada uno. */
  html.mv .rfi-resumen-barra {
    display: grid !important;
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    gap: 10px !important;
  }
  html.mv .rfi-tramo {
    display: flex !important;
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 5px !important;
    min-width: 0 !important;
    width: auto !important;
  }
  html.mv .rfi-tramo-b { width: 100% !important; }
  html.mv .rfi-tramo-l {
    position: static !important;
    width: auto !important;
    max-width: none !important;
    white-space: normal !important;
    font-size: 12.5px !important;
    line-height: 1.35 !important;
    text-align: left !important;
  }

  /* ── RFI / SIG · la lista atrapada y su barra de filtros ───────────────
     LA LISTA NO SE VEÍA. El propio JS calcula un alto para la sección y lo
     escribe en línea —`--rfi-alto: 320px`— y la hoja de escritorio la fija
     con `height: var(--rfi-alto)` y `display:flex`: en escritorio tiene
     sentido, la lista desplaza dentro de su caja. En el teléfono no: la
     sección medía 320 con 1.783 px de contenido, así que los seis registros
     estaban compuestos —seis tarjetas de 346×163— pero pintados fuera de la
     caja. Se veía «Mostrando 6 de 6 registros» encima de la barra de abajo y
     ni un registro.

     En el teléfono la sección crece y desplaza la página, como el resto. */
  html.mv #sec-rfis.active {
    height: auto !important;
    min-height: 0 !important;
    display: block !important;
  }

  /* LA BARRA DE FILTROS. Dos desplegables de 176 en una fila de 346 que no
     envuelve: 352 no caben en 346, así que el texto salía cortado —«Todos los
     estadosB», «Importar / Exporta»—. Cada uno a su línea y a todo el ancho;
     las dos acciones comparten la suya, que es lo que son. */
  /* Y LA TABLA ORIGINAL, QUE SEGUÍA AHÍ. `listas.js` compone las seis fichas
     pero no acierta a ocultar la caja que reemplaza, así que la tabla de
     escritorio —900×347— quedaba debajo con sus celdas apretadas a 8 px de
     ancho. No se veía sólo porque la sección medía 320 y la recortaba; al
     dejarla crecer salió a la luz. Compuesta la lista, la tabla sobra. */
  html.mv #sec-rfis:has(.mv-registros) .rfi-table-wrap { display: none !important; }

  html.mv #sec-rfis *:has(> .rfi-sel) { flex-wrap: wrap !important; }
  html.mv #sec-rfis .rfi-sel {
    flex: 1 0 100% !important;
    width: 100% !important;
    min-width: 0 !important;
    max-width: none !important;
  }
  html.mv #sec-rfis .rfi-pub,
  html.mv #sec-rfis .rfi-crear {
    flex: 1 1 0 !important;
    min-width: 0 !important;
    min-height: 44px !important;
    justify-content: center !important;
  }

  /* ── APU's · una hoja que SE EDITA ─────────────────────────────────────
     Aquí no se reconstruye en fichas, y es a propósito. `hojas.js` la reclama
     por su id y después la rechaza —su lector exige `inputs.length === 0`— y
     hace bien: la tabla tiene 50 campos editables, y convertir eso en
     tarjetas de solo lectura sería quitar la función de la vista. Como
     `atiende` significa propiedad, el comodín tampoco entra: la vista se
     quedaba sin nadie, con cero reglas móviles.

     Se trata EN SITIO, que es lo que pide una tabla editable: ocho columnas
     —código, recurso, unidad, cuadrilla, cantidad, precio, parcial y la
     acción— suman 820 px y su caja mide 358. El carril horizontal se queda,
     porque es el único sitio de la aplicación donde se justifica: se está
     rellenando una hoja de cálculo, no leyendo una lista.

     LO QUE SE ARREGLA es poder orientarse dentro de él. */

  /* El código se queda fijo: sin él, desplazando a la derecha no se sabe qué
     recurso se está editando. */
  html.mv #sec-apus .apuf-t thead th:first-child,
  html.mv #sec-apus .apuf-t tbody td:first-child {
    position: sticky !important;
    left: 0 !important;
    z-index: 3 !important;
    background: var(--mv-papel, #fff) !important;
    box-shadow: 1px 0 0 var(--mv-borde, #E3EAF2), 3px 0 7px rgba(0, 0, 0, .05) !important;
  }
  html.mv #sec-apus .apuf-t thead th:first-child { z-index: 4 !important; }

  /* El botón de quitar fila medía 28 de ancho: por debajo del mínimo táctil,
     y es el único destructivo de la tabla. */
  html.mv #sec-apus .apuf-quitar {
    min-width: 44px !important;
    min-height: 44px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
  }

  /* Que se note que hay más a la derecha, y que el gesto no arrastre la
     página al llegar al final. */
  html.mv #sec-apus .apuf-tabla-card {
    overscroll-behavior-x: contain !important;
    -webkit-overflow-scrolling: touch !important;
  }

  /* ── Reporte Gerencial · lo que no se lee en la mano ───────────────────
     La vista ya está sana —sin desborde, sin textos cortados y sin toques por
     debajo de 44— y lo que quedaba era densidad: 60 textos por debajo de
     12,5 px. Contados por clase, los de VERDAD ilegibles son los de 10: el
     rótulo de cada cifra, su nota, la etiqueta de la barra de hitos y el chip
     de brecha. Veintiocho elementos.

     Los de 11 y 12 se dejan, como en Programación meta: son el tamaño de
     apoyo de esta vista y subirlos todos la estira sin ganar legibilidad. */
  html.mv #sec-reporte .rg3-lbl,
  html.mv #sec-reporte .rg3-tab,
  html.mv #sec-reporte .rg3-chip,
  html.mv #sec-reporte .c { font-size: 12.5px !important; line-height: 1.4 !important; }

  /* ══════════════════════════════════════════════════════════════════════
     PANEL DE CALIDAD · el lenguaje del Resumen, en el teléfono
     ──────────────────────────────────────────────────────────────────────
     Antes (390 px, con sesión): `panel.js` lo reconstruía, tapaba la curva
     del SIG y dejaba las 16 tarjetas de escritorio apiladas. 5.169 px, seis
     pantallas; 101 textos por debajo de 12,5 y los cinco botones de 36.

     Ahora se enriquece en sitio (panel.js lo suelta) con las MISMAS piezas
     del Resumen: cabecera de la obra, tarjeta con la curva y sus tres
     lecturas en filas, y cada sección con sus cuatro `.r-kpi` en el carril
     de Control de operaciones —mismo asomo, mismo encaje, mismo hueco—.
     Nada se quita: cada cifra sigue en pantalla.

     Cascada: las reglas de index.html van con `#sec-panel-calidad` delante
     y varias con `!important` (se nombra en cada caso). Aquí gana
     `html.mv #sec-panel-calidad`: una clase y un id más.
     ══════════════════════════════════════════════════════════════════════ */

  /* ── Cabecera de la obra ── */
  /* El kicker iba a 10 px (index.html, `.pcz-kick` con !important). */
  html.mv #sec-panel-calidad .pcz-kick { font-size: 12.5px !important; line-height: 15px !important; }
  html.mv #sec-panel-calidad .pcz-title { font-size: 26px; line-height: 31px; }

  /* ── Curva del SIG y tres lecturas: una columna ──
     Escritorio ya la parte por debajo de su @media, pero deja la curva a
     flex-basis 320 y la columna de lecturas a 300 con 28 de hueco: en 358
     px quedaban lado a lado a medias. En el teléfono, curva arriba y las
     lecturas debajo en filas con filete, como las del Resumen. */
  /* `align-items: flex-start` viene del @media de escritorio: en columna
     encogía las lecturas a 235 de los 330 px de la tarjeta. */
  html.mv #sec-panel-calidad .pcz-top {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 14px 14px 4px;
    min-height: 0;
  }
  html.mv #sec-panel-calidad .pcz-curva { flex: none; padding: 0; }
  /* La regla general `html.mv .rhc-svg, .rhc-svg svg` (arriba, con
     !important) da 200 px a toda curva. Esta se dibuja con
     preserveAspectRatio «meet»: no se estira, se centra, y dejaba 82 px de
     aire mudo (118 de dibujo en una caja de 200). Aquí la curva mide lo
     que dibuja. */
  html.mv #sec-panel-calidad .pcz-curva-svg,
  html.mv #sec-panel-calidad .pcz-curva-svg svg { height: auto !important; min-height: 0 !important; }
  /* Las marcas de los ejes (78 · 89 · 100 y las dos fechas) salían a 8 y
     8,5 px: el dibujo es de 330 unidades y a 390 se pinta a escala 1. El
     `font-size` de CSS gana al atributo de presentación del <text>. */
  html.mv #sec-panel-calidad .pcz-curva-svg text { font-size: 11px; }
  /* El delta frente a la meta («+10 pp») iba a 10 px. */
  html.mv #sec-panel-calidad .pcz-curva-cmp b:is(.bad, .warn, .ok) { font-size: 12px; line-height: 15px; }
  /* `.pcz-proy` fija flex-basis de 332 px y `!important` en display y gap. */
  html.mv #sec-panel-calidad .pcz-proy {
    flex: none !important;
    margin-top: 8px;
    border-top: 1px solid #EDF1F6;
  }
  html.mv #sec-panel-calidad .pcz-proy .po-ins-i { padding: 12px 0 !important; }
  /* El rótulo de cada lectura iba a 10 px (`.po-ins-l` con !important). */
  html.mv #sec-panel-calidad .pcz-proy .po-ins-l { font-size: 12.5px !important; line-height: 15px !important; }

  /* ── Cabecera de cada sección ──
     Título, bajada y botón en una fila con `wrap`: a 390 partían en tres
     alturas distintas y en «SIG y capacitación» el segundo botón caía solo
     a una línea propia. Se apilan: título, bajada, y las acciones en su
     fila a partes iguales, cada una de 44. */
  html.mv #sec-panel-calidad .pcz-sec-h { flex-direction: column; align-items: stretch; gap: 4px; }
  html.mv #sec-panel-calidad .pcz-sec-der { gap: 8px; }
  html.mv #sec-panel-calidad .pcz-sec-der > span { flex: 1 1 100%; font-size: 12.5px; line-height: 16px; }
  /* index.html fija 32 de alto y 12 de letra: 36 medidos con el borde. */
  html.mv #sec-panel-calidad .pcz-sec-der .pc-ir {
    flex: 1 1 0;
    justify-content: center;
    height: 44px;
    font-size: 13px;
  }

  /* ── Los cuatro indicadores de cada sección: carril ──
     Cuatro `.r-kpi` apilados medían 1.150–1.200 px por sección. Es la misma
     pieza del carril de Control de operaciones del Resumen, y se desliza
     igual: el 22 % que asoma es la señal de que hay más.
     `.pcz-kpis` es rejilla en index.html y `unaColumna()` puede escribirle
     estilo en línea; por eso display y columnas van con !important. */
  html.mv #sec-panel-calidad .pcz-kpis {
    display: flex !important;
    grid-template-columns: none !important;
    gap: 10px !important;
    align-items: stretch !important;
    overflow-x: auto;
    scrollbar-width: none;
    padding: 2px 16px 8px !important;
    margin: 0 -16px !important;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: 16px;
    overscroll-behavior-x: contain;   /* no arrastra la página al llegar al final */
    -webkit-overflow-scrolling: touch;
  }
  html.mv #sec-panel-calidad .pcz-kpis::-webkit-scrollbar { width: 0; height: 0; }
  html.mv #sec-panel-calidad .pcz-kpis > .r-kpi {
    flex: 0 0 78% !important;
    max-width: 320px;
    min-width: 0;
    scroll-snap-align: start;
  }
  /* El rótulo de cada indicador iba a 10 px. */
  html.mv #sec-panel-calidad .pcz-kpis .r-kpi-label { font-size: 12.5px !important; line-height: 15px !important; }

  /* ══════════════════════════════════════════════════════════════════════
     CALIDAD · lo común a sus vistas (NC, Capacitaciones, Dossier, Gestión
     SIG, Equipos de medición, SAME)
     ══════════════════════════════════════════════════════════════════════ */

  /* Las pestañas medían 42: el rediseño homogéneo de Calidad les pone
     `min-height:0` con `:is(#sec-calidad-nc, …) .insp-cab-tabs .rfi-tab`,
     que por su id gana a `html.mv button{min-height:44px}`. Registro de
     Inspecciones se libraba (tiene su regla propia y no ese 0). */
  html.mv :is(#sec-calidad-nc, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig,
    #sec-calidad-equipos, #sec-sames) .insp-cab-tabs .rfi-tabs .rfi-tab { min-height: 44px; }

  /* Tres pestañas (Capacitaciones: 178 + 92 + 139 px de texto) no caben en
     326. `:where(html.mv .scroll-area *){min-width:0}` las dejaba encoger y
     el texto, sin partir, se montaba sobre la vecina. No se encogen: la tira
     ya se desliza (overflow-x:auto) y la que asoma cortada es la señal de
     que hay más, como en los carriles. */
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig,
    #sec-calidad-equipos, #sec-sames) .insp-cab-tabs :is(.rfi-tab, .sst-tab) { flex: none; }
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig,
    #sec-calidad-equipos, #sec-sames) .insp-cab-tabs :is(.rfi-tabs, .sst-tabs) { scrollbar-width: none; overscroll-behavior-x: contain; }

  /* La nota de Indicadores («En vivo desde…») pone 13 en la caja, pero su
     texto va en un <div> con 12 propio. */
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig) .ssoma-note > div,
  html.mv :is(#sec-calidad-nc, #sec-calidad-sig, #sec-calidad-cap, #sec-calidad-dossier, #sec-calidad-gestionsig) .ssoma-note > div b { font-size: 13px; }

  /* ══════════════════════════════════════════════════════════════════════
     STATUS DOSSIER · lista de semanas
     ──────────────────────────────────────────────────────────────────────
     La lista usa «Arquetipo R». Lo propio: el estado viene en .rfi-badge (el
     de RFI) y no en .insp-est; se le da la misma forma que al de las demás
     tarjetas. El título «Status del dossier 6» se oculta como en las demás
     listas (lo dice la cabecera), pero la nota de cómo se corrige se queda. */
  html.mv :is(#sec-calidad-dossier, #sec-calidad-gestionsig) .mv-ncr .rfi-badge {
    flex: 0 0 auto;
    padding: 3px 8px;
    border-radius: 4px;
    font: 700 12.5px/17px 'Inter', sans-serif;
    text-transform: uppercase;
  }
  html.mv :is(#sec-calidad-dossier, #sec-calidad-gestionsig).mv-ncr-on :is(#dossierRoot, #calFormRoot) .rfi-list-head { margin: 0 0 4px; }
  html.mv :is(#sec-calidad-dossier, #sec-calidad-gestionsig).mv-ncr-on :is(#dossierRoot, #calFormRoot) .dos-ro-note { font-size: 13px; line-height: 18px; color: var(--ncr-gris); }
  /* El delta frente a la semana anterior: verde si sube, rojo si baja, como
     en escritorio (.dos-comp-ok / .dos-comp-mal); sin clase, en gris.
     Gestión SIG usa la misma lista de semanas. */
  html.mv :is(#sec-calidad-dossier, #sec-calidad-gestionsig) .mv-dos-delta { font-size: 12.5px; font-weight: 600; color: var(--ncr-gris); }
  html.mv :is(#sec-calidad-dossier, #sec-calidad-gestionsig) .mv-dos-delta.dos-comp-ok { color: #1F7A43; }
  html.mv :is(#sec-calidad-dossier, #sec-calidad-gestionsig) .mv-dos-delta.dos-comp-mal { color: #B42318; }

  /* Gestión SIG · Indicadores: la leyenda de la gráfica iba a 11 y el botón
     «Ampliar gráfico» medía 38 de ancho. */
  html.mv #gsigPane-indicadores .cal-ley span { font-size: 12.5px; }
  html.mv #gsigPane-indicadores .chart-max-btn { min-width: 44px; }

  /* Acciones de una fila de detalle (Gestión SIG: «Abrir» la semana, el PDF):
     tocan el botón original. Píldora de borde, 44 de alto. */
  html.mv .mv-nci-acc-fila { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; }
  html.mv .mv-nci-accion {
    flex: 1 1 0;
    min-width: 0;
    height: 44px;
    padding: 0 14px;
    background: #E6F2FA;
    border: 1px solid var(--ncr-azul, #077FCF);
    border-radius: 50px;
    font: 500 14px/1 'Inter', sans-serif;
    color: var(--ncr-azul, #077FCF);
    cursor: pointer;
  }

  /* ══════════════════════════════════════════════════════════════════════
     CONTROL DE CAPACITACIONES · lo que no comparte con NC
     ──────────────────────────────────────────────────────────────────────
     Lista, Indicadores y el detalle usan «Arquetipo R» (extendido con :is).
     «Mis capacitaciones» es una tabla de solo lectura que va en
     .rfi-table-wrap (no en .table-wrap como el detalle de Indicadores): se
     oculta aquí cuando registros.js ya la pintó en filas. */
  html.mv #sec-calidad-cap.mv-nci-on #capregPane-mios .rfi-table-wrap:has(> .rfi-table) { display: none !important; }
  /* «Capacitación:» del filtro iba a 11,5 (en línea). */
  html.mv #sec-calidad-cap #capregPane-indicadores .insp-toolbar > span { font-size: 12.5px !important; }
  /* Sin la tabla, su cabecera de lista queda como título de la pestaña. */
  html.mv #sec-calidad-cap.mv-nci-on #capregPane-mios .rfi-list-head { margin: 0 0 4px; }

  /* ══════════════════════════════════════════════════════════════════════
     REGISTRO DE INSPECCIONES · lo que no comparte con Control de NC
     ──────────────────────────────────────────────────────────────────────
     La lista y los indicadores usan las reglas de «Arquetipo R» de arriba
     (extendidas con :is a #sec-calidad-sig): misma tarjeta, misma hoja de
     indicadores. Aquí solo lo que Inspecciones tiene y NC no.
     ══════════════════════════════════════════════════════════════════════ */

  /* Tres desplegables (categoría, registro, estado) donde NC tiene uno. Con
     la regla de NC —cada uno a su ancho, máx. 46 %— se partían en tres filas
     de alturas distintas. Buscador y estado en la primera fila, como en NC;
     categoría y registro debajo, a partes iguales y con su borde, porque son
     filtros que se eligen, no un ajuste. */
  /* Con base 0 los cuatro cabían en una línea: el buscador quedaba en 56 px
     y los dos desplegables en 50. Con base 140 el buscador empuja a los dos
     de filtro a la fila de abajo, donde se reparten a mitades. */
  html.mv #sec-calidad-sig.mv-ncr-on #inspBody .rfi-search { order: 0; flex: 1 1 140px; }
  html.mv #sec-calidad-sig.mv-ncr-on #inspBody .insp-sel:nth-of-type(3) { order: 1; }
  html.mv #sec-calidad-sig.mv-ncr-on #inspBody .insp-sel:is(:nth-of-type(1), :nth-of-type(2)) {
    order: 2;
    flex: 1 1 calc(50% - 6px);
    max-width: none !important;     /* gana al max-width en línea (280 px) */
    min-width: 0;
    padding: 0 30px 0 12px;
    background-color: #fff;
    background-position: right 10px center;
    border: 1px solid #7F8FA4;
    border-radius: 8px;
    text-align: left;
    text-overflow: ellipsis;
  }
  html.mv #sec-calidad-sig.mv-ncr-on #inspBody :is(#inspDraftBadge, .rfi-btn) { order: 3; }
  /* «Mostrando 9 de 9 registros» salía ENCIMA de la primera tarjeta (el pie
     va dentro de #inspBody y las tarjetas después) y contradecía la página
     de tres. La paginación de abajo ya dice cuántas hay. */
  html.mv #sec-calidad-sig.mv-ncr-on #inspBody .rfi-pie { display: none; }

  /* «TE TOCA»: en escritorio la fila lleva la franja roja y la etiqueta;
     la tarjeta, lo mismo. La franja va por dentro del borde (inset) para
     no mover el contenido. */
  html.mv .mv-ncr.mv-ncr-mio { box-shadow: inset 3px 0 0 #D92D20; background: #FFFAFA; }
  html.mv .mv-ncr .insp-te-toca { margin-left: 6px; font-size: 12.5px; vertical-align: 1px; }

  /* ═══════════════════════════════════════════════════════════════════════
     SAME · Estatus (SIG.002-F03)
     ═══════════════════════════════════════════════════════════════════════
     Medido a 390 px con ocho SAME sembradas: la pestaña de estatus traía DOS
     tablas más anchas que la pantalla —880 px la de especialidades y 1.528 la
     del estatus, de doce columnas— cada una con su propio desplazamiento
     lateral, tres pantallas de alto y 53 rótulos por debajo de 12,5.

     NO SE RECONSTRUYE EN FICHAS, y es a propósito. El SIG.002-F03 es un
     formato del cliente que se lee entero y se compara columna con columna; su
     propia bajada dice «se arma solo con los SAME registrados; no se edita
     aquí». Mismo criterio que APU's y Dimensionamiento: a un documento se le
     arregla poder orientarse dentro de él, no se le cambia la forma. */

  /* Las siete cifras iban apiladas: siete tarjetas para siete números gastaban
     más de una pantalla. En carril, con el 18 % de la siguiente asomando como
     señal de que hay más. Es el mismo carril de todas las vistas. */
  html.mv #sec-sames .sme-kpis {
    display: flex !important;
    flex-wrap: nowrap !important;
    gap: 10px !important;
    overflow-x: auto;
    scrollbar-width: none;
    padding: 2px 13px 8px;
    margin: 0 -13px 4px;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: 13px;
    overscroll-behavior-x: contain;
  }
  html.mv #sec-sames .sme-kpis::-webkit-scrollbar { width: 0; height: 0; }
  html.mv #sec-sames .sme-kpi {
    flex: 0 0 44% !important;
    max-width: 200px;
    min-width: 0;
    scroll-snap-align: start;
  }
  /* Subir la letra a 12,5 sin tocar el alto cortaba los siete rótulos por
     abajo: la caja seguía calculada para 11 px. Se mide, no se supone. */
  html.mv #sec-sames .sme-kpi span {
    font-size: 12.5px !important;
    line-height: 1.35 !important;
    height: auto !important;
    max-height: none !important;
  }

  /* La de especialidades son CUATRO columnas y un resumen, no un documento:
     esa sí se apila.

     `:not(:has(#smeRows))` NO sobra: sin él estas reglas alcanzaban también a
     la tabla de la lista de registros, y su `display:block` le ganaba al
     ocultado que le hace el comodín `listas`. Resultado medido: las ocho
     tarjetas Y la tabla a la vez, 3,1 pantallas en vez de 2,1. Una fila por especialidad, el nombre arriba y las tres
     cifras en cápsulas, que es como ya se leen en Panel de Operaciones. */
  html.mv #sec-sames .rfi-table-wrap:not(.sme-est-wrap):not(:has(#smeRows)) > table { min-width: 0 !important; }
  html.mv #sec-sames .rfi-table-wrap:not(.sme-est-wrap):not(:has(#smeRows)) thead { display: none; }
  html.mv #sec-sames .rfi-table-wrap:not(.sme-est-wrap):not(:has(#smeRows)) :is(table, tbody, tr) { display: block; width: 100%; }
  html.mv #sec-sames .rfi-table-wrap:not(.sme-est-wrap):not(:has(#smeRows)) tr {
    padding: 10px 0;
    border-bottom: 1px solid var(--mv-borde, #E3EAF2);
  }
  html.mv #sec-sames .rfi-table-wrap:not(.sme-est-wrap):not(:has(#smeRows)) tr:last-child { border-bottom: 0; }
  html.mv #sec-sames .rfi-table-wrap:not(.sme-est-wrap):not(:has(#smeRows)) td {
    display: inline-block;
    border: 0 !important;
    padding: 2px 10px 2px 0 !important;
    text-align: left !important;
  }
  /* La primera celda es el nombre y manda: fila propia y más peso. */
  html.mv #sec-sames .rfi-table-wrap:not(.sme-est-wrap):not(:has(#smeRows)) td:first-child {
    display: block;
    font-weight: 700;
    font-size: 14px;
    padding-bottom: 4px !important;
  }
  /* Las tres cifras llevan su rótulo delante, que estaba sólo en el <thead>
     que acabamos de ocultar: sin esto quedarían tres números sueltos. */
  html.mv #sec-sames .rfi-table-wrap:not(.sme-est-wrap):not(:has(#smeRows)) td:nth-child(2)::before { content: 'Presentadas '; }
  html.mv #sec-sames .rfi-table-wrap:not(.sme-est-wrap):not(:has(#smeRows)) td:nth-child(3)::before { content: 'Respondidas '; }
  html.mv #sec-sames .rfi-table-wrap:not(.sme-est-wrap):not(:has(#smeRows)) td:nth-child(4)::before { content: 'Esperando '; }
  html.mv #sec-sames .rfi-table-wrap:not(.sme-est-wrap):not(:has(#smeRows)) td:nth-child(n+2)::before {
    color: var(--mv-tenue, #8E9BAD);
    font-size: 12.5px;
    font-weight: 600;
  }

  /* El formato, en sitio. El ITEM se queda fijo al desplazar: sin él, llegando
     a la columna «Respuesta» —la duodécima— ya no se sabe de qué SAME es. */
  html.mv #sec-sames .sme-est-wrap {
    max-height: 62vh;
    overflow: auto;
    overscroll-behavior: contain;
  }
  html.mv #sec-sames .sme-est thead th:first-child,
  html.mv #sec-sames .sme-est tbody td:first-child {
    position: sticky !important;
    left: 0 !important;
    z-index: 3 !important;
    background: var(--mv-papel, #fff) !important;
    box-shadow: 1px 0 0 var(--mv-borde, #E3EAF2), 3px 0 7px rgba(0, 0, 0, .05) !important;
  }
  /* La cabecera se queda arriba mientras se recorre la hoja, por la misma
     razón que la primera columna se queda a la izquierda. */
  html.mv #sec-sames .sme-est thead th {
    position: sticky !important;
    top: 0 !important;
    z-index: 2 !important;
  }
  html.mv #sec-sames .sme-est thead th:first-child { z-index: 4 !important; }
  /* 10 y 11 px en una hoja que ya se lee con lupa. */
  html.mv #sec-sames .sme-est :is(th, td) { font-size: 12.5px !important; }
  /* La respuesta traía el comentario entero y estiraba la fila a lo alto. */
  html.mv #sec-sames .sme-est td.sme-rsp {
    max-width: 200px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* ═══════════════════════════════════════════════════════════════════════
     EQUIPOS DE MEDICIÓN · la hoja de una semana abierta (SIG.003-F01)
     ═══════════════════════════════════════════════════════════════════════
     Medido a 390 px sembrando tres semanas y seis equipos. La hoja son doce
     columnas con anchos fijos que suman 1.120 px, y arriba su cajetín.

     EN SITIO, no en fichas: es un formato del cliente, y su propio código dice
     que el dato se edita en el pop-up del equipo y no en la tabla. Mismo
     criterio que APU's, Dimensionamiento y el estatus de SAME. */

  /* El ítem se queda fijo: sin él, llegando a «Próxima calibración» ya no se
     sabe de qué equipo se está leyendo. */
  html.mv #sec-calidad-equipos #equmDocIn table tbody td:first-child,
  html.mv #sec-calidad-equipos #equmDocIn table thead th:first-child {
    position: sticky !important;
    left: 0 !important;
    z-index: 3 !important;
    background: var(--mv-papel, #fff) !important;
    box-shadow: 1px 0 0 var(--mv-borde, #E3EAF2), 3px 0 7px rgba(0, 0, 0, .05) !important;
  }
  html.mv #sec-calidad-equipos #equmDocIn table thead th { position: sticky !important; top: 0 !important; z-index: 2 !important; }
  html.mv #sec-calidad-equipos #equmDocIn table thead th:first-child { z-index: 4 !important; }
  /* Su propia ventana: dejándola crecer, la hoja estiraba la página entera. */
  html.mv #sec-calidad-equipos #equmDocIn {
    max-height: 62vh;
    overflow: auto;
    overscroll-behavior: contain;
  }
  html.mv #sec-calidad-equipos #equmDocIn :is(th, td) { font-size: 12.5px !important; }

  /* El semáforo son botones que FILTRAN la tabla: tienen que poder tocarse. */
  html.mv #sec-calidad-equipos .equm-chip {
    min-height: 44px !important;
    display: inline-flex !important;
    align-items: center !important;
    gap: 5px !important;
  }
  /* La alerta de calibración vencida es lo que no puede perderse de vista:
     un protocolo firmado con un equipo sin calibración vigente es un registro
     nulo, y lo dice la propia vista. */
  html.mv #sec-calidad-equipos .equm-alerta {
    font-size: 13px !important;
    line-height: 1.45 !important;
  }

  /* ═══════════════════════════════════════════════════════════════
     COMPONENTES COMUNES · lote 4 de la migración de la UI
     ═══════════════════════════════════════════════════════════════ */

  /* Excel del inyector (G06): 36 de alto en escritorio; en el teléfono,
     toque de 44. Avance no entra: su «Excel» va dentro de la cabecera de
     su tabla y es otra pieza. */
  html.mv :where(.section:not(#sec-avance)) .tbl-tools > .tbl-xlsx-btn { min-height: 44px; }

  /* Ampliar gráfica: medía 38 × 44 (la regla general sube el alto a 44 y
     el ancho se quedaba en 38): cuadrado de 44, que es un icono solo.
     Avance, que migra otro worker, queda como está. */
  html.mv :where(.section:not(#sec-avance)) .chart-max-btn { width: 44px; min-width: 44px; height: 44px; }

  /* «● sin publicar» a 11 px (index.html) → 12, el piso del teléfono (G04).
     Presupuestos ya lo hacía en su hoja; Avance queda fuera de este lote. */
  html.mv :where(.section:not(#sec-avance)) .rfi-draft-badge { font-size: 12px; }

  /* Confirmar y pedir nombre como hoja desde abajo (modales.js los marca).
     Antes, a 390: tarjeta centrada con márgenes, que dejaba ver la barra de
     pestañas por debajo. El pie, como el de las demás hojas: la acción
     principal primero y a todo el ancho, la otra debajo, 46 de alto; fijo
     abajo mientras el cuerpo desplaza. */
  html.mv :is(#adicCfOv, #drefNmOv) > [data-mv-hoja-inf="1"] {
    padding: 20px 16px 0 !important;
    overflow-y: auto !important;
  }
  html.mv :is(#adicCfOv, #drefNmOv) :is(.adic-nv-pie, .dref-nm-pie) {
    display: flex !important;
    flex-wrap: wrap !important;
    gap: 9px !important;
    position: sticky;
    bottom: 0;
    z-index: 1;
    background: var(--gray-1, #fff);
    margin: 14px -16px 0 !important;
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0px)) !important;
  }
  html.mv :is(#adicCfOv, #drefNmOv) :is(.adic-nv-pie, .dref-nm-pie) > button {
    flex: 1 1 0 !important;
    min-width: 0 !important;
    min-height: 46px !important;
    font-size: 14px !important;
    justify-content: center;
  }
  /* En los dos, la principal es el último botón («Confirmar», «Guardar»). */
  html.mv :is(#adicCfOv, #drefNmOv) :is(.adic-nv-pie, .dref-nm-pie) > button:last-child {
    order: -1;
    flex-basis: 100% !important;
  }
  /* Cierre de 44 × 44 (la ✕ de confirmar medía 27 de ancho). */
  html.mv #adicCfOv .adic-cf-tb .x { min-width: 44px !important; min-height: 44px !important; }

  /* Cuatro pestañas o más: dos por fila, todas a la vista (M06: pestañas
     visibles, sin carrusel). La regla de arriba (`flex: 1 0 auto`, sin
     partir) reparte bien dos o tres; con las cuatro de Avance —«Dashboard»,
     «Registro de avances», «Cronograma de ejecución», «Corte semanal»— a 390
     la tira se deslizaba y «Corte semanal» quedaba fuera de la pantalla.
     Gana a `#sec-avance .avf-tabs.presup-subtabs { display: flex;
     overflow-x: auto }` (avance.css) con !important: la hoja de la vista no
     lleva el suyo. Con tres o menos no cambia nada. */
  html.mv .presup-subtabs:has(> .presup-subtab ~ .presup-subtab ~ .presup-subtab ~ .presup-subtab) {
    display: grid !important;
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    overflow: visible !important;
  }
  html.mv .presup-subtabs:has(> .presup-subtab ~ .presup-subtab ~ .presup-subtab ~ .presup-subtab) > .presup-subtab {
    min-width: 0 !important;
    white-space: normal !important;
    text-align: center;
    line-height: 1.25 !important;
  }
}
