/* Visión · hoja de estilo única
   Identidad de Agarimo Comunicación: gris grafito, blanco y negro. Rubik. */

:root{
  --grafito:#3C3C3B;
  --grafito-claro:#5E5E5C;
  --tinta:#141413;
  --papel:#FFFFFF;
  --fondo:#F5F5F4;
  --fondo-2:#EBEBE9;
  --linea:#DCDCD9;
  --linea-fuerte:#B8B8B4;
  --apagado:#6F6F6D;
  --radio:3px;
  --sombra:0 1px 2px rgba(20,20,19,.06);
  --ancho-lateral:232px;
  /* Señales (1.221.0): verde lo que mejora o va bien, rojo lo que empeora o
     se pierde, ámbar lo justo. Los mismos valores que Senal::VERDE/ROJO/AMBAR,
     que son los que usan los PDF: la prueba 257 compara los dos sitios. */
  --bien:#1E7A4B;
  --mal:#B3261E;
  --justo:#8A6100;
}

/* El «hidden» del navegador es «display:none» a secas, y CUALQUIER clase con su
   propio «display» —.boton, .multiselect-opcion, .barra-seleccion— le gana por
   especificidad. El elemento se marca como oculto en JavaScript y se sigue
   viendo, sin error en ninguna parte.
   Ha pasado tres veces en esta hoja y cada una se tapó con una regla suelta.
   Esta es la general: si algo lleva «hidden», no se ve, y punto. */
[hidden]{display:none !important}

*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  font-family:"Rubik",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  font-size:15px;line-height:1.55;color:var(--tinta);background:var(--fondo);
  -webkit-font-smoothing:antialiased;
}
a{color:var(--tinta);text-decoration-color:var(--linea-fuerte);text-underline-offset:2px}
a:hover{text-decoration-color:var(--grafito)}
h1,h2,h3,h4{margin:0;font-weight:600;letter-spacing:-.01em}
code,.mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.88em}
/* Un «pre» con una URL dentro —la que arma el generador de UTM, un JSON-LD, una
   línea de log— no parte por sí solo y empuja la página entera hacia la
   derecha. Se parte por donde sea: una URL no tiene espacios por los que
   cortar, así que «anywhere» es lo único que sirve. Las tablas y los bloques de
   código que sí deben desplazarse llevan su propio contenedor con scroll. */
pre.mono,pre.bloque-codigo{white-space:pre-wrap;overflow-wrap:anywhere;word-break:break-word}

/* ---------- estructura ----------
   Dos navegaciones y cada una en su sitio: la barra de arriba dice adónde ir
   dentro de Visión, y la de la izquierda dónde estás dentro de un proyecto. */
.app{display:flex;flex-direction:column;min-height:100vh}
.cuerpo-app{display:grid;grid-template-columns:var(--ancho-lateral) minmax(0,1fr);flex:1;min-height:0}

/* La barra general, arriba de todo */
/* La altura es un MÍNIMO, no una medida fija.

   Con `height` fija, el día que la barra creció —al agrupar el menú en
   desplegables— el menú saltó de línea y la segunda fila se quedó FUERA del
   fondo gris: letra blanca sobre el blanco de la página, ilegible, y solo por
   debajo de cierto ancho de ventana. La barra tiene que poder crecer con lo que
   lleva dentro. */
.barra-superior{
  background:var(--grafito);color:#fff;display:flex;align-items:center;gap:22px;
  padding:7px 20px;min-height:54px;position:sticky;top:0;z-index:20;
}
.marca{
  display:flex;align-items:baseline;gap:8px;text-decoration:none;color:#fff;
  flex:0 0 auto;white-space:nowrap;
}
.marca .nombre{font-size:19px;font-weight:700;letter-spacing:-.02em;line-height:1}
.marca .sub{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:rgba(255,255,255,.5)}
/* La caja de buscar, en la barra: discreta hasta que se usa */
.buscador{flex:0 1 220px;min-width:120px;display:flex}
.buscador input[type=search]{
  width:100%;padding:6px 10px;border-radius:var(--radio);font:inherit;font-size:13px;
  background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.22);color:#fff;
}
.buscador input[type=search]::placeholder{color:rgba(255,255,255,.55)}
.buscador input[type=search]:focus{
  outline:none;background:#fff;color:var(--grafito);border-color:#fff;
}
.buscador input[type=search]:focus::placeholder{color:var(--apagado)}
/* Texto solo para quien lee la pantalla con un lector.
 *
 * Va ANCLADO con «left/top», y esa es la parte que importa. Sin anclar, se
 * queda en su posición estática, y si esa posición cae dentro de una tabla
 * ancha con scroll propio —la barra de acciones de una fila— su bloque
 * contenedor acaba siendo la página entera: el elemento se pinta a 460 px del
 * borde y arrastra la página de lado 71 px, en un sitio donde no se ve nada
 * porque mide un píxel y está recortado. Costó encontrarlo justamente por eso.
 */
.oculto{
  position:absolute;left:0;top:0;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;
}
.menu-general{display:flex;align-items:center;gap:2px;flex:1 1 auto;min-width:0;flex-wrap:wrap}
.menu-general a,.menu-desplegable summary{
  display:inline-flex;align-items:center;gap:6px;padding:6px 10px;border-radius:var(--radio);
  color:rgba(255,255,255,.8);text-decoration:none;font-size:13.5px;white-space:nowrap;
}
.menu-general a:hover,.menu-desplegable summary:hover{background:rgba(255,255,255,.1);color:#fff}
.menu-general a.activo,.menu-desplegable summary.activo{background:#fff;color:var(--grafito);font-weight:500}
.menu-desplegable{position:relative}
/* Cerrado, el panel NO ocupa sitio. Se escribe aquí en vez de dejárselo al
   navegador: medido en un móvil de 390 px, el panel de un desplegable cerrado
   seguía maquetándose —112 px de ancho con 226 px de enlaces dentro— y
   empujaba la página entera de lado en cualquier pantalla. El navegador esconde
   lo que hay dentro de un «details» cerrado, pero deja de hacerlo en cuanto
   alguien le toca el «display» a sus hijos, y aquí se le toca al abrirse. Con
   la regla escrita no depende de eso. */
.menu-desplegable:not([open]) > .desplegado{display:none}
.menu-desplegable summary{cursor:pointer;list-style:none}
.menu-desplegable summary::-webkit-details-marker{display:none}
.menu-desplegable summary::after{content:"▾";font-size:10px;opacity:.7}
.menu-desplegable[open] > .desplegado{
  position:absolute;top:calc(100% + 6px);left:0;z-index:30;
  /* «max-content» con tope: el panel mide lo que miden sus entradas, pero sin
     pasarse de la pantalla. Con solo «min-width» se quedaba estrujado a los
     112 px del resumen que lo abre y sus enlaces —«Recomendación semanal»—
     sobresalían del panel y, con él pegado al borde derecho, de la ventana:
     eso arrastraba la página ENTERA de lado, barra y menú incluidos. */
  width:max-content;min-width:190px;max-width:min(320px, calc(100vw - 24px));
  background:var(--grafito);border-radius:var(--radio);padding:6px;
  display:flex;flex-direction:column;gap:1px;box-shadow:0 8px 24px rgba(0,0,0,.28);
}
.menu-desplegable .desplegado a{
  display:block;padding:7px 10px;border-radius:var(--radio);font-size:13.5px;
  color:rgba(255,255,255,.82);text-decoration:none;
}
.menu-desplegable .desplegado a:hover{background:rgba(255,255,255,.1);color:#fff}
.menu-desplegable .desplegado a.activo{background:#fff;color:var(--grafito);font-weight:500}
/* Abierto, el resumen se queda marcado, pero con los colores de la barra.
   Este es el fallo que había: más abajo hay un «details[open] > summary» con
   fondo claro pensado para los desplegables del contenido, y también alcanzaba
   al menú de arriba —fondo casi blanco y letra blanca encima, ilegible—. Se
   sobrescribe aquí, que es más específico, y no se toca el otro. */
.menu-desplegable[open] > summary{background:rgba(255,255,255,.16);color:#fff}
.menu-desplegable[open] > summary.activo{background:#fff;color:var(--grafito)}
.menu-desplegable[open] > summary::after{transform:rotate(180deg)}
.menu-desplegable summary::after{transition:transform .12s}
.menu-desplegable summary:focus-visible{outline:2px solid #fff;outline-offset:1px}

/* La barra del proyecto, a la izquierda */
/* Se pega justo debajo de la barra. La altura de la barra la mide el navegador
   y la deja en --alto-barra, porque cuando el menú salta de línea deja de ser
   54 px y una barra lateral pegada a la altura de ayer se mete por debajo. */
.lateral{
  background:var(--fondo-2);border-right:1px solid var(--linea);
  padding:18px 0;display:flex;flex-direction:column;gap:16px;
  position:sticky;top:var(--alto-barra,54px);
  height:calc(100vh - var(--alto-barra,54px));overflow-y:auto;
}
/* El cambio rápido de proyecto, arriba del todo de la barra.
   Ocupa el ancho entero y el dominio se recorta con puntos suspensivos: los
   dominios largos hacían crecer la barra y descuadraban la pantalla entera. */
.selector-proyecto{display:flex;gap:6px;padding:0 16px 4px;align-items:center}
.selector-proyecto select{
  flex:1 1 auto;min-width:0;text-overflow:ellipsis;font-size:13px;padding:7px 10px;
}

.lateral-cabeza{padding:0 16px;display:flex;flex-direction:column;gap:2px}
.lateral-cabeza .volver{
  font-size:11.5px;color:var(--apagado);text-decoration:none;margin-bottom:4px;
}
.lateral-cabeza .volver:hover{color:var(--tinta)}
.lateral-cabeza .titulo{
  font-size:15px;font-weight:600;color:var(--tinta);text-decoration:none;
  letter-spacing:-.01em;line-height:1.25;overflow-wrap:anywhere;
}
.lateral-cabeza .sub{font-size:11.5px;color:var(--apagado)}
.menu{display:flex;flex-direction:column;gap:1px;padding:0 8px}
.menu a{
  display:block;padding:6px 10px;border-radius:var(--radio);color:var(--apagado);
  text-decoration:none;font-size:13.5px;overflow-wrap:anywhere;
}
.menu a:hover{background:var(--papel);color:var(--tinta)}
.menu a.activo{background:var(--grafito);color:#fff;font-weight:500}
.menu .grupo{
  font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--apagado);
  padding:14px 10px 4px;font-weight:600;opacity:.75;
}
/* Los dominios, un punto menos que el resto del menú: son cadenas largas y sin
   espacios, y a 13,5 px partían en dos líneas media lista. */
.menu a.dominio{font-size:12.5px}
.lateral .pie{margin-top:auto;padding:0 16px;font-size:11.5px;color:var(--apagado)}

/* ------------------------------------------------- la barra lateral, plegable
   Plegada no deja un carril de iconos sino solo el botón: las secciones de
   Visión son nombres, no dibujos, y un carril de iconos inventados obliga a
   aprenderse un idioma nuevo para ahorrar veinte píxeles.

   El estado viaja en una galleta y lo pinta el servidor en el <html>, así que
   la barra nunca sale abierta para cerrarse de golpe al terminar de cargar. */
.lateral-plegar{
  align-self:flex-end;margin:0 12px;flex:0 0 26px;width:26px;height:26px;padding:0;
  border:1px solid var(--linea);background:var(--papel);color:var(--apagado);
  border-radius:var(--radio);cursor:pointer;line-height:1;font-size:15px;
}
.lateral-plegar::before{content:"‹"}
.lateral-plegar:hover{color:var(--tinta);border-color:var(--linea-fuerte)}
.lateral-plegar:focus-visible{outline:2px solid var(--grafito);outline-offset:2px}
.lateral-contenido{display:flex;flex-direction:column;gap:16px;flex:1;min-height:0}

html.lateral-plegado .cuerpo-app{grid-template-columns:46px minmax(0,1fr)}
html.lateral-plegado .lateral-contenido{display:none}
html.lateral-plegado .lateral-plegar{align-self:center;margin:0}
html.lateral-plegado .lateral-plegar::before{content:"›"}

.principal{display:flex;flex-direction:column;min-width:0}
.cabecera{
  background:var(--papel);border-bottom:1px solid var(--linea);
  padding:16px 30px;display:flex;align-items:center;justify-content:space-between;gap:16px;
}
.cabecera h1{font-size:20px}
.identidad{display:flex;align-items:center;gap:12px;font-size:13.5px;color:rgba(255,255,255,.7);flex:none}
.identidad .quien{text-align:right;line-height:1.25;font-size:12px}
.identidad .quien strong{display:block;color:#fff;font-weight:500;font-size:13px}
.barra-superior .boton.secundario,.barra-superior .boton.secundario:link,.barra-superior .boton.secundario:visited{
  background:transparent;border:1px solid rgba(255,255,255,.35);color:#fff;
}
.barra-superior .boton.secundario:hover{background:rgba(255,255,255,.14);border-color:rgba(255,255,255,.6)}
/* El contenido ocupa lo que haya. La caja de 1180 px venía de cuando esto eran
   fichas y formularios; con tablas de veinte columnas y gráficos de cartera,
   dejar medio monitor en blanco es tirar la pantalla que se ha pagado. Lo que
   sí sigue teniendo medida es lo que se lee seguido: la prosa se corta en 70
   caracteres y los campos en 520 px, porque una línea de texto de dos mil
   píxeles no la lee nadie. */
.contenido{padding:26px 30px 70px;max-width:none}

/* ---------- avisos ---------- */
.avisos{display:flex;flex-direction:column;gap:8px;margin-bottom:20px}
.aviso{
  padding:11px 14px;border-radius:var(--radio);border:1px solid var(--linea);
  background:var(--papel);font-size:14px;border-left:3px solid var(--grafito);
}
.aviso.error{border-left-color:var(--tinta);background:var(--fondo-2)}

/* ---------- tarjetas ---------- */
.rejilla{display:grid;gap:14px}
/* «min(N, 100%)» y no «N» a secas en el mínimo de la columna.
   Un minmax(320px,·) dentro de un hueco de 316 px no cabe, y la rejilla se
   pasa de ancho en vez de encoger: cuatro píxeles que arrastran la página. Con
   «min()», cuando no cabe el mínimo pasa a ser el ancho disponible. */
.rejilla.c4{grid-template-columns:repeat(auto-fit,minmax(min(190px,100%),1fr))}
.rejilla.c3{grid-template-columns:repeat(auto-fit,minmax(min(250px,100%),1fr))}
.rejilla.c2{grid-template-columns:repeat(auto-fit,minmax(min(320px,100%),1fr))}
.tarjeta{background:var(--papel);border:1px solid var(--linea);border-radius:var(--radio);padding:16px 18px;box-shadow:var(--sombra)}
.tarjeta h3{font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--apagado);margin-bottom:8px}
.tarjeta .cifra{font-size:30px;font-weight:600;letter-spacing:-.02em;line-height:1;font-variant-numeric:tabular-nums}
.tarjeta .pie{font-size:12.5px;color:var(--apagado);margin-top:6px}

/* La comparación entre periodos: la cifra del tramo con el que se compara va
   debajo de la principal y más pequeña, en el color de su línea del gráfico.
   Los dos colores son lo único que ata «esta cifra» con «esta línea»: sin eso,
   dos números en una tarjeta son solo dos números. */
.tarjeta.comparada .cifra{color:#2a78d6}
.tarjeta .cifra-comparada{
  font-size:19px;font-weight:600;line-height:1;margin-top:5px;
  font-variant-numeric:tabular-nums;color:#eb6834;
}
.muestra-serie{
  display:inline-block;width:22px;height:3px;border-radius:2px;
  vertical-align:middle;margin-right:5px;
}
/* A rayas, no solo de otro color: uno de cada doce hombres no distingue el azul
   del naranja, y la leyenda tiene que decir cuál es cuál sin el color. */
.muestra-serie.rayada{
  background-image:repeating-linear-gradient(90deg,
    transparent 0,transparent 3px,var(--papel) 3px,var(--papel) 5px);
}

.bloque{background:var(--papel);border:1px solid var(--linea);border-radius:var(--radio);box-shadow:var(--sombra);margin-bottom:20px}
/* «flex-wrap» y no una línea rígida: la cabecera lleva el título a la izquierda
   y a la derecha los botones de la pantalla —«Añadir desde Bing», «Comprobar
   posiciones ahora»— y en un móvil no caben los dos en la misma línea. Sin
   esto, los botones se salían de la pantalla y había que arrastrar la página
   entera de lado para verlos. */
.bloque > header{padding:14px 18px;border-bottom:1px solid var(--linea);display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.bloque > header h2{font-size:15px}
/* Un titular que es una URL no tiene por dónde partirse, y en el móvil se sale
   de la pantalla arrastrando la página entera con él. Pasó en la ficha de una
   página del rastreo y en la mesa de trabajo de Enlazado, que titulan con la URL
   que se está mirando. El «min-width:0» hace falta además del «overflow-wrap»:
   dentro de un flex, un hijo no baja de su tamaño de contenido sin él, así que
   la regla de partir palabras no llegaba a aplicarse nunca. */
.bloque > header h1,
.bloque > header h2{min-width:0;overflow-wrap:anywhere}
/* El relleno del cuerpo de un bloque.
   Va también al que cuelga de un FORM, porque el formulario de las acciones en
   lote tiene que envolver la tabla y su barra —uno dentro de otro no es HTML
   válido, así que va por fuera— y con «hijo directo» a secas esos cuerpos se
   quedaban sin relleno: los campos y los botones salían pegados al borde de la
   tarjeta, mientras que el bloque de al lado respetaba sus dieciocho píxeles.
   Pasaba en el estudio de keywords, en el Rank Tracker, en la bandeja y en
   incidencias; se veía enseguida y costaba encontrarlo, porque el CSS estaba
   bien escrito y lo que fallaba era el sitio del formulario en el marcado. */
.bloque > .cuerpo,
.bloque > form > .cuerpo{padding:18px}

/* Un bloque que se pliega. Es un «details» y no un botón con JavaScript porque
   así funciona también con la política de contenido puesta, y porque el
   navegador ya sabe hacerlo. El «summary» imita la cabecera de un bloque para
   que no se note que por dentro es otra cosa. */
details.bloque.plegable > summary{
  padding:14px 18px;display:flex;align-items:center;gap:12px;cursor:pointer;
  list-style:none;user-select:none;
}
details.bloque.plegable > summary::-webkit-details-marker{display:none}
details.bloque.plegable > summary::after{
  content:"Mostrar";margin-left:auto;font-size:12px;color:var(--apagado);
  border:1px solid var(--linea-fuerte);border-radius:var(--radio);padding:4px 10px;
}
details.bloque.plegable[open] > summary::after{content:"Ocultar"}
details.bloque.plegable[open] > summary{border-bottom:1px solid var(--linea)}
details.bloque.plegable > summary:hover{background:var(--fondo-2)}
details.bloque.plegable > summary h2{font-size:15px}
details.bloque.plegable > summary:focus-visible{outline:2px solid var(--grafito);outline-offset:-2px}
.bloque > .cuerpo.sin-relleno,
.bloque > form > .cuerpo.sin-relleno{padding:0}
/* Un «.cuerpo» dentro de otro. El de fuera lleva «sin-relleno» para que la
   tabla llegue al borde de la tarjeta, y el de dentro es el texto que la
   acompaña —el «todavía no hay nada», la nota de debajo—, que sí tiene que
   respetar el margen. El selector de hijo directo de arriba no llega hasta él
   y ese texto salía pegado al borde, que es el fallo que se ve en siete
   pantallas. */
.bloque .cuerpo .cuerpo{padding:18px}
.bloque .cuerpo .cuerpo.sin-relleno{padding:0}
/* Y lo que NO sangra aunque viva dentro de un «.cuerpo sin-relleno».
   El bloque se marca sin relleno para que la TABLA llegue al borde de la
   tarjeta; lo que la acompaña —la nota del asterisco de un volumen del país, un
   párrafo de aviso, una rejilla con dos tablitas, la barra de acciones— no es la
   tabla, y sin relleno sale pegado al borde: en una pantalla de móvil parece
   texto cortado, que es justo lo que se vio en el estudio de keywords.
   Se arregla aquí, en una regla, y no acordándose en cada una de las 249 veces
   que la aplicación escribe «sin-relleno». Lo que sangra a propósito —la tabla,
   su caja con desplazamiento, el tablero de contenidos, un «.cuerpo» anidado,
   las pestañas— se queda fuera de la lista a propósito. */
.cuerpo.sin-relleno > p,
.cuerpo.sin-relleno > ul,
.cuerpo.sin-relleno > ol,
.cuerpo.sin-relleno > h3,
.cuerpo.sin-relleno > .nota,
.cuerpo.sin-relleno > .rejilla,
.cuerpo.sin-relleno > .acciones{padding-left:18px;padding-right:18px}

/* ---------- el calendario de estrategia ----------
   Seis meses por fila, como la hoja de Excel de la que sale: dos filas de seis
   es la forma en la que el equipo ya lee un año, y romperla en cuatro y cuatro
   y cuatro obliga a recontar para saber por dónde va uno.
   Se estrecha por pasos y no con «auto-fit» porque auto-fit daba cuatro
   columnas en una pantalla normal, que es justo lo que no se quiere. */
.calendario{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:14px;
  align-items:start;margin-bottom:22px}
@media (max-width:1200px){.calendario{grid-template-columns:repeat(4,minmax(0,1fr))}}
@media (max-width:900px){.calendario{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media (max-width:640px){.calendario{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:460px){.calendario{grid-template-columns:minmax(0,1fr)}}

/* Cada año, el ancho entero y uno debajo del otro.
   En columnas cabían tres meses por fila y una acción de una línea se partía en
   cuatro: la parrilla dejaba de leerse, que es lo único que tiene que hacer. */
.ano-estrategia{margin-bottom:26px}
.ano-estrategia > .calendario{margin-bottom:0}

/* La cabecera de cada año. El del año en curso lleva una raya gruesa a la
   izquierda y el año en grande: con dos parrillas idénticas en pantalla, saber
   en cuál se está trabajando no puede depender de leer cuatro cifras pequeñas. */
.ano-estrategia > .cabeza-ano{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;
  padding:0 0 10px;margin-bottom:14px;border-bottom:2px solid var(--linea)}
.ano-estrategia > .cabeza-ano h2{margin:0;font-size:24px;letter-spacing:-.02em;
  color:var(--apagado);font-variant-numeric:tabular-nums}
.ano-estrategia.en-curso > .cabeza-ano{border-bottom-color:var(--grafito)}
.ano-estrategia.en-curso > .cabeza-ano h2{color:var(--tinta)}

.calendario .mes{background:var(--papel);border:1px solid var(--linea);
  border-radius:var(--radio);box-shadow:var(--sombra);overflow:hidden}
.calendario .mes.ahora{box-shadow:0 0 0 2px var(--grafito)}
.calendario .mes > .cabeza{
  padding:10px 12px;border-bottom:1px solid var(--linea);display:flex;
  align-items:baseline;justify-content:space-between;gap:8px;
}
.calendario .mes > .cabeza h3{margin:0;font-size:13.5px;letter-spacing:-.01em}
.calendario .accion{padding:9px 12px;border-bottom:1px solid var(--linea);font-size:12.5px;
  line-height:1.35}
.calendario .accion:last-of-type{border-bottom:0}
.calendario .accion.fuera{opacity:.5;text-decoration:line-through}
/* Los mandos de una acción: el estado y la papelera en una fila, y mover de mes
   en la suya. Los tres seguidos cabían de ancho pero no de contenido: en una
   columna de doce, el desplegable de estado enseñaba «Per» y el de mes «Marz»,
   y un control que no deja leer su valor no sirve para decidir nada. */
.calendario .accion .mandos{display:flex;flex-wrap:wrap;gap:5px;margin-top:6px;align-items:center}
.calendario .accion .mandos select{font-size:11.5px;padding:3px 6px;flex:1 1 auto;min-width:0}
.calendario .accion .mandos .mover{flex:1 0 100%}
.calendario .accion .mandos .boton{padding:3px 8px;font-size:11.5px;line-height:1.2}
.calendario .mes > .anadir{padding:9px 12px;border-top:1px solid var(--linea)}
.calendario .mes > .anadir summary{font-size:12px;color:var(--apagado);cursor:pointer;
  list-style:none}
.calendario .mes > .anadir summary::-webkit-details-marker{display:none}
.calendario .mes > .anadir summary::before{content:"+ "}
.calendario .mes > .anadir summary:hover{color:var(--tinta)}
.calendario .mes > .anadir textarea{font-size:12.5px}

/* La fila de edición de una actuación: pegada a la suya, sin la raya que
   separa una actuación de la siguiente, para que se lea como parte de ella y no
   como una fila más del registro. */
tr.fila-editar > td{padding:0 14px 10px;border-bottom:1px solid var(--linea)}
tr.fila-editar{background:var(--fondo-2)}
table.datos tr.fila-editar + tr > td{border-top:0}
/* El desplegable de editar.
   El botón que se ve y se pulsa es el de la COLUMNA de la fila —«Editar», con
   los demás botones—; esto de aquí es su cabecera una vez abierto. Antes era lo
   único que había, en gris de doce píxeles con un lápiz delante, y así no se
   leía como algo que se pudiera pulsar: Gabriel pidió dos veces poder editar lo
   que ya se podía editar. Un control que hay que descubrir no existe.

   Se queda discreto a propósito: con el botón de la fila al lado, dos controles
   iguales para lo mismo se leen como dos cosas distintas. */
.editar-actuacion > summary,.editar-mapa > summary{
  display:inline-block;cursor:pointer;list-style:none;
  font-size:12px;line-height:1;padding:5px 0;color:var(--apagado);
}
.editar-actuacion > summary::-webkit-details-marker,
.editar-mapa > summary::-webkit-details-marker{display:none}
.editar-actuacion > summary::before,.editar-mapa > summary::before{content:"\270E  "}
.editar-actuacion > summary:hover,.editar-mapa > summary:hover{color:var(--tinta)}
.editar-actuacion > summary:focus-visible,.editar-mapa > summary:focus-visible{
  outline:2px solid var(--grafito)}
.editar-actuacion[open] > summary,.editar-mapa[open] > summary{
  color:var(--tinta);font-weight:500}
.editar-actuacion > form{padding:10px 0 12px;max-width:1000px}
.editar-mapa > form{padding:10px 0 4px;max-width:900px}

/* El nombre de trabajo de una URL, encima de su ruta. Encima y no al lado
   porque es lo que se lee primero: en una reunión se señala «la de bodas», no
   «/catalogo/salones/bodas-y-eventos». */
.celda-url .nombre-pagina{
  display:block;font-weight:600;font-size:13.5px;margin-bottom:2px;
}
.celda-url .nombre-pagina.sin-poner{font-weight:400;color:var(--apagado)}

/* Los comentarios de una URL, a todo el ancho debajo de su fila. En su propia
   fila y no dentro de la celda de la URL: son frases, y en una columna de un
   tercio del ancho se leen a cuatro palabras por línea. */
table.datos tr.fila-comentarios > td{
  padding-top:0;border-bottom:1px solid var(--linea);
}
tr.fila-comentarios .texto{
  font-size:12.5px;color:var(--apagado);white-space:pre-line;
  padding-left:10px;border-left:2px solid var(--linea);margin:0 0 8px;
}

/* Los proyectos de un cliente, dentro de su resultado del buscador.
   Uno por línea y no separados por comas: el enlace de cada uno tiene que
   poderse pulsar sin apuntar, que es justo lo que se venía a hacer. */
.proyectos-del-cliente > div{padding:2px 0;line-height:1.4}
.proyectos-del-cliente .nota{margin-left:7px}

/* ---------- tablas ----------

   TODA tabla vive en una caja con su propio scroll, a lo ancho y a lo alto.

   Lo de lo alto es lo que faltaba: una tabla de cuatrocientas filas empujaba
   hacia abajo todo lo que viniera detrás —los bloques de temas, las
   explicaciones, los botones— y para llegar a ellos había que pasar por delante
   de un scroll de varios metros. Y, peor, los botones de acción quedaban tan
   lejos de las casillas que había que subir a comprobar qué se había marcado.

   Se hace con un ALTO MÁXIMO y no contando filas, que es lo que permite que sea
   una sola regla para toda la aplicación: una tabla de cuatro filas mide
   ciento sesenta píxeles, no llega al tope y no cambia nada; una de cuatrocientas
   se queda en la caja y se desplaza por dentro. Ninguna vista tiene que
   acordarse de nada.

   El tope se descuenta de la altura de la ventana para que la caja llegue hasta
   abajo sin sacar la página de sitio, y con «max()» porque en una pantalla baja
   restar la barra dejaba una ventana de doscientos píxeles, que es peor que no
   poner tope. */
.tabla-scroll{
  overflow-x:auto;
  max-height:max(420px, calc(100vh - var(--alto-barra,54px) - 170px));
  overflow-y:auto;
  /* Y QUE SE VEA QUE LA TABLA SIGUE. En un móvil, una tabla de diez columnas se
     corta por el canto de la tarjeta y parece rota: el navegador no pinta barra
     de desplazamiento hasta que alguien arrastra, así que quien mira da por
     perdido lo que hay detrás y se queja de que la tabla «desborda».
     Son cuatro fondos: los dos primeros, blancos, van «local» —se desplazan con
     la tabla— y tapan a los otros dos cuando se llega al principio o al final;
     los dos de debajo, la sombra, van «scroll» y se quedan quietos en el borde.
     El resultado es una sombra que aparece solo por el lado por el que queda
     tabla. Se hace con fondos y no con JavaScript porque así vale para las más
     de cien tablas de la aplicación sin que ninguna vista tenga que acordarse
     de nada, y porque sin JavaScript tiene que seguir funcionando. */
  background:
    linear-gradient(to right, var(--papel), rgba(255,255,255,0)) 0 0 / 20px 100% no-repeat local,
    linear-gradient(to left,  var(--papel), rgba(255,255,255,0)) 100% 0 / 20px 100% no-repeat local,
    linear-gradient(to right, rgba(20,20,19,.16), rgba(20,20,19,0)) 0 0 / 13px 100% no-repeat scroll,
    linear-gradient(to left,  rgba(20,20,19,.16), rgba(20,20,19,0)) 100% 0 / 13px 100% no-repeat scroll;
}
/* Y la cabecera se queda pegada arriba, siempre: en la fila ciento veinte ya no
   se sabe qué columna es cada número. Necesita fondo propio o se ve el
   contenido de las filas pasando por debajo de las letras. */
.tabla-scroll > table.datos thead th{position:sticky;top:0;z-index:2;background:var(--fondo-2)}
/* Tres listas que se leen ENTERAS y no se pueden meter en una ventanita: el
   seguimiento del Rank Tracker, el mapa de doce meses y las búsquedas que trae
   Search Console. En las tres, lo que se hace es recorrerlas de arriba abajo
   marcando casillas, y una caja con desplazamiento propio obliga a desplazar
   dos veces —la caja y la página— y esconde justo lo que se estaba marcando.
   El desplazamiento horizontal se queda: el mapa tiene doce columnas de meses
   y en un portátil no caben. */
.tabla-scroll.entera{max-height:none;overflow-y:visible}
.tabla-scroll.entera > table.datos thead th{position:static}
/* Al imprimir no hay ventana que desplazar: una caja con tope deja fuera del
   papel justo lo que se quería imprimir. Esta pantalla se lleva a reuniones. */
@media print{
  .tabla-scroll{max-height:none;overflow:visible;background:none}
  .tabla-scroll > table.datos thead th{position:static}
}
table.datos{width:100%;border-collapse:collapse;font-size:14px}
table.datos th,table.datos td{padding:9px 14px;text-align:left;border-bottom:1px solid var(--linea);vertical-align:top}
table.datos thead th{
  background:var(--fondo-2);font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--apagado);font-weight:600;white-space:nowrap;
}
table.datos tbody tr:last-child td{border-bottom:0}
table.datos tbody tr:hover{background:var(--fondo)}
td.num,th.num{font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap}
.vacio{padding:34px 18px;text-align:center;color:var(--apagado);font-size:14px}

/* ---------- encabezados de una auditoría on-page ---------- */
.lista-encabezados{list-style:none;margin:10px 0 0;padding:0;font-size:13px;line-height:1.7}
.lista-encabezados li{border-left:2px solid var(--linea);padding-left:10px}

/* ---------- URLs de una actuación ---------- */
.urls-actuacion{display:flex;flex-direction:column;gap:2px;margin-top:6px}
.urls-actuacion a.mono{color:var(--grafito);text-decoration:none;border-bottom:1px solid var(--linea);
  align-self:flex-start;max-width:100%;overflow-wrap:anywhere}
.urls-actuacion a.mono:hover{border-bottom-color:var(--grafito)}
.urls-actuacion a.nota{text-decoration:none}
.urls-actuacion a.nota:hover{text-decoration:underline}

/* ---------- etiquetas ---------- */
.etiqueta{
  display:inline-block;padding:2px 8px;border-radius:20px;font-size:11.5px;font-weight:500;
  border:1px solid var(--linea-fuerte);color:var(--grafito);background:var(--papel);white-space:nowrap;
}
.etiqueta.solida{background:var(--grafito);color:#fff;border-color:var(--grafito)}
.etiqueta.tenue{color:var(--apagado);border-color:var(--linea)}
.etiqueta.rayada{background:repeating-linear-gradient(45deg,var(--fondo-2),var(--fondo-2) 4px,var(--papel) 4px,var(--papel) 8px)}

/* Los pasos numerados de una importación.

   Se usan donde hay que hacer algo FUERA de Visión antes de subir un fichero
   —las dos exportaciones de Screaming Frog— y el orden importa. En prosa,
   «la exportación de Internal → All es la que más trae» no le dice a nadie por
   dónde empezar, y cada uno subía lo que tenía a mano. */
.pasos-frog{margin:14px 0;padding-left:20px;font-size:13.5px;line-height:1.6;color:var(--grafito)}
.pasos-frog li{margin-bottom:8px}
.pasos-frog code{background:var(--fondo-2);padding:1px 5px;border-radius:2px;white-space:nowrap}

/* Los colores del registro de actuaciones.

   Visión es gris a propósito y esto es la excepción razonada: en un registro de
   doscientas filas, buscar «las que están en programación» leyendo once
   palabras distintas fila a fila es lo que hace que nadie las busque. Son los
   mismos colores que el equipo ya usa en sus hojas de cálculo, así que la
   lectura no hay que aprenderla.

   EL COLOR NO VA NUNCA SOLO: la etiqueta lleva siempre su texto dentro. Un chip
   verde sin palabra no lo lee quien no distingue el verde del rojo —uno de cada
   doce hombres— ni quien imprime el registro en blanco y negro para llevarlo a
   una reunión, que es lo que se hace con esta pantalla.

   Los tonos son apagados y el texto de cada uno es su propio color oscurecido:
   un chip saturado con letra blanca repetido doscientas veces convierte la
   tabla en un semáforo y deja de distinguirse nada, que es el problema que se
   venía a resolver. */
.etiqueta.verde{background:#1E7A4B;color:#fff;border-color:#1E7A4B}
.etiqueta.verde-claro{background:#DFF0E4;color:#1B5E3A;border-color:#B9DCC5}
.etiqueta.azul{background:#CFE3F7;color:#1B4F80;border-color:#A9CBEE}
.etiqueta.azul-claro{background:#E8F1FA;color:#2A5C8A;border-color:#C7DDF2}
.etiqueta.morado{background:#E4DBF5;color:#4B2E83;border-color:#CDBEEB}
.etiqueta.naranja{background:#FBE0D2;color:#8A4218;border-color:#F3C4AC}
.etiqueta.ambar{background:#FBEFC9;color:#7A5A10;border-color:#F0DC9A}
.etiqueta.turquesa{background:#D3EDEC;color:#1D5F5C;border-color:#ABDBD8}
.etiqueta.rojo{background:#F8D7D7;color:#8B2020;border-color:#EFB4B4}
.etiqueta.gris{background:var(--fondo-2);color:var(--grafito);border-color:var(--linea-fuerte)}
/* Cancelado va tachado ADEMÁS de gris: es el único estado que significa «esto
   no va a pasar», y en una lista de once colores el gris solo se confunde con
   «pendiente». */
.etiqueta.tachado{background:var(--fondo);color:var(--apagado);border-color:var(--linea);
  text-decoration:line-through}

/* ---------- formularios ---------- */
.campo{margin-bottom:16px;max-width:520px}
.campo.ancho{max-width:none}
.campo label{display:block;font-size:12.5px;font-weight:500;margin-bottom:5px;color:var(--grafito)}
.campo .ayuda{font-size:12.5px;color:var(--apagado);margin-top:5px;line-height:1.45}
/* La lista va por tipo, y la que faltaba se notaba: un input[type=url] sin
   estilo salía con el ancho por defecto del navegador —dos dedos— al lado de
   uno de texto a toda anchura. */
input[type=text],input[type=email],input[type=password],input[type=number],
input[type=date],input[type=url],input[type=search],input[type=tel],
input[type=file],select,textarea{
  width:100%;padding:8px 10px;border:1px solid var(--linea-fuerte);border-radius:var(--radio);
  font:inherit;font-size:14px;background:var(--papel);color:var(--tinta);
}
input[type=file]{padding:7px 10px;font-size:13px;color:var(--apagado);cursor:pointer}
input[type=file]::file-selector-button{
  font:inherit;font-size:13px;margin-right:10px;padding:4px 10px;cursor:pointer;
  border:1px solid var(--linea-fuerte);border-radius:var(--radio);
  background:var(--fondo-2);color:var(--tinta);
}
input:focus,select:focus,textarea:focus{outline:2px solid var(--grafito);outline-offset:-1px;border-color:var(--grafito)}
.interruptor{display:flex;align-items:center;gap:9px;font-size:14px;margin-bottom:14px}
.interruptor input{width:16px;height:16px;accent-color:var(--grafito)}
.fila-campos{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:0 16px;max-width:760px}
/* Un campo que ocupa dos columnas de la fila. Para los que llevan una frase y
   no un dato: en una caja del ancho de un desplegable se escribe a ciegas,
   viendo media docena de palabras del final. */
.fila-campos .campo.doble{grid-column:span 2}
@media (max-width:640px){.fila-campos .campo.doble{grid-column:span 1}}
/* Un documento de Drive dentro de una actuación. No lleva monoespaciada como
   las URLs del sitio: de aquellas importa la ruta —se leen, se comparan—, y de
   estas solo que se puedan abrir. */
.urls-actuacion a.documento{font-size:12.5px}

.boton{
  display:inline-block;padding:8px 16px;border-radius:var(--radio);border:1px solid var(--grafito);
  background:var(--grafito);color:#fff;font:inherit;font-size:14px;font-weight:500;cursor:pointer;text-decoration:none;
}
.boton:hover{background:var(--tinta);border-color:var(--tinta)}
.boton.secundario{background:var(--papel);color:var(--grafito)}
.boton.secundario:hover{background:var(--fondo-2);color:var(--tinta)}
.boton.pequeno{padding:4px 10px;font-size:12.5px}
.boton:disabled{opacity:.45;cursor:not-allowed}
.acciones{display:flex;gap:9px;flex-wrap:wrap;align-items:center;margin-top:18px}
.qr-lienzo{display:inline-block;background:#fff;padding:10px;border:1px solid var(--linea);border-radius:var(--radio)}
.qr-lienzo svg{display:block;max-width:100%;height:auto}
.lista-nota{margin:0;padding-left:18px;font-size:13.5px;color:var(--apagado);line-height:1.55}
.lista-nota li{margin-bottom:8px}
.lista-nota li:last-child{margin-bottom:0}
.lista-nota strong{color:var(--tinta);font-weight:600}
form.enlinea{display:inline}

/* Las keywords asignadas a una URL, dentro del mapa. En pastillas y no en una
   lista separada por comas: cada una lleva su puesto y su botón de quitarla, y
   con comas no se sabe dónde acaba una y empieza la siguiente. */
.keywords-de-url{display:flex;flex-wrap:wrap;gap:6px}
.keywords-de-url .asignada{
  /* Inline-block y no inline-flex, y no es un capricho: dentro de una celda de
     tabla, el navegador reparte el ancho de las columnas por el contenido, y el
     ancho que declara un flex anidado se queda muy por debajo del que necesita.
     Resultado: la columna salía estrecha y la pastilla de la keyword principal
     —en negrita, y por tanto más ancha— se partía en cuatro líneas: la
     estrella, el texto, el volumen y la ×, una debajo de otra. Con inline-block
     y sin permitir el salto, la pastilla mide lo que ocupa y la columna se
     dimensiona bien. */
  display:inline-block;white-space:nowrap;font-size:12.5px;
  background:var(--fondo-2);border:1px solid var(--linea);
  border-radius:var(--radio);padding:2px 4px 2px 8px;
}
.keywords-de-url .asignada > *{vertical-align:middle}
.keywords-de-url .asignada > * + *{margin-left:6px}
.keywords-de-url .asignada .nota{font-variant-numeric:tabular-nums}
.keywords-de-url .asignada button{
  border:0;background:none;cursor:pointer;color:var(--apagado);
  font-size:14px;line-height:1;padding:2px 4px;border-radius:var(--radio);
}
.keywords-de-url .asignada button:hover{background:var(--papel);color:var(--tinta)}
.keywords-de-url .asignada button:focus-visible{outline:2px solid var(--grafito)}

/* La principal, marcada. Con el borde y la estrella y no solo con color: la
   distinción tiene que verse impresa y en blanco y negro, que es como acaba la
   mitad de los mapas encima de la mesa de una reunión. */
.keywords-de-url .asignada.principal{border-color:var(--grafito);font-weight:600}
.keywords-de-url .asignada .estrella{
  color:var(--apagado);font-size:13px;line-height:1;padding:0 2px;
}
.keywords-de-url .asignada.principal .estrella{color:var(--tinta)}

/* El mapa reordenable: el agarre, las flechas de sangrar y la fila en vuelo. */
.datos [draggable="true"]{cursor:grab}
.datos tr.arrastrando{opacity:.45}
.celda-url .agarre{color:var(--apagado);cursor:grab;user-select:none;margin-right:2px}
.celda-url .sangrar{
  border:1px solid var(--linea);background:var(--fondo-2);color:var(--apagado);
  cursor:pointer;font-size:10px;line-height:1;padding:2px 4px;border-radius:var(--radio);
}
.celda-url .sangrar:hover{background:var(--papel);color:var(--tinta)}
.celda-url .sangrar:focus-visible{outline:2px solid var(--grafito)}

/* El título de trabajo de una URL y la zona de un enlace: dos campos en línea
   que viven dentro de una celda y no pueden robarle el ancho a la tabla. */
.titulo-mapa,.zona-enlace{display:flex;gap:6px;align-items:center;margin-top:4px}
.titulo-mapa input[type="text"]{max-width:200px;min-width:0;margin:0}
.zona-enlace input[type="text"]{max-width:180px;margin:0}
.zona-enlace select{max-width:150px;margin:0}

/* Una página que tiene keywords y ya no sale en el último rastreo. Apagada,
   no en rojo: no es un error, es un aviso —puede haber cambiado de dirección o
   el rastreo puede no haber llegado— y pintarla de alarma haría que se
   ignorase la que sí importa. */
table.datos tr.perdida > td:first-child{opacity:.65}

/* ---------- pestañas ---------- */
.pestanas{display:flex;gap:2px;border-bottom:1px solid var(--linea);margin-bottom:22px;flex-wrap:wrap}
.pestanas a{
  padding:8px 14px;font-size:14px;text-decoration:none;color:var(--apagado);
  border:1px solid transparent;border-bottom:none;border-radius:var(--radio) var(--radio) 0 0;margin-bottom:-1px;
}
.pestanas a:hover{color:var(--tinta);background:var(--fondo-2)}
.pestanas a.activa{background:var(--papel);border-color:var(--linea);color:var(--tinta);font-weight:500}

/* ---------- acceso e instalación ---------- */
.centrado{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:30px;background:var(--fondo)}
.panel-acceso{width:100%;max-width:420px;background:var(--papel);border:1px solid var(--linea);border-radius:var(--radio);box-shadow:0 2px 14px rgba(20,20,19,.07)}
.panel-acceso .cabeza{background:var(--grafito);color:#fff;padding:24px 26px}
.panel-acceso .cabeza .nombre{font-size:26px;font-weight:700;letter-spacing:-.02em;line-height:1}
.panel-acceso .cabeza .sub{font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:rgba(255,255,255,.6);margin-top:4px}
.panel-acceso .cuerpo{padding:24px 26px}
.panel-instalacion{width:100%;max-width:760px;background:var(--papel);border:1px solid var(--linea);border-radius:var(--radio)}
.codigo-grande{font-size:26px;letter-spacing:.35em;text-align:center;font-family:ui-monospace,monospace}
.qr{display:flex;justify-content:center;padding:14px;background:#fff;border:1px solid var(--linea);border-radius:var(--radio)}
.secreto{
  background:var(--fondo-2);border:1px solid var(--linea);border-radius:var(--radio);
  padding:10px 12px;font-family:ui-monospace,monospace;font-size:14px;letter-spacing:.06em;word-break:break-all;text-align:center;
}
.codigos-recuperacion{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:6px;
  font-family:ui-monospace,monospace;font-size:13.5px;
}
.codigos-recuperacion span{background:var(--fondo-2);padding:6px 8px;border-radius:var(--radio);text-align:center}

/* ---------- requisitos ---------- */
.requisitos{list-style:none;margin:0;padding:0}
.requisitos li{display:grid;grid-template-columns:22px minmax(0,1fr) auto;gap:10px;padding:7px 0;border-bottom:1px solid var(--linea);font-size:14px;align-items:baseline}
.requisitos li:last-child{border-bottom:0}
.marca-ok::before{content:"✓";color:var(--grafito);font-weight:700}
.marca-mal::before{content:"×";color:var(--tinta);font-weight:700;font-size:17px}
.marca-aviso::before{content:"·";color:var(--apagado);font-weight:700;font-size:20px}
.requisitos .detalle{color:var(--apagado);font-size:12.5px}

.migas{font-size:12.5px;color:var(--apagado);margin-bottom:14px}
/* Las dos clases con las que está escrita la letra pequeña de la aplicación.
   Iban distintas sin que nadie lo hubiera decidido: «.nota» tenía su tamaño y
   un ancho máximo de 70 caracteres, y «.ayuda» fuera de un campo no tenía
   regla ninguna, así que heredaba el tamaño del cuerpo y se iba a todo el
   ancho. En el mismo bloque, una explicación empezaba pequeña y estrecha y
   terminaba grande y ancha. Ahora las dos son lo mismo: tamaño pequeño y todo
   el ancho del contenedor. El ancho lo pone el bloque, que es quien sabe
   cuánto sitio hay. */
.nota,.ayuda{font-size:13px;color:var(--apagado);line-height:1.5}
/* Dentro de una nota larga, el <br> separa PÁRRAFOS y no líneas: es como están
   escritas las explicaciones de media aplicación —«esto no gasta saldo», «no es
   lo mismo que el índice de visibilidad», «solo se ve lo que pasa en nuestras
   keywords»— y sin aire entre ellos se leen como un muro que nadie lee. Se le da
   el aire aquí, en una regla, en vez de partir en párrafos de verdad veintinueve
   bloques de texto con PHP interpolado dentro. */
p.nota br{content:"";display:block;height:.85em}
.separador{height:1px;background:var(--linea);margin:22px 0;border:0}

/* POR QUÉ «minmax(0,1fr)» Y NO «1fr», AQUÍ Y EN TODAS LAS REJILLAS DE ABAJO.
   «1fr» es en realidad «minmax(auto,1fr)», y ese «auto» significa «al menos lo
   que mida su contenido sin partir». Una tabla ancha dentro de una columna así
   no encoge: estira la columna, la rejilla y con ella la página entera, y el
   «overflow-x:auto» del contenedor de la tabla no llega a hacer nada porque el
   contenedor ya es tan ancho como la tabla. El síntoma es una pantalla de móvil
   que se arrastra de lado con toda la interfaz —barra y menú incluidos—
   desplazándose con ella.
   Con «minmax(0,1fr)» la columna puede encoger hasta cero y la tabla se
   desplaza por dentro, que es lo que se quería. */
@media (max-width:900px){
  .cuerpo-app{grid-template-columns:minmax(0,1fr)}
  .barra-superior{height:auto;flex-wrap:wrap;padding:10px 18px;gap:10px;position:static}
  .menu-general{order:3;flex-basis:100%}
  .buscador{order:2;flex:1 1 auto}
  .identidad{margin-left:auto}
  .lateral{position:static;height:auto;border-right:none;border-bottom:1px solid var(--linea)}
  /* El menú del proyecto son más de cuarenta enlaces y en una pantalla
     estrecha se comía la primera pantalla ENTERA: había que pasar el dedo por
     todo el menú antes de ver una sola cifra de la página que se había pedido.
     Con tope de alto y desplazamiento propio, el menú sigue arriba —donde se
     busca— pero el contenido empieza a la vista. */
  .lateral-contenido{max-height:40vh;overflow-y:auto;overscroll-behavior:contain}
  .lateral-plegar{display:none}
  html.lateral-plegado .cuerpo-app{grid-template-columns:minmax(0,1fr)}
  html.lateral-plegado .lateral-contenido{display:flex}
  .menu{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
  .menu .grupo{grid-column:1/-1;padding-top:10px}
  /* La cabecera de la barra, el selector de proyecto y el pie, al mismo margen
     que el resto de la página. En el escritorio la barra es una columna aparte
     y sus dieciséis píxeles no se comparan con nada; apilada encima del
     contenido, dos píxeles de diferencia con el titular y con los bloques se
     ven como un escalón. */
  .lateral-cabeza,.selector-proyecto,.lateral .pie{padding-left:18px;padding-right:18px}
  .contenido,.cabecera{padding-left:18px;padding-right:18px}
}

/* ---------- salud y gráficos (fase 1A) ---------- */
.salud{display:flex;align-items:center;gap:10px}
.salud .cifra-salud{
  font-size:15px;font-weight:600;font-variant-numeric:tabular-nums;min-width:30px;text-align:right;
}
.barra{position:relative;height:7px;background:var(--fondo-2);border-radius:4px;overflow:hidden;min-width:64px;flex:1}
.barra span{position:absolute;left:0;top:0;bottom:0;background:var(--grafito);border-radius:4px}
.barra.aviso span{background:repeating-linear-gradient(45deg,var(--grafito),var(--grafito) 3px,var(--grafito-claro) 3px,var(--grafito-claro) 6px)}
.barra.critico span{background:var(--tinta)}
.barra.sin span{background:var(--linea-fuerte);width:100%!important;opacity:.4}

.delta{font-size:12px;font-variant-numeric:tabular-nums;color:var(--apagado);white-space:nowrap}
.delta.sube::before{content:"▲ ";font-size:9px}
.delta.baja::before{content:"▼ ";font-size:9px}
/* «sube» es MEJORA, no «el número ha crecido»: en posiciones, pasar del 4 al 2
   es sube. Lo decide Senal::de(), una vez para toda la aplicación. */
.delta.sube{color:var(--bien)}
.delta.baja{color:var(--mal)}
/* Una cifra por debajo de cero que es mala noticia sola (se pierde dinero, se
   dan horas de más). Sin flecha: el signo menos ya lo dice. */
/* Y un cambio que ya lleva su signo («+32 %», «-4 puestos») o que va en una
   cifra grande, donde el 12 px de «.delta» no cabe: solo el color. */
.negativo,.empeora{color:var(--mal)}
.mejora{color:var(--bien)}
.cifra.negativo,.cifra.empeora{color:var(--mal)}
.cifra.mejora{color:var(--bien)}

.grafico{width:100%;height:auto;display:block;overflow:visible}
.grafico .area{opacity:.10;stroke:none}
.grafico .linea{fill:none;stroke-width:2;stroke-linejoin:round;stroke-linecap:round}
.grafico .rejilla{stroke:var(--linea);stroke-width:1}
.grafico .punto{stroke:var(--papel);stroke-width:2}
.grafico .columna{stroke:var(--papel);stroke-width:1}
/* Las capas apiladas se separan con blanco, no con un borde de color */
.grafico .capa{stroke:var(--papel);stroke-width:2}
.grafico .cruz{stroke:var(--linea-fuerte);stroke-width:1;display:none}
.grafico .cruz.visible{display:block}
.grafico text{font-size:10px;fill:var(--apagado);font-family:inherit}
.grafico .eje{font-variant-numeric:tabular-nums}
.grafico .remate{font-size:10.5px;fill:var(--tinta)}

/* Anotaciones: una raya discontinua de arriba abajo con su número en la cabeza.
   Va por debajo de los datos —el dibujante la pinta con el marco— para que una
   marca no tape nunca la línea que pretende explicar. */
.grafico .anotacion-linea{stroke:var(--linea-fuerte);stroke-width:1;stroke-dasharray:3 3;opacity:.55}
.grafico .anotacion-marca{fill:var(--tinta);stroke:var(--papel);stroke-width:1.5}
.grafico .anotacion-numero{font-size:9px;fill:var(--papel);font-weight:600}

/* ---------- caja del gráfico: leyenda, globo y tabla ---------- */
.filtros-rango{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.filtros-rango .nota{margin-left:6px}
/* Titular de un gráfico dentro de un bloque que lleva más de uno: sin él, el
   segundo dibujo parece la continuación del primero. */
.titulo-grafico{
  font-size:14px;font-weight:600;margin:0 0 10px;
  display:flex;flex-wrap:wrap;align-items:baseline;gap:8px;
}
.titulo-grafico .nota{font-weight:400}
.grafico-caja{margin:0;position:relative}
.grafico-leyenda{display:flex;flex-wrap:wrap;gap:14px;margin-top:10px;font-size:12.5px;color:var(--apagado)}
.grafico-leyenda span{display:inline-flex;align-items:center;gap:6px}
.grafico-leyenda i{width:11px;height:11px;border-radius:2px;display:inline-block}
.grafico-leyenda.linea i{width:14px;height:2px;border-radius:1px}
.grafico-globo{
  position:absolute;pointer-events:none;z-index:5;background:var(--papel);
  border:1px solid var(--linea);border-radius:var(--radio);box-shadow:var(--sombra);
  padding:8px 10px;font-size:12.5px;min-width:132px;
}
.grafico-globo .cuando{color:var(--apagado);font-size:11.5px;margin-bottom:4px}
.grafico-globo .fila{display:flex;align-items:center;gap:7px;line-height:1.7}
.grafico-globo .fila i{width:10px;height:2px;border-radius:1px;flex:none}
.grafico-globo .fila b{font-weight:600;font-variant-numeric:tabular-nums}
.grafico-globo .fila span{color:var(--apagado)}
.grafico-tabla{margin-top:12px}
.grafico-tabla summary{font-size:12.5px;color:var(--apagado);cursor:pointer}
.grafico-tabla table{margin-top:8px}

.bloques-salud{display:flex;flex-direction:column;gap:0}
/* Las dos primeras columnas tienen un ancho DESEADO, no fijo. En el resumen
   del proyecto estos bloques van dentro de una tarjeta a media pantalla, y con
   150+118 px clavados solo quedaban veintinueve para el detalle: la tarjeta se
   ensanchaba y con ella la página. Con «minmax» encogen hasta donde haga falta
   y en pantalla ancha siguen midiendo lo de siempre. */
.bloque-salud{
  display:grid;gap:12px;align-items:center;
  grid-template-columns:minmax(90px,150px) minmax(70px,118px) minmax(0,1fr);
  padding:9px 0;border-bottom:1px solid var(--linea);font-size:13.5px;
}
/* Cuando no caben las tres columnas, el detalle se va a su propia línea.
   Y se mira el ancho del CONTENEDOR, no el de la ventana, porque el problema no
   era el móvil: en el resumen del proyecto estos bloques viven dentro de una
   tarjeta a media pantalla, así que en una ventana de 768 px la tarjeta mide
   357 y el detalle se quedaba con veintinueve. Una media query no puede saber
   eso —mide la ventana, que ahí sobra— y por eso es una consulta de contenedor:
   la pregunta que hay que hacer es «¿cabe en MI caja?». */
.bloques-salud{container-type:inline-size}
@container (max-width:420px){
  .bloque-salud{grid-template-columns:minmax(0,1fr) auto}
  .bloque-salud .detalle{grid-column:1/-1}
}
/* Y por si el navegador no entiende «@container»: en pantalla estrecha, lo
   mismo. Es un suelo, no la regla principal. */
@media (max-width:640px){
  .bloque-salud{grid-template-columns:minmax(0,1fr) auto}
  .bloque-salud .detalle{grid-column:1/-1}
}
/* La barra tiene un ancho mínimo de 64px que se comía la columna del detalle:
   dentro de esta rejilla se deja encoger, que para eso la columna ya la mide. */
.bloque-salud .barra{min-width:0}
.bloque-salud:last-child{border-bottom:0}
.bloque-salud .peso{font-size:11px;color:var(--apagado);font-variant-numeric:tabular-nums}
.bloque-salud .detalle{color:var(--apagado);font-size:12.5px}
.bloque-salud.sin-datos{opacity:.55}

.posicion{
  display:inline-block;min-width:30px;text-align:center;font-variant-numeric:tabular-nums;
  font-weight:600;font-size:13.5px;
}
.posicion.fuera{color:var(--apagado);font-weight:400}

/* ---------- auditoría, incidencias y alertas (fase 1B) ---------- */
.contador{
  display:inline-block;min-width:18px;padding:0 5px;border-radius:9px;background:#fff;color:var(--grafito);
  font-size:11px;font-weight:600;text-align:center;line-height:17px;vertical-align:middle;
}
.menu a.activo .contador{background:var(--grafito);color:#fff}

.sub-menu{display:flex;gap:2px;border-bottom:1px solid var(--linea);margin-bottom:22px;flex-wrap:wrap}
.sub-menu a{
  padding:8px 14px;font-size:14px;text-decoration:none;color:var(--apagado);
  border:1px solid transparent;border-bottom:none;margin-bottom:-1px;border-radius:var(--radio) var(--radio) 0 0;
}
.sub-menu a:hover{color:var(--tinta);background:var(--fondo-2)}
.sub-menu a.activa{background:var(--papel);border-color:var(--linea);color:var(--tinta);font-weight:500}
/* Los grupos se separan con aire y una línea fina, no con un título más */
.sub-menu .grupo-menu{display:flex;gap:2px;padding-right:10px;margin-right:8px;
  border-right:1px solid var(--linea)}
.sub-menu .grupo-menu:last-child{border-right:none;padding-right:0;margin-right:0}
/* Cabeceras de tabla que ordenan */
/* Una tabla larga que se lee de arriba abajo y cuya cabecera no se puede
   perder: con cincuenta proyectos y diez columnas, a la tercera pantalla ya no
   se sabe si el número que se mira es del mes o del año.

   El envoltorio pasa a tener alto máximo y a desplazarse por dentro, y no se
   deja que la página entera desplace por debajo de una cabecera pegada. Es la
   diferencia entre que funcione y que no: «position:sticky» se pega al
   contenedor que se desplaza, y .tabla-scroll ya era uno —basta un overflow en
   un eje para serlo en los dos—, así que sin alto máximo no se desplazaba nunca
   por dentro y la cabecera no se pegaba a nada.

   El alto se descuenta de la altura de la ventana para que la tabla llegue
   hasta abajo sin sacar la página de sitio. */
.tabla-scroll.con-cabecera-pegada{
  /* Con «max()» y no a secas: en una pantalla baja, restar la barra y el hueco
     dejaba una ventana de doscientos píxeles, que es peor que no pegar nada. */
  max-height:max(360px, calc(100vh - var(--alto-barra,54px) - 120px));
}
table.datos.cabecera-pegada thead th{position:sticky;z-index:2}
table.datos.cabecera-pegada thead tr.grupos th{top:0}
/* La segunda fila se pega justo debajo de la primera. La medida se fija aquí
   —y la primera fila se fija a esa misma altura— porque si se calcula «a ojo»
   sobra o falta por tres píxeles, y por esos tres píxeles se ve pasar el
   contenido de las filas entre las dos cabeceras. */
table.datos.cabecera-pegada thead tr.grupos th{height:28px;box-sizing:border-box}
table.datos.cabecera-pegada thead tr.grupos + tr th{top:28px}
/* Sin fila de grupos, la única cabecera va arriba del todo. */
table.datos.cabecera-pegada thead tr:only-child th{top:0}
/* La cabecera pegada necesita fondo propio: si no, se ve el contenido de las
   filas pasando por debajo de las letras. */
table.datos.cabecera-pegada thead th{background:var(--fondo-2)}

/* Una subactuación, colgada de la de arriba. La línea a la izquierda y no solo
   la sangría: con cincuenta filas, tres píxeles de sangría no se ven, y lo que
   hay que poder leer de un vistazo es de qué cuelga cada cosa. */
table.datos tr.subactuacion > td:first-child{
  box-shadow:inset 3px 0 0 var(--linea);
}

table.datos thead a{text-decoration:none;color:inherit;white-space:nowrap}
table.datos thead a:hover{text-decoration:underline}
table.datos thead a.orden-activo{color:var(--tinta);font-weight:700}
@media (max-width:900px){
  .sub-menu .grupo-menu{border-right:none;padding-right:0;margin-right:0;flex-wrap:wrap}
}

/* En pantalla estrecha el desplegable del menú se abre HACIA ABAJO, empujando
   lo que tiene debajo, en vez de flotar. Flotando hay que decidir si se alinea
   a la izquierda o a la derecha según dónde caiga el botón, y cualquiera de las
   dos se sale por un lado en algún ancho. Abierto en vertical no se puede
   salir, que es la única manera de que esto no vuelva. */
@media (max-width:900px){
  .menu-desplegable[open] > .desplegado{
    position:static;width:auto;min-width:0;max-width:none;
    margin:4px 0 2px;box-shadow:none;background:rgba(255,255,255,.08);
  }
  /* Solo ABIERTO ocupa la línea entera. Puesto siempre, cada desplegable
     —Herramientas, Gestión, Sistema— se llevaba un renglón para él solo y la
     barra de arriba pasaba a medir media pantalla antes de empezar la página. */
  .menu-desplegable[open]{width:100%}
}

.sev{
  display:inline-block;padding:1px 8px;border-radius:3px;font-size:11px;font-weight:600;
  text-transform:uppercase;letter-spacing:.05em;white-space:nowrap;border:1px solid var(--linea-fuerte);
}
.sev.critica{background:var(--tinta);color:#fff;border-color:var(--tinta)}
.sev.alta{background:var(--grafito);color:#fff;border-color:var(--grafito)}
.sev.media{background:var(--fondo-2);color:var(--grafito)}
.sev.baja{background:var(--papel);color:var(--apagado)}

.item-check{
  display:grid;grid-template-columns:minmax(0,1fr) auto;gap:12px;align-items:start;
  padding:12px 0;border-bottom:1px solid var(--linea);
}
.item-check:last-child{border-bottom:0}
/* La barra de arriba es fija: sin este margen de desplazamiento, volver a un
   punto por su ancla lo dejaba justo debajo de la barra, medio tapado. */
.item-check{scroll-margin-top:calc(var(--alto-barra,54px) + 16px)}
/* Y cuál se acaba de guardar, para no tener que buscarlo con la vista. Se quita
   solo a los dos segundos: un resalte que se queda deja de decir «este». */
.item-check.recien-guardado{
  background:var(--fondo-2);box-shadow:inset 3px 0 0 var(--tinta);
  transition:background .4s ease;
}
@media (prefers-reduced-motion: reduce){.item-check.recien-guardado{transition:none}}
.item-check .titulo{font-size:14.5px;font-weight:500;margin-bottom:3px}
.item-check .meta{font-size:12px;color:var(--apagado)}
.item-check .evidencia{
  font-size:12.5px;color:var(--apagado);margin-top:6px;padding-left:10px;
  border-left:2px solid var(--linea-fuerte);
}
.item-check form{display:flex;gap:6px;align-items:center;flex-wrap:wrap;justify-content:flex-end}
.item-check select,.item-check input[type=text]{width:auto;min-width:130px;font-size:13px;padding:5px 8px}
.item-check.estado-incidencia{background:var(--fondo);margin:0 -18px;padding:12px 18px}
.item-check.estado-no_aplica{opacity:.5}
/* Qué hay que hacer con el punto, plegado.
   Va plegado porque son setenta y nueve puntos y desplegarlos todos convierte
   la pantalla en un documento de treinta pantallazos; se abre solo el que ya
   tiene texto escrito por una persona, que es el que hay que poder ver de un
   vistazo para saber cuáles se han trabajado. */
.item-check .accion-punto{margin-top:8px}
.item-check .accion-punto > summary{cursor:pointer;font-size:12.5px}
.item-check .accion-punto > summary:focus-visible{outline:2px solid var(--tinta);outline-offset:2px}
.item-check .accion-punto > *:not(summary){margin-top:8px}
/* El formulario del texto NO es el de guardar el estado: aquel se alinea a la
   derecha en una fila, y este es un cuadro de texto que ocupa el ancho. Sin
   este reajuste, el textarea se encogía a la derecha de la tarjeta. */
.item-check form.accion-editor{display:block;justify-content:flex-start;max-width:640px}
.item-check form.accion-editor textarea{
  width:100%;font-size:13px;padding:8px 10px;line-height:1.45;
}

.progreso{display:flex;height:8px;border-radius:4px;overflow:hidden;background:var(--fondo-2);margin:10px 0}
.progreso span{display:block;height:100%}
.progreso .correcto{background:var(--grafito)}
.progreso .incidencia{background:var(--tinta)}
.progreso .no_aplica{background:var(--linea-fuerte)}
.leyenda{display:flex;gap:16px;font-size:12.5px;color:var(--apagado);flex-wrap:wrap}
.leyenda i{display:inline-block;width:9px;height:9px;margin-right:5px;border-radius:2px;vertical-align:middle}

.diff{font-family:ui-monospace,monospace;font-size:12px;line-height:1.6}
.diff .antes{color:var(--apagado);text-decoration:line-through}
.diff .ahora{color:var(--tinta);font-weight:500}

/* ---------- informes y rentabilidad (fase 1C) ---------- */
.datos-informe{
  display:flex;flex-wrap:wrap;gap:0 26px;padding:12px 14px;margin-bottom:14px;
  background:var(--fondo-2);border-radius:var(--radio);
}
.dato-informe{display:flex;flex-direction:column;gap:2px;padding:4px 0;min-width:104px}
.dato-informe .et{font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--apagado)}
.dato-informe .va{font-size:19px;font-weight:600;font-variant-numeric:tabular-nums;line-height:1.15}
.dato-informe .ex{font-size:11.5px;color:var(--apagado)}

.bloque > header .interruptor{font-size:12.5px;color:var(--apagado);white-space:nowrap}
.bloque > header .interruptor input{width:15px;height:15px}

details > summary{list-style:none}
/* Un resumen que es solo texto no parece que se pueda abrir: se le pone su
   triángulo y su cursor para que se vea que es un control. */
summary.desplegable{cursor:pointer;display:inline-flex;align-items:center;gap:6px}
summary.desplegable::before{content:"▸";font-size:11px;transition:transform .12s}
details[open] > summary.desplegable::before{transform:rotate(90deg)}
details[open] > summary.desplegable{background:none}
details > summary::-webkit-details-marker{display:none}
details[open] > summary{background:var(--fondo-2)}

@media (max-width:1000px){
  .rejilla[style*="320px"]{grid-template-columns:minmax(0,1fr)!important}
}

/* ---------- histórico (fase 1D) ---------- */
.cobertura td{vertical-align:middle}
.cobertura .salud{gap:8px}
.cobertura .barra{min-width:90px;max-width:150px}
.cobertura tr.en-curso{opacity:.6}
.cobertura tr.en-curso td:first-child{font-style:italic}

/* ---------- contenidos y mapa (fase 2) ---------- */
.tablero{display:grid;grid-template-columns:repeat(5,minmax(190px,1fr));gap:0;overflow-x:auto}
.tablero .columna{padding:14px;border-right:1px solid var(--linea);min-width:190px}
.tablero .columna:last-child{border-right:0}
.tablero .columna h3{
  font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--apagado);
  margin-bottom:10px;display:flex;justify-content:space-between;align-items:center;
}
.contador-col{
  background:var(--fondo-2);color:var(--grafito);border-radius:9px;padding:1px 7px;
  font-size:11px;letter-spacing:0;
}
.tarjeta-contenido{
  display:block;text-decoration:none;color:inherit;background:var(--papel);
  border:1px solid var(--linea);border-radius:var(--radio);padding:10px 11px;margin-bottom:8px;
}
.tarjeta-contenido:hover{border-color:var(--linea-fuerte);background:var(--fondo)}
.tarjeta-contenido .titulo{display:block;font-size:13.5px;font-weight:500;line-height:1.35}
.tarjeta-contenido .kw{display:block;font-size:12px;color:var(--grafito);margin-top:4px}
.tarjeta-contenido .meta{display:block;font-size:11.5px;color:var(--apagado);margin-top:6px}
.tarjeta-contenido .atrasado{color:var(--tinta);font-weight:500}
.tarjeta-contenido .sin-briefing{font-style:italic}

.boton.secundario.activo{background:var(--grafito);color:#fff;border-color:var(--grafito)}

textarea.mono,input.mono{font-family:ui-monospace,monospace;font-size:12.5px;line-height:1.55}
.briefing-texto{
  font-family:ui-monospace,monospace;font-size:12.5px;line-height:1.6;white-space:pre-wrap;
  background:var(--fondo-2);padding:16px;border-radius:var(--radio);overflow-x:auto;
}

@media (max-width:1100px){
  .tablero{grid-template-columns:repeat(5,minmax(170px,1fr))}
}

/* ---------- rastreo (fase 3) ---------- */
.cobertura td, .datos td{vertical-align:top}
.datos th[style*="210px"]{color:var(--apagado);font-weight:500}

/* Cabeceras agrupadas: arriba de qué va cada bloque de columnas */
.datos thead tr.grupos th{
  border-bottom:0;padding-bottom:2px;color:var(--grafito);font-size:11px;
}
.datos thead tr.grupos th[colspan]{border-left:1px solid var(--linea)}
.datos thead tr.grupos + tr th{padding-top:2px}
.datos thead tr.grupos .nota{font-size:10.5px;text-transform:none;letter-spacing:0;font-weight:400}

.lista-simple{margin:6px 0 12px;padding-left:20px;font-size:13px;color:var(--apagado)}
.lista-simple li{margin-bottom:2px}

/* ---------- tablas que se ordenan ---------- */
.datos th.ordenable{cursor:pointer;user-select:none;position:relative;padding-right:18px}
.datos th.ordenable:hover{color:var(--tinta)}
.datos th.ordenable::after{
  content:"";position:absolute;right:6px;top:50%;margin-top:-5px;
  width:0;height:0;border-left:3.5px solid transparent;border-right:3.5px solid transparent;
  border-top:4px solid var(--linea-fuerte);border-bottom:4px solid var(--linea-fuerte);
  opacity:0;transition:opacity .12s;
}
.datos th.ordenable:hover::after,.datos th.ordenable:focus-visible::after{opacity:.55}
.datos th[aria-sort]{color:var(--tinta)}
.datos th[aria-sort]::after{opacity:1;border-color:var(--grafito)}
.datos th[aria-sort="ascending"]::after{border-top-color:transparent;border-bottom-color:var(--grafito)}
.datos th[aria-sort="descending"]::after{border-bottom-color:transparent;border-top-color:var(--grafito)}
.datos th.ordenable:focus-visible{outline:2px solid var(--grafito);outline-offset:-2px}

/* ---------- arquitectura y PageRank interno: el gráfico de burbujas (1.234.0) ----------
   Lo pinta el servidor (BurbujasPagerank) y burbujas.js solo acerca, mueve y
   señala. La burbuja señalada se marca también sin JavaScript, con :target. */
.burbujas-marco{
  border:1px solid var(--linea);border-radius:var(--radio);background:var(--papel);overflow:hidden;
}
.burbujas{display:block;width:100%;height:auto;max-height:620px;touch-action:none}
.burbujas.moviendo{cursor:grabbing}
/* El borde en píxeles de pantalla, no del dibujo: al acercar no engorda. */
.burbujas circle{stroke:var(--papel);stroke-width:1;vector-effect:non-scaling-stroke}
.burbujas circle:hover{stroke:var(--tinta);stroke-width:1.5}
.burbujas circle:target,.burbujas circle.senalada{stroke:var(--tinta);stroke-width:3}
.burbujas-mandos{display:flex;gap:6px;justify-content:flex-end;margin-bottom:8px}
.burbujas-mandos[hidden]{display:none}
.arquitectura-leyenda{
  display:flex;flex-wrap:wrap;align-items:center;gap:6px 14px;margin-top:10px;
  font-size:11.5px;color:var(--apagado);
}
.arquitectura-leyenda .titulo{
  font-size:10px;letter-spacing:.1em;text-transform:uppercase;font-weight:600;
}
.arquitectura-leyenda .paso{display:flex;align-items:center;gap:6px}
.arquitectura-leyenda i{width:10px;height:10px;border-radius:50%;display:block;flex:0 0 10px}

/* ---------------------------------------------------------------- SERP
   La simulación de un resultado de Google.

   Es el único sitio de Visión que no usa la identidad de Agarimo, y es a
   propósito: lo que se está enseñando es cómo se vería la página EN GOOGLE, y
   pintarlo en gris grafito con Rubik contestaría a otra pregunta. Va dentro de
   un recuadro etiquetado como simulación para que nadie lo confunda con una
   captura de verdad. */
.serp{
  border:1px solid var(--linea);border-radius:var(--radio);background:#fff;
  padding:20px 22px;max-width:640px;
  font-family:arial,-apple-system,"Segoe UI",sans-serif;
}
.serp-resultado{font-size:14px;line-height:1.58;color:#4d5156}
.serp-sitio{display:flex;align-items:center;gap:8px;margin-bottom:2px}
.serp-favicon{
  width:26px;height:26px;border-radius:50%;flex:0 0 26px;
  background:#f1f3f4;border:1px solid #dadce0;
}
.serp-ruta{font-size:12px;color:#202124;line-height:1.3;word-break:break-all}
.serp-titulo{
  font-size:20px;line-height:1.3;color:#1a0dab;margin:2px 0 3px;
  font-family:arial,sans-serif;
}
.serp-titulo.sin{color:#70757a}
.serp-estrellas{font-size:14px;color:#70757a;display:flex;gap:5px;flex-wrap:wrap;margin-bottom:2px}
/* Las estrellas se recortan por la parte que toca en vez de redondearse a
   estrellas enteras: un 4,7 pintado con cinco llenas promete un cinco. */
.serp-estrellas .estrellas{
  position:relative;display:inline-block;color:#dadce0;letter-spacing:.5px;
}
.serp-estrellas .estrellas::before{
  content:"★★★★★";position:absolute;left:0;top:0;width:var(--parte,0%);
  overflow:hidden;color:#e7711b;white-space:nowrap;
}
.serp-texto{font-size:14px;color:#4d5156}
.serp-texto.sin{color:#9aa0a6}
.serp-extra{font-size:13px;color:#70757a;margin-top:3px}
.serp-faq{margin-top:10px;border-top:1px solid #ebebeb}
.serp-pregunta{
  display:flex;justify-content:space-between;align-items:center;gap:10px;
  padding:11px 0;border-bottom:1px solid #ebebeb;font-size:14px;color:#202124;
}
.serp-pregunta span{color:#70757a;font-size:15px}
.serp-pregunta.mas{color:#70757a;font-size:13px;border-bottom:0}

/* ------------------------------------------- los elementos marcados, en crudo */
.marcado-item{padding:14px 16px;border-bottom:1px solid var(--linea)}
.marcado-item:last-child{border-bottom:0}
.marcado-item.anidado{padding-left:34px;background:var(--fondo)}
.marcado-cabeza{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;margin-bottom:6px}
.marcado-cabeza strong{font-size:14px}
table.datos.apretada td{padding:4px 10px;font-size:12.5px}
td.marcado-clave{
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;
  color:var(--apagado);width:190px;vertical-align:top;
}

/* La barra de acciones de una tabla con casillas. Solo se enseña cuando hay
   algo marcado: un botón de «añadir» que no puede hacer nada enseña a ignorarlo. */
.barra-seleccion{
  display:flex;align-items:flex-end;gap:14px;flex-wrap:wrap;
  background:var(--fondo-2);border-bottom:1px solid var(--linea);
}
/* Un `display` puesto en una clase gana al `[hidden]{display:none}` que trae el
   navegador, así que la barra se quedaba a la vista con nada marcado por mucho
   que el atributo estuviera puesto. Hay que decirlo aquí. */
.barra-seleccion[hidden]{display:none}
.barra-seleccion > strong{padding-bottom:8px;white-space:nowrap}
.barra-seleccion .nota{padding-bottom:9px}

/* ------------------------------------------------------ el mapa de keywords
   Doce meses en una parrilla. Aquí el color SÍ informa —dice en qué banda de
   Google está la keyword— y por eso es la única tabla de Visión con fondos de
   color: no es decoración, es el dato.

   Una sola familia de color, del más claro al más oscuro, y no un semáforo de
   verde-amarillo-rojo. La posición es una magnitud ordenada, no una alarma:
   con una escala de un solo tono se lee de un vistazo cuál está mejor sin
   tener que aprenderse qué significa cada color. Más allá del 30 no se pinta
   nada, porque un 47 y un 82 son la misma noticia.

   Del 30 en adelante no hay fondo: así el ojo encuentra las buenas sin leer. */
.mapa-keywords th.pegada{
  position:sticky;left:0;z-index:2;background:var(--papel);min-width:230px;max-width:320px;
  font-weight:500;color:var(--tinta);
}
.mapa-keywords thead th.pegada{background:var(--fondo-2);z-index:3}
.mapa-keywords th.pegada a{color:var(--tinta);text-decoration:none;font-weight:500}
.mapa-keywords th.pegada a:hover{text-decoration:underline}
.mapa-keywords th.pegada .nota,.mapa-keywords th.pegada .etiqueta{
  display:inline-block;margin-left:6px;font-weight:400;
}
.mapa-keywords td,.mapa-keywords tbody th{vertical-align:middle}
/* La última fila no lleva raya, igual que en el resto de tablas. La regla de
   arriba solo habla de <td> y aquí la primera celda de cada fila es un <th>:
   sin esto, la parrilla acababa con media raya debajo de la columna pegada. */
.mapa-keywords tbody tr:last-child th{border-bottom:0}
.mapa-keywords td.num{padding:5px 8px;text-align:center}
.mapa-keywords thead th.num{text-align:center}
.mapa-keywords thead th .anio{display:block;font-size:9px;opacity:.75;letter-spacing:.04em}
.celda-mapa{
  display:inline-block;min-width:42px;padding:5px 8px;border-radius:var(--radio);
  font-size:13px;font-variant-numeric:tabular-nums;color:var(--tinta);
}
.celda-mapa.vacia{color:var(--apagado)}
.celda-mapa.top30{background:#DCEDE2}
.celda-mapa.top10{background:#8FC7A6;color:#123322}
.celda-mapa.top3{background:#186B41;color:#fff;font-weight:600}
.leyenda-mapa{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:14px 0 0}
.leyenda-mapa .celda-mapa{min-width:0;font-size:12px}
.leyenda-mapa .nota{margin-left:6px}

/* ---------------------------------------------------- Open Graph: la tarjeta
   La vista previa de cómo queda un enlace al compartirlo. Va con los colores
   de la casa y NO imitando a Facebook: lo que hay que comprobar aquí es el
   encuadre de la imagen y dónde corta el texto, no de qué color es el marco de
   una red concreta —que además cambia cada temporada—. */
.og-tarjeta{
  border:1px solid var(--linea);border-radius:var(--radio);overflow:hidden;
  max-width:520px;background:var(--papel);
}
.og-imagen{background:var(--fondo-2);aspect-ratio:1200/630;overflow:hidden}
.og-imagen img{width:100%;height:100%;object-fit:cover;display:block}
.og-imagen.pequena{aspect-ratio:1/1;max-width:130px;float:left}
.og-imagen.vacia{
  display:flex;align-items:center;justify-content:center;color:var(--apagado);font-size:12.5px;
}
.og-texto{padding:12px 14px;border-top:1px solid var(--linea)}
.og-dominio{font-size:11px;letter-spacing:.06em;color:var(--apagado);text-transform:uppercase}
.og-titulo{font-size:15px;font-weight:600;color:var(--tinta);margin-top:3px;line-height:1.3}
.og-descripcion{font-size:12.5px;color:var(--apagado);margin-top:4px;line-height:1.45}
.codigo{
  font-family:ui-monospace,monospace;font-size:12.5px;line-height:1.6;white-space:pre-wrap;
  background:var(--fondo-2);padding:16px;border-radius:var(--radio);overflow-x:auto;margin:0;
  overflow-wrap:anywhere;
}

/* ------------------------------------------------ conversiones: periodos
   Los seis botones de periodo y las casillas de los eventos. El punto de
   color de cada casilla es el de su línea en el gráfico: sin él hay que
   adivinar cuál es cuál, y con seis líneas eso no se adivina. */
.botonera-periodos{display:flex;gap:8px;flex-wrap:wrap}
.casillas-eventos{display:flex;gap:10px 18px;flex-wrap:wrap}
.casilla-evento{
  display:inline-flex;align-items:center;gap:7px;font-size:13.5px;cursor:pointer;
  padding:5px 10px;border:1px solid var(--linea);border-radius:var(--radio);background:var(--papel);
}
.casilla-evento:hover{border-color:var(--grafito)}
.casilla-evento input{width:15px;height:15px;margin:0}
.casilla-evento .nota{font-variant-numeric:tabular-nums}
.punto{
  display:inline-block;width:9px;height:9px;border-radius:50%;flex:0 0 auto;
  background:var(--grafito);
}

/* ---------------------------------------------- desplegable de marcar varios
   Un botón que dice qué hay elegido y, al abrirlo, buscador y casillas. Sin
   JavaScript el panel se queda visible y sigue funcionando: por eso no se
   esconde desde aquí, sino desde el guion. */
.multiselect{position:relative;margin:0;max-width:260px}
.multiselect > label{display:block;font-size:12.5px;font-weight:500;margin-bottom:5px;
  color:var(--grafito)}
.multiselect-boton{
  width:100%;padding:8px 26px 8px 10px;border:1px solid var(--linea-fuerte);
  border-radius:var(--radio);background:var(--papel);color:var(--tinta);
  font:inherit;font-size:14px;text-align:left;cursor:pointer;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
/* La flecha, dibujada con bordes: una imagen de fuera no la deja cargar la
   política de contenido, y un carácter tipográfico se descoloca según la
   fuente que acabe usando el navegador. */
.multiselect-boton::after{
  content:"";position:absolute;right:11px;top:calc(50% + 5px);
  border:4px solid transparent;border-top-color:var(--apagado);pointer-events:none;
}
.multiselect.abierto .multiselect-boton{border-color:var(--grafito)}
/* El panel es más ancho que el botón a propósito: el botón vive en una fila de
   filtros estrechos y, atado a su ancho, «Seleccionar todo» partía en dos
   líneas y los nombres largos no cabían. */
.multiselect-panel{
  position:absolute;z-index:40;left:0;top:100%;margin-top:2px;
  min-width:100%;width:max-content;max-width:340px;
  background:var(--papel);border:1px solid var(--linea-fuerte);border-radius:var(--radio);
  box-shadow:0 6px 18px rgba(20,20,19,.12);
}
.multiselect-buscar{padding:8px;border-bottom:1px solid var(--linea)}
.multiselect-buscar input{width:100%}
.multiselect-lista{max-height:260px;overflow-y:auto;padding:4px 0}
.multiselect-opcion{
  display:flex;align-items:center;gap:8px;padding:6px 10px;font-size:13.5px;
  cursor:pointer;line-height:1.3;
}
/* Esta línea no es una redundancia: «display:flex» de la regla de arriba gana
   al «[hidden]{display:none}» del navegador, y sin esto el buscador escondía
   las opciones en el papel y en ninguna otra parte —seguían todas a la vista—.
   Lo mismo para el aviso de que no hay coincidencias. */
.multiselect-opcion[hidden],.multiselect-nada[hidden],.multiselect-panel[hidden]{display:none}
.multiselect-opcion:hover{background:var(--fondo-2)}
.multiselect-opcion input{margin:0;flex:0 0 auto}
.multiselect-opcion span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.multiselect-todo{border-bottom:1px solid var(--linea);margin-bottom:4px;padding-bottom:8px;
  font-weight:500}
.multiselect-nada{padding:10px;margin:0}

/* Los meses en vigor de un proyecto de temporada: una rejilla que cabe en tres
   líneas en el móvil y en una o dos en el escritorio. */
.meses-rejilla{display:grid;grid-template-columns:repeat(auto-fill,minmax(122px,1fr));gap:4px 10px}
.mes-check{display:flex;align-items:center;gap:7px;font-size:13.5px;cursor:pointer;padding:3px 0}
.mes-check input{margin:0}

/* El texto largo que escribe la IA: ancho de lectura y párrafos que respiran.
   A toda la anchura de la pantalla no lo lee nadie. */
.texto-ia{max-width:70ch;line-height:1.6;font-size:14.5px;color:var(--tinta)}
.texto-ia strong{font-weight:600}

/* Un valor juzgado contra un umbral. No lleva flecha a propósito: la flecha de
   «.delta» dice «ha subido respecto a antes», y esto dice «está dentro o fuera
   del umbral», que es otra cosa. Un LCP con flecha hacia arriba se leería como
   una mejora cuando es lo contrario. */
.umbral{font-variant-numeric:tabular-nums;white-space:nowrap}
.umbral.bien{color:var(--bien)}
.umbral.justo{color:var(--justo);font-weight:600}
.umbral.mal{color:var(--mal);font-weight:600}

/* La fila de botones de descarga de un bloque. Va dentro del cuerpo y no en la
   cabecera a propósito: un botón dentro de <summary> abre y cierra el bloque al
   pulsarlo, que es justo lo que no puede pasar al bajarse un fichero. */
.cuerpo.descargas{display:flex;gap:8px;align-items:center;flex-wrap:wrap;
  border-bottom:1px solid var(--linea)}
.cuerpo.descargas .nota{flex:1 1 260px;margin:0}

/* Buscador de localizaciones de DataForSEO.
   La lista se dibuja por encima de lo que venga detrás —dentro de un formulario
   siempre hay otro campo justo debajo— y se le pone un alto máximo: hay
   búsquedas que devuelven veinte resultados y sin tope empujarían el formulario
   entero hacia abajo cada vez que alguien escribe una letra. */
.con-sugerencias{position:relative}
.sugerencias{position:absolute;z-index:30;left:0;right:0;top:100%;margin-top:2px;
  background:var(--papel);border:1px solid var(--linea-fuerte);border-radius:6px;
  box-shadow:0 6px 20px rgba(20,20,19,.10);max-height:280px;overflow-y:auto}
.sugerencia{display:block;width:100%;text-align:left;padding:7px 10px;border:0;
  background:none;font:inherit;font-size:14px;color:var(--tinta);cursor:pointer;
  border-bottom:1px solid var(--linea)}
.sugerencia:last-child{border-bottom:0}
.sugerencia:hover,.sugerencia.marcada{background:var(--fondo-2)}
.sugerencia .nota{font-size:12px;margin:0}

/* Cada grupo de keywords se edita en su sitio: son pocos y lo que se viene a
   cambiar —la localización— tiene que estar a un clic, no detrás de otra
   pantalla. El recuadro separa un grupo del siguiente sin convertirlos en una
   tabla, que con cuatro campos por fila no cabría. */
.grupo-editable{border:1px solid var(--linea);border-radius:8px;padding:12px 14px 4px;
  margin-bottom:8px;background:var(--papel)}
.grupo-editable .acciones{display:flex;gap:10px;align-items:center;margin:0 0 10px}

/* ---------------------------------------------------------- brecha de keywords

   Los dominios que se comparan, como fichas. Sin esto salían todos pegados en
   una línea corrida —«casadoneto.com nosotros 3 kw · del 06/09 rival.com 3 kw»—
   y no se distinguía dónde acababa uno y empezaba el otro. */
.fichas-dominios{display:flex;flex-wrap:wrap;gap:8px}
.fichas-dominios .ficha{
  display:inline-flex;align-items:baseline;gap:8px;
  padding:7px 12px;border:1px solid var(--linea);border-radius:var(--radio);
  background:var(--papel);
  /* La ficha lleva el dominio y dos notas al lado, y en un móvil eso no cabe
     en una línea: sin envolver, la ficha se pasaba del ancho de la pantalla y
     arrastraba la página. Envolviendo, crece hacia abajo, que es a donde hay
     sitio. Y un dominio largo se parte antes que salirse. */
  flex-wrap:wrap;max-width:100%;
}
.fichas-dominios .ficha > *{min-width:0;overflow-wrap:anywhere}
/* El nuestro se distingue: es contra el que se mide todo lo demás. */
.fichas-dominios .ficha.solida{border-color:var(--grafito);border-width:1.5px}
.fichas-dominios .ficha .nota{font-size:12px}
/* Una ficha que se puede marcar: la de elegir rivales para el linkbuilding. La
   casilla se alinea arriba y no en la línea base porque debajo del dominio va
   su visibilidad, y centrada quedaba a media altura de las dos líneas. */
.fichas-dominios .ficha.elegible{align-items:flex-start;cursor:pointer}
.fichas-dominios .ficha.elegible:hover{border-color:var(--linea-fuerte)}
.fichas-dominios .ficha .nota.linea{display:block;margin-top:2px}
.fichas-dominios .ficha .enlace{
  border:0;background:none;cursor:pointer;color:var(--apagado);
  font-size:16px;line-height:1;padding:0 0 0 2px;
}
.fichas-dominios .ficha .enlace:hover{color:var(--tinta)}
/* El motivo de un intento fallido. Subrayado y no en rojo, como el resto de la
   aplicación: el color solo no lo ve todo el mundo y aquí el texto ya dice lo
   que pasa. Se recorta porque un mensaje de DataForSEO puede ser largo y no
   puede reventar la fila de fichas; entero está en el «title». */
.fichas-dominios .ficha .nota.mal{
  font-weight:600;text-decoration:underline;
  text-decoration-color:var(--linea-fuerte);text-underline-offset:3px;
  max-width:34ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}

/* La intención de búsqueda: la inicial dentro de un círculo.
   
   Es un círculo y no una etiqueta con la palabra entera porque va INTERCALADO
   entre la keyword y su posición, en sitios donde ya compiten cinco columnas
   por el ancho. Una letra siempre en el mismo sitio se lee de un vistazo; la
   palabra empujaría la posición fuera de la vista.
   
   Sin color: hay cuatro intenciones y ninguna es mejor que otra, así que
   pintarlas de cuatro colores diría que las hay buenas y malas —además de
   dejar fuera a quien no distingue dos de ellos—. Lo que dice cuál es, es la
   letra; el nombre entero está en el «title».
   
   Ancho y alto iguales y «line-height» clavado: sin eso, una «I» deja un
   óvalo estrecho y una «T» uno ancho, y dejan de leerse como la misma cosa. */
.intencion{
  display:inline-flex;align-items:center;justify-content:center;
  width:19px;height:19px;flex:0 0 19px;border-radius:50%;
  border:1px solid var(--linea-fuerte);color:var(--grafito);
  font-size:11px;font-weight:700;line-height:1;
  vertical-align:middle;cursor:help;
}

/* Una tabla que se reparte el ancho en vez de desbordarlo.

   La de linkbuilding tiene nueve columnas y dos de ellas con texto largo —el
   consejo de la IA y la URL de ejemplo— y no cabía: salía la barra horizontal y
   media tabla quedaba fuera de la pantalla. Con «fixed» el navegador reparte lo
   que hay siguiendo los anchos declarados, en vez de pedir más sitio.

   Va con «word-break» porque con «fixed» una URL sin espacios de doscientos
   caracteres se sale de su celda igual: aquí se parte donde toque. */
/* ---------- el portal del cliente ----------
   Su propio marco, sin menú ni nada en lo que pinchar: una sola página. El
   acento sale de la marca de quien lleva el proyecto —que en marca blanca no
   es Agarimo— y viaja en una variable para cambiarse en un sitio. */
body.portal{background:var(--fondo);margin:0}
.portal-ancho{max-width:900px;margin:0 auto;padding:0 20px}
.portal-cabecera{background:var(--marca);color:#fff;padding:28px 0 24px;margin-bottom:26px}
.portal-cabecera h1{font-size:26px;margin:2px 0 6px}
.portal-marca{font-size:11px;letter-spacing:.12em;text-transform:uppercase;opacity:.75}
.portal-cabecera .portal-nota{color:#fff;opacity:.8}
.portal-nota{font-size:12.5px;color:var(--apagado)}
/* El botón de descarga, sobre la banda de la marca: borde claro y fondo
   transparente, que un botón blanco sólido ahí compite con el nombre del
   proyecto, que es lo que tiene que leerse primero. */
.portal-descarga{display:inline-block;margin-top:10px;padding:6px 14px;border-radius:20px;
  border:1px solid rgba(255,255,255,.55);color:#fff;text-decoration:none;font-size:12.5px}
.portal-descarga:hover{background:rgba(255,255,255,.14)}
.portal-bloque{background:var(--papel);border:1px solid var(--linea);border-radius:var(--radio);
  padding:20px;margin-bottom:20px}
.portal-bloque h2{font-size:17px;margin:0 0 12px}
.portal-cifras{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(150px,100%),1fr));gap:16px}
/* Las tablas del portal se desplazan DENTRO de su bloque.
   Es la página que abre el cliente, muchas veces desde el móvil del correo, y
   sus tablas —diez búsquedas con impresiones, clics y posición— no caben en
   390 px por mucho que se aprieten. Sin esto, la página entera se arrastraba de
   lado: el titular, el logotipo de la agencia y todo lo demás moviéndose con
   la tabla. El bloque es el contenedor correcto porque es la caja que ya
   delimita cada apartado del informe. */
.portal-bloque{overflow-x:auto}
.portal-bloque table.datos{min-width:min(100%, 34rem)}
.portal-cifras > div{display:flex;flex-direction:column;gap:2px}
.portal-numero{font-size:30px;font-weight:600;line-height:1.1}
.portal-etiqueta{font-size:12.5px;color:var(--apagado)}
.portal-var{font-size:12px;color:var(--apagado)}
/* La medida de una actuación: la cifra a la izquierda y el porqué al lado, que
   es el orden en que se lee —«esto subió» y luego «esto es lo que hicimos»—. */
.portal-medida{display:flex;gap:16px;align-items:flex-start;padding:12px 0;
  border-top:1px solid var(--linea)}
.portal-medida:first-of-type{border-top:0}
.portal-medida-cifra{font-size:24px;font-weight:600;min-width:92px;color:var(--marca)}
/* Lo que bajó, en rojo (1.221.0). Hasta entonces iba en gris «para que el
   cliente no leyera catástrofe»; Gabriel pidió verde y rojo en toda la
   aplicación, también en lo que ve el cliente. */
.portal-medida-cifra.baja{color:var(--mal)}
.portal-var.mejora{color:var(--bien)}
.portal-var.empeora{color:var(--mal)}
/* Los tres paneles del gráfico: uno debajo de otro y con los mismos meses
   alineados. Tres paneles y no una gráfica de tres ejes —ver el porqué en la
   plantilla—. */
.portal-graficas{display:grid;gap:14px;margin-top:14px}
.portal-graficas figure{margin:0}
.portal-graficas figcaption{font-size:12.5px;font-weight:600;margin-bottom:4px}
/* Lo hecho y lo previsto, uno al lado del otro: es la misma pregunta en dos
   tiempos y leerlas juntas es lo que contesta «¿qué estáis haciendo?». */
.portal-mes{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:20px}
@media (max-width:720px){.portal-mes{grid-template-columns:minmax(0,1fr)}}
.portal-lista{margin:8px 0 0;padding-left:18px}
.portal-lista li{margin-bottom:6px}
.portal-subtitulo{font-size:14px;margin:20px 0 8px}
table.datos tr.portal-nosotros > td{background:var(--fondo-2);font-weight:600}
.portal-pie{padding:18px 20px 40px;font-size:12px;color:var(--apagado)}

/* El editor de contenido: el texto y la comprobación, uno al lado del otro.
   En pantalla estrecha se apilan —el panel debajo— porque un textarea de
   trescientos píxeles no sirve para escribir. */
.editor-columnas{display:grid;grid-template-columns:minmax(0,1.6fr) minmax(0,1fr);gap:18px;align-items:start}
.editor-columnas textarea{width:100%;min-height:520px;font-size:13.5px;line-height:1.55}
@media (max-width:1000px){.editor-columnas{grid-template-columns:minmax(0,1fr)}}

table.datos.ajustada{table-layout:fixed}
table.datos.ajustada td{overflow-wrap:anywhere;word-break:break-word}
/* Los encabezados dejan de ir en una sola línea: con anchos fijos, «nowrap»
   obligaría a la columna a ser al menos tan ancha como su título. */
table.datos.ajustada thead th{white-space:normal}
/* Y las etiquetas tampoco: una etiqueta es «nowrap» por defecto y con la tabla
   de anchos fijos «Asociación, colegio o cámara» se salía de su columna y se
   pintaba encima de la URL de al lado. Aquí dentro se parte en dos líneas. */
table.datos.ajustada td .etiqueta{white-space:normal;max-width:100%}
/* Los controles de la última columna se encogen con ella. Sin esto el desplegable
   mantenía su ancho natural y la fila terminaba sobresaliendo por la derecha,
   que era justo lo que hacía que la tabla no encajase en el ancho disponible. */
table.datos.ajustada td select{max-width:100%}
/* Y esos controles van uno debajo de otro, no en línea: el desplegable de estado
   y el botón de consejo juntos no caben en la columna y sobresalían por el borde
   derecho de la tabla. */
table.datos.ajustada td form.enlinea{display:block;max-width:100%}
table.datos.ajustada td form.enlinea + form.enlinea{margin-top:4px}

/* Una celda que recorta lo que no cabe en UNA línea: la URL de ejemplo. Lo
   entero está en el «title», y debajo va el ancla, que sí puede partir. */
table.datos .recortada > a{
  display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}

/* Un párrafo dentro de una celda estrecha: el consejo de la IA y el borrador de
   correo. Respeta los saltos de línea que trae el texto y no estira la fila,
   porque va dentro de un desplegable cerrado. */
.texto-largo{white-space:pre-wrap;font-size:12px;margin-top:6px}

/* Un cluster semántico: su nombre, sus cifras y sus keywords debajo.

   Se reutilizan las fichas de la brecha para las keywords —son lo mismo: una
   lista de cosas cortas que se leen de un vistazo— y lo único propio es la
   separación entre clusters. Inventar aquí una segunda manera de pintar una
   lista de etiquetas daría dos estilos para lo mismo, que es cómo se acaba
   teniendo una aplicación que parece dos. */
.racimo{padding:12px 0;border-top:1px solid var(--linea)}
.racimo:first-child{padding-top:0;border-top:0}
.racimo h3{margin:0 0 8px;font-size:15px}
.racimo h3 .nota{font-weight:400;margin-left:8px}
.racimo .ficha{padding:5px 10px}

/* Las casillas de «traerlos de Competidores»: en columna y con aire, que si no
   se leen como una frase larga. */
.lista-casillas{display:flex;flex-direction:column;gap:4px;margin:2px 0 8px}
.lista-casillas .casilla{display:flex;align-items:center;gap:7px;font-size:14px}
.lista-casillas .casilla input{margin:0}

/* La barra de acciones de una tabla larga: pegada abajo del bloque, con sus
   controles en línea y sin que el desplegable se coma el ancho entero. */
.acciones-tabla{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  padding:12px 16px;border-top:1px solid var(--linea);
}
.acciones-tabla select{width:auto;min-width:140px}
.acciones-tabla .nota{flex:1 1 200px}

/* El botón de abrir la URL del cliente en una pestaña nueva.
   Discreto a propósito: va en casi todas las filas de casi todas las tablas de
   URLs, y un icono con peso convertiría un listado de doscientas en una pared
   de iconos. Se aclara al pasar por encima, que es cuando se busca. */
.abrir-fuera{
  display:inline-flex;align-items:center;justify-content:center;
  width:20px;height:20px;margin-left:4px;vertical-align:-4px;
  color:var(--linea);border-radius:4px;flex:0 0 auto;
  text-decoration:none;transition:color .12s,background .12s;
}
.abrir-fuera:hover{color:var(--grafito);background:var(--fondo-2)}
.abrir-fuera:focus-visible{outline:2px solid var(--grafito);outline-offset:1px;color:var(--grafito)}
/* En una celda que ya tiene el ratón encima, el icono se insinúa sin esperar a
   que se acierte con él: sin esto hay que barrer la fila buscándolo. */
tr:hover .abrir-fuera{color:var(--apagado)}

/* Las marcas de una keyword: con qué dispositivo se mide, desde dónde y qué
   quiere quien busca eso.

   Van las tres juntas y pegadas a la palabra clave porque son datos DE LA
   KEYWORD. Repartidas por la tabla —el dispositivo debajo de la posición, la
   intención tres columnas más allá— había que recomponerlas con la vista en
   cada una de las doscientas filas.

   En línea con el texto y no debajo: lo de debajo doblaba el alto de la fila, y
   una tabla de doscientas keywords que ocupa el doble se deja de leer entera.

   Sin color, como el círculo de intención y por el mismo motivo: no hay un
   dispositivo mejor que otro ni una ubicación mejor que otra, y pintarlos diría
   que sí. Lo que dice cuál es, es el dibujo; el dato entero está en el «title». */
.marcas-kw{
  display:inline-flex;align-items:center;gap:5px;
  margin-left:7px;vertical-align:middle;
}
.marca-kw{
  display:inline-flex;align-items:center;justify-content:center;
  width:19px;height:19px;flex:0 0 19px;
  color:var(--apagado);cursor:help;
}
.marca-kw:hover{color:var(--grafito)}

/* Una cifra con explicación detrás. El subrayado punteado es lo único que
   avisa de que hay algo que mirar: sin él, nadie pasa el ratón por encima de un
   número porque no hay motivo para pensar que diga nada más. */
.con-pista{
  cursor:help;
  text-decoration:underline dotted var(--linea-fuerte);
  text-underline-offset:3px;
}

/* ---------- el estado de cada acción del calendario ----------

   El símbolo dice CUÁL es el estado y el color lo hace saltar a la vista, en
   ese orden. Con el color como única señal, quien no distingue el rojo del
   verde —uno de cada doce hombres— se queda sin la pantalla entera; con el
   símbolo solo, doce meses de acciones son una mancha gris en la que hay que
   leerlo todo para encontrar lo que está atascado.

   Los cuatro tonos son oscuros a propósito: sobre papel blanco, un verde o un
   ámbar de los de avisar tienen demasiado poco contraste para un símbolo de
   trece píxeles. */
.calendario .accion .punto{
  display:inline-flex;align-items:center;justify-content:center;
  width:14px;height:14px;flex:0 0 14px;
  vertical-align:-2px;cursor:help;
}
.calendario .accion .punto.espera{color:#9a7000}   /* pendiente · ámbar */
.calendario .accion .punto.andando{color:#c2560a}  /* en curso  · naranja */
.calendario .accion .punto.parada{color:#c0281f}   /* bloqueada · rojo */
.calendario .accion .punto.lista{color:#1f7a3d}    /* hecha     · verde */
/* La descartada no lleva color: no está atascada ni pendiente, es que ya no
   cuenta. Pintarla la volvería a meter en la conversación. */
.calendario .accion .punto.fuera{color:var(--linea-fuerte)}

/* El editor de una acción: todo lo suyo en un formulario y no en tres.
   Repartido en tres —estado por un lado, mover por otro, y el texto en ninguno—
   es lo que hacía que se quedara a medias: se cambiaba el estado, se olvidaba
   el tipo, y para corregir el tipo había que borrar la acción y reescribirla. */
.editor-accion{
  display:flex;flex-direction:column;gap:5px;margin-top:8px;
  padding-top:8px;border-top:1px dashed var(--linea);
}
.editor-accion textarea,
.editor-accion select,
.editor-accion input[type="date"]{
  width:100%;font-size:11.5px;padding:4px 6px;
}
.editor-accion textarea{resize:vertical;line-height:1.35}
.editor-accion .nota{margin:2px 0 -2px}
.editor-accion .boton{align-self:flex-start;padding:3px 10px;font-size:11.5px;line-height:1.2}

/* Las vistas guardadas del listado de keywords: los filtros que se usan a
   diario, con nombre.

   En una fila y no en un desplegable: son cuatro o cinco por proyecto y lo que
   se hace con ellas es saltar de una a otra, que en un desplegable son tres
   clics y aquí uno. La que está puesta va marcada, porque si no hay que mirar
   los filtros de arriba para saber en cuál se está. */
.vistas-guardadas{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  margin-top:12px;padding-top:12px;border-top:1px solid var(--linea);
}
.vistas-guardadas .vista{
  display:inline-flex;align-items:center;gap:2px;
  border:1px solid var(--linea);border-radius:999px;
  padding:2px 4px 2px 11px;font-size:12.5px;background:var(--papel);
}
.vistas-guardadas .vista a{text-decoration:none;color:var(--grafito)}
.vistas-guardadas .vista.puesta{border-color:var(--grafito);background:var(--fondo-2)}
.vistas-guardadas .vista.puesta a{color:var(--tinta);font-weight:600}
/* La equis de borrar, discreta hasta que se pasa por encima: va en cada vista y
   con peso convertiría la fila en una hilera de aspas. */
.vistas-guardadas .vista button{
  border:0;background:none;cursor:pointer;color:var(--linea-fuerte);
  font-size:14px;line-height:1;padding:0 4px;
}
.vistas-guardadas .vista:hover button{color:var(--apagado)}
.vistas-guardadas .vista button:hover{color:var(--tinta)}
.vistas-guardadas .guardar-vista{margin-left:auto;gap:6px}
.vistas-guardadas .guardar-vista input{font-size:12.5px;padding:3px 8px;min-width:200px}

/* La fila de la keyword principal de un cluster. Un fondo tenue y nada más:
   la palabra «principal» va dentro de la fila, porque el color solo no vale
   —esta tabla se imprime en blanco y negro para las reuniones—. */
table.datos tr.destacada > td{background:var(--fondo)}

/* El cluster de una página, debajo de sus keywords en el Keyword Mapping.
   En su propia línea y no pegado a la última keyword: es de la página, no de
   ninguna de ellas, y en la misma línea se leía como una más. */
.cluster-de-url{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  margin-top:6px;padding-top:6px;border-top:1px dashed var(--linea);font-size:12px}
.cluster-de-url select{font-size:12px;padding:2px 6px;max-width:100%}
.cluster-de-url form.enlinea button{border:0;background:none;cursor:pointer;color:var(--apagado)}
/* Una página lleva varios clusters: uno manda y los demás son apoyo. Cada uno
   en su propia cápsula para que se lea dónde empieza y acaba cada nombre, que
   con tres seguidos y separados solo por espacios se leían como uno largo.

   Inline-block y no inline-flex, por lo mismo que las pastillas de keywords de
   aquí al lado: dentro de una celda de tabla el navegador reparte el ancho por
   el contenido, y el ancho que declara un flex anidado se queda por debajo del
   que necesita. La cápsula se partía en dos líneas y la etiqueta «Principal»
   quedaba encima del nombre, leyéndose como dos cosas distintas.

   Y el modificador se llama «manda» y no «principal» a propósito: «.principal»
   ya es la columna de contenido del armazón —display:flex, dirección columna— y
   reusar ese nombre aquí le ponía a la cápsula la dirección de la página entera.
   Es la clase de choque que no da error y solo se ve mirando. */
.cluster-chip{display:inline-block;white-space:nowrap;max-width:100%;
  padding:2px 7px 2px 3px;border:1px solid var(--linea);border-radius:11px}
.cluster-chip.manda{border-color:var(--grafito)}
.cluster-chip > *{vertical-align:middle}
.cluster-chip > * + *{margin-left:5px}
.cluster-chip .etiqueta{font-size:10.5px;padding:1px 6px}
.cluster-chip button.estrella{border:0;background:none;cursor:pointer;padding:0}
/* El desplegable de casillas cabe en la fila de una tabla de trescientas: sin
   el tope, abre a 260px y empuja las columnas de la derecha fuera de la vista. */
.cluster-de-url .clusters-de-url{display:flex;align-items:center;gap:6px}
.cluster-de-url .multiselect{max-width:190px}
.cluster-de-url .multiselect > label{display:none}

/* El botón de una acción que no se puede deshacer. Rojo y con su palabra
   dentro: el color no distingue nada para quien no lo ve, y esto es lo último
   que se pulsa antes de borrar un cliente entero. */
.boton.peligro{background:#B3261E;border-color:#B3261E;color:#fff}
.boton.peligro:hover{background:#8E1D17;border-color:#8E1D17}
/* Un plegable sin la caja del bloque: para un detalle dentro de otro. */
details.plegable-simple > summary{cursor:pointer;margin-top:10px}

/* ---------- la explicación de un bloque, plegada ----------
   Media aplicación lleva debajo de su tabla o de su gráfico dos o tres
   párrafos explicando de dónde sale cada número y qué NO dice. Hacen falta —es
   lo que evita que alguien lea mal la tabla— pero no hacen falta CADA VEZ:
   quien entra veinte veces al mes a mirar una cifra se encuentra el mismo
   muro de texto gris veinte veces, y acaba sin leer ninguno.

   Así que van plegadas y con un enlace que dice exactamente qué hay dentro:
   «¿Qué significan estos datos?» cuando explican una tabla o un gráfico, y
   «¿Cómo funciona?» cuando explican qué hace un botón o una pantalla. Son las
   dos únicas etiquetas que se usan, a propósito: un enlace que cada vez se
   llama distinto obliga a leerlo, y este tiene que poder ignorarse.

   Es un «details» y no un botón con JavaScript porque así funciona con la
   política de contenido puesta y porque el navegador ya sabe hacerlo: se abre
   sin recargar, se imprime abierto si el navegador quiere, y el buscador del
   navegador encuentra el texto de dentro. */
details.explica{margin-top:14px}
details.explica > summary{
  cursor:pointer;list-style:none;display:inline-flex;align-items:center;gap:6px;
  /* El grafito de la casa y no el gris apagado de la propia nota: si el enlace
     para abrir se pinta del mismo color que el texto que esconde, no parece
     que se pueda pulsar. */
  font-size:13px;color:var(--grafito);line-height:1.5;user-select:none;
  text-decoration:underline;text-decoration-color:var(--linea-fuerte);
  text-underline-offset:2px;
}
details.explica > summary::-webkit-details-marker{display:none}
details.explica > summary::before{
  content:"▸";font-size:10px;display:inline-block;transition:transform .12s;
}
details.explica[open] > summary::before{transform:rotate(90deg)}
details.explica > summary:hover{text-decoration-color:var(--grafito)}
details.explica > summary:focus-visible{outline:2px solid var(--grafito);outline-offset:2px}
/* El primer párrafo pega con el enlace si no se le separa, y entonces al abrir
   parece que el enlace se ha convertido en texto. */
details.explica > *:not(summary){margin-top:8px}
details.explica > p:first-of-type{margin-top:8px}

/* ---------- test de marcado Schema.org v2 (1.212.0) ----------
   El grafo lo dibuja el servidor con su propio estilo dentro (para que el SVG
   descargado se vea igual); aquí va solo lo de alrededor: los mandos, la caja
   que se desplaza y las fichas de cada entidad. En pantalla estrecha las
   fichas pasan debajo del grafo. */
.sg-vocabulario{display:flex;flex-wrap:wrap;align-items:center;gap:8px 12px;margin-top:14px}
.tarjeta .sg-sobre{font-size:14px;font-weight:400;color:var(--apagado);margin-left:2px;letter-spacing:0}
.sg-mandos{display:flex;flex-wrap:wrap;align-items:center;gap:10px 22px}
.sg-zoom{display:inline-block;min-width:48px;text-align:center;font-size:12.5px;color:var(--apagado);font-variant-numeric:tabular-nums}
.sg-leyenda{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:6px 14px;font-size:12px;color:var(--apagado)}
.sg-leyenda li{display:flex;align-items:center;gap:6px}
.sg-marco{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,360px);border-top:1px solid var(--linea)}
.sg-caja{overflow:auto;max-height:72vh;background:var(--papel);min-width:0;cursor:grab;touch-action:pan-x pan-y}
.sg-caja.arrastrando{cursor:grabbing;user-select:none}
.sg-caja:focus-visible{outline:2px solid var(--tinta);outline-offset:-2px}
.sg-caja svg{display:block}
.sg-fichas{border-left:1px solid var(--linea);max-height:72vh;overflow:auto;padding:16px 18px;min-width:0;background:var(--papel)}
.sg-ficha + .sg-ficha{border-top:1px solid var(--linea);margin-top:18px;padding-top:18px}
.sg-js .sg-ficha + .sg-ficha{border-top:0;margin-top:0;padding-top:0}
.sg-ficha h3{font-size:15px;display:flex;align-items:center;gap:8px;overflow-wrap:anywhere}
.sg-ficha .sg-sub{margin:4px 0 10px;color:var(--apagado);font-size:13px;overflow-wrap:anywhere}
.sg-datos{display:grid;grid-template-columns:auto minmax(0,1fr);gap:4px 12px;font-size:12.5px;margin:0 0 12px}
.sg-datos dt{color:var(--apagado)}
.sg-datos dd{margin:0;overflow-wrap:anywhere}
.sg-problemas{list-style:none;margin:0 0 12px;padding:0;display:grid;gap:8px;font-size:13px}
.sg-entran{margin-top:10px}
.sg-json{margin-top:10px}
.sg-json > summary{cursor:pointer;font-size:13px;color:var(--grafito);text-decoration:underline;
  text-decoration-color:var(--linea-fuerte);text-underline-offset:2px}
.sg-json pre{max-height:320px;overflow:auto}
@media (max-width:900px){
  .sg-marco{grid-template-columns:minmax(0,1fr)}
  .sg-fichas{border-left:0;border-top:1px solid var(--linea);max-height:none}
}
/* El código corregido con IA (1.214.0): se lee y se copia entero */
.sg-codigo-mandos{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:10px}
.sg-codigo{max-height:480px;overflow:auto;background:var(--fondo);border:1px solid var(--linea);
  border-radius:var(--radio);padding:12px 14px}
/* Antes / ahora del marcado de una URL (1.217.0): lo quitado tachado en rojo
   suave, lo nuevo en verde suave; la palabra de la etiqueta dice cuál es, el
   color solo acompaña. */
.sg-antes{background:#FBE9E9;color:#8B2020;text-decoration:line-through;text-decoration-color:rgba(139,32,32,.45);
  padding:1px 4px;border-radius:2px;overflow-wrap:anywhere}
.sg-ahora{background:#E7F4EC;color:#1B5E3A;padding:1px 4px;border-radius:2px;overflow-wrap:anywhere}
.sg-titulo-version{font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--apagado);margin-bottom:8px}
/* Las páginas que llevan un enlace roto, desplegadas en su fila (1.219.0) */
.rotos-quienes{margin-top:6px}
.rotos-quienes > summary{cursor:pointer;font-size:12.5px;color:var(--grafito);text-decoration:underline;
  text-decoration-color:var(--linea-fuerte);text-underline-offset:2px}
.rotos-quienes ul{margin:8px 0 2px;padding-left:18px;display:grid;gap:4px;font-size:13px}
.rotos-quienes li .nota{margin-left:4px}

/* ===================================================================
   Visión · lo propio de este panel
   -------------------------------------------------------------------
   El resto de la hoja viene de Delfos sin tocar, a propósito: es la
   misma base de diseño y lo que se arregle allí se puede traer aquí
   de un copiado. Lo de abajo son solo las diferencias de Visión.
   =================================================================== */

/* Visión no tiene barra lateral: es UNA pantalla con su desglose, no una
   aplicación de cincuenta fichas. Sin esto, «.cuerpo-app» dejaba una columna
   vacía de 232 px a la izquierda del panel. */
.app > .principal{flex:1;min-height:0}

.pie-app{
  padding:14px 30px;color:var(--apagado);font-size:12px;
  border-top:1px solid var(--linea);
}

/* La tarjeta de un KPI sin dato.
   Un hueco no es un cero (regla 2 de la casa): la cifra se sustituye por
   «sin dato» en gris y el motivo va debajo, en el pie, con letra pequeña. Un 0
   en caja o en cobros vencidos se lee como «no hay nada» y es mentira. */
.tarjeta .sin-dato{color:var(--apagado);font-weight:400}
.tarjeta .motivo{color:var(--apagado);font-size:12px;line-height:1.45;margin-top:6px}

/* La fila de cabecera del panel: ejercicio, filtro de frecuencia y cuándo se
   trajo cada cosa. */
.filtro-frecuencia{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.filtro-frecuencia a{
  font-size:12px;padding:3px 10px;border:1px solid var(--linea);border-radius:var(--radio);
  color:var(--grafito-claro);text-decoration:none;background:var(--papel);
}
.filtro-frecuencia a.activo{background:var(--grafito);color:#fff;border-color:var(--grafito)}

/* El semáforo de una fuente de datos: configurada y sincronizada, o no. */
.punto-fuente{
  display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:7px;
  background:var(--linea-fuerte);vertical-align:middle;
}
.punto-fuente.bien{background:var(--bien)}
.punto-fuente.mal{background:var(--mal)}
.punto-fuente.justo{background:var(--justo)}

/* Una fila que está ahí pero no cuenta: una ausencia rechazada, un coste de un
   año que ya no se usa. Apagada y no escondida, porque esconderla haría creer
   que no existe y la diferencia entre «no está» y «no cuenta» es justo lo que
   hay que poder ver. */
table.datos tr.apagada > td{opacity:.55}

/* La barra de utilización por persona. Es la única tabla del panel donde la
   cifra sola no se lee: lo que importa es quién se sale del grupo, y eso se ve
   antes en una barra que leyendo trece porcentajes. */
.barra-uso{
  position:relative;height:8px;border-radius:4px;background:var(--fondo-2);
  overflow:hidden;min-width:70px;
}
.barra-uso span{display:block;height:100%;background:var(--linea-fuerte)}
.barra-uso span.bien{background:var(--bien)}
.barra-uso span.justo{background:var(--justo)}
.barra-uso span.mal{background:var(--mal)}
