/* ANDAMIAJE DE LA PLATAFORMA — lo que NO es diseño de Edna.
   NO EDITAR pensando en estética: el color, la tipografía, el espaciado y los
   componentes salen de diseno/<negocio>.css, extraído de su maqueta.

   Aquí vive sólo lo que su maqueta no tiene porque no forma parte del producto
   que ella diseñó: la banda que distingue staging de producción, la hoja
   lateral de las fichas, la caja de la pantalla de entrar, los campos de
   formulario de las pantallas que construimos nosotros, y los avisos.

   SE RECONSTRUYÓ EL 16 OCT 2026 porque al cambiar a la hoja de Edna me quedé
   con 27 bloques y tiré el resto: desapareció .campo, .caja, .aviso, .rejilla-2
   y el reset de fieldset, así que la pantalla de entrar perdió su tarjeta y los
   formularios salieron con los bordes por omisión del navegador. Llegó a
   producción. El comparador no podía verlo: sólo compara clases que existen en
   las DOS partes, y estas son nuestras, no suyas. Por eso ahora hay una prueba
   que falla si una clase que usamos no está definida en ninguna hoja. */

/* ── PUENTE DE TOKENS ───────────────────────────────────────────────────────
   Las reglas de abajo venían de mi hoja anterior y usan SUS nombres de token
   (--line, --surface, --sans…). Esa hoja ya no existe: la de Edna nombra las
   mismas cosas distinto (--gris-borde, --blanco…), y además distinto entre
   negocios (--morado en PH, --marino en PMedic).

   El síntoma era desconcertante: las reglas SÍ aplicaban, pero
   `border:1px solid var(--line)` con --line indefinido se descarta entera, así
   que los campos de la pantalla de entrar salían invisibles. No faltaba la
   regla; faltaba el token.

   Esto los traduce. Cada negocio se cuelga de su propia paleta, y si Edna
   cambia un color, el andamiaje lo sigue sin tocar nada. */
:root{
  --sans:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
  --mono:ui-monospace,SFMono-Regular,Menlo,"Cascadia Mono",monospace;
  --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:24px; --sp-6:32px; --sp-7:48px;
  --r:var(--r-md,8px);
}
[data-negocio="ph"]{
  --ground:var(--gris-piedra); --surface:var(--blanco);
  --line:var(--gris-borde);    --line-soft:var(--realce,#F3F1EC);
  --ink:var(--morado);         --ink-2:var(--texto-suave); --ink-3:var(--texto-suave);
  --acento:var(--amarillo);    --acento-ink:var(--morado);
  /* El armazón NO redefine --acento-tinte: en PMedic ese nombre es de Edna y
     significa "la tinta que va SOBRE el lavanda" (#016377). Al redefinirlo como
     el lavanda mismo, su propia regla .card-accion{color:var(--acento-tinte)}
     pintaba lavanda sobre lavanda: la píldora «Editar» salía vacía, las
     insignias sin glifo y el aviso como una barra azul en blanco. El aviso,
     que es clase nuestra, usa tokens nuestros. */
  --aviso-fondo:var(--realce-fuerte,#F3E8F7); --aviso-ink:var(--morado,#2B1734);
  /* El menú lateral y la barra móvil son armazón nuestro montado sobre su
     paleta. Estos cinco tokens se usaban sin existir en ningún archivo, así que
     la declaración entera se descartaba: la barra móvil quedaba sin fondo y su
     título blanco sobre claro, ilegible. */
  --menu:var(--morado);            --menu-ink:rgba(255,255,255,.7);
  --menu-ink-fuerte:var(--blanco); --menu-activo:var(--amarillo);
  --menu-activo-ink:var(--morado);
  --ok:var(--verde); --ok-tinte:var(--realce,#EDF8D4); --ok-ink:var(--morado);
  --riesgo:var(--rojo); --foco:rgba(254,200,0,.3);
  --brand-filo:var(--amarillo); --lema-ink:var(--morado);
  /* EL ANILLO DE LA FILA NO ES EL ACENTO. Edna, 27 oct 2026: «mis selectores
     tienen una franja amarilla que no me gusta, solo es morado». El anillo de
     hover de las tablas clicables se dibujaba con `--acento`, que en PH es su
     amarillo —el de los botones primarios y el menú activo—, y encima del
     relleno morado quedaban dos marcas de color discutiendo. Su acento sigue
     siendo amarillo donde ella lo puso; lo que cambia es ESTE anillo. */
  --anillo-fila:var(--morado);
}
[data-negocio="pmedic"]{
  --ground:var(--gris-piedra); --surface:var(--blanco);
  --line:var(--gris-borde);    --line-soft:var(--lavanda);
  --ink:var(--marino);         --ink-2:var(--texto-suave); --ink-3:var(--texto-suave);
  --acento:var(--indigo);      --acento-ink:var(--blanco);
  --aviso-fondo:var(--lavanda);    --aviso-ink:var(--acento-tinte,#016377);
  --menu:var(--panel);             --menu-ink:rgba(255,255,255,.7);
  --menu-ink-fuerte:var(--blanco); --menu-activo:var(--lavanda);
  --menu-activo-ink:var(--marino);
  --ok:var(--turquesa); --ok-tinte:var(--lavanda); --ok-ink:var(--marino);
  --riesgo:var(--rojo); --foco:rgba(1,123,153,.28);
  --brand-filo:var(--lavanda); --lema-ink:var(--marino);
  /* PMedic conserva su acento como anillo: su turquesa sobre el lavanda del
     relleno no compite, y cambiarlo sería decidir el diseño de otro negocio. */
  --anillo-fila:var(--acento);
}



/* ── tipografía ─────────────────────────────────────────────────────── */
.mono{font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink-3)}

.linkb{background:none;border:0;color:var(--ink-3);cursor:pointer;font-family:var(--sans);
  font-size:13px;text-decoration:underline;padding:0}

.linkb:hover{color:var(--ink)}

.tabla .folio{font-family:var(--mono);font-size:11.5px;color:var(--ink-3);letter-spacing:.04em}


/* ── formularios ────────────────────────────────────────────────────── */
/* `align-content:start` NO es decoración: es lo que mantiene alineados dos
   campos lado a lado. `.campo` es una rejilla de renglones automáticos, y el
   valor por omisión —`stretch`— reparte el espacio sobrante entre esos
   renglones. Dos campos en el mismo renglón de `.rejilla-2` miden lo mismo de
   alto; si uno lleva nota de ayuda y el otro no, el que NO la lleva reparte
   esos píxeles entre su etiqueta y su control: el control crecía de 45 a 59 px
   y la etiqueta bajaba quince. Se veía exactamente como lo describió Fernando,
   «unprofessional», y la causa no estaba en ninguno de los dos campos sino en
   el valor por omisión de la rejilla. */
.campo{display:grid;align-content:start;gap:6px;margin-bottom:var(--sp-4)}

.campo label{font-size:13px;font-weight:600}

/* :not([type=checkbox]):not([type=radio]) — una casilla no es un campo de
   texto. Con width:100% y padding de 14px, la casilla «El servicio sigue
   activo» se estiraba a todo el ancho y empujaba su leyenda al otro extremo. */
.campo input:not([type="checkbox"]):not([type="radio"]),
.campo select,.campo textarea{font-family:var(--sans);font-size:16px;
  padding:12px 14px;border-radius:var(--r);border:1px solid var(--line);
  background:var(--surface);color:var(--ink);width:100%}
.campo input[type="checkbox"],.campo input[type="radio"]{width:16px;height:16px;
  flex:none;margin:0;accent-color:var(--acento)}

.campo input:focus,.campo select:focus,.campo textarea:focus{
  outline:0;border-color:var(--acento);box-shadow:0 0 0 3px var(--foco)}

.campo textarea{min-height:86px;resize:vertical;line-height:1.5}

.campo input[aria-invalid="true"]{border-color:var(--riesgo)}

fieldset{border:0;padding:0;margin:0 0 var(--sp-5)}

legend{font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink-3);padding:0;margin-bottom:var(--sp-3)}

.rejilla-2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 var(--sp-4)}

/* Base del aviso. Sólo existían las variantes de color, así que la banda salía
   sin relleno, a escuadra dentro de un diseño todo redondeado, y pegada a la
   tarjeta de abajo. El radio es el mismo de las tarjetas (--r-lg, 12px). */
.aviso{padding:11px 14px;border-radius:var(--r-lg,12px);font-size:13.5px;
  line-height:1.45;margin-bottom:var(--sp-4,16px)}

.aviso-mal{background:rgba(179,38,30,.08);color:var(--riesgo);border:1px solid var(--riesgo)}

.aviso-ok{background:var(--ok-tinte);color:var(--ok-ink);border:1px solid var(--ok)}

.aviso-ojo{background:var(--aviso-fondo);color:var(--aviso-ink);border:1px solid var(--acento)}

.pm-wordmark{font-size:23px;font-weight:700;letter-spacing:-.02em;color:var(--lema-ink);
  display:block;text-align:center;line-height:1}

.sidebar-rotulo{font-family:var(--mono);font-size:10px;font-weight:500;letter-spacing:.14em;
  text-transform:uppercase;color:rgba(255,255,255,.45);padding:var(--sp-3) 12px var(--sp-2)}

.nav-item .niv{flex:none;font-family:var(--mono);font-size:8.5px;letter-spacing:.1em;
  text-transform:uppercase;padding:2px 5px;border-radius:99px;
  background:rgba(255,255,255,.14);color:rgba(255,255,255,.75)}

.nav-item[aria-current="true"] .niv{background:rgba(0,0,0,.12);color:var(--menu-activo-ink)}

/* LA PÍLDORA DE NIVEL NO SE MUESTRA EN EL MENÚ. Edna vio los nombres cortados
   y midió por qué (su LEEME-M01-LISTA-Y-MENU.md trae la cuenta completa):

     .nav-item mide 208 y su relleno se come 24 → 184 para el contenido
     cada renglón pide: icono 18 + hueco 12 + texto + hueco 12 + píldora 22

     | Gestión de Clientes    | texto 136 | pide 200 | sobra 16 |
     | Mascotas y Expedientes | texto 169 | pide 233 | sobra 49 |
     | Agenda de Servicios    | texto 143 | pide 207 | sobra 23 |

   Con `white-space:nowrap`, lo que sobra se sale. Son DOS causas: la píldora
   cuesta 34 px con su hueco y su maqueta NO la tiene; y «Mascotas y
   Expedientes» es un nombre nuestro —el suyo es «Gestión de Mascotas»— que sin
   píldora pediría 199 y seguiría sin caber. Ese segundo no se toca aquí: los
   nombres los manda el catálogo del servidor.

   Cede la píldora, que es lo AÑADIDO, no el nombre, que es lo diseñado. El
   nivel sigue estando: va en el `title` del renglón, que ya existía.

   Su primer arreglo fue recortar el texto con puntos suspensivos y dejaba
   «Gestión de Cli…» en los tres: cumplía la queja literal —ya no desbordaba— y
   rompía justo lo que ella pidió. Lo vio en la captura, no en la medida, que
   seguía diciendo «0 desbordes». */
.nav-item .niv{display:none}
/* Y EL RECORTE SE FUE, 22 oct 2026. Quedaba «de red, por si algún nombre futuro
   no cupiera», y con los nombres suyos devueltos la red cuesta un nombre: de
   los catorce de PH, `Gestión de Incidencias` pide 158 px y el hueco da 154.
   Medido en SU maqueta, el mismo renglón se desborda los mismos 4 px y se ve
   ENTERO: su botón es `overflow:visible`, así que el texto invade el relleno
   derecho y nadie lo nota. El recorte convertía ese desborde invisible en
   «Gestión de Incidenci…» — exactamente la queja que ella ya hizo una vez.
   Su maqueta no envuelve el texto en un span: el `.nav-texto` es nuestro, y
   también lo era el recorte. Los otros trece caben, y los quince de PMedic
   también, en escritorio y en celular.
   Si algún día un nombre no cupiera, se arregla donde ella lo arreglaría —el
   ancho de la píldora o el tamaño de letra—, no cortándole la palabra. */
.nav-item .nav-texto,.nav-item>span:not(.niv){min-width:0}


.sidebar-pie{padding-top:var(--sp-4);margin-top:var(--sp-4);
  border-top:1px solid rgba(255,255,255,.14)}

.sidebar-yo{font-size:13px;font-weight:600;color:var(--menu-ink-fuerte)}

.sidebar-yo-p{font-size:11.5px;color:var(--menu-ink);margin-bottom:var(--sp-3)}

.sidebar-salir{background:none;border:1px solid rgba(255,255,255,.22);color:var(--menu-ink);
  font-family:var(--sans);font-size:12.5px;padding:7px 12px;border-radius:var(--r-sm);
  cursor:pointer;width:100%}

.sidebar-salir:hover{background:rgba(255,255,255,.1);color:var(--menu-ink-fuerte)}


/* ── banda de ambiente: staging NUNCA se puede confundir con producción ── */
.banda-amb{background:#2B1734;color:#FEC800;font-family:var(--mono);font-size:11px;
  font-weight:500;letter-spacing:.14em;text-transform:uppercase;text-align:center;
  padding:6px 12px;position:relative;z-index:40}

.banda-amb b{color:#fff;letter-spacing:.14em}


/* ── hoja deslizante (ficha) ────────────────────────────────────────── */
.velo{position:fixed;inset:0;background:rgba(0,0,0,.34);z-index:200;display:grid;
  place-items:end stretch}

/* El atributo hidden lo apaga cualquier clase que fije display: la regla del
   navegador ([hidden]{display:none}) es de la hoja del agente de usuario y
   pierde contra una regla de autor. .card-accion{display:inline-flex} de Edna
   dejaba visible la píldora «Editar» aunque el código hiciera b.hidden = true,
   y como su onclick va en línea —que el CSP bloquea— quedaba un botón que no
   hace nada. Esto vale para los ~80 usos de .hidden en el código. */
/* El botón primario queda COMO LO ESCRIBIÓ EDNA: .btn-primario con fondo
   lavanda. Yo lo había puesto en marino sólido; su maqueta lo muestra claro y
   ésa es la referencia. Aquí no se redefine nada de color: sólo se coloca.

   RETIRADAS DOS REGLAS DE AQUÍ, y las dos eran mías:

       .m3-encabezado{justify-content:flex-start}
       .m3-encabezado .suc-sw{margin-left:auto}

   El comentario que las justificaba decía «su diseño pone el botón PEGADO al
   título». Medido en su maqueta de PMedic a 1440: el encabezado tiene DOS
   hijos, `justify-content:space-between`, y «Agendar cita» está en 1249→1408,
   o sea pegado al borde DERECHO. Lo contrario de lo que escribí.

   La cadena entera era nuestra, y cada eslabón tapaba el anterior:
     1. metimos el conmutador de sucursal como tercer hijo de su encabezado,
        cuando su diseño lo pone en un `<div id="suc-sw-casa">` fuera de los
        módulos;
     2. su regla de posición es `#suc-sw{margin-left:auto}` —un ID— y nosotros
        emitíamos sólo la clase `suc-sw`, así que esa regla estaba en la hoja y
        no se aplicaba a nada;
     3. para arreglar lo que 1 y 2 descolocaban escribí estas dos reglas, que
        pisan su `space-between`;
     4. resultado: su botón se movía 417 px y el conmutador se le encimaba —el
        botón acababa en 991 y el conmutador empezaba en 879—.

   Con el conmutador en su casa y con su id, estas dos reglas sobran y además
   mentían. Su hoja vuelve a mandar. Lo pidió Edna: retiró la nota gemela del
   encabezado de Clientes por lo mismo y dejó ésta sin medir, para que la
   midiera yo antes de tocarla. */

/* Barra de controles de la agenda, a petición de Fernando (17 oct): el borde
   derecho de «Mes» alineado con el borde derecho de la tarjeta del calendario,
   «Servicios y horarios» en la columna de la derecha —donde antes estaban Día /
   Semana / Mes—, y el mismo espacio a los dos lados del selector de semana.
   Las dos columnas repiten el template de .grid-2-1 para que la alineación sea
   exacta y no a ojo. Es una desviación DELIBERADA de la maqueta de Edna. */
/* La alineación exacta sólo cabe cuando la columna del calendario mide más que
   los tres grupos juntos (~917 px): por debajo de ~1760 px de ventana, «Mes» se
   iba de línea y quedaba peor que antes. Ahí se mantiene la fila completa. */
.m3-controles-rejilla{display:flex;align-items:center;gap:var(--sp-3) var(--sp-4);
  flex-wrap:wrap}
.m3-controles-rejilla .m3-controles-izq{display:contents}
.m3-controles-rejilla .m3-controles-der{margin-left:var(--sp-4)}
@media (min-width: 1760px){
  .m3-controles-rejilla{display:grid;
    grid-template-columns:minmax(0,2fr) minmax(0,1fr);
    gap:var(--hueco);align-items:center}
  .m3-controles-rejilla .m3-controles-izq{display:flex}
  .m3-controles-rejilla .m3-controles-der{margin-left:0}
}
.m3-controles-izq{display:flex;align-items:center;justify-content:space-between;
  gap:var(--sp-4);flex-wrap:wrap;min-width:0}
.m3-controles-der{display:flex;justify-content:flex-end;align-items:center;min-width:0}
.m3-controles-izq .periodo-sw{margin-left:0}
@media (max-width: 860px){
  .m3-controles-rejilla{grid-template-columns:1fr}
  .m3-controles-der{justify-content:flex-start}
}

/* Barra de «volver al listado / editar» de la ficha. Es añadido nuestro: su
   maqueta navega con un modal que no está en lo que extraemos, así que la ficha
   necesita una salida visible. Se queda arriba del todo y discreta. */
.m1-perfil-barra{display:flex;gap:8px;align-items:center;flex-wrap:wrap;
  margin-bottom:var(--sp-3,12px)}

/* ── correcciones que pidió Fernando tras revisar staging (18 oct) ──────── */

/* (a) Todo lo que se pulsa dice que se pulsa. Su hoja pone cursor:pointer en
   casi todo, pero no en .btn cuando es un <span role="button"> ni en las
   flechas de la semana. */
.btn,[role="button"],.m3-semana-nav-flecha,.pf-tab,.pf-fila,.card-accion{cursor:pointer}
.btn:disabled,[aria-disabled="true"]{cursor:not-allowed}

/* RETIRADA LA REGLA (i), que era una cuenta mal hecha. Decía:

       .m1-lista-encabezado{justify-content:flex-start}
       .m1-lista-encabezado > :last-child:not(.modulo-header):not(.btn){margin-left:auto}

   «Su encabezado tiene tres hijos —su JS añade uno más— así que ahí el botón
   queda junto al título». Medido por Edna en su propia maqueta a 1440: el
   encabezado tiene DOS hijos —.modulo-header en 272→651 y el botón en
   1242→1408— y el botón está pegado al borde DERECHO. La corrección lo movió a
   un sitio que su diseño nunca tuvo.
   Y la segunda línea excluía `.btn`, que es la clase exacta del botón que
   pretendía empujar: aunque la premisa hubiera sido buena, no hacía nada.

   La nota gemela del encabezado de la agenda la medí yo después, y era falsa
   igual: ver más abajo, donde estaban las dos reglas de .m3-encabezado. */

/* (c) El aire entre los dos botones del pie. Lo daba el margin-top de
   .sidebar-soporte cuando iba abajo; al subirlo, ese margen quedó separándolo
   del nombre y los dos botones se pegaron. Ahora lo pone el de abajo. */
.sidebar-soporte + .sidebar-salir{margin-top:var(--sp-4,16px)}

/* (d) El resalte del renglón NO mueve el texto: el relleno horizontal es fijo
   —estaba en 0, por eso el fondo pegaba con las letras— y al pasar por encima
   sólo cambia el color.
   El rectángulo lleva el radio de la tarjeta en sus cuatro esquinas, puesto en
   la primera y la última CELDA (el <tr> no acepta radio de forma fiable).
   Y el borde de arriba se veía más delgado que los otros tres porque no era un
   borde del rectángulo: era el border-bottom del renglón de ARRIBA, que el
   fondo no tapa. Se apaga ese y el propio mientras dura el resalte, para que
   el contorno sea uno solo y del mismo grosor. */
.tabla-clicable tbody td:first-child{padding-left:10px}
.tabla-clicable tbody td:last-child{padding-right:10px}
.tabla-clicable tbody tr:hover td{border-bottom-color:transparent}
.tabla-clicable tbody tr:has(+ tr:hover) td{border-bottom-color:transparent}
/* (g) El contorno es UNO y redondo. El anillo global de hover se pinta con
   box-shadow sobre el <tr>, y un <tr> no acepta border-radius: por eso el
   rectángulo salía a escuadra aunque las celdas estuvieran redondeadas. Se
   apaga ese anillo para estas filas y se dibuja el contorno con sombras
   INTERIORES en las celdas, que sí siguen el radio de cada esquina. */
.tabla-clicable tbody tr:hover{box-shadow:none}
.tabla-clicable tbody tr:hover td{
  box-shadow:inset 0 1px 0 var(--anillo-fila,var(--acento)),
             inset 0 -1px 0 var(--anillo-fila,var(--acento))}
.tabla-clicable tbody tr:hover td:first-child{
  border-top-left-radius:12px;border-bottom-left-radius:12px;
  box-shadow:inset 0 1px 0 var(--anillo-fila,var(--acento)),
             inset 0 -1px 0 var(--anillo-fila,var(--acento)),
             inset 1px 0 0 var(--anillo-fila,var(--acento))}
.tabla-clicable tbody tr:hover td:last-child{
  border-top-right-radius:12px;border-bottom-right-radius:12px;
  box-shadow:inset 0 1px 0 var(--anillo-fila,var(--acento)),
             inset 0 -1px 0 var(--anillo-fila,var(--acento)),
             inset -1px 0 0 var(--anillo-fila,var(--acento))}

/* (d-bis) El foco del buscador. Su input no tiene borde propio —el marco lo
   pone .buscador— así que el anillo genérico caía sobre un elemento sin forma
   y salía un rectángulo plano. Ahora el marco entero reacciona, con el mismo
   anillo de 3 px que usan los campos de los formularios. */
.buscador:focus-within{border-color:var(--acento);box-shadow:0 0 0 3px var(--foco)}
.buscador input:focus{outline:none;box-shadow:none}

/* (d) Aire entre «Horarios» y «Editar», que salían pegados. */
.m3-cfg-acciones{display:flex;gap:8px;justify-content:flex-end;flex-wrap:nowrap}

/* REGLA DE PROYECTO · una etiqueta nunca se ilumina al pasar el cursor.
   Su hoja global pinta un anillo sobre todo lo pulsable e incluye `label[for]`
   —técnicamente un <label> sí es pulsable: enfoca su campo—. Pero visto desde
   la pantalla, el anillo promete una acción que no existe: se encendía al pasar
   por «SUCURSAL», por «Nombre completo» y por cada etiqueta de formulario, con
   el mismo aspecto que el control de abajo, y parecían dos cosas distintas que
   se pueden picar.
   Decisión de Fernando el 19 oct 2026, para todo el proyecto. Empezó siendo el
   parche estrecho `.m3-filtros label` y se encontró otra vez en «Alta de
   paciente»: un parche por pantalla no es una regla.
   La especificidad iguala a la suya, y esta hoja carga después. */
label:hover,label:focus,label[for]:hover,label[for]:focus,
legend:hover,legend:focus{box-shadow:none}

/* (h) El resalte del renglón respira y respeta el radio de su tarjeta. Las
   celdas venían con padding horizontal 0, así que el fondo del hover pegaba
   con el texto, y las esquinas salían a escuadra dentro de una tarjeta
   redondeada. Deliberado y a petición: su maqueta se comporta igual. */

/* (k) El anillo del hover de las pestañas se veía cortado: .pf-tabs lleva
   overflow-x:auto y recortaba los 2px del box-shadow en los bordes. Con un
   respiro interior el anillo cabe entero. */
.pf-tabs{padding:3px 3px 0;scrollbar-width:thin}
.pf-tabs .pf-tab{margin-bottom:3px}

/* ── Campo de fecha con calendario propio ───────────────────────────────── */
/* El <input type="date"> abre el calendario del sistema operativo, que no se
   parece al resto y no hay CSS que lo cambie. Se sustituye el CALENDARIO, no
   el campo: el input real sigue ahí, fuera de la vista, para que el navegador
   valide y el formulario lo lea igual. */
.fecha-caja{position:relative}
.fecha-real{position:absolute;opacity:0;pointer-events:none;width:1px;height:1px;
  left:0;bottom:0}
.fecha-txt{cursor:pointer}
.fecha-pop{position:absolute;z-index:40;top:calc(100% + 6px);left:0;min-width:268px;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg,12px);
  box-shadow:0 12px 32px rgba(0,0,0,.14);padding:10px}
.fecha-cab{display:flex;align-items:center;justify-content:space-between;gap:8px;
  margin-bottom:6px}
.fecha-mes{font-size:13px;font-weight:700;color:var(--ink);text-transform:capitalize}

/* El título del calendario es pulsable en DOS mitades: el mes abre los doce
   meses, el año abre una rejilla de años. Llegar a 1985 con la flecha de mes
   son casi quinientos clics, y una fecha de nacimiento siempre está lejos. */
.fecha-titulo{display:flex;align-items:center;gap:6px;background:none;border:0;
  padding:3px 6px;border-radius:var(--r-sm,6px);cursor:pointer;font:inherit}
.fecha-titulo:hover{background:var(--aviso-fondo)}
.fecha-mes-n,.fecha-anio-n{font-size:13px;font-weight:700;color:var(--ink);
  padding:1px 4px;border-radius:5px;text-transform:capitalize}
.fecha-mes-n:hover,.fecha-anio-n:hover{background:var(--acento);color:#fff}

/* La rejilla de salto reusa la caja de la de días: se cambia el contenido, no
   el lugar, para que el salto no se sienta como otra pantalla. */
.fecha-salto{display:grid;grid-template-columns:repeat(3,1fr);gap:4px;margin-top:6px}
.fecha-salto-op{min-height:34px;border:1px solid var(--line);border-radius:var(--r-sm,6px);
  background:var(--surface);color:var(--ink);font:inherit;font-size:13px;cursor:pointer;
  text-transform:capitalize}
.fecha-salto-op:hover{background:var(--aviso-fondo)}
.fecha-salto-op.elegida{background:var(--acento);border-color:var(--acento);color:#fff}
.fecha-nav{width:26px;height:26px;border-radius:50%;border:1px solid var(--line);
  background:var(--surface);color:var(--ink);cursor:pointer;line-height:1;font-size:15px}
.fecha-nav:hover{background:var(--aviso-fondo)}
/* EL CALENDARIO DE LA CASA LLEVA SU PROPIA REJILLA.
   Edna: «cuando le doy a elegir una fecha de nacimiento no aparece el
   calendario, sólo las iniciales de la semana». No era que no apareciera: se
   pintaba en UNA COLUMNA, así que las siete iniciales llenaban el alto visible
   y los 34 días seguían hacia abajo, fuera de la pantalla.

   La causa: `campoFecha` arma la rejilla como `<div class="m3-mes fecha-rejilla">`
   y la que reparte en siete columnas es `.m3-mes` — que está definida SÓLO en
   `diseno/pmedic.css:960` y no existe ni en `ph.css` ni aquí. Medido en vivo:
   `display:block`, `grid-template-columns:none`, 41 hijos en fila.

   O sea que el control compartido de la casa dependía de una clase que define
   la maqueta de UNO de los dos negocios. En PMedic el calendario funciona y en
   Perritos House no, y lleva así desde que existe. Un control de la casa tiene
   que traer su propio acomodo: `.fecha-rejilla` es la clase que le pone la
   plataforma, y es la que debe mandar. */
.fecha-rejilla{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:2px}
.fecha-rejilla .m3-mes-dia,.fecha-dia{min-height:30px;padding:0;align-items:center;
  justify-content:center;cursor:pointer}
.fecha-dia:hover{background:var(--aviso-fondo)}
.fecha-rejilla .m3-mes-dia.vacia{cursor:default}
.fecha-rejilla .m3-mes-dia.elegida{background:var(--acento);border-color:var(--acento)}
.fecha-rejilla .m3-mes-dia.elegida .num{color:#fff}
/* «Hoy» a la izquierda, «Confirmar» a la derecha: el que cierra el
   calendario es el que manda, y va donde se espera un botón primario. */
.fecha-pie{display:flex;justify-content:space-between;align-items:center;
           gap:8px;margin-top:8px}
.fecha-ok{flex:0 0 auto}

/* ── Ausencias del equipo ───────────────────────────────────────────────── */
.ausencia-alcance{border-top:1px solid var(--line);padding-top:var(--sp-4,16px);
  margin-top:var(--sp-2,8px)}
.ausencia-titulo{font-size:14px;margin:var(--sp-5,20px) 0 var(--sp-2,8px)}
.ausencia-pendientes{margin-top:8px;display:grid;gap:3px;font-size:12.5px}

/* Varios servicios a la vez, con fichas que se quitan: un <select multiple>
   obliga a saber que hay que dejar pulsado Ctrl, que es justo lo que no
   queremos en una pantalla que usa recepción con prisa. */
.ms-caja{display:grid;gap:8px}
.ms-op{display:flex;align-items:center;gap:9px;padding:7px 9px;border-radius:8px;
  cursor:pointer;font-size:13.5px;color:var(--ink)}
.ms-op:hover{background:var(--aviso-fondo)}
.ms-op.elegida{background:var(--aviso-fondo);font-weight:600}
.ms-op input[type="checkbox"]{width:15px;height:15px;flex:none;margin:0;
  accent-color:var(--acento);cursor:pointer}
.ms-lista{display:grid;gap:4px;max-height:170px;overflow:auto;
  border:1px solid var(--line);border-radius:var(--r-md,10px);padding:6px}

/* La rueda de horas. Es scroll con scroll-snap y no una lista: en el teléfono
   se gira con el dedo y en el escritorio con la rueda del ratón, que es como
   se espera que responda algo que parece una rueda. La franja central marca
   cuál está elegida, sin tapar lo de arriba y lo de abajo. */
/* Un solo carrete, centrado en su caja. */
.rueda{display:grid;grid-template-columns:minmax(0,1fr);justify-items:center;
  align-items:center;border:1px solid var(--line);border-radius:var(--r-md,10px);
  padding:6px;position:relative;background:var(--surface)}
.rueda .rueda-carrete{width:100%;max-width:150px}
.rueda::before{content:'';position:absolute;left:6px;right:6px;top:50%;
  height:34px;transform:translateY(-50%);border-radius:8px;
  background:var(--aviso-fondo);pointer-events:none;z-index:0}
.rueda-carrete{height:136px;overflow-y:auto;scroll-snap-type:y mandatory;
  position:relative;z-index:1;scrollbar-width:none;text-align:center}
.rueda-carrete::-webkit-scrollbar{display:none}
.rueda-carrete:focus-visible{outline:2px solid var(--acento);outline-offset:2px;
  border-radius:8px}
.rueda-relleno{height:51px}
.rueda-op{height:34px;line-height:34px;scroll-snap-align:center;font-size:14px;
  color:var(--ink-3,#5A6672);transition:color .12s ease,font-weight .12s ease}
.rueda-op.activa{color:var(--ink);font-weight:700}
.rueda-a{font-size:13px;color:var(--ink-3,#5A6672);z-index:1;padding:0 2px}

/* (a) Los desplegables dentro de un modal quedaban DEBAJO del pie, que es
   sticky con z-index:20 en su hoja: la lista de «Motivo» se enredaba con
   «Cerrar» y «Registrar ausencia». */
/* Por encima de todo lo del modal. La regla de .flota ya lo dice, pero este
   selector es más específico y la pisaba. */
.modal-caja .busca-lista,.modal-caja .fecha-pop,.modal-caja .ms-lista{z-index:400}
.modal-caja .modal-pie{z-index:10}

/* (e) Las barras de desplazamiento respetan la esquina redondeada del elemento
   que las contiene. Pegadas al borde se veían como una pieza encima, no como
   parte de la caja. */
.ms-lista,.rueda-carrete,.fecha-pop,.busca-lista,.modal-caja,.pf-tabs,
.m3-semana,.tabla-env{scrollbar-width:thin;scrollbar-color:var(--line) transparent}
.ms-lista::-webkit-scrollbar,.busca-lista::-webkit-scrollbar,
.modal-caja::-webkit-scrollbar,.m3-semana::-webkit-scrollbar,
.pf-tabs::-webkit-scrollbar,.tabla-env::-webkit-scrollbar{width:10px;height:10px}
.ms-lista::-webkit-scrollbar-track,.busca-lista::-webkit-scrollbar-track,
.modal-caja::-webkit-scrollbar-track,.m3-semana::-webkit-scrollbar-track,
.pf-tabs::-webkit-scrollbar-track,.tabla-env::-webkit-scrollbar-track{
  background:transparent;margin:10px}
.ms-lista::-webkit-scrollbar-thumb,.busca-lista::-webkit-scrollbar-thumb,
.modal-caja::-webkit-scrollbar-thumb,.m3-semana::-webkit-scrollbar-thumb,
.pf-tabs::-webkit-scrollbar-thumb,.tabla-env::-webkit-scrollbar-thumb{
  background:var(--line);border-radius:99px;border:3px solid transparent;
  background-clip:content-box}
.ms-lista::-webkit-scrollbar-thumb:hover,.modal-caja::-webkit-scrollbar-thumb:hover{
  background:var(--ink-3,#5A6672);background-clip:content-box}

/* El <select> real que queda detrás de un desplegable propio, y cualquier
   campo que sólo exista para que el formulario y las pruebas lo lean. */
/* El control REAL que se queda detrás cuando sustituimos su apariencia: el
   <select> que el formulario y las pruebas siguen leyendo, el <input type=date>
   que valida el formato. Invisible, sin recibir clics y sin ocupar lugar.
   Calificar por elemento no bastó: dentro de `.modal-caja` hay reglas de dos
   clases que le ganan a `select.campo-oculto`, y el control «escondido» volvía
   a medir 1440 px. Lo reportó Edna montando el formulario, y en su código no
   dependió de este ayudante: le puso además `hidden`. Tenía razón en no fiarse.
   Aquí va `!important`, que en esta hoja sólo se usa para `[hidden]` y por la
   misma razón: la única función de esto es DESAPARECER. Un ayudante de esconder
   que pierde una carrera de especificidad no es un ayudante, es una trampa. */
.campo-oculto,select.campo-oculto,input.campo-oculto,textarea.campo-oculto{
  position:absolute !important;opacity:0 !important;pointer-events:none;
  width:1px !important;height:1px !important;
  margin:-1px;padding:0;border:0;overflow:hidden;clip-path:inset(50%)}
/* Las sugerencias del buscador cuelgan del campo. */
.busca-suelta{position:relative}

/* (b) La capa de arriba. Un popover dentro de .modal-caja -que tiene
   overflow:auto- se recorta, empuja el contenido o se enreda con el pie
   sticky. Con position:fixed sale del modal y se coloca a mano. */
.flota{position:fixed;z-index:400;overflow:auto;
  box-shadow:0 14px 36px rgba(0,0,0,.18)}

/* El contorno del renglón SE QUEDA: es el de las opciones de los desplegables
   el que sobraba. Fernando lo aclaró el 19 oct — en la tabla le gusta. */

/* (a) Las opciones de un desplegable no llevan contorno. Su regla global de
   hover pinta un anillo de 2 px a toda la lista de controles, y sobre una
   opción de ancho completo ese anillo se lee como dos rayas, arriba y abajo.
   Lo que señala la opción bajo el cursor es el fondo. */
.busca-lista .busca-op:hover,.busca-lista .busca-op:focus-visible,
.ms-lista .busca-op:hover,.pfh-hora:hover{box-shadow:none}

/* (b) Un desplegable mide cinco opciones y el resto se desplaza. Abierto a su
   altura natural, el de servicios llegaba hasta el borde de la pantalla y
   tapaba todo lo demás. Regla del proyecto desde el 19 oct: cinco, salvo que
   haya una razón escrita para otra cosa. */
.busca-lista,.ms-lista{max-height:calc(5 * 38px + 12px)}

/* (c) El hueco del calendario tampoco recibe el anillo del hover. Apagué el
   fondo pero no la sombra, que es lo que de verdad se veía. */
.fecha-rejilla .m3-mes-dia.vacia,.fecha-rejilla .m3-mes-dia.vacia:hover{
  box-shadow:none;pointer-events:none}

/* (d) “Ausencias del equipo” y “Recordatorios” centran su texto. text-align no
   basta: .card-accion es inline-flex y el texto es un elemento de la caja.

   ACOTADA A PH EL 4-NOV-2026, Y SE LE ESCAPABA A LA MEDICIÓN. La escribí sin
   `[data-negocio]`, así que alcanzaba también a PMedic, donde su maqueta deja
   ese botón en `normal`. No salía roja porque `comparar-estilos.js` emparejaba
   por firma y se quedaba con UN `.card-accion` elegido por orden de documento;
   al emparejar por linaje apareció. Una regla de la casa escrita para una
   pantalla de un negocio no debería alcanzar al otro: eso es decidir el diseño
   ajeno desde la hoja compartida. */
[data-negocio="ph"] .m3-filtros-acciones .card-accion{justify-content:center}

/* (e) Un hueco del calendario no es una fecha: no se ilumina ni invita a
   pulsarlo. Y los números van centrados en su caja. */
.fecha-rejilla .m3-mes-dia.vacia{background:none;border:0;cursor:default}
.fecha-rejilla .m3-mes-dia.vacia:hover{background:none}
.fecha-dia{display:flex;align-items:center;justify-content:center;text-align:center}
/* Especificidad por encima de .m3-mes-dia .num, que en su hoja fija width:21px
   y align-self:flex-start para la vista de MES —donde el número va arriba a la
   izquierda de una celda alta—. En el calendario de elegir fecha la celda es
   un cuadrito y el número va en el centro. */
.fecha-rejilla .m3-mes-dia .num{width:auto;height:auto;margin:0;align-self:auto}

/* (f) Panel de fecha y hora: calendario fijo a la izquierda, horarios que se
   desplazan a la derecha. Con los horarios debajo del formulario, elegir una
   hora obligaba a bajar y perder de vista la fecha. */
.pfh{display:grid;grid-template-columns:minmax(0,248px) minmax(0,1fr);gap:14px;
  border:1px solid var(--line);border-radius:var(--r-lg,12px);padding:12px;
  background:var(--surface)}
.pfh-cal{min-width:0}
.pfh-col{min-width:0;display:flex;flex-direction:column;max-height:290px}
.pfh-titulo{font-size:12.5px;font-weight:700;color:var(--ink);
  text-transform:capitalize;padding-bottom:8px;border-bottom:1px solid var(--line);
  margin-bottom:8px;flex:none}
.pfh-cuerpo{overflow-y:auto;display:grid;gap:6px;align-content:start;padding-right:4px}
.pfh-hora{width:100%;padding:9px 10px;border-radius:var(--r-md,10px);
  border:1px solid var(--line);background:var(--surface);color:var(--ink);
  font-family:inherit;font-size:13px;font-weight:600;cursor:pointer;text-align:center}
.pfh-hora:hover:not(:disabled){border-color:var(--acento);background:var(--aviso-fondo)}
.pfh-hora.elegida{background:var(--acento);border-color:var(--acento);color:#fff}
/* Un horario tomado se ve, apagado. Si no se pintara, la rejilla saldría con
   huecos salteados y no se sabría si falta personal o ya está ocupado. */
/* Una opción apagada del desplegable se ve apagada. Mismos valores que
   .pfh-hora:disabled, que es la convención de esta hoja para lo que no se
   puede pulsar: hasta el 27 oct 2026 `.busca-op` era el único control de lista
   sin ella, y el desplegable enseñaba como pulsable lo que el <select> tenía
   deshabilitado. Parecía bloqueado y no lo estaba. */
.busca-lista .busca-op:disabled,.ms-lista .busca-op:disabled{
  opacity:.45;cursor:not-allowed;background:var(--ground)}
.pfh-hora:disabled{opacity:.45;cursor:not-allowed;background:var(--ground);
  text-decoration:line-through}
.pfh .rueda{grid-column:1 / -1}
@media (max-width: 720px){
  .pfh{grid-template-columns:1fr}
  .pfh-col{max-height:220px}
}

/* (a) Las notas explicativas, bajo un icono. A la vista, cada pantalla
   acababa con párrafos de letra chica que nadie lee y que empujan hacia abajo
   lo que sí importa. El texto sigue estando, a un gesto. */
.info-caja{position:relative;display:inline-flex;vertical-align:middle;margin-left:6px}
.info{width:17px;height:17px;border-radius:50%;border:1px solid var(--line);
  background:var(--surface);color:var(--ink-3,#5A6672);font-size:11px;font-weight:700;
  line-height:1;cursor:help;display:inline-flex;align-items:center;
  justify-content:center;font-family:var(--serif,Georgia,serif);padding:0}
.info:hover,.info:focus-visible{border-color:var(--acento);color:var(--ink)}
.info-globo{position:absolute;z-index:500;top:calc(100% + 7px);right:0;width:272px;
  background:var(--ink);color:var(--surface);font-size:12.5px;line-height:1.45;
  padding:9px 11px;border-radius:var(--r-md,10px);box-shadow:0 10px 26px rgba(0,0,0,.22);
  font-weight:400;text-transform:none;letter-spacing:0}
.modal-header .info-caja{margin-left:auto}

/* El calendario con su rueda al lado. Sin rueda mantiene su ancho propio. */
/* (d) El calendario es un tercio más angosto. Las celdas se estaban dejando
   crecer al ancho natural de la rejilla y quedaba un cuadro de 430 px para
   enseñar 31 números. */
.fecha-pop{min-width:0;width:max-content}
.fecha-rejilla{gap:1px}
.fecha-rejilla .m3-mes-dia,.fecha-rejilla .m3-mes-cab{min-width:34px;min-height:28px}

/* Y LAS INICIALES DE LOS DÍAS, por el mismo motivo que la rejilla.
   `.m3-mes-cab` sólo está declarada en `diseno/pmedic.css:961`, así que en
   Perritos House las siete iniciales salían con lo heredado del cuerpo.
   Medido, el mismo calendario en los dos negocios:
     PMedic   10px · rgb(90,102,114) · centradas
     PH       14px · rgb(43,23,52)   · a la izquierda
   Es el hallazgo del calendario en pequeño: Edna dijo «sólo aparecen las
   iniciales de la semana» y la rejilla era la causa grande, pero las iniciales
   además se veían mal. La declaración es la suya, portada tal cual porque
   `--texto-suave` existe en las DOS hojas —#5A6672 en PMedic, #6B6B6B en PH—,
   así que cada negocio pone su propio gris. */
.fecha-rejilla .m3-mes-cab{font-size:10px;font-weight:600;text-transform:uppercase;
  color:var(--texto-suave);text-align:center;padding-bottom:4px}
.fecha-pop-ancho{display:flex;gap:10px;align-items:flex-start}
.fecha-pop-ancho .fecha-lado{flex:0 0 auto}
/* Cinco opciones de alto, la misma regla que los desplegables. Con 118px se
   veían dos y media y no parecía una rueda: parecía un campo cortado. */
.fecha-pop-ancho .rueda{flex:0 0 164px;margin-top:30px}
.fecha-pop-ancho .rueda-carrete{height:170px}
.fecha-pop-ancho .rueda-relleno{height:68px}
@media (max-width: 620px){
  .fecha-pop-ancho{flex-direction:column;min-width:0}
  .fecha-pop-ancho .rueda{flex:none;width:100%;margin-top:0}
}

/* UN TAMAÑO POR OMISIÓN PARA `.icon`.
   En la hoja de Edna, `.icon` sólo define trazo y relleno: el TAMAÑO se lo da
   cada contexto, y hay cuarenta reglas así (`.nav-item svg.icon{18px}`,
   `.topbar-nota svg.icon{13px}`…). El contexto número cuarenta y uno fue el
   icono que la plataforma metió dentro de `.topbar-fecha` de Perritos House —
   que ella diseñó como texto, sin icono—. Sin regla, el SVG se estira a su
   viewBox y medía **182 × 182 px** en las tres pantallas de PH, escritorio y
   celular. PMedic no lo sufría porque su hoja sí trae la regla.
   Lo encontró Edna midiendo el staging real; yo lo tuve delante en una captura
   de producción y no lo perseguí.
   Esto no arregla un icono: hace que `.icon` falle en pequeño en vez de fallar
   en gigante. Cualquier regla de contexto gana por especificidad, así que las
   cuarenta siguen mandando donde existen. */
/* Sólo el TAMAÑO. La primera versión traía además `flex:none`, que protege a
   un icono de encogerse dentro de una fila flexible — pero eso es un cambio de
   comportamiento que Edna no hizo, y el comparador lo marcó al instante:
   flex-shrink 1 en su maqueta, 0 en lo nuestro. Arreglar un tamaño no autoriza
   a cambiar otra cosa de paso. */
svg.icon{width:18px;height:18px}
.topbar-fecha svg.icon,.topbar-suc svg.icon{width:16px;height:16px}

/* El aviso que sustituye al `alert` del navegador: dentro de la pantalla, con
   la forma del resto, y se va solo. */
.aviso-flotante{margin:0 0 12px;animation:entra .18s ease}

[hidden]{display:none !important}
.velo[hidden]{display:none}

.hoja{background:var(--ground);width:min(640px,100%);height:100%;margin-left:auto;
  overflow-y:auto;border-left:1px solid var(--line);
  animation:entra .22s cubic-bezier(.2,.8,.2,1)}

.hoja-top{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);
  padding:var(--sp-4) var(--sp-5);background:var(--surface);
  border-bottom:1px solid var(--line);position:sticky;top:0;z-index:1}

.hoja-cuerpo{padding:var(--sp-5)}

.cerrar{width:34px;height:34px;flex:none;border-radius:var(--r-md);border:1px solid var(--line);
  background:var(--surface);color:var(--ink-2);cursor:pointer;font-size:18px;line-height:1}

.cerrar:hover{background:var(--realce)}


/* ── pares dato/valor de la ficha ───────────────────────────────────── */
.pares{display:grid;gap:var(--sp-3)}

.par{display:grid;grid-template-columns:140px minmax(0,1fr);gap:var(--sp-3);
  font-size:14px;align-items:start}

.par dt{color:var(--ink-3);font-size:13px}

.par dd{margin:0;overflow-wrap:anywhere}

.par dd:empty::after{content:"—";color:var(--ink-3)}


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

/* ── de los <style> en línea de las páginas de entrar y cambio de clave ──
   Estaban dentro del HTML de cada pantalla. Al moverlas aquí dejan de
   depender de que alguien recuerde copiarlas al crear una pantalla nueva. */
.envoltura{display:grid;place-items:center;min-height:100vh;padding:24px}
.caja{background:var(--blanco,#fff);border:1px solid var(--gris-borde,#E8E5E0);
  border-radius:14px;padding:34px 32px;width:100%;max-width:440px}
.caja-brand{text-align:center;padding-bottom:16px;margin-bottom:16px;
  border-bottom:3px solid var(--brand-filo,var(--amarillo,#FEC800))}
.caja-brand .sidebar-logo-img{max-width:140px}
.caja h1{font-size:23px;font-weight:700;letter-spacing:-.01em;margin:10px 0 8px}
.caja .sub{color:var(--texto-suave,#6B6B6B);font-size:14px;margin-bottom:22px}
.caja .pie{margin-top:22px;padding-top:18px;border-top:1px solid var(--gris-borde,#E8E5E0);
  font-size:13px;color:var(--texto-suave,#6B6B6B)}
.fuerza{height:5px;border-radius:99px;background:var(--gris-borde,#E8E5E0);
  overflow:hidden;margin-top:-8px}
.fuerza i{display:block;height:100%;width:0;background:var(--rojo,#B3261E);
  transition:width .2s,background .2s}
.lead{color:var(--texto-suave,#6B6B6B);margin:10px 0 0;max-width:62ch}
/* PMedic define .pm-wordmark en su hoja; PH no lo usa, pero si algún día
   mostrara un wordmark no debe salir sin estilo. */
.pm-wordmark{font-size:23px;font-weight:700;letter-spacing:-.02em;
  color:var(--lema-ink,var(--morado,#2B1734));display:block;text-align:center;line-height:1}
/* La vista de personal y el "+N" de la rejilla existen en la hoja de PMedic
   pero no en la de PH, y la agenda de PH los usa igual. */
.m3-staff-rejilla{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:12px}
.m3-staff-ficha{display:block;width:100%;text-align:left;background:var(--blanco,#fff);
  border:1px solid var(--gris-borde,#E8E5E0);border-radius:12px;padding:14px;cursor:pointer}
.m3-staff-ficha:hover{border-color:var(--amarillo,var(--indigo,#017B99))}
.m3-staff-top{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.m3-staff-foto{width:36px;height:36px;border-radius:50%;flex:none;display:grid;
  place-items:center;font-weight:700;background:var(--realce,#F3F1EC)}
.m3-staff-id{min-width:0}
.m3-staff-id b{display:block;font-size:13.5px}
.m3-staff-id span{display:block;font-size:11.5px;color:var(--texto-suave,#6B6B6B)}
.m3-staff-datos{display:flex;gap:16px;margin-bottom:8px}
.m3-staff-dato b{display:block;font-size:16px;font-weight:700}
.m3-staff-dato span{font-size:11px;color:var(--texto-suave,#6B6B6B)}
.m3-staff-barra{height:5px;border-radius:99px;background:var(--gris-borde,#E8E5E0);overflow:hidden}
.m3-staff-barra i{display:block;height:100%;background:var(--verde,var(--turquesa,#35BBCA))}
.m3-staff-pie{display:block;margin-top:7px;font-size:11.5px;color:var(--texto-suave,#6B6B6B)}
/* Sólo PH: pmedic.css ya trae su propia .m3-mas y la mía la pisaba
   (margin-top 2px y font-weight 600 contra sus 0 y 700).

   EL «+N» DE PH SE PARECE AL DE PMEDIC, QUE ES LA REFERENCIA QUE PIDIÓ EDNA.
   El 27 oct 2026 dijo: «debería de estar como en el pm donde se abre un +2 o
   el numero que hay en ese mismo horario». Medido en las hojas ese mismo día:
   `pmedic.css:1015` lo dibuja como una pastilla con borde discontinuo, y aquí
   era texto suave de 10 px sin borde ni fondo — un contador que no se lee como
   algo que se puede pulsar. Mismo contorno que allá, con el morado y el
   amarillo de PH en vez del índigo y la lavanda: el hueco libre de la celda ya
   usa ese amarillo al pasar el cursor (`.m3-libre:hover`), así que el
   calendario conserva un solo idioma.
   El alto va en `min-height` y no en `flex-basis`: la celda es una columna
   flexible de 38 px y un `flex:0 0 26px` encogía los bloques de cita. */
[data-negocio="ph"] .m3-mas{display:block;width:100%;margin-top:2px;
  min-height:16px;padding:1px 4px;border:1px dashed var(--gris-borde,#E4E0E6);
  border-radius:5px;background:none;cursor:pointer;font-family:inherit;
  font-size:10px;font-weight:700;color:var(--texto-suave,#6B6B6B)}
[data-negocio="ph"] .m3-mas:hover,
[data-negocio="ph"] .m3-mas:focus-visible{
  border-color:var(--morado,#2B1734);color:var(--morado,#2B1734);
  background:#FFFBEA;outline:none}
/* .barra (fila de botones) existe en la hoja de PH pero no en la de PMedic.
   Las clases que usamos tienen que estar definidas para LOS DOS negocios: que
   una exista sólo en una hoja es exactamente cómo PMedic se quedó sin ella. */
.barra{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:24px 0}

/* ═══ CELULAR ═══════════════════════════════════════════════════════════════
   Las maquetas de Edna son de escritorio: su barra lateral es fija, de 240 px
   en PH y 292 en PMedic. En un teléfono de 390 px eso deja 98 px para el
   contenido y empuja la página a desbordarse a lo ancho.

   Esta capa vivía en mi hoja anterior y se fue con ella. El equipo usa la
   plataforma DESDE EL CELULAR —recepción, cuidadores, fisioterapeutas—, así
   que no es un detalle: sin esto la plataforma no se puede usar.

   Va después de la hoja de Edna, así que con la misma especificidad gana. No
   cambia ningún color, y de su tipografía cambia UNA cosa: el tamaño de letra
   del renglón del menú, que baja a 13 px porque la rejilla de módulos de aquí
   abajo es nuestra y su 14 px no cabe en una celda de 150. Está medido y
   declarado abajo, junto a la regla. Decía «ni una tipografía» y era falso. */
@media (max-width: 860px) {
  .app{display:block}

  /* La barra deja de ser fija y se vuelve el encabezado de la página. */
  .sidebar{position:static;width:auto;min-width:0;max-height:none;
    padding:0 0 var(--sp-3,12px);overflow:visible}
  .sidebar-brand{margin:0 0 var(--sp-3,12px);padding:var(--sp-4,16px)}
  .sidebar-logo-img{max-width:130px}

  /* Los módulos en rejilla: en vertical, doce módulos serían doce pantallazos
     de desplazamiento antes de llegar al contenido. */
  .sidebar-nav{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));
    gap:4px;padding:0 var(--sp-3,12px)}
  /* ESTE `font-size` ES LA EXCEPCIÓN A LO QUE DICE EL COMENTARIO DE ARRIBA, y
     el comentario estaba mintiendo: decía «no cambia ni un color ni una
     tipografía» con esta línea tres renglones más abajo.
     El motivo es real y está medido: la rejilla de arriba es NUESTRA —su maqueta
     no tiene menú de celular, 0 apariciones de hamburguesa, velo y cajón— y en
     celdas de 150 px el nombre más largo pide 164 a 14 px, así que se saldría
     encima de su vecina. A 13 px pide 148 y cabe.
     Así que es una desviación de su tipografía con causa, no un descuido, y
     está DECLARADA en `pruebas/pildora-del-menu.js` con esta misma cuenta: el
     candado la nombra en vez de taparla, y caduca si deja de darse.
     LO QUE HAY QUE DECIDIR, y está preguntado: o se conserva su 14 px y la
     rejilla pasa a una columna de 214 px en el celular, o se conservan las dos
     columnas y el texto va a 13. Las dos se pueden; la que no vale es que el
     comentario diga que no tocamos su tipografía mientras la tocamos. */
  .nav-item{padding:9px 10px;font-size:13px}
  .nav-item .niv{display:none}          /* el nivel cabe en el escritorio, aquí estorba */
  .sidebar-rotulo{grid-column:1/-1;padding:4px 2px}
  /* En COLUMNA. En fila, el nombre más los dos botones piden 372 px dentro de
     un cajón de 266 y la barra se desplazaba de lado — que es justo lo que no
     debe pasar nunca en un teléfono. */
  .sidebar-pie{display:flex;flex-direction:column;align-items:stretch;gap:8px;
    margin:var(--sp-3,12px) var(--sp-3,12px) 0;padding-top:var(--sp-3,12px)}
  .sidebar-yo-p{margin:0 0 4px}
  .sidebar-soporte,.sidebar-salir{width:100%;flex:none;justify-content:center}
  .sidebar-soporte + .sidebar-salir{margin-top:0}

  .main{margin-left:0}
  .contenido{padding:var(--sp-4,16px)}
  .topbar{padding:10px var(--sp-4,16px);min-height:0;position:static}
  .breadcrumb{font-size:12.5px}

  /* Una tabla ancha se desplaza DENTRO de su tarjeta; la página nunca se
     mueve de lado. Es la regla que hace que todo lo demás quepa. */
  .card{overflow-x:auto}
  .tabla{min-width:520px}
  /* La tabla de personas se queda en tres columnas y CABE: sin desplazamiento
     lateral, el anillo del resalte de la fila se cierra por los cuatro lados.
     Con la tabla a 520 px dentro de una tarjeta de 356, ese anillo se cortaba
     en los dos bordes y parecía un borde a medio pintar. */
  [data-col="secundaria"]{display:none}
  table[data-compacta="movil"]{min-width:0;width:100%}

  /* El calendario no se puede apretar a 390 px sin volverse ilegible: se
     desplaza a lo ancho. El ancho mínimo va en las FILAS, no en el contenedor:
     ponerlo en el contenedor que scrollea lo ensancha a él y entonces es la
     página la que se desborda —que es justo lo que pasaba—. */
  .m3-semana{overflow-x:auto}
  .m3-semana-fila{min-width:620px}

  /* Nada se sale de su caja, y los botones anchos ocupan el renglón completo
     en vez de empujar la página tres píxeles. */
  .contenido *{max-width:100%}
  .modulo-header,.m1-lista-encabezado,.m3-encabezado{flex-wrap:wrap}
  .btn-primario,.btn{max-width:100%}
  .m1-lista-encabezado .btn-primario,.modulo-header .btn-primario{width:100%;text-align:center}
  .buscador{max-width:100%}
  /* CUALQUIER rejilla baja a una columna. Enumerarlas una por una falló: la
     de la agenda se llama grid-2-1 y no estaba en mi lista, así que en el
     teléfono el calendario y el panel de detalle seguían lado a lado, con el
     calendario apretado a dos días y el detalle partiendo palabras. */
  .contenido [class*="grid-"],.m3-duo,#m3-vista-calendario,#m3-duo{
    grid-template-columns:1fr !important;display:grid !important}
  .contenido [class*="grid-"] > *{min-width:0}
  .m3-controles{flex-wrap:wrap;gap:10px}
  /* Los filtros van DESPUÉS del calendario. Los puse primero por costumbre de
     escritorio —donde están a un lado y no estorban—; en el teléfono eso mete
     tres desplegables y una leyenda entre el título y lo que la persona vino a
     ver. Decisión de Fernando, 19 oct. */
  .m3-filtros{order:9}

  /* Formularios y hoja lateral a ancho completo. */
  .rejilla-2{grid-template-columns:1fr}
  .hoja{width:100%;border-left:0}
  .hoja-cuerpo{padding:var(--sp-4,16px)}
  .envoltura{padding:16px}
  .caja{padding:26px 20px}

  h1,.tipo-h1{font-size:25px}
  .banda-amb{font-size:9.5px;letter-spacing:.08em;padding:5px 10px}
}

/* En escritorio estrecho el calendario también puede no caber junto al panel
   de detalle: se desplaza dentro de su tarjeta en vez de empujar la página.
   Es lo que pasaba en la agenda de PH a 1440 px. */
.m3-vista-calendario .card{overflow-x:auto}

/* ═══ MENÚ DE CELULAR ══════════════════════════════════════════════════════
   El cajón y su barra. En escritorio no existen. */
.barra-movil{display:none}
.velo-menu{display:none}
@media (max-width: 860px){
  .barra-movil{display:flex;align-items:center;gap:12px;padding:10px 14px;
    background:var(--menu);color:#fff;position:sticky;top:0;z-index:60}
  .barra-movil[hidden]{display:none}
  .barra-movil-modulo{flex:1;min-width:0;font-weight:600;font-size:15px;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* La marca arriba a la derecha, sobre su placa blanca para que el logotipo
     tenga el fondo claro que necesita. */
  .barra-movil-marca{flex:none;background:#fff;border-radius:7px;padding:4px 8px;
    display:grid;place-items:center;max-width:116px}
  .barra-movil-marca img{max-width:96px;height:auto;display:block}
  .barra-movil-marca .pm-wordmark{font-size:15px;line-height:1.1}

  .burger{flex:none;width:36px;height:36px;border:0;background:rgba(255,255,255,.14);
    border-radius:8px;display:grid;place-content:center;gap:4px;cursor:pointer;padding:0}
  .burger span{display:block;width:17px;height:2px;border-radius:2px;background:#fff;
    transition:transform .18s ease,opacity .18s ease}
  .burger:focus-visible{outline:2px solid #fff;outline-offset:2px}
  .menu-abierto .burger span:nth-child(1){transform:translateY(6px) rotate(45deg)}
  .menu-abierto .burger span:nth-child(2){opacity:0}
  .menu-abierto .burger span:nth-child(3){transform:translateY(-6px) rotate(-45deg)}

  .velo-menu{position:fixed;inset:0;background:rgba(0,0,0,.4);z-index:70}
  .velo-menu[hidden]{display:none}

  /* El cajón: fuera de pantalla hasta que se pide. */
  .sidebar{position:fixed;top:0;bottom:0;left:0;width:min(290px,84vw);z-index:80;
    transform:translateX(-102%);transition:transform .22s cubic-bezier(.2,.8,.2,1);
    overflow-y:auto;padding-bottom:var(--sp-4,16px)}
  .menu-abierto .sidebar{transform:none;box-shadow:0 0 40px rgba(0,0,0,.3)}
  .sidebar-nav{display:block;padding:0 var(--sp-3,12px)}
  /* El tamaño de letra es el SUYO, 14 px. Tenía 14.5 sin motivo escrito, y eso
     hacía que el mismo nombre pidiera un 3.6% más de ancho en el cajón que en
     su maqueta. Lo cazó el contraste de `pildora-del-menu.js`, que mide el
     mismo texto en los dos sitios: la divergencia era constante —14.5/14— y por
     eso se veía que lo roto era el estilo y no la medición.
     El cajón móvil entero es NUESTRO: su maqueta no tiene hamburguesa ni velo
     ni menú lateral de celular (medido: 0 apariciones de las tres). Pero
     `.nav-item` es suyo, y un valor suyo no se cambia sin decir por qué. */
  .nav-item{padding:11px 12px}
  /* La píldora de nivel («op» / «ver») SÍ se muestra aquí, y es lo contrario de
     lo que hace en el escritorio. El motivo es el que ya estaba escrito arriba:
     se cedió porque en 208 px no cabía con el nombre, no porque esté prohibida.
     En el cajón el renglón mide 266 y el hueco da 178 con la píldora puesta,
     contra los 164 del nombre más largo — medido, cabe. Si Edna prefiere que no
     esté tampoco aquí, se quita: su diseño no cubre este cajón porque no lo
     tiene, así que esto es una decisión nuestra y está preguntada. */
  .nav-item .niv{display:inline-block}
  @media (prefers-reduced-motion: reduce){ .sidebar{transition:none} }
}

/* Los cuatro indicadores de la agenda, en 2×2 en el celular: apilados uno sobre
   otro eran cuatro pantallazos antes de llegar al calendario. */
@media (max-width: 860px){
  /* Va con la MISMA especificidad que la regla general de una columna
     —.contenido [class*="grid-"]— y después que ella. Con .grid-kpi4 a secas
     no ganaba, aunque llevara !important: la general es más específica. */
  .contenido .grid-kpi4{grid-template-columns:repeat(2,minmax(0,1fr)) !important;gap:10px}
  .contenido .grid-kpi4 .kpi{padding:12px}
  .contenido .grid-kpi4 .tipo-dato,
  .contenido .grid-kpi4 [id^="m3-k-"]{font-size:24px}
  .contenido .grid-kpi4 .tipo-label{font-size:11px}
  .contenido .grid-kpi4 .kpi-delta,
  .contenido .grid-kpi4 .kpi .suave{font-size:10.5px}
  .contenido .grid-kpi4 .icon-badge{width:28px;height:28px}
}

/* En el celular los dos botones del encabezado van en línea, no uno sobre otro
   ocupando media pantalla: la regla de ancho completo era para el botón único
   del listado, no para una fila de acciones. */
@media (max-width: 860px){
  .m3-encabezado .btn-primario,.m3-encabezado .btn{width:auto}
  .m3-encabezado .modulo-header,.m3-encabezado{gap:8px}
}

/* ── «¿Necesitas ayuda?» ─────────────────────────────────────────────────── */
/* El aspecto lo pone .sidebar-soporte de Edna (en ph.css y pmedic.css).
   Aquí sólo se neutraliza lo que un <button> trae de fábrica y que un <div>
   suyo no tiene. */
button.sidebar-soporte{width:100%;background:none;font-family:inherit;
  justify-content:center;text-align:center;cursor:pointer}
.sidebar-soporte:hover{background:rgba(255,255,255,.1);color:var(--menu-ink-fuerte)}
.sidebar-soporte:focus-visible{outline:2px solid var(--menu-activo);outline-offset:2px}

/* El recorte: se oscurece todo menos lo que se marca. */
.sop-recorte{position:fixed;inset:0;z-index:300;cursor:crosshair;
  background:rgba(20,14,28,.55);user-select:none;-webkit-user-select:none;touch-action:none}
.sop-guia{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  background:#fff;color:#241B2E;font-family:var(--sans);font-size:14.5px;font-weight:600;
  padding:12px 20px;border-radius:99px;box-shadow:0 8px 30px rgba(0,0,0,.3);
  text-align:center;max-width:86vw}
.sop-rect{position:absolute;border:2px solid #fff;border-radius:3px;
  box-shadow:0 0 0 9999px rgba(20,14,28,.55);background:transparent;pointer-events:none}
.sop-previa img.sop-img{display:block;max-width:100%;border:1px solid var(--line,#E4DED6);
  border-radius:8px;margin-bottom:8px}
.sop-aviso{position:fixed;left:50%;bottom:22px;transform:translateX(-50%);z-index:400;
  background:#241B2E;color:#fff;font-family:var(--sans);font-size:14.5px;
  padding:13px 20px;border-radius:10px;box-shadow:0 10px 36px rgba(0,0,0,.3);
  max-width:92vw;text-align:center}
@media (max-width: 860px){
  .sidebar-soporte{margin-top:10px}
}


/* ─── HUECOS CARGANDO ────────────────────────────────────────────────────────
   Por qué existe: el marcado de la maqueta se inyecta al DOM CON sus datos de
   ejemplo dentro y después se sobrescribe con los de la API. Entre una cosa y
   otra el usuario veía, durante un instante, un nombre de paciente, un RFC y un
   régimen fiscal inventados. Fernando lo reportó el 24-oct-2026: «parece un
   parpadeo defectuoso». Medido: 20 de 22 huecos de PMedic y 12 de 22 de PH
   llegaban a la pantalla con dato de muestra.
   Ahora el hueco llega VACÍO y con esta clase, y el dato de ejemplo no se ve
   nunca. `pon()` la quita al escribir el dato real. */
.hueco-cargando{
  display:inline-block; min-width:5.5em; min-height:1em; border-radius:4px;
  background:linear-gradient(90deg,
    var(--borde,#E3E3E3) 25%, var(--fondo-suave,#F2F2F2) 50%, var(--borde,#E3E3E3) 75%);
  background-size:200% 100%; animation:hueco-brillo 1.2s ease-in-out infinite;
  color:transparent;
}
@keyframes hueco-brillo{ 0%{background-position:200% 0} 100%{background-position:-200% 0} }

/* Sin animación para quien la pidió apagada: se queda el bloque gris quieto,
   que sigue diciendo «esto está cargando» sin moverse. */
@media (prefers-reduced-motion: reduce){
  .hueco-cargando{ animation:none; background:var(--borde,#E3E3E3) }
}

/* ESTAS REGLAS LAS BORRÉ YO Y LAS RECUPERÉ DEL HISTORIAL, NO DE MEMORIA.
   Al limpiar el CSS de una pantalla que retiré, el recorte por índices se llevó
   también lo de al lado: cuatro clases desaparecieron sin un solo error — la
   pantalla seguía funcionando, sólo que sin estilo en cuatro sitios.
   TERCERA VEZ EL MISMO DÍA que un borrado por rango se lleva lo contiguo: antes
   un `git checkout --` sobre un archivo entero que deshizo una edición buena, y
   antes el recorte del CSS de la nota. La regla ya estaba escrita en nuestra
   deuda —borrar por LITERAL EXACTO, nunca por rango— y la rompí tres veces en
   un día. Lo que las salvó fue `clases-definidas.py`, que las echó de menos. */
.lista-actos{display:block}
/* Una celda atenuada SIGUE SIENDO UNA CELDA: sólo color y tamaño, sin caja
   propia. `campo-ayuda` trae la suya y partía la línea del renglón. */
.celda-suave{color:var(--texto-suave,#5A6672);font-size:12.5px}
.celda-acciones{white-space:nowrap}
.celda-acciones .btn{margin-right:6px}
.celda-acciones .btn:last-child{margin-right:0}
.tabla-desliza .celda-acciones{overflow:visible}
/* La tarjeta es el marco del pendiente, así que tiene que ser su bloque
   contenedor. Esta línea se perdió en el destrozo del CSS y el síntoma fue
   exacto: el texto de «Antecedentes médicos» se salía 32 px de su tarjeta,
   porque sin `position:relative` el `inset:0` se medía contra un antepasado
   más grande. Lo cazó `nada-se-sale.js` en la batería. */
.exp-grid>.card{position:relative}
.pendiente-centrado{
  position:absolute;inset:0;z-index:2;display:flex;align-items:center;
  justify-content:center;text-align:center;padding:0 var(--sp-4,16px);
  color:var(--texto-suave,#5A6672);font-style:italic;font-size:13px;
  line-height:1.5;pointer-events:none}
/* En «Evolución del paciente» no se puede centrar en vertical: caería encima de
   los dos selectores. Ahí sólo se centra en X y se queda donde estaba. */
.pendiente-centrado.solo-x{
  position:static;display:block;text-align:center;padding:var(--sp-3,12px) 0 0}

/* ===== Expediente clínico · lo que el diseño no cubre ======================
   TRES REGLAS, LAS TRES POR ALGO QUE SE VIO EN UNA CAPTURA DE STAGING Y QUE
   NINGUNA PRUEBA PODÍA CAZAR: todas comprueban si el elemento EXISTE, y existía.
   Nada mide si se puede alcanzar con el dedo. */

/* La tabla del historial de notas lleva seis columnas y hasta dos botones por
   fila. En 1440 px las acciones salían cortadas por el borde derecho de la
   tarjeta, y lo que quedaba fuera era justo «Cerrar y firmar» y «Agregar
   corrección». Se desliza ella sola; la página nunca se mueve de lado. */
.tabla-desliza{overflow-x:auto;max-width:100%}
/* SIN `min-width`. La puse en 860 px «para que no se apretara» y el candado
   midió lo que eso significaba: el último botón de cada nota seguía 120 px
   fuera de la tarjeta. Una anchura mínima escogida a ojo es exactamente el
   defecto que esta regla venía a arreglar. Sin ella, el navegador encoge las
   columnas de texto —que sí pueden partirse— y las acciones, que no, caben. */
.tabla-desliza>table{width:100%}
.tabla-desliza td,.tabla-desliza th{word-break:break-word}

/* Las acciones de una fila no se parten en dos renglones ni estiran la columna:
   la fila de una nota tiene que leerse de un vistazo. */
.m2-acciones{white-space:nowrap}
.m2-acciones .btn{margin-right:6px}
.m2-acciones .btn:last-child{margin-right:0}

/* (g) EL REPARTO DE COLUMNAS DE LA TABLA DE NOTAS.
   La hoja de Edna le da a la última columna un 7 % —pensado para un enlace de
   «Ver todo»— y ahí no caben dos botones; con `table-layout:fixed` el resto se
   apretaba y la tabla salía, en palabras de Fernando, «desordenada». Se
   reparte de nuevo contando lo que de verdad va en cada columna. No se toca
   `pmedic.css`: es la hoja de Edna, y esto es una decisión nuestra sobre un
   contenido que ella no tenía cuando la escribió. */
.tabla-desliza .tabla-valoraciones th:nth-child(1),
.tabla-desliza .tabla-valoraciones td:nth-child(1){width:11%}
.tabla-desliza .tabla-valoraciones th:nth-child(2),
.tabla-desliza .tabla-valoraciones td:nth-child(2){width:18%}
.tabla-desliza .tabla-valoraciones th:nth-child(3),
.tabla-desliza .tabla-valoraciones td:nth-child(3){width:18%}
.tabla-desliza .tabla-valoraciones th:nth-child(4),
.tabla-desliza .tabla-valoraciones td:nth-child(4){width:18%}
.tabla-desliza .tabla-valoraciones th:nth-child(5),
.tabla-desliza .tabla-valoraciones td:nth-child(5){width:11%}
.tabla-desliza .tabla-valoraciones th:nth-child(6),
.tabla-desliza .tabla-valoraciones td:nth-child(6){width:24%;text-align:right}

/* (a) Un marco pensado para varias filas de datos, con un pendiente de una
   línea dentro, parece un campo vacío. Sin dato, sin marco. */
.sin-marco{border:0 !important;border-radius:0 !important;padding:0 !important}

/* Y las tres tarjetas del renglón cierran a la misma altura. No lo hacían: la
   fila medía 219 px y las dos de la derecha 207, pegadas ABAJO —medido, no
   supuesto: `top` 263 contra 275, con el mismo borde inferior en 482—. Fernando
   lo vio antes que cualquier prueba: «al estar en el mismo renglón, se ven
   mal». `align-items` en la rejilla estaba en `normal`, que debería estirar, y
   no estiraba; se dice explícitamente en vez de confiar en el valor por
   omisión. Nada mide la altura de una tarjeta contra la de su vecina, así que
   esto lo comprueba ahora `m2-navegador.js`. */
.exp-grid{align-items:stretch}
.exp-grid>.card{align-self:stretch}
/* Y LA CAUSA DE VERDAD, que no era el estiramiento: `pmedic.css:212` apila las
   tarjetas de una columna con `.card + .card{margin-top:var(--hueco)}`, y la
   propia Edna ya había escrito la excepción para sus rejillas —líneas 216-218,
   con el comentario de cuando le pasó—. La lista dice `[class*="grid-"]`, con
   el guion detrás, y esta rejilla se llama `exp-grid`: el «grid» va al final.
   Así que la segunda y la tercera tarjeta del renglón nacían con 12 px de
   margen arriba y cerraban 12 px más cortas. Medido: `margin-top: 12px` en las
   dos, `0px` en la primera.
   La excepción va en NUESTRA hoja y no en la suya: el patrón es de ella y
   funciona; lo que falta es que esta rejilla entre, y es nuestra pantalla la
   que la usa. */
.exp-grid>.card+.card{margin-top:0}

/* (e) Un control cuyo destino todavía no existe se ve, y se ve que no está
   disponible. Visible lo pide la regla de «nada se esconde: se explica»; que
   parezca pulsable es lo que convierte la explicación en una mentira. */
.card-accion:disabled,.btn:disabled,[data-apagado="1"]{
  opacity:.5;cursor:not-allowed;pointer-events:auto}

/* La pantalla de la nota clínica: sus tarjetas se apilan con aire, porque una
   historia clínica son cinco campos largos y leerlos pegados cansa. */
#m2-nota>.card{margin-bottom:var(--sp-4,16px)}
#m2-nota textarea{width:100%;min-height:88px;resize:vertical}

/* UN RADIO DE PÍLDORA NO SOBREVIVE AL CAMBIO DE ALTURA.
   `pmedic.css:1441` le da `border-radius:999px` a todo `.campo-form .input`, y
   en un campo de 38 px eso es una píldora — una convención deliberada y
   correcta, la de los buscadores y los filtros. Al convertir los campos
   clínicos en textarea de 79 px, el MISMO valor deja de leerse como «esquina
   redondeada» y pasa a ser un estadio: la curva se come 40 px por esquina, el
   50 % del alto. Fernando lo notó sin saber el número —«no recuerdo haberlo
   visto antes»— y tenía razón: no se ve porque no se hace.
   El radio de una caja alta se acota; aquí al del propio modal, 12 px, para que
   el campo y la ventana que lo contiene hablen el mismo idioma. */
/* CORRECCIÓN, 29 oct. Esta regla estaba acotada a `#modal-valoracion`, y el
     acotamiento era el error: el radio se había resuelto para LA PANTALLA donde
     Fernando vio el problema, no para la FORMA de campo que lo causa. Sus dos
     textarea de maqueta —`#m1-notas-textarea` en la ficha y `#ob-texto` en
     observaciones— llevan `class="input"` dentro de un `.campo-form`, así que
     heredaban los 999px y salían como pastillas de seis renglones. Nadie lo
     había medido porque el parche anterior tapaba el único sitio que yo había
     mirado.
     La regla va por forma, no por sitio: una línea es píldora, varias líneas
     son 12 px. Vale para todo modal, el de hoy y el que Edna mande mañana.
     Gana por especificidad (0,2,1 contra 0,2,0): sin `!important`. */
  /* Y la regla general tampoco podía ser global: `plataforma.css` la comparten
     los dos negocios, y la píldora es el idioma de PMedic, NO del proyecto. La
     hoja de PH deja `.input` en `--r-md` y no tiene regla de píldora en ningún
     lado: aplicarla a secas le cambiaba la forma a todos los campos de un
     producto que está en producción y que no llevo. Va acotada por
     `data-negocio`, comprobado en caliente: el atributo dice «pmedic» y el
     selector empata.

     LA CAUSA RAÍZ, que no era el radio. En la maqueta de Edna cada campo va
     envuelto en `.campo-form`, y ahí `pmedic.css:1441` lo vuelve píldora. Pero
     nuestro JS envuelve con `.campo` —otro envoltorio, de `plataforma.css`—
     que da `--r` (8px). Dos envoltorios, dos formas, en la misma ventana: por
     eso en «Ausencias del equipo» los dos desplegables que construye
     `m3-ausencias.js` salían de 8px al lado de campos de maqueta en píldora.
     No era un campo mal puesto; era un envoltorio que no hablaba el idioma de
     la casa. Se igualan los dos envoltorios en vez de parchar cada pantalla.

     Y la forma la decide EL CAMPO, no su sitio: una línea es píldora, varias
     líneas son 12px —una píldora de seis renglones es un estadio—. Así cubre
     también lo que Edna mande mañana, sin otra regla. */
  html[data-negocio="pmedic"] .campo input:not([type="checkbox"]):not([type="radio"]),
  html[data-negocio="pmedic"] .campo select,
  html[data-negocio="pmedic"] .input,
  html[data-negocio="pmedic"] .select{border-radius:999px}
  html[data-negocio="pmedic"] .campo textarea,
  html[data-negocio="pmedic"] textarea.input,
  html[data-negocio="pmedic"] textarea.select{border-radius:var(--r-lg,12px)}

/* ===== Agenda · la columna de filtros mide lo mismo que el calendario =====
   Treinta y un servicios, uno por renglón, hacían crecer la columna y empujar
   la página. El primer intento fue plegar la leyenda tras un botón, y Fernando
   lo rechazó midiendo lo que yo no había medido: al expandirla el contenedor
   CRECE igual. El plegado no resolvía el problema, lo movía a la segunda
   pulsación.
   Lo que sí lo resuelve: la fila tiene una altura estable, decidida por el
   calendario, y la lista de servicios se desliza dentro de lo que sobra. Nada
   de lo que pase en la leyenda mueve la página.
   `min-height:0` es la pieza que no se puede omitir: sin ella un hijo flexible
   no se deja encoger por debajo de su contenido y el `overflow` nunca entra. */
#m3-vista-calendario{align-items:stretch}
/* SÓLO CON `overflow` NO BASTABA, y está medido: la tarjeta se iba a 1203 px
   contra 747 del calendario. En una rejilla la altura de la fila es la del
   contenido MÁS ALTO, y `overflow:hidden` no impide que un elemento declare su
   altura intrínseca — sólo recorta lo que se sale de ella.
   El envoltorio no tiene altura propia, así que la fila la decide el
   calendario; la tarjeta, absoluta dentro de él, se estira a esa altura. */
.col-filtros{position:relative;min-height:0}
/* EL ABSOLUTO ES NUESTRO, NO DE SU TARJETA. Antes caía sobre `.m3-filtros` y
   costaba seis desviaciones de maqueta: `position` y `min-width` en `.card`,
   `.m3-filtros` y `#m3-filtros`. El `min-width` no lo declaró nadie —
   `min-width:auto` sólo sobrevive como `auto` en hijos de flex o de grid, y una
   caja absoluta deja de ser hijo del grid, así que computa 0px—. Con esta caja
   de en medio su tarjeta vuelve a ser estática y vuelve a ser hijo flexible:
   las seis desaparecen y en pantalla no cambia nada.
   `height:100%` y no sólo `inset:0`: con `top` y `bottom` a cero el alto
   debería deducirse del envoltorio, y medido NO lo hacía — resolvía 1203 px
   dentro de un contenedor de 747. Una caja absoluta sobre-restringida hace que
   el navegador descarte `bottom` y mande la altura del contenido. */
.col-filtros>.col-filtros-caja{
  position:absolute;top:0;left:0;right:0;height:100%;
  display:flex;flex-direction:column;min-height:0;overflow:hidden}
/* Su tarjeta llena la caja con `height:100%`, NO con `flex:1 1 auto`. Los dos
   se ven igual y uno cuesta tres desviaciones más: `flex:1 1 auto` pone
   `flex-grow:1`, y su maqueta dice 0 en `.card`, `.m3-filtros` y `#m3-filtros`.
   Para lo único que hacía falta ser hijo de flex —que `min-width` siga
   computando `auto`— basta estar DENTRO de la caja; no hace falta además
   pedirle que crezca. Medido: con `flex` quitado, de 7 desviaciones a 4. */
.col-filtros-caja>.m3-filtros{
  height:100%;margin:0;
  display:flex;flex-direction:column;min-height:0;overflow:hidden}
/* `!important`, Y AQUÍ ESTÁ LA RAZÓN, porque no se pone por gusto:
   `pmedic.css:2178` dice `.m3-filtros>*{flex:none!important}` — congela a TODOS
   los hijos de la tarjeta de filtros. Un `!important` no se gana con
   especificidad, se gana con otro `!important`; lo medí antes de escribirlo:
   mi `flex:1 1 auto` con selector de tres clases computaba `0 0 auto`.
   Se acota al envoltorio nuevo, así que fuera de esta disposición la regla de
   ella sigue mandando intacta. */
.col-filtros-caja>.m3-filtros>.m3-leyenda-lista{
  flex:1 1 auto!important;min-height:0;overflow-y:auto;overscroll-behavior:contain}
/* El título de la leyenda no se va con el deslizamiento: si se pierde, lo que
   queda es una lista de colores sin nombre. */
.col-filtros-caja>.m3-filtros>.m3-leyenda-titulo{flex:none}
/* En un teléfono las dos columnas se apilan: ahí un alto fijo sobra y lo que
   hace falta es que se vea entera. */
@media (max-width:860px){
  .col-filtros{position:static}
  .col-filtros>.col-filtros-caja{position:static;overflow:visible}
  .col-filtros-caja>.m3-filtros{overflow:visible}
  .col-filtros-caja>.m3-filtros>.m3-leyenda-lista{overflow:visible}
}

/* ── .busca-punto · la pinta CÓDIGO COMPARTIDO, así que su regla va aquí ─────
   `m3-ausencias.js:132` crea `H('span','busca-punto')` y ese archivo lo cargan
   LOS DOS NEGOCIOS: las ausencias del personal no son de Perritos House ni de
   PMedic, son de la agenda. La regla, en cambio, vivía sólo en la maqueta de PH
   (`diseno/ph.css:3006`), así que en PMedic ese punto salía sin medida ni
   redondeo —un `<span>` vacío de 0×0, invisible, y nadie se enteraría mirando
   PH—. Lo encontró clases-definidas.js: «pmedic: 1 clase(s) sin definir ·
   busca-punto».
   Son los mismos valores de la maqueta, sin color: el color lo decide quien
   dibuja y ahí no lo hay. Si Edna quiere otra medida, la cambia en su hoja y
   gana por orden de carga. */
.busca-punto{width:10px;height:10px;border-radius:50%;flex:none}

/* ── #ci-cupo · DOS HECHOS EN UN RENGLÓN, Y QUE NO SE CONFUNDAN ─────────────
   Ese banner decía sólo «Quedan 7 horarios libres» —huecos en la agenda de
   quien atiende— y ahora lleva además el tope de capacidad: 170 perritos en la
   casa a la vez, 13 familias por hike, 3 paseos al día. Puede haber siete
   horarios libres y la casa llena, así que llamar «cupo» a lo primero era
   invitar a leer «caben 7 perritos más».
   Mi primer intento los encadenó con « · » y la sesión de pantalla midió el
   resultado con datos reales: «Quedan 3 horarios libres · Quedan 7 de 8
   perritos…». Dos «Quedan N» contando cosas distintas: la misma confusión con
   otra forma. Por eso cada mitad lleva ETIQUETA («Agenda», y el nombre del
   cupo) y vive en su propio bloque.
   AQUÍ VA SÓLO LA ESTRUCTURA. El color, la tipografía y el tratamiento del
   caso «sin lugar» son de quien dibuja —la sesión de pantalla ya los tiene
   pensados con los tokens de la plataforma— y lo que pongo son las medidas
   para que el renglón no salga roto mientras llegan. Sus reglas ganan por
   orden de carga. */
#ci-cupo{display:flex;flex-wrap:wrap;gap:4px 16px;align-items:baseline}
.ci-cupo-bloque{display:inline-flex;gap:6px;align-items:baseline;min-width:0}
.ci-cupo-et{flex:none;font-size:11px;letter-spacing:.04em;text-transform:uppercase;opacity:.7}
.ci-cupo-num{font-weight:600;min-width:0}
/* El caso que no se puede enterar uno leyendo hasta el final del renglón. */
.ci-cupo-lleno .ci-cupo-num{font-weight:700}

/* ── EL COLOR DEL RENGLÓN DE CUPO · PH ──────────────────────────────────────
   La sesión de servidor dejó las medidas y ningún color, a propósito, para que
   el color lo pusiera quien lleva el diseño. Va aquí y sólo para PH: PMedic
   comparte `plataforma.css` y su formulario de agenda es otro.

   DOS BLOQUES Y DOS COSAS DISTINTAS. El de la izquierda cuenta huecos de la
   agenda de quien atiende; el de la derecha cuenta lugares en la casa. Pueden
   decir números parecidos y no tienen nada que ver: puede haber siete horarios
   libres y la casa llena. Por eso cada mitad lleva su etiqueta y un separador
   visible entre las dos — un punto medio no basta cuando los dos lados
   empiezan por un número.

   Y «SIN LUGAR» NO SE LEE: SE VE. Que una reserva se vaya a rechazar no puede
   depender de que alguien llegue al final del renglón. El bloque entero se
   tiñe con el mismo rojo del chip de riesgo —el que ya significa «para» en el
   resto de la plataforma—, así que no hay un código de color nuevo que
   aprender. */
[data-negocio="ph"] #ci-cupo{gap:6px 0; align-items:stretch}
[data-negocio="ph"] .ci-cupo-bloque{
  padding:6px 12px; border-radius:8px; align-items:baseline;
  background:var(--realce,rgba(92,58,107,.11));
  color:var(--morado,#2B1734);
}
/* El separador es el hueco, no un carácter: dos bloques con fondo propio ya se
   leen como dos cosas y un «·» entre ellos sólo añade ruido. */
[data-negocio="ph"] .ci-cupo-bloque + .ci-cupo-bloque{margin-left:10px}
[data-negocio="ph"] .ci-cupo-et{opacity:1; font-weight:600; color:var(--texto-suave,#6B6B6B)}
[data-negocio="ph"] .ci-cupo-num{color:var(--morado,#2B1734)}
[data-negocio="ph"] .ci-cupo-lleno{
  background:rgba(179,38,30,.13);
  box-shadow:inset 0 0 0 1px rgba(179,38,30,.38);
}
[data-negocio="ph"] .ci-cupo-lleno .ci-cupo-et,
[data-negocio="ph"] .ci-cupo-lleno .ci-cupo-num{color:#8E1E18}

/* ── .m1-aviso-cobranza · decir que no se puede filtrar SIN borrar la lista ──
   Pulsar «Pagado» en Gestión de Clientes reemplazaba la tabla entera por el
   aviso de que la cobranza no tiene ruta, y para recuperar a sus clientes
   había que acordarse de pulsar «Todos». Lo vio Fernando el 2-nov-2026.
   Ahora el aviso vive FUERA de la tabla y los renglones se quedan. Hereda el
   aspecto de `.vacio` —que es el que la plataforma ya usa para «aquí no hay
   nada»— y sólo añade su sitio: encima de la tabla, con aire. */
.m1-aviso-cobranza{display:block;margin:0 0 var(--sp-3,12px);padding:10px 14px;
  border-radius:var(--r-md,8px);white-space:normal;text-align:left}

/* ═══ IMPRIMIR · sólo el recibo ═══════════════════════════════════════════
   El botón «Imprimir» de su `modal-recibo` llama a `window.print()`, y sin
   estas reglas eso imprimía la aplicación ENTERA alrededor del recibo: el
   menú lateral, la barra de arriba, la lista de clientes que había detrás y
   la ficha abierta. Cuatro hojas para entregar un papel de ocho renglones.

   No había NINGUNA regla `@media print` en todo el proyecto —ni aquí ni en las
   hojas de diseño—, así que esto es la primera vez que se dice qué se imprime.
   La maqueta del recibo es de Edna; esto sólo decide qué se esconde.

   El recibo se marca con `.recibo-hoja` desde `m1-ficha-ph.js`. Se esconde
   todo y se vuelve a mostrar la cadena de padres hasta la hoja, porque
   esconder el `body` esconde también lo que cuelga de él. */
@media print {
  body > *:not(.modal-backdrop) { display: none !important; }
  .modal-backdrop { position: static !important; display: block !important;
                    background: none !important; padding: 0 !important; }
  .modal-backdrop:not(:has(.recibo-hoja)) { display: none !important; }
  .modal-caja { box-shadow: none !important; border: 0 !important; max-width: none !important;
                width: auto !important; max-height: none !important; }
  .modal-header, .modal-pie, .modal-cerrar { display: none !important; }
  .modal-body { overflow: visible !important; padding: 0 !important; }
  .recibo-hoja { max-width: 78mm; font-size: 11px; }
  .recibo-hoja .tabla th, .recibo-hoja .tabla td { padding: 3px 4px; font-size: 11px; }
  /* Un fondo de color no se imprime por defecto y los chips quedaban en blanco
     sobre blanco. El recibo no usa chips, pero la hoja sí pide respetar color
     por si alguien imprime a color. */
  * { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}
