/* =====================================================================
   QuieroSoftware — hoja de estilos base
   Diseño responsive, sin dependencias externas.
   ===================================================================== */

:root {
    --azul:        #1d4ed8;
    --azul-oscuro: #1e3a8a;
    --azul-claro:  #eff6ff;

    --texto:       #1f2937;
    --texto-suave: #6b7280;
    --borde:       #e5e7eb;
    --fondo:       #f8fafc;
    --blanco:      #ffffff;

    --verde:   #047857;
    --verde-bg:#ecfdf5;
    --rojo:    #b91c1c;
    --rojo-bg: #fef2f2;
    --ambar:   #b45309;
    --ambar-bg:#fffbeb;

    --radio:  10px;
    --sombra: 0 1px 3px rgba(15, 23, 42, .08), 0 1px 2px rgba(15, 23, 42, .04);
}

*, *::before, *::after { box-sizing: border-box; }

body {
    margin: 0;
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    font-size: 16px;
    line-height: 1.6;
    color: var(--texto);
    background: var(--fondo);
    -webkit-text-size-adjust: 100%;
}

h1, h2, h3, h4 { line-height: 1.25; margin: 0 0 .5rem; }
h1 { font-size: 1.75rem; }
h2 { font-size: 1.35rem; }
h3 { font-size: 1.1rem; }

a { color: var(--azul); text-decoration: none; }
a:hover, a:focus-visible { text-decoration: underline; }

img { max-width: 100%; height: auto; }

/* Foco siempre visible: requisito de accesibilidad. */
:focus-visible {
    outline: 3px solid var(--azul);
    outline-offset: 2px;
}

/* Enlace de salto para lectores de pantalla y navegación por teclado. */
.saltar {
    position: absolute;
    left: -9999px;
    top: 0;
    background: var(--azul);
    color: #fff;
    padding: .75rem 1rem;
    z-index: 100;
}
.saltar:focus { left: 0; }

.contenedor {
    width: 100%;
    /* 1400 en vez de los 1100 de antes: la página se veía estrecha y
       las rejillas se quedaban en tres columnas por muy poco. */
    max-width: 1400px;
    margin: 0 auto;
    padding: 0 1rem;
}
.contenedor-estrecho { max-width: 480px; }

/* --- Cabecera ------------------------------------------------------ */

.cabecera {
    background: var(--blanco);
    border-bottom: 1px solid var(--borde);
}
.cabecera .contenedor {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    min-height: 64px;
    flex-wrap: wrap;
}
.marca {
    font-weight: 700;
    font-size: 1.05rem;
    color: var(--texto);
}
.marca span { color: var(--azul); }

/* En la cabecera pública la marca lleva el lema debajo. Se apilan con
   flex en columna para que el conjunto siga siendo un único enlace. */
.marca:has(.marca__lema) {
    display: inline-flex;
    flex-direction: column;
    gap: .1rem;
    line-height: 1.2;
}
/* `.marca span` de arriba pinta de azul cualquier span; con la marca en
   dos líneas hay que devolver el color a los dos contenedores, para que
   siga siendo «Quiero» en negro y «Software» en azul. La especificidad
   tiene que ganar a `.marca span`, de ahí el selector descendente. */
.marca .marca__nombre {
    color: var(--texto);
    font-size: 1.15rem;
}

/* El lema acompaña, no compite: peso normal y color suave. */
.marca .marca__lema {
    color: var(--texto-suave);
    font-size: .78rem;
    font-weight: 400;
    letter-spacing: .01em;
}

/* En móvil el lema ocuparía media pantalla y empujaría el menú. */
@media (max-width: 560px) {
    .marca__lema { display: none; }
}

.menu {
    display: flex;
    align-items: center;
    gap: 1.25rem;
    flex-wrap: wrap;
}
.menu a { color: var(--texto-suave); font-size: .95rem; }
.menu a:hover, .menu a.activo { color: var(--azul); }
.menu form { margin: 0; }

/* Un enlace con aspecto de botón dentro del menú conserva el color del
   botón: `.menu a` tiene más especificidad que `.boton` y, sin esto, le
   pisaba el color dejando texto gris sobre fondo azul. */
.menu a.boton { color: #fff; }
.menu a.boton:hover { color: #fff; }
.menu a.boton-secundario, .menu a.boton-secundario:hover { color: var(--texto); }

/* --- Contenido ----------------------------------------------------- */

.principal { padding: 2rem 0 4rem; }

.encabezado-pagina {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1.5rem;
}
.encabezado-pagina p { margin: 0; color: var(--texto-suave); }

.tarjeta {
    background: var(--blanco);
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    box-shadow: var(--sombra);
    padding: 1.5rem;
    margin-bottom: 1.5rem;
}
.tarjeta > h2:first-child, .tarjeta > h3:first-child { margin-top: 0; }
.tarjeta-subtitulo { color: var(--texto-suave); font-size: .9rem; margin: -.25rem 0 1.25rem; }

.rejilla {
    display: grid;
    gap: 1.5rem;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}

/* --- Formularios --------------------------------------------------- */

.campo { margin-bottom: 1.1rem; }
.campo label {
    display: block;
    font-weight: 600;
    font-size: .9rem;
    margin-bottom: .35rem;
}
.campo .ayuda {
    display: block;
    font-size: .82rem;
    color: var(--texto-suave);
    margin-top: .3rem;
}

/* El color del texto es explícito, no `inherit`: el campo lleva su propio
   fondo blanco, así que heredar el color del contenedor lo deja ilegible
   en cuanto el contenedor es oscuro. Le pasaba al buscador de la portada,
   dentro de `.heroe`, que es azul con texto blanco: se escribía en blanco
   sobre blanco y solo se veía el marcador de posición, porque a ese el
   navegador le pone su propio gris. */
input[type="text"], input[type="email"], input[type="password"],
input[type="url"], input[type="tel"], input[type="number"],
input[type="search"], select, textarea {
    width: 100%;
    padding: .6rem .75rem;
    font: inherit;
    color: var(--texto);
    background: var(--blanco);
    border: 1px solid #cbd5e1;
    border-radius: 8px;
}
input:focus, select:focus, textarea:focus {
    border-color: var(--azul);
    outline: 2px solid rgba(29, 78, 216, .25);
    outline-offset: 0;
}
textarea { min-height: 120px; resize: vertical; }

input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"] {
    border-color: var(--rojo);
}

.error-campo {
    display: block;
    color: var(--rojo);
    font-size: .85rem;
    margin-top: .35rem;
}

.fila {
    display: grid;
    gap: 0 1rem;
    grid-template-columns: 1fr 1fr;
}
@media (max-width: 640px) {
    .fila { grid-template-columns: 1fr; }
}

.casilla {
    display: flex;
    align-items: flex-start;
    gap: .55rem;
    margin-bottom: .6rem;
    font-size: .92rem;
}
.casilla input { margin-top: .25rem; flex-shrink: 0; }
.casilla label { font-weight: 400; margin: 0; }

/* La aceptación de las condiciones, destacada del resto del formulario:
   es una decisión, no un campo más que rellenar de carrerilla. */
.casilla-legal {
    margin: 1.25rem 0 .75rem;
    padding: .9rem 1rem;
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    background: var(--fondo);
    line-height: 1.45;
}

/* Listas largas de casillas (sectores, plataformas) en columnas que se
   adaptan al ancho disponible. */
.rejilla-casillas {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 0 1rem;
}

fieldset {
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    padding: 1rem 1.25rem 1.25rem;
    margin: 0 0 1.5rem;
}
legend { font-weight: 600; padding: 0 .4rem; }

/* Explicación al principio de un fieldset. `.ayuda` a secas solo está
   definida dentro de `.campo`, y aquí no hay ninguno. */
.ayuda-bloque {
    font-size: .85rem;
    color: var(--texto-suave);
    margin: 0 0 .9rem;
    max-width: 62ch;
}

/* --- Botones ------------------------------------------------------- */

.boton {
    display: inline-block;
    padding: .6rem 1.1rem;
    font: inherit;
    font-weight: 600;
    line-height: 1.4;
    color: #fff;
    background: var(--azul);
    border: 1px solid var(--azul);
    border-radius: 8px;
    cursor: pointer;
    text-align: center;
}
.boton:hover { background: var(--azul-oscuro); border-color: var(--azul-oscuro); text-decoration: none; }

.boton-secundario {
    color: var(--texto);
    background: var(--blanco);
    border-color: #cbd5e1;
}
.boton-secundario:hover { background: #f1f5f9; border-color: #94a3b8; }

.boton-peligro { color: var(--rojo); background: var(--blanco); border-color: #fca5a5; }
.boton-peligro:hover { background: var(--rojo-bg); border-color: var(--rojo); }

.boton-pequeno { padding: .35rem .65rem; font-size: .85rem; }
.boton-bloque { display: block; width: 100%; }

.acciones {
    display: flex;
    gap: .6rem;
    flex-wrap: wrap;
    align-items: center;
    margin-top: 1.25rem;
}
.acciones-tabla { display: flex; gap: .4rem; flex-wrap: wrap; margin: 0; }
.acciones-tabla form { margin: 0; display: inline; }

/* --- Avisos -------------------------------------------------------- */

.aviso {
    padding: .85rem 1rem;
    border-radius: var(--radio);
    border: 1px solid;
    margin-bottom: 1.25rem;
    font-size: .95rem;
}
.aviso-success { color: var(--verde); background: var(--verde-bg); border-color: #a7f3d0; }
.aviso-error   { color: var(--rojo);  background: var(--rojo-bg);  border-color: #fecaca; }
.aviso-info    { color: var(--azul-oscuro); background: var(--azul-claro); border-color: #bfdbfe; }

/* --- Temas del blog --------------------------------------------------
   Los temas van a la vista, en pastillas, y no dentro de un desplegable:
   son la clasificación del blog, y esconderlas detrás de un clic las
   convierte en algo que nadie descubre. Envuelven en varias líneas
   cuando no caben, que es lo que pasa en el móvil. */

.temas-blog {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    margin-bottom: 1.25rem;
}

.tema-pastilla {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: .35rem .85rem;
    border: 1px solid var(--borde);
    border-radius: 999px;
    background: var(--blanco);
    color: var(--texto);
    font-size: .9rem;
    text-decoration: none;
    line-height: 1.4;
}
.tema-pastilla:hover { border-color: var(--azul); color: var(--azul); }

.tema-pastilla.activo {
    background: var(--azul);
    border-color: var(--azul);
    color: var(--blanco);
}
.tema-pastilla.activo .tema-pastilla__cuenta { color: var(--blanco); opacity: .85; }

.tema-pastilla__cuenta {
    color: var(--texto-suave);
    font-size: .8rem;
    font-variant-numeric: tabular-nums;
}

/* Dentro de una tarjeta el tema es una etiqueta, no un botón: más
   pequeña y sin competir con el título. */
.tema-pastilla--mini {
    padding: .15rem .55rem;
    font-size: .78rem;
    background: var(--azul-claro);
    border-color: #bfdbfe;
    color: var(--azul-oscuro);
}

.tarjeta-temas {
    display: flex;
    flex-wrap: wrap;
    gap: .3rem;
    margin: 0 0 .5rem;
}

/* --- Vista previa del administrador ---------------------------------
   Banda ámbar a todo lo ancho, arriba del todo. A propósito no se parece
   a nada del directorio: lo que tiene que quedar claro de un vistazo es
   que esa ficha aún no la ve nadie más. */

.vista-previa {
    background: var(--ambar-bg);
    border-bottom: 2px solid var(--ambar);
    padding: .75rem 0;
}
.vista-previa__caja {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}
.vista-previa__texto {
    margin: 0;
    color: var(--ambar);
    font-size: .95rem;
}

/* --- Tablas -------------------------------------------------------- */

.tabla-scroll { overflow-x: auto; }

table {
    width: 100%;
    border-collapse: collapse;
    font-size: .93rem;
}
th, td {
    text-align: left;
    padding: .7rem .6rem;
    border-bottom: 1px solid var(--borde);
    vertical-align: middle;
}
th {
    font-size: .8rem;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--texto-suave);
    white-space: nowrap;
}
tbody tr:hover { background: #f8fafc; }

.miniatura {
    width: 44px;
    height: 44px;
    object-fit: cover;
    border-radius: 6px;
    border: 1px solid var(--borde);
    background: var(--fondo);
}

/* --- Galería ------------------------------------------------------- */

.galeria {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 1rem;
    margin-top: 1.25rem;
}
.galeria figure {
    margin: 0;
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    overflow: hidden;
    background: var(--blanco);
}
.galeria img {
    display: block;
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    background: var(--fondo);
}
.galeria figcaption { padding: .6rem; text-align: center; }
.galeria figcaption form { margin: 0; }

/* --- Etiquetas de estado ------------------------------------------- */

.etiqueta {
    display: inline-block;
    padding: .15rem .55rem;
    font-size: .78rem;
    font-weight: 600;
    border-radius: 999px;
    white-space: nowrap;
}
.etiqueta-published { color: var(--verde);  background: var(--verde-bg); }
.etiqueta-draft     { color: var(--texto-suave); background: #f1f5f9; }
.etiqueta-pending   { color: var(--ambar);  background: var(--ambar-bg); }
.etiqueta-disabled  { color: var(--rojo);   background: var(--rojo-bg); }

/* --- Estado vacío -------------------------------------------------- */

.vacio {
    text-align: center;
    padding: 2.5rem 1rem;
    color: var(--texto-suave);
}
.vacio p { margin: 0 0 1rem; }

/* --- Autenticación ------------------------------------------------- */

.pantalla-auth {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 2rem 1rem 3rem;
}
.pantalla-auth .marca { display: block; text-align: center; margin-bottom: 1.5rem; font-size: 1.2rem; }
.pantalla-auth .tarjeta { margin-bottom: 1rem; }
.enlace-auxiliar { text-align: center; font-size: .92rem; color: var(--texto-suave); }

/* --- Portada pública ----------------------------------------------- */

.heroe {
    background: linear-gradient(160deg, var(--azul-oscuro), var(--azul));
    color: #fff;
    padding: 3.5rem 0;
    text-align: center;
}
.heroe h1 { font-size: 2rem; color: #fff; }
.heroe p { max-width: 620px; margin: 0 auto; color: #dbeafe; }
.heroe .acciones { justify-content: center; }
.heroe .boton-secundario { background: transparent; color: #fff; border-color: rgba(255,255,255,.5); }
.heroe .boton-secundario:hover { background: rgba(255,255,255,.12); }

.nube-categorias { display: flex; flex-wrap: wrap; gap: .5rem; }
.nube-categorias a, .nube-categorias span {
    display: inline-block;
    padding: .35rem .8rem;
    background: var(--blanco);
    border: 1px solid var(--borde);
    border-radius: 999px;
    font-size: .88rem;
    color: var(--texto);
}
.nube-categorias a:hover {
    border-color: var(--azul);
    color: var(--azul);
    text-decoration: none;
}

/* --- Buscadores ---------------------------------------------------- */

.buscador-cabecera {
    display: flex;
    gap: .5rem;
    flex: 1 1 240px;
    max-width: 420px;
    margin: 0;
}
.buscador-cabecera input { flex: 1; }

.buscador-principal {
    display: flex;
    gap: .6rem;
    max-width: 620px;
    margin: 1.75rem auto 0;
}
.buscador-principal input {
    flex: 1;
    padding: .8rem 1rem;
    border: 0;
}
@media (max-width: 560px) {
    .buscador-principal { flex-direction: column; }
}

/* --- Gráfica de visitas --------------------------------------------- */

.dl-datos--cifras { display: flex; flex-wrap: wrap; gap: 2rem; }
.cifra { font-size: 1.75rem; font-weight: 700; color: var(--azul); }

.grafica { margin: 1.5rem 0 .5rem; }
/* El SVG se estira a lo ancho; el alto queda fijo para que la gráfica
   no cambie de proporción según la pantalla y siga siendo comparable. */
.grafica__svg { display: block; width: 100%; height: 180px; }
.grafica__barra { fill: var(--azul); }
.grafica__barra:hover { fill: var(--azul-oscuro); }
/* Los días sin visitas: una línea tenue, para que se vea que el día
   existe y no hubo nadie, en vez de un hueco que parece un fallo. */
.grafica__vacio { fill: var(--borde); }
.grafica__eje { stroke: var(--borde); stroke-width: 1; }
.grafica__pie {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    font-size: .82rem;
    color: var(--texto-suave);
}

/* --- Blog ----------------------------------------------------------- */

/* El texto de un artículo se lee, no se escanea: columna estrecha y
   línea alta. 70ch es el ancho en el que el ojo no se pierde al saltar
   de renglón. */
/* 88ch en vez de 70ch. El ancho de lectura cómodo está entre 45 y 75
   caracteres, y 70 era el libro de texto; el problema es que en una
   pantalla de 1400 px dejaba el artículo como una columna estrecha
   perdida en medio de la página. 88 sigue leyéndose bien y llena mucho
   mejor, y en pantallas pequeñas manda el 100%. */
.post { max-width: min(88ch, 100%); margin: 0 auto; }
.post__cabecera { margin-bottom: 1.5rem; }
.post__cabecera h1 { margin: .5rem 0; }
.post__firma {
    display: flex;
    align-items: center;
    gap: .6rem;
    color: var(--texto-suave);
    font-size: .95rem;
}
/* La portada del artículo se ve a su tamaño, nunca estirada.
   Con `width: 100%` cualquier imagen más estrecha que la columna se
   ampliaba hasta llenarla, y ampliar no añade detalle: solo emborrona.
   Las grandes siguen ocupando el ancho entero por el max-width. */
.post__portada {
    display: block;
    width: auto;
    max-width: 100%;
    margin: 0 auto 1.75rem;
    border-radius: var(--radio);
    border: 1px solid var(--borde);
}
.post__pie { margin-top: 2rem; font-size: .92rem; color: var(--texto-suave); }

/* Contenedor del HTML que pega la empresa. Todo su CSS propio cuelga de
   aquí, así que no puede alcanzar la cabecera ni el resto de la página. */
.html-post { line-height: 1.75; }
.html-post h2 { margin-top: 2rem; }
.html-post h3 { margin-top: 1.5rem; }
.html-post p, .html-post ul, .html-post ol { margin-bottom: 1.1rem; }
.html-post img { max-width: 100%; height: auto; border-radius: var(--radio); }
.html-post blockquote {
    margin: 1.5rem 0;
    padding: .25rem 0 .25rem 1.2rem;
    border-left: 3px solid var(--azul);
    color: var(--texto-suave);
}
.html-post table { width: 100%; }
.html-post pre, .html-post code {
    background: var(--fondo);
    border-radius: 6px;
}
.html-post pre { padding: 1rem; overflow-x: auto; }
.html-post code { padding: .1rem .3rem; font-size: .92em; }

/* Vídeo incrustado. El truco clásico para hacerlo responsive usa
   position:absolute dentro de un contenedor con padding-bottom, pero
   `position` está prohibido en el CSS de los usuarios. `aspect-ratio`
   hace lo mismo en una línea y sí está permitido, así que sale bien
   incluso si la empresa no escribe una sola regla. */
.html-post iframe,
.html-empresa iframe,
.html-producto iframe,
.html-servicio iframe {
    display: block;
    width: 100%;
    aspect-ratio: 16 / 9;
    height: auto;
    border: 0;
    border-radius: var(--radio);
    margin: 1.5rem 0;
}

/* --- Tarjetas de producto ------------------------------------------ */

.rejilla-productos {
    display: grid;
    /* 280 y no 240: con el contenedor a 1400 el mínimo antiguo dejaba
       entrar cinco columnas y las fichas quedaban raquíticas. Con 280
       caben cuatro justas, y al estrecharse la ventana baja a tres y a
       dos por su cuenta. */
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 1.25rem;
}

.tarjeta-producto {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    overflow: hidden;
    background: var(--blanco);
}
/* La imagen va fuera del flujo, en posición absoluta, y ese es el
   detalle que importa: si estuviera dentro, su altura natural estiraría
   la caja y el aspect-ratio dejaría de mandar. Es justo lo que pasaba
   —capturas de 1920×1188 y fotos casi cuadradas daban cajas de 137, 151
   y 228 píxeles de alto— y descuadraba la fila entera. */
.tarjeta-producto__imagen {
    position: relative;
    display: block;
    aspect-ratio: 16 / 9;
    background: var(--azul-claro);
    overflow: hidden;
}
.tarjeta-producto__imagen img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    /* contain y no cover: son capturas de pantalla y fotos de producto,
       y recortarlas para llenar el hueco cortaría justo lo que la
       empresa quiere enseñar. Se ve entera, centrada, sobre el fondo. */
    object-fit: contain;
    padding: .5rem;
    display: block;
}
.tarjeta-producto__imagen .sin-imagen {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%; height: 100%;
    font-size: 2.5rem;
    font-weight: 700;
    color: var(--azul);
}
.tarjeta-producto__cuerpo { padding: 1rem; flex: 1; display: flex; flex-direction: column; }
.tarjeta-producto__cuerpo h3 { font-size: 1.05rem; margin-bottom: .15rem; }
.tarjeta-producto__cuerpo h3 a { color: var(--texto); }
.tarjeta-producto__cuerpo h3 a:hover { color: var(--azul); }
.tarjeta-producto__cuerpo p { font-size: .9rem; }
/* El precio a la izquierda y la forma de pago a la derecha. Con
   space-between, si solo hay uno de los dos se queda a la izquierda él
   solo en lugar de dejar un hueco raro. El `margin: auto 0 0` pega la
   línea al fondo de la ficha, así que queda a la misma altura en todas
   aunque las descripciones midan distinto. */
.tarjeta-producto__precio {
    margin: auto 0 0;
    padding-top: .5rem;
    font-size: .9rem;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: .5rem;
    flex-wrap: wrap;
}
.tarjeta-producto__modelo {
    color: var(--texto-suave);
    font-size: .82rem;
    white-space: nowrap;
}

/* --- Fichas públicas ------------------------------------------------ */

.portada-empresa { max-height: 280px; overflow: hidden; background: var(--azul-claro); }
.portada-empresa img { width: 100%; height: 280px; object-fit: cover; display: block; }

.cabecera-empresa, .cabecera-producto {
    display: flex;
    gap: 1.25rem;
    align-items: flex-start;
    margin-bottom: 1.75rem;
    flex-wrap: wrap;
}
.logo-empresa {
    width: 88px; height: 88px;
    object-fit: contain;
    background: var(--blanco);
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    padding: .5rem;
    flex-shrink: 0;
}
.lema { font-size: 1.05rem; color: var(--texto-suave); margin: .4rem 0 0; }

.imagen-principal {
    width: 100%;
    border-radius: var(--radio);
    border: 1px solid var(--borde);
}

.dos-columnas {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    gap: 1.5rem;
    align-items: start;
}
/* La columna de filtros no necesita crecer con la pantalla: son
   desplegables de ancho fijo. Antes iba en proporción y con el
   contenedor ancho se comía 400px que le hacían falta a los
   resultados. */
.dos-columnas--filtros { grid-template-columns: 300px minmax(0, 1fr); }

/* Junto a los filtros hay 300px menos de sitio, así que las fichas
   admiten ser algo más estrechas para que sigan entrando cuatro. Es el
   mínimo que tenían antes en toda la web, así que no se aprieta nada
   que no estuviera ya probado. */
.dos-columnas--filtros .rejilla-productos {
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}
.dos-columnas--filtros .rejilla {
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}

/* Las empresas, a tres columnas.
   Con los 230px de la rejilla común entraban cuatro y la tarjeta se
   quedaba en nada: el nombre comercial se partía en tres renglones y la
   descripción no daba para una frase. 320 es el mínimo con el que solo
   caben tres en el hueco que dejan los filtros, y sigue bajando sola a
   dos y a una al estrecharse la ventana. */
.dos-columnas--filtros .rejilla-empresas {
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
}
@media (max-width: 860px) {
    .dos-columnas, .dos-columnas--filtros { grid-template-columns: 1fr; }
}

.filtros h2 { font-size: 1.05rem; }
.filtros .acciones { flex-direction: column; align-items: stretch; }

.lista-servicios { list-style: none; margin: 0; padding: 0; }
.lista-servicios li {
    padding: 1rem 0;
    border-bottom: 1px solid var(--borde);
}
.lista-servicios li:last-child { border-bottom: 0; padding-bottom: 0; }
.lista-servicios h3 { font-size: 1.02rem; }

.lista-caracteristicas { margin: 0; padding-left: 1.2rem; }
.lista-caracteristicas li { margin-bottom: .4rem; }

.migas { font-size: .88rem; color: var(--texto-suave); margin-bottom: 1.25rem; }

/* --- Resumen estructurado y procedencia ---------------------------- */

.resumen-estructurado { border-left: 4px solid var(--azul); }
.resumen-estructurado dl { margin: 0; }
.resumen-estructurado dl > div {
    display: grid;
    grid-template-columns: minmax(140px, 190px) 1fr;
    gap: .25rem 1rem;
    padding: .55rem 0;
    border-bottom: 1px solid var(--borde);
}
.resumen-estructurado dl > div:last-child { border-bottom: 0; padding-bottom: 0; }
.resumen-estructurado dt { font-weight: 600; color: var(--texto-suave); font-size: .9rem; }
.resumen-estructurado dd { margin: 0; }
@media (max-width: 560px) {
    .resumen-estructurado dl > div { grid-template-columns: 1fr; }
}

.procedencia { background: #fbfcfe; }
.procedencia p { font-size: .92rem; }

.lista-capacidades { list-style: none; margin: 0; padding: 0; font-size: .93rem; }
.lista-capacidades li {
    display: flex;
    gap: .5rem;
    align-items: baseline;
    padding: .35rem 0;
}
.lista-capacidades li span[aria-hidden] { width: 1em; flex-shrink: 0; text-align: center; }
.lista-capacidades li.si { color: var(--verde); font-weight: 600; }
.lista-capacidades li.no { color: var(--texto-suave); }

.lista-enlaces { list-style: none; margin: 0; padding: 0; }
.lista-enlaces li { padding: .4rem 0; border-bottom: 1px solid var(--borde); font-size: .93rem; }
.lista-enlaces li:last-child { border-bottom: 0; }

.empresa-mini { display: flex; gap: .9rem; align-items: flex-start; }
.empresa-mini p { font-size: .9rem; }

/* Bloque de acciones irreversibles: se distingue del resto a propósito. */
.tarjeta-peligro { border-color: #fca5a5; background: #fffcfc; }
.tarjeta-peligro h2 { color: var(--rojo); }

/* --- Navegación del panel de administración ------------------------ */

.nav-admin, .pestanas {
    display: flex;
    gap: .35rem;
    flex-wrap: wrap;
    margin-bottom: 1.5rem;
    border-bottom: 1px solid var(--borde);
}
.nav-admin a, .pestanas a {
    padding: .55rem 1rem;
    font-size: .92rem;
    font-weight: 600;
    color: var(--texto-suave);
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
}
.nav-admin a:hover, .pestanas a:hover { color: var(--azul); text-decoration: none; }
.nav-admin a.activo, .pestanas a.activo {
    color: var(--azul);
    border-bottom-color: var(--azul);
}

.pestanas { margin-top: -.5rem; }

.buscador-admin { display: flex; gap: .6rem; flex-wrap: wrap; margin: 0; }
.buscador-admin input { flex: 1; min-width: 200px; }

/* --- Comparativa ---------------------------------------------------- */

.comparativa { font-size: .93rem; }
.comparativa thead th { vertical-align: bottom; padding-bottom: 1rem; }
.comparativa thead th a { display: block; font-size: 1rem; color: var(--texto); }
.comparativa thead th a:hover { color: var(--azul); }
.comparativa thead th .texto-suave {
    display: block;
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0;
    font-size: .82rem;
}
.comparativa tbody th {
    text-transform: none;
    letter-spacing: 0;
    font-size: .9rem;
    color: var(--texto);
    font-weight: 600;
    width: 30%;
    white-space: normal;
}
.comparativa td { vertical-align: top; }

.comparativa .fila-grupo th {
    background: var(--azul-claro);
    color: var(--azul-oscuro);
    text-transform: uppercase;
    font-size: .78rem;
    letter-spacing: .04em;
    width: auto;
}
.comparativa .fila-grupo:hover th { background: var(--azul-claro); }

/* Resalta en qué se diferencian, que es lo que se viene a mirar. */
.comparativa .fila-difiere { background: #fffdf5; }
.comparativa .fila-difiere:hover { background: #fffbe8; }

.marca-si { color: var(--verde); font-weight: 600; }
.marca-no { color: var(--texto-suave); }

.rejilla-comparar {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
    gap: 1rem;
}
.opcion-comparar {
    padding: .9rem 1rem;
    border: 1px solid var(--borde);
    border-radius: var(--radio);
}
.opcion-comparar .texto-suave { display: block; font-size: .85rem; margin-bottom: .3rem; }

.paginacion {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1rem;
    margin-top: 2rem;
    flex-wrap: wrap;
}

.pie {
    padding: 2rem 0;
    border-top: 1px solid var(--borde);
    color: var(--texto-suave);
    font-size: .88rem;
    text-align: center;
    background: var(--blanco);
}

/* Segunda línea del pie, con los legales separados de la navegación. */
.pie__legales {
    margin: .6rem 0 0;
    font-size: .84rem;
}

/* Botón de acción sobre lo seleccionado, bajo una tabla. */
.acciones-bloque {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
    margin-top: 1.25rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--borde);
}
.acciones-bloque p { max-width: 60ch; font-size: .85rem; }

/* La cabecera de la ficha de empresa acepta el logotipo entero: caja
   apaisada con alto fijo y ancho libre hasta un tope. Antes era un
   cuadrado de 88, y ahí un logotipo con el nombre se veía como una
   franja diminuta. `contain` respeta la proporción sea cual sea. */
.logo-empresa--ancho {
    width: auto;
    max-width: 260px;
    min-width: 88px;
    height: 88px;
}

/* Vista previa del logotipo en el formulario: el anagrama se ve en el
   cuadrado de siempre y el logotipo necesita más ancho. */
.miniatura-ancha {
    width: auto;
    max-width: 240px;
    height: auto;
    max-height: 80px;
    object-fit: contain;
}

/* --- Tarjeta de servicio ------------------------------------------- */

/* Rejilla propia y no la genérica: la tarjeta de servicio lleva
   logotipo, título, categoría, empresa, modalidad y tres líneas de
   descripción. Con el mínimo de la rejilla común entraban tres columnas
   y el título se partía en tres renglones. */
.rejilla-servicios {
    display: grid;
    gap: 1.5rem;
    grid-template-columns: repeat(auto-fill, minmax(330px, 1fr));
}

.tarjeta-servicio__cabecera {
    display: flex;
    align-items: flex-start;
    gap: .8rem;
}

/* El logotipo de la empresa, para reconocerla de un vistazo. Cuadrado y
   con `contain`: los logotipos vienen en proporciones muy distintas y
   recortarlos por el centro parte los que llevan el nombre al lado. */
.tarjeta-servicio__logo {
    flex-shrink: 0;
    width: 52px;
    height: 52px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 4px;
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    background: var(--blanco);
    overflow: hidden;
}
.tarjeta-servicio__logo img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
}
.tarjeta-servicio__logo .sin-imagen {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--azul);
    line-height: 1;
}

/* Tres líneas exactas, las tenga o no el texto: así todas las tarjetas
   de una fila miden lo mismo y la rejilla no queda dentada. El recorte
   se hace aquí y no al generar el texto porque depende del ancho real,
   que cambia con la pantalla. */
.tarjeta-servicio__descripcion {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin-bottom: 0;
    /* Reserva del alto por si el navegador no entiende line-clamp: se
       queda en tres líneas igual, cortando por desbordamiento. */
    max-height: calc(1.6em * 3);
}

/* Familias de categorías con sus hijas sangradas debajo. */
.grupo-categorias {
    padding: .6rem 0;
    border-bottom: 1px solid var(--borde);
}
.grupo-categorias:last-child { border-bottom: 0; }
.rejilla-casillas--sangrada {
    margin-left: 1.7rem;
    margin-top: .2rem;
}

/* --- Página temática (VeriFactu) ----------------------------------- */

/* Entradilla: el párrafo que resume la página bajo el h1. */
.entradilla {
    font-size: 1.05rem;
    color: var(--texto-suave);
    max-width: 70ch;
}

/* Distintivo de cumplimiento en la ficha del programa. Verde porque es
   una afirmación positiva y verificable, no un adorno de marca. */
.tarjeta-destacada {
    border-color: var(--verde);
    background: var(--verde-bg);
}
.distintivo-verifactu {
    display: flex;
    align-items: flex-start;
    gap: .7rem;
    margin: 0;
}
.distintivo-verifactu__marca {
    flex-shrink: 0;
    width: 1.6rem;
    height: 1.6rem;
    border-radius: 50%;
    background: var(--verde);
    color: var(--blanco);
    font-size: .95rem;
    line-height: 1.6rem;
    text-align: center;
}

/* Preguntas frecuentes. Sin desplegables a propósito: el contenido tiene
   que estar visible en el HTML para que lo lean buscadores y asistentes,
   y esconderlo tras un clic no aporta nada con cinco preguntas. */
.faq > div {
    padding: 1rem 0;
    border-bottom: 1px solid var(--borde);
}
.faq > div:last-child { border-bottom: 0; }
.faq dt {
    font-weight: 600;
    margin-bottom: .35rem;
}
.faq dd {
    margin: 0;
    color: var(--texto-suave);
}

/* --- HTML personalizado de la empresa ------------------------------ */

.campo-codigo {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: .88rem;
    line-height: 1.5;
    white-space: pre;
    overflow-x: auto;
}

/* Filas de perfiles oficiales: tipo a la izquierda, dirección a la derecha. */
.fila-enlace {
    display: grid;
    grid-template-columns: minmax(150px, 220px) 1fr;
    gap: 0 .75rem;
    align-items: start;
}
.fila-enlace .campo { margin-bottom: .6rem; }
@media (max-width: 560px) {
    .fila-enlace { grid-template-columns: 1fr; }
}

/* Bloque que ofrece las instrucciones para la IA, sobre el campo de HTML. */
.descarga-instrucciones {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.25rem;
    flex-wrap: wrap;
    margin-bottom: 1.25rem;
    padding: 1rem 1.15rem;
    background: var(--azul-claro);
    border: 1px solid #bfdbfe;
    border-radius: var(--radio);
}
.descarga-instrucciones p { font-size: .9rem; margin-top: .25rem; max-width: 60ch; }
.descarga-instrucciones .boton { flex-shrink: 0; }

.detalle-codigo { margin-top: 1rem; }
.detalle-codigo summary { cursor: pointer; font-weight: 600; font-size: .92rem; }
.detalle-codigo pre {
    background: #f8fafc;
    border: 1px solid var(--borde);
    border-radius: 8px;
    padding: .9rem;
    overflow-x: auto;
    font-size: .82rem;
}

/* Contenedor del HTML que pega la empresa.
   Va a ancho completo, sin la caja del directorio: la empresa trae su
   propio diseño y una tarjeta alrededor solo estorbaría. Se acota lo que
   puede desbordar para que una maquetación ajena no rompa la página. */
.html-empresa,
.html-producto,
.html-servicio {
    margin: 0 0 1.5rem;
    overflow-wrap: break-word;
    /* Aísla el desbordamiento del contenido pegado sin recortarlo. */
    max-width: 100%;
}
.html-empresa img,
.html-producto img,
.html-servicio img { max-width: 100%; height: auto; border-radius: 8px; }
.html-empresa table,
.html-producto table,
.html-servicio table { display: block; overflow-x: auto; }
.html-empresa > :first-child,
.html-producto > :first-child,
.html-servicio > :first-child { margin-top: 0; }
.html-empresa > :last-child,
.html-producto > :last-child,
.html-servicio > :last-child { margin-bottom: 0; }
.html-empresa h2, .html-producto h2, .html-servicio h2 { font-size: 1.3rem; }
.html-empresa h3, .html-producto h3, .html-servicio h3 { font-size: 1.1rem; }

/* --- Utilidades ----------------------------------------------------

   Estas clases sustituyen a los atributos style="..." inline: la
   política de seguridad de contenidos declara style-src 'self', que
   bloquea también los estilos inline, no solo los <script>.
   -------------------------------------------------------------------- */

.seccion          { padding-top: 2.5rem; padding-bottom: 3rem; }
.pagina-centrada  { padding: 4rem 1rem; text-align: center; }
.acciones-centradas { justify-content: center; }
.acciones-compactas { margin-top: 0; }
.bloque-separado  { margin-top: 1.5rem; }
.imagen-destacada { max-width: 320px; border-radius: 8px; }


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

.texto-suave { color: var(--texto-suave); }
.sin-margen  { margin: 0; }
.dl-datos { margin: 0; }
.dl-datos div {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: .45rem 0;
    border-bottom: 1px solid var(--borde);
}
.dl-datos div:last-child { border-bottom: 0; }
.dl-datos dt { color: var(--texto-suave); font-size: .9rem; }
.dl-datos dd { margin: 0; text-align: right; font-weight: 500; }

/* --- Suscripción ----------------------------------------------------- */

/* Campo trampa para robots: fuera de la vista sin usar display:none,
   que algunos rellenadores automáticos detectan y saltan. */
.trampa {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}
.suscripcion .legal { margin-top: 1.25rem; font-size: .9rem; }
.suscripcion .legal dt { font-weight: 600; }
.contenedor-lectura { max-width: 760px; }

/* --- Consentimiento de cookies --------------------------------------- */

/* Abajo y a lo ancho. `position: fixed` es del directorio, no del CSS de
   los usuarios: ahí sigue prohibido. */
.cookies {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 90;
    background: var(--blanco);
    border-top: 1px solid var(--borde);
    box-shadow: 0 -4px 16px rgba(15, 23, 42, .12);
    padding: 1rem;
}
.cookies[hidden] { display: none; }

.cookies__caja {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.25rem;
    flex-wrap: wrap;
    max-width: 1400px;
    margin: 0 auto;
}
.cookies__texto { flex: 1 1 420px; font-size: .92rem; }
.cookies__titulo { font-size: 1rem; margin: 0 0 .25rem; }

/* Los dos botones con el mismo tamaño y el mismo peso: rechazar tiene
   que costar lo mismo que aceptar. */
.cookies__botones {
    display: flex;
    gap: .6rem;
    flex-shrink: 0;
}
.cookies__botones .boton { min-width: 130px; }

@media (max-width: 560px) {
    .cookies__botones { width: 100%; }
    .cookies__botones .boton { flex: 1; min-width: 0; }
}

/* --- Formulario de contacto ------------------------------------------
   Va al pie de todas las páginas públicas, así que lo primero es que no
   compita con el contenido: mismo ancho que el resto y separado por
   arriba. */

.seccion-pie { margin: 2.5rem auto 0; }

.contacto .rejilla-campos {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 0 1rem;
}

/* El campo trampa. Fuera de la vista sin usar `display:none` ni
   `visibility:hidden`: los robots que se molestan en mirar el CSS
   descartan justo esos dos, y aquí lo que interesa es que lo rellenen. */
.campo-trampa {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.obligatorio { color: var(--rojo); }

/* --- Borradores del panel --------------------------------------------
   La lista de fichas a medias va dentro de una celda, así que no puede
   heredar los márgenes de una lista normal: descuadraría la fila. */

.lista-borradores {
    list-style: none;
    margin: .2rem 0 .8rem;
    padding: 0;
    font-size: .9rem;
}
.lista-borradores li { padding: .12rem 0; }
.lista-borradores li:last-child { padding-bottom: 0; }

.acciones-bloque {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
    margin-top: 1.25rem;
}

/* --- Compartir --------------------------------------------------------
   Al final del artículo, discreto: acompaña a la lectura, no la
   interrumpe. En móvil la etiqueta y el botón se apilan solos. */

.compartir {
    display: flex;
    align-items: center;
    gap: .75rem;
    flex-wrap: wrap;
    margin: 1.25rem 0 0;
    padding-top: 1rem;
    border-top: 1px solid var(--borde);
}
.compartir__etiqueta { color: var(--texto-suave); font-size: .95rem; }

/* El icono y el texto, alineados por su centro. */
.compartir__enlace {
    display: inline-flex;
    align-items: center;
    gap: .45rem;
}
.compartir__icono { flex-shrink: 0; }
