/* =========================================================================
   Tipografías, servidas desde el propio sitio.

   Antes venían de fonts.googleapis.com. Traerlas aquí gana cuatro cosas:
   se quita una hoja de estilos externa que bloqueaba el renderizado y dos
   preconexiones; se quitan dos orígenes de la política de contenido; deja de
   viajar la dirección IP de cada instalador a un tercero cada vez que abre la
   tienda —lo cual, con el aviso de cookies que ya hay, no es un detalle menor
   bajo la LFPDPPP—; y el sitio deja de depender de que un servicio ajeno esté
   en pie para verse como debe.

   Son fuentes variables: un archivo por familia y subconjunto cubre todos los
   pesos. Los subconjuntos son latin y latin-ext y nada más; el navegador baja
   el que necesite según lo que haya que pintar, y para un sitio en español el
   segundo casi nunca hace falta. Las tres son SIL Open Font License 1.1, cuyo
   texto está en wwwroot/tipografias/OFL.txt.

   Para actualizarlas: pedir a fonts.googleapis.com el CSS con el mismo juego
   de familias y pesos que declara App.razor, quedarse con los bloques latin y
   latin-ext, y sustituir los archivos y los unicode-range de aquí abajo.
   ========================================================================= */

/* Archivo · latin */
@font-face {
    font-family: 'Archivo';
    font-style: normal;
    font-weight: 600 800;
    font-display: swap;
    src: url('tipografias/archivo-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Archivo · latin-ext */
@font-face {
    font-family: 'Archivo';
    font-style: normal;
    font-weight: 600 800;
    font-display: swap;
    src: url('tipografias/archivo-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Source Sans 3 · latin */
@font-face {
    font-family: 'Source Sans 3';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url('tipografias/source-sans-3-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Source Sans 3 · latin-ext */
@font-face {
    font-family: 'Source Sans 3';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url('tipografias/source-sans-3-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* JetBrains Mono · latin */
@font-face {
    font-family: 'JetBrains Mono';
    font-style: normal;
    font-weight: 400 600;
    font-display: swap;
    src: url('tipografias/jetbrains-mono-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* JetBrains Mono · latin-ext */
@font-face {
    font-family: 'JetBrains Mono';
    font-style: normal;
    font-weight: 400 600;
    font-display: swap;
    src: url('tipografias/jetbrains-mono-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* =========================================================================
   Tienda Diexsa · sistema visual
   Instaladores Solex que compran desde el taller, casi siempre en el móvil:
   precios grandes, claves legibles, botones que se aciertan con guantes.

   Los colores, la letra, los espacios y los radios no se escriben aquí: son
   variables de tokens.css, que App.razor carga antes que esta hoja. Un color
   escrito a mano en este archivo rompe EstilosTests (F6-15).
   ========================================================================= */

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    background: var(--fondo);
    color: var(--tinta);
    font-family: var(--letra-texto);
    font-size: var(--letra-base);
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
    font-family: var(--letra-titulos);
    margin: 0;
    line-height: 1.15;
    letter-spacing: -.015em;
    text-wrap: balance;
}

h1 { font-size: clamp(var(--letra-h1-min), 4vw, var(--letra-h1-max)); font-weight: 800; }
h2 { font-size: clamp(var(--letra-h2-min), 3vw, var(--letra-h2-max)); font-weight: 700; }
h3 { font-size: var(--letra-h3); font-weight: 700; }

p { margin: .6em 0; }

a { color: var(--primario); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Un enlace en medio de un texto se subraya siempre: sólo por el color no se distingue de lo que lo rodea
   (WCAG 1.4.1; axe, regla link-in-text-block, F3-16). Los menús, las listas de enlaces y los botones no lo
   necesitan, porque ahí no hay texto alrededor con el que confundirlo. */
:where(p, dd, address, .prosa li) a:not(.boton) {
    text-decoration: underline;
    text-underline-offset: 2px;
}

img { max-width: 100%; }

:focus-visible {
    outline: 2px solid var(--primario);
    outline-offset: 2px;
}

/* El enrutador de Blazor enfoca el h1 en cada navegación para que un lector de pantalla empiece
   por el título. Ese foco es del programa, no del teclado, así que no lleva marco visible: quien
   tabula si lo ve, porque entonces el elemento tiene tabindex propio. */
h1[tabindex="-1"]:focus {
    outline: none;
}

/* ---------- estructura ---------- */

/* El aire de los lados crece con la pantalla: 20 px en un teléfono, 32 en una tableta y 48 en
   escritorio. Con 20 px fijos, en un monitor el texto quedaba pegado al borde de la ventana. */
.envoltura {
    max-width: 1180px;
    margin: 0 auto;
    padding: 0 clamp(20px, 4vw, 48px);
}

/* Solo el aire de arriba y abajo: el de los lados lo pone .envoltura, y un padding completo aquí
   lo estaba pisando con cero. Por eso el texto salía pegado al borde en pantallas anchas. */
.contenido { padding-block: 26px 80px; }

/* ---------- cabecera ---------- */

.cabecera {
    background: var(--superficie);
    border-bottom: 1px solid var(--linea);
    position: sticky;
    top: 0;
    z-index: 40;
}

.cabecera-fila {
    display: flex;
    align-items: center;
    gap: 20px;
    padding: 14px 0;
}

.marca {
    font-family: var(--letra-titulos);
    font-weight: 800;
    font-size: var(--letra-cifra);
    letter-spacing: -.02em;
    color: var(--tinta);
    white-space: nowrap;
}
.marca:hover { text-decoration: none; }
.marca span { color: var(--primario); }

.buscador { flex: 1; display: flex; max-width: 620px; }
.buscador input {
    flex: 1;
    font: inherit;
    padding: 11px 14px;
    border: 1px solid var(--linea-2);
    border-right: 0;
    border-radius: var(--radio) 0 0 var(--radio);
    background: var(--fondo);
    color: var(--tinta);
    min-width: 0;
}
.buscador input::placeholder { color: var(--tenue); }
.buscador button {
    font: inherit;
    font-weight: 600;
    padding: 11px 18px;
    border: 1px solid var(--primario);
    background: var(--primario);
    color: var(--sobre-primario);
    border-radius: 0 var(--radio) var(--radio) 0;
    cursor: pointer;
}
.buscador button:hover { filter: brightness(1.06); }

.acciones { display: flex; align-items: center; gap: 8px; margin-left: auto; }

.usuario {
    font-size: var(--letra-chica);
    color: var(--tinta-2);
    text-align: right;
    line-height: 1.25;
    display: none;
}
@media (min-width: 900px) { .usuario { display: block; } }
.usuario strong { display: block; color: var(--tinta); font-weight: 600; }

/* ---------- menú de categorías ---------- */

.menu {
    border-top: 1px solid var(--linea);
    background: var(--superficie);
    overflow-x: auto;
    scrollbar-width: thin;
}
.menu-lista {
    display: flex;
    gap: 2px;
    list-style: none;
    margin: 0;
    padding: 0;
    white-space: nowrap;
}
.menu-lista a {
    display: block;
    padding: 12px 14px;
    color: var(--tinta-2);
    font-weight: 600;
    font-size: var(--letra-compacta);
    border-bottom: 3px solid transparent;
}
.menu-lista a:hover { color: var(--tinta); background: var(--superficie-2); text-decoration: none; }
.menu-lista a.activo { color: var(--primario); border-bottom-color: var(--primario); }

/* ---------- botones ---------- */

.boton {
    font: inherit;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 11px 18px;
    border-radius: var(--radio);
    border: 1px solid transparent;
    cursor: pointer;
    text-align: center;
    transition: filter .12s ease, background-color .12s ease;
}
.boton:hover { text-decoration: none; }
.boton:disabled { opacity: .5; cursor: not-allowed; }

.boton-primario { background: var(--primario); color: var(--sobre-primario); border-color: var(--primario); }
.boton-primario:hover:not(:disabled) { background: var(--primario-al-pasar); border-color: var(--primario-al-pasar); }

.boton-secundario { background: var(--superficie); color: var(--tinta); border-color: var(--linea-2); }
.boton-secundario:hover:not(:disabled) { background: var(--superficie-2); }

.boton-plano { background: none; color: var(--primario); padding: 8px 10px; }
.boton-plano:hover:not(:disabled) { background: var(--superficie-2); }

.boton-bloque { width: 100%; }
.boton-grande { padding: 14px 22px; font-size: var(--letra-realce); }

/* ---------- carrito en la cabecera ---------- */

.carrito-enlace {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 14px;
    border: 1px solid var(--linea-2);
    border-radius: var(--radio);
    color: var(--tinta);
    font-weight: 600;
}
.carrito-enlace:hover { background: var(--superficie-2); text-decoration: none; }
.carrito-cuenta {
    min-width: 22px;
    height: 22px;
    padding: 0 6px;
    border-radius: 11px;
    background: var(--primario);
    color: var(--sobre-primario);
    font-family: var(--letra-mono);
    font-size: var(--letra-mini);
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* ---------- rejillas y tarjetas ---------- */

.rejilla {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 18px;
}

.tarjeta {
    background: var(--superficie);
    border: 1px solid var(--linea);
    border-radius: var(--radio);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    transition: box-shadow .15s ease, border-color .15s ease;
}
.tarjeta:hover { box-shadow: var(--sombra); border-color: var(--linea-2); }

.tarjeta-imagen {
    aspect-ratio: 4 / 3;
    background: var(--superficie-2);
    display: grid;
    place-items: center;
    overflow: hidden;
}
.tarjeta-imagen img { width: 100%; height: 100%; object-fit: contain; padding: 12px; }
.tarjeta-imagen .sin-foto { color: var(--tenue); font-size: var(--letra-nota); }

.tarjeta-cuerpo { padding: 14px; display: flex; flex-direction: column; gap: 6px; flex: 1; }
.tarjeta-nombre { font-weight: 600; font-size: var(--letra-compacta); line-height: 1.3; color: var(--tinta); }
.tarjeta-pie { margin-top: auto; padding-top: 10px; }

.sku {
    font-family: var(--letra-mono);
    font-size: var(--letra-mini);
    color: var(--tenue);
    letter-spacing: .02em;
}

/* ---------- precios ---------- */

.precio {
    font-family: var(--letra-titulos);
    font-weight: 800;
    font-size: var(--letra-cifra);
    color: var(--tinta);
    font-variant-numeric: tabular-nums;
    letter-spacing: -.02em;
}
.precio-grande { font-size: var(--letra-cifra-grande); }
.precio-antes {
    font-size: var(--letra-chica);
    color: var(--tenue);
    text-decoration: line-through;
    margin-right: 8px;
    font-variant-numeric: tabular-nums;
}

/* ---------- etiquetas ---------- */

.etiqueta {
    display: inline-flex;
    align-items: center;
    padding: 3px 9px;
    border-radius: var(--radio-chico);
    font-size: var(--letra-mini);
    font-weight: 600;
    letter-spacing: .03em;
    text-transform: uppercase;
}
.etiqueta-oferta { background: var(--primario-suave); color: var(--primario); }
.etiqueta-agotado { background: var(--alerta-suave); color: var(--alerta-tinta); }
.etiqueta-ok { background: var(--exito-suave); color: var(--exito-tinta); }

/* ---------- avisos ---------- */

.aviso {
    padding: 12px 16px;
    border-radius: var(--radio);
    border-left: 3px solid var(--linea-2);
    background: var(--superficie);
    margin: 14px 0;
}
.aviso-ok { border-left-color: var(--exito); background: var(--exito-suave); color: var(--exito-tinta); }
.aviso-error { border-left-color: var(--alerta); background: var(--alerta-suave); color: var(--alerta-tinta); }
/* El par de información del sistema central (estado.info): primario sobre azul.50, 6.4:1. */
.aviso-info { border-left-color: var(--primario); background: var(--primario-suave); color: var(--primario); }

/* Dentro de un aviso, un enlace sólo por el color no se distingue: con el texto de error da 1.0:1 y con el
   informativo 1.95:1 (WCAG 1.4.1). Subrayado y en negritas, que es la salida del aviso (F6-18). */
.aviso a { text-decoration: underline; font-weight: 600; }

/* ---------- formularios ---------- */

.campo { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
.campo label { font-weight: 600; font-size: var(--letra-chica); color: var(--tinta-2); }
.campo input, .campo select, .campo textarea {
    font: inherit;
    padding: 11px 13px;
    border: 1px solid var(--linea-2);
    border-radius: var(--radio);
    background: var(--superficie);
    color: var(--tinta);
}
.campo .error { color: var(--alerta); font-size: var(--letra-nota); }

.tarjeta-formulario {
    background: var(--superficie);
    border: 1px solid var(--linea);
    border-radius: var(--radio);
    padding: 28px;
    max-width: 420px;
    margin: 40px auto;
    box-shadow: var(--sombra);
}

/* ---------- migas ---------- */

.migas {
    font-size: var(--letra-chica);
    color: var(--tenue);
    margin-bottom: 14px;
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    align-items: center;
}
.migas a { color: var(--tenue); }
.migas a:hover { color: var(--tinta); }

/* ---------- encabezado de sección ---------- */

.seccion-titulo {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    margin: 30px 0 16px;
    flex-wrap: wrap;
}
.seccion-titulo p { margin: 0; color: var(--tenue); font-size: var(--letra-compacta); }

/* ---------- carrusel ---------- */

.carrusel {
    display: flex;
    gap: 12px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    border-radius: var(--radio);
    margin-bottom: 8px;
}
.carrusel img {
    flex: 0 0 100%;
    scroll-snap-align: center;
    border-radius: var(--radio);
    object-fit: cover;
    max-height: 340px;
    width: 100%;
}

/* ---------- ficha de producto ---------- */

.producto {
    display: grid;
    gap: 30px;
    grid-template-columns: 1fr;
    align-items: start;
}
@media (min-width: 860px) {
    .producto { grid-template-columns: minmax(0, 5fr) minmax(0, 4fr); }
}

.producto-foto {
    background: var(--superficie);
    border: 1px solid var(--linea);
    border-radius: var(--radio);
    aspect-ratio: 1 / 1;
    display: grid;
    place-items: center;
    overflow: hidden;
}
.producto-foto img { width: 100%; height: 100%; object-fit: contain; padding: 24px; }

.opciones { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0 20px; }
.opcion {
    font: inherit;
    font-weight: 600;
    padding: 9px 16px;
    border: 1px solid var(--linea-2);
    border-radius: var(--radio);
    background: var(--superficie);
    color: var(--tinta);
    cursor: pointer;
    font-variant-numeric: tabular-nums;
}
.opcion:hover:not(:has(input:disabled)) { border-color: var(--primario); }
.opcion.elegida { background: var(--primario); border-color: var(--primario); color: var(--sobre-primario); }

.etiqueta-grupo {
    font-size: var(--letra-nota);
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--tenue);
    margin-top: 18px;
}

.cantidad { display: flex; align-items: center; gap: 0; }
.cantidad button {
    font: inherit;
    font-size: var(--letra-h2-min);
    width: 46px;
    height: 46px;
    border: 1px solid var(--linea-2);
    background: var(--superficie);
    color: var(--tinta);
    cursor: pointer;
}
.cantidad button:first-child { border-radius: var(--radio) 0 0 var(--radio); }
.cantidad button:last-child { border-radius: 0 var(--radio) var(--radio) 0; }
.cantidad input {
    font: inherit;
    font-family: var(--letra-mono);
    width: 64px;
    height: 46px;
    text-align: center;
    border: 1px solid var(--linea-2);
    border-left: 0;
    border-right: 0;
    background: var(--superficie);
    color: var(--tinta);
}

/* ---------- carrito ---------- */

.linea-carrito {
    display: grid;
    grid-template-columns: 84px 1fr auto;
    gap: 16px;
    align-items: center;
    padding: 16px 0;
    border-bottom: 1px solid var(--linea);
}
.linea-carrito .foto {
    width: 84px;
    height: 84px;
    background: var(--superficie-2);
    border-radius: var(--radio);
    display: grid;
    place-items: center;
    overflow: hidden;
}
.linea-carrito .foto img { width: 100%; height: 100%; object-fit: contain; padding: 6px; }
.linea-carrito .acciones-linea { display: flex; align-items: center; gap: 14px; }

/* En el teléfono las tres columnas no caben y html/body recortan lo que se sale (overflow-x: hidden): «Quitar»
   quedaba fuera de la pantalla a 360 px (F3-86). Foto y datos arriba; importe y botones en su propio renglón. */
@media (max-width: 719px) {
    .linea-carrito { grid-template-columns: 64px minmax(0, 1fr); gap: 12px; }
    .linea-carrito .foto { width: 64px; height: 64px; }
    .linea-carrito > .apilado:last-child {
        grid-column: 1 / -1;
        flex-direction: row;
        flex-wrap: wrap;
        justify-content: space-between;
    }
    .linea-carrito .acciones-linea { flex-wrap: wrap; gap: 10px; }

    /* En la página de pago el último hijo es el importe, no un bloque .apilado: también va a su renglón. */
    .linea-pago > .precio { grid-column: 1 / -1; justify-self: end; }
}

.resumen {
    background: var(--superficie);
    border: 1px solid var(--linea);
    border-radius: var(--radio);
    padding: 20px;
    position: sticky;
    top: calc(var(--alto-cabecera) + 16px);
}
.resumen-fila {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 8px 0;
    font-variant-numeric: tabular-nums;
}
.resumen-total {
    border-top: 1px solid var(--linea);
    margin-top: 8px;
    padding-top: 14px;
    font-weight: 700;
    font-size: var(--letra-h3);
}

.dos-columnas { display: grid; gap: 26px; grid-template-columns: 1fr; }
@media (min-width: 880px) { .dos-columnas { grid-template-columns: minmax(0, 1fr) 320px; } }

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

.vacio {
    text-align: center;
    padding: 60px 20px;
    color: var(--tenue);
}
/* El título va en tinta y no en el gris del bloque: en la página de error y en la de no
   encontrado el h1 salía gris, como si fuera texto secundario. */
.vacio h1, .vacio h2 { color: var(--tinta); }
.vacio h2 { margin-bottom: 8px; }

/* ---------- pie ---------- */

.pie {
    border-top: 1px solid var(--linea);
    background: var(--superficie);
    padding: 28px 0;
    color: var(--tenue);
    font-size: var(--letra-chica);
}
.pie-fila { display: flex; flex-wrap: wrap; gap: 8px 24px; justify-content: space-between; }

/* ---------- utilidades ---------- */

.silencio { color: var(--tenue); }
.mono { font-family: var(--letra-mono); }
.fila { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }

/* Los espacios de la ficha de artículo y de línea, que antes iban en style= copiados en las dos (F3-121). */
.ficha-oferta { margin-top: 14px; }
.ficha-compartir { margin-top: 10px; }
.ficha-compra { margin-top: 24px; }
.ficha-agotado { margin-top: 20px; }
.apilado { display: flex; flex-direction: column; gap: 4px; }
.centrado { text-align: center; }

/* Lo que antes iba en atributos style= sueltos por las páginas (F6-23): 42 en 11 archivos, con
   tamaños y márgenes que se repetían a mano. Una clase por necesidad: los espacios, sobre la
   escala de tokens.css; los tamaños de letra pequeños, los que ya usaba la tienda, porque la
   escala central todavía no los tiene. EstilosTests impide que vuelvan los style=. */
.texto-chico { font-size: var(--letra-chica); }
.texto-nota { font-size: var(--letra-nota); }
.peso-normal { font-weight: 400; }
.separado-2 { margin-top: var(--espacio-2); }
.separado-4 { margin-top: var(--espacio-4); }
.separado-6 { margin-top: var(--espacio-6); }
.separado-abajo-4 { margin-bottom: var(--espacio-4); }
.sin-margen-final { margin-bottom: 0; }
.parrafo-junto { margin: var(--espacio-1) 0; }
.hueco-2 { gap: var(--espacio-2); }
.hueco-3 { gap: var(--espacio-3); }
.fila-extremos { justify-content: space-between; }

.tarjeta-cuerpo-amplio { padding: var(--espacio-6); gap: var(--espacio-3); }
.tarjeta-seccion { padding: var(--espacio-6); margin-bottom: var(--espacio-6); }
.rejilla-campos { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); margin-top: var(--espacio-4); }

/* Las direcciones y las formas de pago de la página de pago: una opción por renglón, a lo ancho. */
.opciones-apiladas { flex-direction: column; align-items: stretch; }
.opciones-apiladas .opcion { text-align: left; }

/* Los grupos de radios de la página de pago: el fieldset sin marco, la leyenda como título de bloque, y la
   etiqueta entera es la opción. El radio va oculto, así que el foco del teclado se pinta en la etiqueta. */
.grupo-opciones { border: 0; padding: 0; margin-inline: 0; min-width: 0; }
.grupo-opciones legend { padding: 0; }
label.opcion { display: block; }
label.opcion:has(input:focus-visible) { outline: 2px solid var(--primario); outline-offset: 2px; }
label.opcion:has(input:disabled) { opacity: .6; cursor: not-allowed; }

/* El importe y los botones del renglón del carrito, alineados a la derecha. */
.linea-carrito-cierre { align-items: flex-end; gap: 10px; }

/* Un pedido no lleva foto: dos columnas, datos e importe. Dos clases para ganarle a la regla del
   teléfono de .linea-carrito, que pide la columna de la foto. */
.linea-carrito.linea-pedido { grid-template-columns: 1fr auto; }

/* «Actualizar» del carrito vive dentro de .cantidad, cuyos botones son los cuadrados de 46 px de
   «−» y «+» de la ficha: con esa medida la palabra se salía del botón y se montaba sobre el campo
   (F6-18). Se queda con el alto y el radio del grupo, y con su propio ancho. */
.cantidad .boton { width: auto; height: 46px; font-size: inherit; padding: 0 var(--espacio-4); }

/* En el carrito el campo va primero, sin «−» a su izquierda: recupera su borde y su esquina. */
.cantidad-con-accion input { border-left: 1px solid var(--linea-2); border-radius: var(--radio) 0 0 var(--radio); }

/* Las líneas del carrito y de la página de pago son una lista: el lector de pantalla dice cuántas hay. */
.lista-carrito { list-style: none; margin: 0; padding: 0; }

/* Los títulos de bloque (Resumen, Dirección de entrega, Forma de pago) son h2 para que la jerarquía no salte
   del h1 al h3, con el tamaño que tenían como h3. Dos clases para ganarle a «.contenido h2». */
.contenido .titulo-bloque { font-size: var(--letra-h3); margin-top: 0; }
.contenido .titulo-bloque.separado-6 { margin-top: var(--espacio-6); }

/* ---------- error de Blazor ---------- */

#blazor-error-ui {
    color-scheme: light only;
    /* Con los tokens del aviso (F3-104) en lugar de colores escritos a mano; el texto, --aviso-tinta (5.1:1). */
    background: var(--aviso-suave);
    color: var(--aviso-tinta);
    bottom: 0;
    box-shadow: var(--sombra-aviso);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 12px 16px;
    position: fixed;
    width: 100%;
    z-index: 1000;
}
#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 12px;
    top: 6px;
    font: inherit;
    color: inherit;
    background: none;
    border: 0;
    padding: var(--espacio-1) var(--espacio-2);
}
#blazor-error-ui .reload { color: var(--aviso-tinta); text-decoration: underline; }

/* ---------- cabecera en pantallas estrechas ----------
   El instalador compra desde el taller, con el teléfono en una mano. A menos de 720 px la marca y
   los botones se quedan arriba y el buscador baja a su propia línea, a lo ancho: es lo que más se
   usa y lo que peor se acierta cuando queda estrecho. */

@media (max-width: 719px) {
    .cabecera-fila {
        flex-wrap: wrap;
        gap: 12px;
    }

    .buscador {
        order: 3;
        flex: 1 0 100%;
        max-width: none;
    }

    .marca { font-size: var(--letra-h2-min); }

    .acciones { gap: 6px; }

    .carrito-enlace, .boton-plano { padding: 9px 11px; }
}

/* ---------- logotipo ----------
   El archivo es el original de marca, con su degradado, sobre fondo claro. */

.marca img {
    display: block;
    height: 38px;
    width: auto;
    }

@media (max-width: 719px) {
    .marca img { height: 32px; }
}

/* =========================================================================
   Páginas públicas, pie y accesorios
   Todo lo que sigue nació con la portada abierta: antes de ella el sitio
   entero vivía detrás del login y no había nada que enseñar sin sesión.
   ========================================================================= */

/* ---------- accesibilidad ---------- */

.salto-contenido {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 100;
    background: var(--primario);
    color: var(--sobre-primario);
    padding: 10px 16px;
    border-radius: 0 0 var(--radio) 0;
    font-weight: 600;
}

.salto-contenido:focus { left: 0; }

.visualmente-oculto {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ---------- portada ---------- */

.portada { padding: 28px 0 8px; }

.antetitulo {
    font-family: var(--letra-mono);
    font-size: var(--letra-nota);
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--primario);
    margin: 0 0 10px;
}

.entrada {
    font-size: clamp(var(--letra-realce), 2.2vw, var(--letra-h2-min));
    color: var(--tinta-2);
    max-width: 62ch;
    margin: 14px 0 0;
}

.portada-acciones {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 24px;
}

/* ---------- contenido de texto largo ---------- */

/* Ancho de lectura. Un renglón demasiado largo cansa —el ojo pierde el salto de línea—, pero 72ch
   se quedaba en media pantalla de laptop y parecía un error de maquetación. 90ch es el límite alto
   de lo cómodo y ya ocupa dos tercios. min(100%) para que nunca desborde en un teléfono. */
.prosa { max-width: min(100%, 90ch); }
.prosa h2 { margin-top: 34px; }
.prosa h3 { margin-top: 22px; }
.prosa ul, .prosa ol { padding-left: 22px; }
.prosa li { margin: 6px 0; }

.contenido h2 { margin-top: 36px; }

/* ---------- pasos numerados ---------- */

.pasos {
    list-style: none;
    counter-reset: paso;
    padding: 0;
    margin: 20px 0 0;
    display: grid;
    gap: 16px;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}

.pasos li {
    counter-increment: paso;
    background: var(--superficie);
    border: 1px solid var(--linea);
    border-radius: var(--radio);
    padding: 20px;
}

.pasos li::before {
    content: counter(paso);
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: var(--primario);
    color: var(--sobre-primario);
    font-family: var(--letra-titulos);
    font-weight: 700;
    margin-bottom: 12px;
}

.pasos h3 { margin-bottom: 6px; }
.pasos p { color: var(--tinta-2); margin: 0; }

/* ---------- preguntas ---------- */

.faq { margin: 16px 0 0; }

.faq dt {
    font-family: var(--letra-titulos);
    font-weight: 700;
    font-size: var(--letra-realce);
    margin-top: 18px;
}

.faq dd {
    margin: 6px 0 0;
    color: var(--tinta-2);
    max-width: min(100%, 90ch);
}

/* ---------- tablas ----------
   Una tabla ancha se desplaza dentro de su caja; la página nunca se mueve de lado. */

.tabla-envoltura {
    overflow-x: auto;
    margin: 18px 0;
    border: 1px solid var(--linea);
    border-radius: var(--radio);
    background: var(--superficie);
}

table {
    border-collapse: collapse;
    width: 100%;
    font-size: var(--letra-compacta);
}

caption {
    text-align: left;
    padding: 12px 16px;
    color: var(--tenue);
    font-size: var(--letra-chica);
}

th, td {
    padding: 11px 16px;
    text-align: left;
    border-bottom: 1px solid var(--linea);
    vertical-align: top;
}

thead th {
    background: var(--superficie-2);
    font-family: var(--letra-titulos);
    font-size: var(--letra-chica);
}

tbody tr:last-child th,
tbody tr:last-child td { border-bottom: 0; }

/* ---------- contacto ---------- */

.rejilla-contacto {
    display: grid;
    gap: 16px;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    margin-top: 24px;
}

.tarjeta-contacto {
    background: var(--superficie);
    border: 1px solid var(--linea);
    border-radius: var(--radio);
    padding: 22px;
}

.tarjeta-contacto h2 { font-size: var(--letra-subtitulo); margin-bottom: 8px; }

.lista-contacto { list-style: none; padding: 0; margin: 0; }

.lista-contacto li {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 9px 0;
    border-bottom: 1px solid var(--linea);
}

.lista-contacto li:last-child { border-bottom: 0; }

address {
    font-style: normal;
    color: var(--tinta-2);
    line-height: 1.7;
}

/* ---------- 404 ---------- */

.vacio-404 { text-align: left; max-width: 64ch; }
.buscador-404 { max-width: 460px; margin: 22px 0; }
.enlaces-404 { margin-top: 26px; }
.enlaces-404 h2 { font-size: var(--letra-base); margin-bottom: 8px; }

.enlaces-404 ul {
    list-style: none;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.enlaces-404 a {
    display: inline-block;
    padding: 7px 12px;
    background: var(--superficie);
    border: 1px solid var(--linea-2);
    border-radius: var(--radio);
}

/* ---------- pie ---------- */

.pie-columnas {
    display: grid;
    gap: 26px;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    padding: 34px 0 26px;
}

.pie-columna h2 {
    font-size: var(--letra-compacta);
    text-transform: uppercase;
    letter-spacing: .04em;
    margin-bottom: 12px;
}

.pie-columna ul { list-style: none; padding: 0; margin: 0; }
.pie-columna li { margin: 7px 0; }

.pie-redes {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    padding: 0;
    margin: 0;
}

/* ---------- aviso de cookies ---------- */

.aviso-cookies {
    position: fixed;
    left: clamp(20px, 4vw, 48px);
    right: clamp(20px, 4vw, 48px);
    bottom: 16px;
    z-index: 60;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    max-width: 760px;
    margin: 0 auto;
    padding: 16px 20px;
    background: var(--superficie);
    border: 1px solid var(--linea-2);
    border-radius: var(--radio);
    box-shadow: var(--sombra);
}

/* El atributo hidden lo pone el servidor y lo quita tienda.js. Sin esta regla, el display:flex
   de arriba gana al [hidden] de la hoja del navegador y el aviso sale siempre. */
.aviso-cookies[hidden] { display: none; }

.aviso-cookies p {
    margin: 0;
    font-size: var(--letra-chica);
    color: var(--tinta-2);
    flex: 1 1 320px;
}

/* ---------- compartir ---------- */

.boton-compartir { font-size: var(--letra-chica); }

/* ---------- barra fija en el movil ---------- */

.cta-movil { display: none; }

@media (max-width: 719px) {
    .cta-movil {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 50;
        display: flex;
        gap: 8px;
        padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
        background: var(--superficie);
        border-top: 1px solid var(--linea);
        box-shadow: var(--sombra-barra);
    }

    .cta-movil a {
        flex: 1;
        text-align: center;
        padding: 13px 10px;
        border-radius: var(--radio);
        font-weight: 700;
        font-family: var(--letra-titulos);
    }

    .cta-movil-primario {
        background: var(--primario);
        color: var(--sobre-primario);
        flex: 2;
    }

    .cta-movil-secundario {
        background: var(--superficie-2);
        color: var(--tinta);
    }

    .cta-movil a:hover { text-decoration: none; }

    /* Que la barra no tape el final de la página ni el aviso de cookies. */
    .contenido { padding-bottom: 100px; }

    .aviso-cookies { bottom: 78px; }

    .rejilla-contacto,
    .pasos { grid-template-columns: 1fr; }
}

/* =========================================================================
   Móvil
   El instalador compra desde el taller, con el teléfono en una mano y a
   veces con guantes en la otra. Aquí no se «adapta» el escritorio: se
   ordena lo que hace falta en una columna, con áreas de toque grandes y
   sin nada que sobresalga a lo ancho.
   ========================================================================= */

/* Nada puede empujar la página de lado. Si algo se sale, que se desplace
   dentro de su caja, no que mueva el documento entero. */
html, body { overflow-x: hidden; }

/* ---------- cabecera antes de entrar ----------
   Sin sesión no hay buscador ni menú de catálogo, así que la fila se reparte
   en tres: un hueco, la marca centrada y la entrada donde siempre. Centrar el
   logotipo con un margen automático lo dejaría descentrado respecto a la
   página, porque el botón de la derecha no mide lo mismo que el hueco. */

.cabecera-publica {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
}

.cabecera-publica .marca { grid-column: 2; justify-self: center; }
.cabecera-publica .acciones { grid-column: 3; justify-self: end; margin-left: 0; }

/* La barra de categorías se desplaza con el dedo, sin barra a la vista. */
.menu { -webkit-overflow-scrolling: touch; }
.menu::-webkit-scrollbar { height: 0; }

@media (max-width: 719px) {
    .menu { scrollbar-width: none; }
    .menu-lista a { padding: 12px 12px; font-size: var(--letra-chica); }

    /* ---------- ritmo general ---------- */

    .contenido { padding-block: 18px 100px; }
    .contenido h2 { margin-top: 28px; }

    h1 { line-height: 1.12; }
    h2 { font-size: clamp(var(--letra-subtitulo), 5.5vw, var(--letra-h2-movil-max)); }

    p, li { font-size: var(--letra-base); }

    /* ---------- portada ---------- */

    .portada { padding: 14px 0 4px; }
    .entrada { font-size: var(--letra-realce); }

    /* Un botón por línea, del ancho del pulgar: en el taller se acierta a la
       primera o se sale del sitio. */
    .portada-acciones { flex-direction: column; gap: 10px; }
    .portada-acciones .boton { width: 100%; padding: 14px 18px; }

    /* ---------- listas y tarjetas ---------- */

    .rejilla { grid-template-columns: 1fr; gap: 12px; }

    .pasos { gap: 12px; }
    .pasos li { padding: 16px 18px; }

    .faq dt { font-size: var(--letra-base); margin-top: 16px; }

    /* ---------- producto ---------- */

    .producto { gap: 20px; }
    .precio-grande { font-size: var(--letra-cifra-grande-movil); }

    /* Cantidad y botón, uno debajo del otro y a lo ancho. */
    .producto form.fila { flex-wrap: wrap; }
    .producto form.fila .cantidad { flex: 0 0 96px; }
    .producto form.fila .boton { flex: 1; }

    /* ---------- pie ---------- */

    .pie-columnas {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 20px;
        padding: 26px 0 20px;
    }

    .pie-fila { flex-direction: column; align-items: flex-start; gap: 10px; }
    .pie-redes { gap: 14px; }
}

/* Teléfonos estrechos de verdad: el pie pasa a una sola columna. */
@media (max-width: 419px) {
    .pie-columnas { grid-template-columns: 1fr; }
    .cabecera-fila { gap: 10px; }
    .acciones .boton { padding: 10px 12px; }
}

/* ---------- áreas de toque ----------
   Los enlaces sueltos dentro de un párrafo no cuentan; los controles, sí. */

@media (pointer: coarse) {
    .boton,
    .carrito-enlace,
    .cta-movil a,
    .menu-lista a,
    .opcion {
        min-height: var(--objetivo-tactil);
        display: inline-flex;
        align-items: center;
    }

    /* Con inline-flex, text-align ya no centra: la barra fija del teléfono salía con el texto a la izquierda. */
    .cta-movil a { justify-content: center; }

    .buscador input,
    .buscador button,
    .campo input,
    .campo select {
        min-height: var(--objetivo-tactil);
    }
}

/* ---------- respeto por quien pide menos movimiento ---------- */

@media (prefers-reduced-motion: reduce) {
    * {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }
}

/* =========================================================================
   Transiciones entre páginas
   La tienda navega con la navegación mejorada de Blazor: el navegador no
   recarga el documento, sino que sustituye el contenido. Es rápido, pero sin
   señales visuales el efecto es raro —se pulsa un enlace y no pasa nada
   durante medio segundo, y luego el contenido cambia de golpe—.

   Aquí se resuelve con tres piezas, todas degradables: una barra de progreso
   mientras se va a buscar la página, una entrada suave del contenido nuevo, y
   la API de transiciones de vista donde el navegador la trae (Chrome 126+ y
   Safari 18+) para las navegaciones que sí recargan el documento.
   ========================================================================= */

@view-transition { navigation: auto; }

.barra-progreso {
    position: fixed;
    top: 0;
    left: 0;
    height: 3px;
    width: 0;
    z-index: 90;
    background: linear-gradient(90deg, var(--primario), var(--cian));
    opacity: 0;
    pointer-events: none;
    transition: width .2s ease, opacity .2s ease;
}

/* La barra avanza rápido hasta el 80 % y espera ahí: el último tramo lo
   completa la llegada de la página. Fingir el 100 % antes de tiempo es lo que
   hace que una barra de progreso se sienta mentirosa. */
.barra-progreso.cargando {
    opacity: 1;
    width: 80%;
    transition: width 1.4s cubic-bezier(.15, .85, .35, 1), opacity .1s ease;
}

.barra-progreso.completa {
    opacity: 0;
    width: 100%;
    transition: width .18s ease, opacity .35s ease .12s;
}

/* El contenido nuevo entra desde un pelo más abajo. Ocho píxeles y 180 ms: lo
   justo para que el ojo siga el cambio sin que nadie sienta que espera. */
@keyframes entra-contenido {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: none; }
}

.contenido.entrando {
    animation: entra-contenido .18s ease-out both;
}

/* =========================================================================
   Safari y iOS
   El instalador que pide desde el taller lo hace tanto en Android como en
   iPhone, y WebKit tiene sus propias reglas. Lo que sigue son las que se
   notan.
   ========================================================================= */

/* iOS pinta un destello gris sobre cualquier cosa que se toque. Con estados
   propios de :active molesta más de lo que ayuda. */
html { -webkit-tap-highlight-color: var(--toque); }

/* Safari le pone forma de píldora y una lupa a los campos de búsqueda, y el
   borde redondeado no coincide con el del botón que va pegado. */
input[type="search"] {
    -webkit-appearance: none;
    appearance: none;
}

input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-cancel-button {
    -webkit-appearance: none;
}

/* En iOS, 100vh cuenta la barra de direcciones que aparece y desaparece: la
   unidad pequeña —svh— es la que no da saltos. Se declara después para que
   los navegadores que no la conocen se queden con la primera. */
.contenido {
    min-height: 60vh;
    min-height: 60svh;
}

/* La barra fija respeta el indicador de inicio del iPhone. Necesita
   viewport-fit=cover en la etiqueta viewport, que está en App.razor. */
.cta-movil {
    padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px));
}

/* Con el teclado en pantalla, una barra fija abajo tapa justo el campo que se
   está escribiendo. tienda.js marca el cuerpo mientras hay un campo con el
   foco y la barra se aparta. */
body.teclado-abierto .cta-movil,
body.teclado-abierto .aviso-cookies {
    display: none;
}

/* Safari no admite todavía el ajuste fino de la partición de líneas en
   títulos; donde no lo entiende, simplemente se ignora y no rompe nada. */

/* El botón de salir vive dentro de un formulario —cerrar sesión no puede ser un GET— y sin esto
   el formulario introduce su propio bloque en la fila de la cabecera. */
.salir {
    display: contents;
}
