/* Harven Surf — child theme de Hummingbird.
   ARCHIVO GENERADO por build.sh — no editar a mano.
   Fuentes: src/css/*.css  ·  Origen: Harven Surf Design System */

/* ===== src/css/00-fonts.css ===== */
/* ============================================================
   Harven Surf — Webfonts AUTOALOJADAS
   ------------------------------------------------------------
   Sustituye los dos @import a fonts.googleapis.com del mockup
   (tokens/fonts.css). Sin peticiones a terceros: rendimiento y RGPD.

   · Archivo   -> fuente VARIABLE: un solo binario cubre 100–900.
                  (Google servía el mismo woff2 para 400/500/600/700/800,
                   verificado por md5 -> deduplicado a 1 archivo/subset).
   · IBM Plex Mono -> estática, 3 pesos.
   · Material Icons -> NO se declara aquí: el tema padre Hummingbird
                  ya la sirve autoalojada desde themes/hummingbird/assets/fonts/.
   Subsets: latin + latin-ext (es/en). 140 KB en total.
   ============================================================ */

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 100%;
  font-display: swap;
  src: url(../fonts/archivo-var-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;
}
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 100%;
  font-display: swap;
  src: url(../fonts/archivo-var-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;
}

/* IBM Plex Mono 400 — latin-ext */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(../fonts/ibm-plex-mono-400-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;
}
/* IBM Plex Mono 400 — latin */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(../fonts/ibm-plex-mono-400-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;
}
/* IBM Plex Mono 500 — latin-ext */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(../fonts/ibm-plex-mono-500-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;
}
/* IBM Plex Mono 500 — latin */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(../fonts/ibm-plex-mono-500-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;
}
/* IBM Plex Mono 600 — latin-ext */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(../fonts/ibm-plex-mono-600-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;
}
/* IBM Plex Mono 600 — latin */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(../fonts/ibm-plex-mono-600-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;
}

/* ===== src/css/01-colors.css ===== */
/* ============================================================
   Harven Surf — Sistema de color
   ------------------------------------------------------------
   B2B mayorista: interfaz sobria, neutra y densa en datos.
   Un solo color de acción (Océano), tinta casi negra del logo,
   grises fríos. Los colores semánticos se reservan para estado
   de stock, validación y avisos — nunca como decoración.
   Construido sobre la convención de tokens de Bootstrap 5 /
   tema Hummingbird de PrestaShop (mapeo --bs-* al final).
   ============================================================ */

:root {
  /* ---- Tinta (negro del logo) ---- */
  --hv-tinta: #14181d;

  /* ---- Escala Océano (primario) ---- */
  --hv-oceano-50:  #ebf3f7;
  --hv-oceano-100: #d3e6ee;
  --hv-oceano-200: #a7cddd;
  --hv-oceano-300: #74adc7;
  --hv-oceano-400: #3f88a8;
  --hv-oceano-500: #176e92;
  --hv-oceano-600: #0e5e80;
  --hv-oceano-700: #0b4d69;
  --hv-oceano-800: #0a3d53;
  --hv-oceano-900: #0a2f40;

  /* ---- Escala Gris (neutros fríos) ---- */
  --hv-gris-0:   #ffffff;
  --hv-gris-50:  #f6f8f9;
  --hv-gris-100: #edf0f2;
  --hv-gris-200: #dde2e6;
  --hv-gris-300: #c2cad0;
  --hv-gris-400: #9aa5ae;
  --hv-gris-500: #6e7b85;
  --hv-gris-600: #4d5963;
  --hv-gris-700: #37424b;
  --hv-gris-800: #232c33;
  --hv-gris-900: #14181d;

  /* ---- Semánticos ---- */
  --hv-exito:        #157a52;  /* en stock, pedido enviado */
  --hv-exito-suave:  #e3f2ea;
  --hv-aviso:        #b26a00;  /* stock bajo, plazo de reposición */
  --hv-aviso-suave:  #fdf1de;
  --hv-error:        #c2293c;  /* sin stock, error de validación */
  --hv-error-suave:  #fbe9ec;
  --hv-info:         var(--hv-oceano-500);
  --hv-info-suave:   var(--hv-oceano-50);

  /* ---- Alias semánticos: texto ---- */
  --text-body:    var(--hv-gris-900);
  --text-muted:   var(--hv-gris-600);
  --text-subtle:  var(--hv-gris-500);
  --text-inverse: #ffffff;
  --text-link:    var(--hv-oceano-600);
  --text-link-hover: var(--hv-oceano-800);
  --text-price:   var(--hv-tinta);     /* precio neto mayorista */
  --text-pvpr:    var(--hv-gris-500);  /* PVPR tachado/referencia */

  /* ---- Alias semánticos: superficies ---- */
  --surface-page:    #ffffff;
  --surface-alt:     var(--hv-gris-50);   /* secciones alternas, fondos de listado */
  --surface-card:    #ffffff;
  --surface-inset:   var(--hv-gris-100);  /* resúmenes de pedido, totales */
  --surface-dark:    var(--hv-tinta);     /* footer, franja pre-header */
  --surface-brand:   var(--hv-oceano-700);

  /* ---- Alias semánticos: bordes ---- */
  --border-default: var(--hv-gris-200);
  --border-strong:  var(--hv-gris-300);
  --border-focus:   var(--hv-oceano-500);

  /* ---- Alias semánticos: acción ---- */
  --action-primary:        var(--hv-oceano-600);
  --action-primary-hover:  var(--hv-oceano-700);
  --action-primary-active: var(--hv-oceano-800);
  --action-secondary:      var(--hv-tinta);      /* botón "tinta" (alto contraste) */
  --action-secondary-hover:#000000;
  --action-disabled-bg:    var(--hv-gris-200);
  --action-disabled-text:  var(--hv-gris-400);

  /* ---- Mapeo Bootstrap / Hummingbird ---- */
  --bs-primary: var(--hv-oceano-600);
  --bs-primary-rgb: 14, 94, 128; /* @kind color */
  --bs-danger: var(--hv-error);
  --bs-success: var(--hv-exito);
  --bs-body-color: var(--text-body);
  --bs-body-bg: var(--surface-page);
  --bs-border-color: var(--border-default);
  --bs-link-color: var(--text-link);
  --bs-link-hover-color: var(--text-link-hover);
}

/* ===== src/css/02-typography.css ===== */
/* ============================================================
   Harven Surf — Tipografía
   ------------------------------------------------------------
   Una sola familia (Archivo) en dos voces:
   - DISPLAY: 800, MAYÚSCULAS, tracking ligero — eco del
     lettering del logo HARVEN. Titulares y nombres de sección.
   - UI/Cuerpo: 400–600, caja normal. Densidad de catálogo B2B.
   - Mono (IBM Plex Mono): referencias, SKU, EAN, tarifas.
   Escala heredada de Hummingbird: h1 = 2 × cuerpo.
   ============================================================ */

:root {
  --font-display: "Archivo", "Helvetica Neue", Arial, sans-serif;
  --font-body:    "Archivo", "Helvetica Neue", Arial, sans-serif;
  --font-mono:    "IBM Plex Mono", "SFMono-Regular", Consolas, monospace;

  /* Tamaños */
  --text-xs:   0.75rem;    /* 12 — legal, metadatos */
  --text-sm:   0.875rem;   /* 14 — tablas, etiquetas, migas */
  --text-base: 1rem;       /* 16 — cuerpo */
  --text-lg:   1.125rem;   /* 18 — h4 */
  --text-xl:   1.25rem;    /* 20 — h3 */
  --text-2xl:  1.5rem;     /* 24 — h2 */
  --text-3xl:  2rem;       /* 32 — h1 */
  --text-4xl:  2.75rem;    /* 44 — display hero */

  /* Pesos */
  --weight-regular:  400;
  --weight-medium:   500;
  --weight-semibold: 600;   /* labels de formulario, th de tabla */
  --weight-bold:     700;
  --weight-display:  800;   /* titulares display */

  /* Interlineado */
  --leading-tight:  1.1;    /* display */
  --leading-snug:   1.3;    /* titulares */
  --leading-normal: 1.5;    /* cuerpo */

  /* Tracking */
  --tracking-display: 0.01em;   /* mayúsculas display */
  --tracking-label:   0.06em;   /* sobretítulos / eyebrows en mayúsculas */
  --tracking-normal:  0;

  /* Composiciones listas para usar */
  --type-display: var(--weight-display) var(--text-4xl)/var(--leading-tight) var(--font-display);
  --type-h1: var(--weight-display) var(--text-3xl)/var(--leading-tight) var(--font-display);
  --type-h2: var(--weight-bold) var(--text-2xl)/var(--leading-snug) var(--font-display);
  --type-h3: var(--weight-semibold) var(--text-xl)/var(--leading-snug) var(--font-body);
  --type-h4: var(--weight-semibold) var(--text-lg)/var(--leading-snug) var(--font-body);
  --type-body: var(--weight-regular) var(--text-base)/var(--leading-normal) var(--font-body);
  --type-small: var(--weight-regular) var(--text-sm)/var(--leading-normal) var(--font-body);
  --type-label: var(--weight-semibold) var(--text-sm)/1.2 var(--font-body);
  --type-eyebrow: var(--weight-semibold) var(--text-xs)/1.2 var(--font-body);
  --type-ref: var(--weight-regular) var(--text-sm)/1.4 var(--font-mono);
  --type-price: var(--weight-bold) var(--text-xl)/1.1 var(--font-body);
}

/* ===== src/css/03-spacing.css ===== */
/* ============================================================
   Harven Surf — Espaciado y retícula
   ------------------------------------------------------------
   Escala Bootstrap (base 0.25rem) tal y como la usa Hummingbird.
   Contenedor 1320px (xxl). Densidad alta: el catálogo B2B
   prioriza filas de datos compactas frente a aire editorial.
   ============================================================ */

:root {
  --space-1:  0.25rem;   /*  4 */
  --space-2:  0.5rem;    /*  8 */
  --space-3:  0.75rem;   /* 12 */
  --space-4:  1rem;      /* 16 */
  --space-5:  1.5rem;    /* 24 */
  --space-6:  2rem;      /* 32 */
  --space-7:  3rem;      /* 48 */
  --space-8:  4rem;      /* 64 */
  --space-9:  6rem;      /* 96 */

  /* Layout */
  --container-max: 1320px;
  --container-pad: 1.5rem;
  --grid-gap: 1.5rem;          /* separación de tarjetas de producto */
  --section-gap: 3rem;         /* entre bloques de la home */

  /* Breakpoints de referencia (Hummingbird) — solo documentación:
     xs 360 / sm 576 / md 768 / lg 992 / xl 1200 / xxl 1400 */
}

/* ===== src/css/04-effects.css ===== */
/* ============================================================
   Harven Surf — Efectos: radios, bordes, sombras, transiciones
   ------------------------------------------------------------
   Valores heredados de Hummingbird (Bootstrap):
   radio base 0.5rem, botones/inputs 0.25rem, sombra media
   0 10px 20px 10%. Estética plana: la sombra solo aparece en
   elevación real (dropdowns, modales, sticky bars).
   ============================================================ */

:root {
  /* Radios */
  --radius-sm:   0.25rem;   /* botones, inputs, badges (Hummingbird) */
  --radius-md:   0.5rem;    /* tarjetas, paneles (Bootstrap base) */
  --radius-pill: 50rem;     /* chips de filtro activo */

  /* Bordes */
  --border-width: 1px;
  --border-card: 1px solid var(--border-default);

  /* Sombras (escala Hummingbird) */
  --shadow-sm: 0 0.125rem 0.25rem rgba(20, 24, 29, 0.08);
  --shadow-md: 0 0.625rem 1.25rem rgba(20, 24, 29, 0.1);   /* --bs-box-shadow-md */
  --shadow-lg: 0 1rem 2.5rem rgba(20, 24, 29, 0.16);       /* modales */
  --shadow-sticky: 0 -0.25rem 1rem rgba(20, 24, 29, 0.08); /* barras inferiores fijas */

  /* Foco accesible (outline Hummingbird: 3px primario) */
  --focus-ring: 0 0 0 3px rgba(14, 94, 128, 0.35);

  /* Transiciones */
  --transition-fast: 120ms ease-out; /* @kind other */
  --transition-default: 0.2s ease-in-out; /* @kind other */ /* $transition-base Bootstrap */
}

/* ===== src/css/05-base.css ===== */
/* ============================================================
   Harven Surf — Estilos base de elementos
   ============================================================ */

body {
  margin: 0;
  font: var(--type-body);
  color: var(--text-body);
  background: var(--surface-page);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6 {
  margin: 0 0 1rem;
  color: var(--text-body);
}

h1 { font: var(--type-h1); text-transform: uppercase; letter-spacing: var(--tracking-display); }
h2 { font: var(--type-h2); text-transform: uppercase; letter-spacing: var(--tracking-display); }
h3 { font: var(--type-h3); }
h4 { font: var(--type-h4); }

a {
  color: var(--text-link);
  text-decoration: none;
  transition: color var(--transition-fast);
}
a:hover { color: var(--text-link-hover); }

code, kbd, samp { font: var(--type-ref); }

::selection { background: var(--hv-oceano-100); }

:focus-visible {
  outline: 3px solid var(--border-focus);
  outline-offset: 1px;
}

/* ===== src/css/06-components.css ===== */
/* ============================================================
   Harven Surf — Componentes (BEM, convención Hummingbird)
   Consumido por los wrappers React de components/.
   ============================================================ */

/* ---------- Botones ---------- */
.hv-btn {
  display: inline-flex;
  gap: 0.375rem;
  align-items: center;
  justify-content: center;
  padding: 0.625rem 1.25rem;
  font: var(--weight-semibold) var(--text-base)/1.25 var(--font-body);
  color: #fff;
  white-space: nowrap;
  cursor: pointer;
  background: var(--action-primary);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  transition: background var(--transition-default), border-color var(--transition-default), color var(--transition-default);
  text-decoration: none;
}
.hv-btn .material-icons { width: 1.2em; height: 1.2em; font-size: 1.25em; line-height: 1.2em; }
.hv-btn:hover { background: var(--action-primary-hover); color: #fff; }
.hv-btn:active { background: var(--action-primary-active); }
.hv-btn--secondary { background: var(--action-secondary); }
.hv-btn--secondary:hover { background: var(--action-secondary-hover); }
.hv-btn--secondary:active { background: #000; }
.hv-btn--outline { color: var(--text-body); background: var(--surface-page); border-color: var(--border-strong); }
.hv-btn--outline:hover { color: var(--text-body); background: var(--surface-page); border-color: var(--hv-gris-900); }
.hv-btn--outline:active { background: var(--hv-gris-50); }
.hv-btn--tertiary { padding-inline: 0.5rem; color: var(--text-link); background: transparent; }
.hv-btn--tertiary:hover { color: var(--text-link-hover); background: transparent; }
.hv-btn--danger { background: var(--hv-error); }
.hv-btn--danger:hover { background: #a82134; }
.hv-btn--sm { padding: 0.375rem 0.75rem; font-size: var(--text-sm); }
.hv-btn--lg { padding: 0.875rem 1.75rem; font-size: var(--text-lg); }
.hv-btn--block { width: 100%; }
.hv-btn:disabled, .hv-btn--disabled {
  color: var(--action-disabled-text);
  pointer-events: none;
  background: var(--action-disabled-bg);
  border-color: transparent;
}

/* ---------- Botón de icono ---------- */
.hv-iconbtn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  color: var(--text-body);
  cursor: pointer;
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  transition: background var(--transition-fast);
}
.hv-iconbtn:hover { background: var(--hv-gris-100); }
.hv-iconbtn:active { background: var(--hv-gris-200); }
.hv-iconbtn--inverse { color: #fff; }
.hv-iconbtn--inverse:hover { background: rgba(255, 255, 255, 0.12); }
.hv-iconbtn__count {
  position: absolute;
  top: 0.125rem;
  right: 0.125rem;
  min-width: 1.125rem;
  height: 1.125rem;
  padding: 0 0.25rem;
  font: 700 0.6875rem/1.125rem var(--font-body);
  color: #fff;
  text-align: center;
  background: var(--action-primary);
  border-radius: var(--radius-pill);
}

/* ---------- Badges ---------- */
.hv-badge {
  display: inline-flex;
  gap: 0.375rem;
  align-items: center;
  padding: 0.25rem 0.5rem;
  font: var(--weight-semibold) var(--text-xs)/1.2 var(--font-body);
  border-radius: var(--radius-sm);
}
.hv-badge--exito { color: var(--hv-exito); background: var(--hv-exito-suave); }
.hv-badge--aviso { color: var(--hv-aviso); background: var(--hv-aviso-suave); }
.hv-badge--error { color: var(--hv-error); background: var(--hv-error-suave); }
.hv-badge--info { color: var(--hv-oceano-700); background: var(--hv-info-suave); }
.hv-badge--neutral { color: var(--hv-gris-700); background: var(--hv-gris-100); }
.hv-badge--tinta { color: #fff; background: var(--hv-tinta); }
.hv-badge__dot { width: 0.5rem; height: 0.5rem; background: currentcolor; border-radius: 50%; }

/* ---------- Alertas ---------- */
.hv-alert {
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
  padding: 0.75rem 1rem;
  font: var(--type-small);
  border: 1px solid;
  border-radius: var(--radius-md);
}
.hv-alert .material-icons { font-size: 1.25rem; }
.hv-alert__title { font-weight: var(--weight-semibold); }
.hv-alert--info { color: var(--hv-oceano-800); background: var(--hv-info-suave); border-color: var(--hv-oceano-200); }
.hv-alert--exito { color: #0e5a3c; background: var(--hv-exito-suave); border-color: #b5dcc8; }
.hv-alert--aviso { color: #7c4a00; background: var(--hv-aviso-suave); border-color: #ecd3a8; }
.hv-alert--error { color: #8e1e2d; background: var(--hv-error-suave); border-color: #f0bfc7; }

/* ---------- Formularios ---------- */
.hv-field { display: flex; flex-direction: column; gap: 0.5rem; }
.hv-label { font: var(--type-label); color: var(--text-body); }
.hv-label__req { color: var(--hv-error); }
.hv-input, .hv-select {
  width: 100%;
  height: 2.75rem;
  padding: 0 1rem;
  font: var(--weight-regular) var(--text-base)/1.5 var(--font-body);
  color: var(--text-body);
  background: #fff;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  transition: border-color var(--transition-fast);
  box-sizing: border-box;
  appearance: none;
}
.hv-input::placeholder { color: var(--hv-gris-400); }
.hv-input:hover, .hv-select:hover { border-color: var(--hv-gris-400); }
.hv-input:focus, .hv-select:focus { outline: 3px solid var(--border-focus); outline-offset: 0; border-color: var(--border-focus); }
.hv-input--error, .hv-select--error { border-color: var(--hv-error); }
.hv-input--error:focus { outline-color: var(--hv-error); }
textarea.hv-input { height: auto; min-height: 6rem; padding: 0.625rem 1rem; resize: vertical; }
.hv-help { font: var(--type-eyebrow); font-weight: 400; color: var(--text-muted); }
.hv-error-msg { display: inline-flex; gap: 0.25rem; align-items: center; font: var(--type-eyebrow); font-weight: 500; color: var(--hv-error); }
.hv-select-wrap { position: relative; }
.hv-select-wrap .material-icons {
  position: absolute;
  top: 50%;
  right: 0.625rem;
  color: var(--hv-gris-500);
  pointer-events: none;
  transform: translateY(-50%);
}
.hv-check { display: flex; gap: 0.625rem; align-items: flex-start; font: var(--type-small); cursor: pointer; }
.hv-check input {
  flex-shrink: 0;
  width: 1.125rem;
  height: 1.125rem;
  margin: 0.125rem 0 0;
  accent-color: var(--action-primary);
  cursor: pointer;
}
.hv-check__desc { color: var(--text-muted); }

/* ---------- Selector de cantidad ---------- */
.hv-qty { display: inline-flex; align-items: stretch; height: 2.75rem; }
.hv-qty__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  color: var(--text-body);
  cursor: pointer;
  background: #fff;
  border: 1px solid var(--border-strong);
  transition: background var(--transition-fast);
}
.hv-qty__btn:hover { background: var(--hv-gris-50); }
.hv-qty__btn:active { background: var(--hv-gris-100); }
.hv-qty__btn:disabled { color: var(--hv-gris-300); pointer-events: none; }
.hv-qty__btn:first-child { border-radius: var(--radius-sm) 0 0 var(--radius-sm); }
.hv-qty__btn:last-child { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
.hv-qty__btn .material-icons { font-size: 1.125rem; }
.hv-qty__input {
  width: 3.5rem;
  font: var(--weight-semibold) var(--text-base)/1 var(--font-body);
  color: var(--text-body);
  text-align: center;
  border: 1px solid var(--border-strong);
  border-right: 0;
  border-left: 0;
  border-radius: 0;
}
.hv-qty__input:focus { outline: 2px solid var(--border-focus); outline-offset: -2px; }

/* ---------- Miniatura de producto (estándar PrestaShop) ---------- */
.hv-pcard {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--surface-card);
  border: var(--border-card);
  border-radius: var(--radius-md);
  transition: border-color var(--transition-default), box-shadow var(--transition-default);
  overflow: hidden;
}
.hv-pcard:hover { border-color: var(--border-strong); box-shadow: var(--shadow-sm); }
.hv-pcard__media {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1 / 1;
  background: var(--hv-gris-50);
}
.hv-pcard__media img { width: 100%; height: 100%; object-fit: cover; }
.hv-pcard__flag { position: absolute; top: 0.625rem; left: 0.625rem; }
.hv-pcard__body { display: flex; flex-direction: column; gap: 0.25rem; padding: 0.875rem; }
.hv-pcard__brand {
  font: var(--type-eyebrow);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
}
.hv-pcard__name {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  min-height: 2.4em;
  margin: 0;
  overflow: hidden;
  font: var(--weight-medium) var(--text-sm)/1.2 var(--font-body);
  color: var(--text-body);
}
.hv-pcard__ref { font: var(--type-ref); font-size: 0.6875rem; color: var(--text-subtle); }
.hv-pcard__pricerow { display: flex; gap: 0.5rem; align-items: baseline; margin-top: 0.25rem; }
.hv-pcard__price { font: var(--type-price); font-size: 1.125rem; color: var(--text-price); }
.hv-pcard__pvpr { font: var(--type-eyebrow); font-weight: 400; color: var(--text-pvpr); }
.hv-pcard__foot { display: flex; gap: 0.5rem; align-items: center; justify-content: space-between; margin-top: 0.5rem; }
.hv-pcard__locked {
  display: inline-flex;
  gap: 0.375rem;
  align-items: center;
  font: var(--type-eyebrow);
  color: var(--text-muted);
}

/* ---------- Facetas (Faceted Search) ---------- */
.hv-facet { padding: 1rem 0; border-bottom: 1px solid var(--border-default); }
.hv-facet__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 0;
  font: var(--type-label);
  color: var(--text-body);
  cursor: pointer;
  background: none;
  border: none;
}
.hv-facet__head .material-icons { font-size: 1.25rem; color: var(--hv-gris-500); transition: transform var(--transition-fast); }
.hv-facet__head--open .material-icons { transform: rotate(180deg); }
.hv-facet__list { display: flex; flex-direction: column; gap: 0.5rem; margin-top: 0.75rem; }
.hv-facet__opt { display: flex; gap: 0.5rem; align-items: center; font: var(--type-small); cursor: pointer; }
.hv-facet__opt input { width: 1rem; height: 1rem; margin: 0; accent-color: var(--action-primary); }
.hv-facet__count { margin-left: auto; font: var(--type-eyebrow); font-weight: 400; color: var(--text-subtle); }
.hv-chip {
  display: inline-flex;
  gap: 0.375rem;
  align-items: center;
  padding: 0.25rem 0.75rem;
  font: var(--type-eyebrow);
  color: var(--hv-oceano-700);
  cursor: pointer;
  background: var(--hv-oceano-50);
  border: 1px solid var(--hv-oceano-200);
  border-radius: var(--radius-pill);
}
.hv-chip .material-icons { font-size: 0.875rem; }
.hv-chip:hover { background: var(--hv-oceano-100); }

/* ---------- Migas de pan ---------- */
.hv-breadcrumb { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; padding: 0.75rem 0; font: var(--type-small); }
.hv-breadcrumb a { color: var(--text-muted); }
.hv-breadcrumb a:hover { color: var(--text-link-hover); }
.hv-breadcrumb__sep { color: var(--text-body); }
.hv-breadcrumb__current { color: var(--text-body); }

/* ---------- Paginación ---------- */
.hv-pagination { display: flex; gap: 0.25rem; align-items: center; }
.hv-pagination__page {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.25rem;
  height: 2.25rem;
  padding: 0 0.5rem;
  font: var(--type-small);
  color: var(--text-body);
  cursor: pointer;
  background: none;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  transition: background var(--transition-fast);
}
.hv-pagination__page:hover { background: var(--hv-gris-100); }
.hv-pagination__page--active { font-weight: var(--weight-semibold); color: #fff; background: var(--hv-tinta); pointer-events: none; }
.hv-pagination__page:disabled { color: var(--hv-gris-300); pointer-events: none; }

/* ---------- Header corporativo ---------- */
.hv-preheader {
  background: var(--surface-dark);
  color: rgba(255, 255, 255, 0.85);
  font: var(--type-eyebrow);
  font-weight: 500;
  letter-spacing: 0.04em;
}
.hv-preheader__inner {
  display: flex;
  gap: 1rem;
  align-items: center;
  justify-content: space-between;
  max-width: var(--container-max);
  padding: 0.5rem var(--container-pad);
  margin: 0 auto;
}
.hv-preheader a { color: #fff; font-weight: 600; }
.hv-header { background: var(--surface-page); border-bottom: 1px solid var(--border-default); }
.hv-header__main {
  display: flex;
  gap: 2rem;
  align-items: center;
  max-width: var(--container-max);
  padding: 1rem var(--container-pad);
  margin: 0 auto;
}
.hv-header__logo img { display: block; height: 2.75rem; }
.hv-header__search { position: relative; flex: 1; max-width: 540px; }
.hv-header__search input { padding-right: 3rem; }
.hv-header__search button {
  position: absolute;
  top: 50%;
  right: 0.25rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  color: var(--hv-gris-500);
  cursor: pointer;
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  transform: translateY(-50%);
}
.hv-header__search button:hover { color: var(--action-primary); }
.hv-header__actions { display: flex; gap: 0.25rem; align-items: center; margin-left: auto; }
.hv-header__action-label { font: var(--type-eyebrow); font-weight: 500; color: var(--text-muted); }
.hv-nav { border-top: 1px solid var(--border-default); }
.hv-nav__inner {
  display: flex;
  gap: 0.25rem;
  max-width: var(--container-max);
  padding: 0 var(--container-pad);
  margin: 0 auto;
  overflow-x: auto;
}
.hv-nav__link {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.875rem 1rem;
  font: var(--weight-semibold) var(--text-sm)/1 var(--font-body);
  color: var(--text-body);
  white-space: nowrap;
  cursor: pointer;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  transition: color var(--transition-fast);
}
.hv-nav__link:hover { color: var(--hv-oceano-600); }
.hv-nav__link--active { color: var(--hv-oceano-700); border-bottom-color: var(--hv-oceano-600); }
.hv-nav__link--featured { color: var(--hv-error); }

/* ---------- Footer corporativo ---------- */
.hv-footer { color: rgba(255, 255, 255, 0.75); background: var(--surface-dark); }
.hv-footer__inner {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1.2fr;
  gap: 2.5rem;
  max-width: var(--container-max);
  padding: 3rem var(--container-pad) 2.5rem;
  margin: 0 auto;
}
.hv-footer__brand img { height: 2.5rem; margin-bottom: 1rem; }
.hv-footer__title {
  margin: 0 0 1rem;
  font: var(--type-eyebrow);
  color: #fff;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
}
.hv-footer__links { display: flex; flex-direction: column; gap: 0.625rem; padding: 0; margin: 0; list-style: none; }
.hv-footer__links a { font: var(--type-small); color: rgba(255, 255, 255, 0.75); }
.hv-footer__links a:hover { color: #fff; }
.hv-footer__legal { border-top: 1px solid rgba(255, 255, 255, 0.15); }
.hv-footer__legal-inner {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  align-items: center;
  justify-content: space-between;
  max-width: var(--container-max);
  padding: 1rem var(--container-pad);
  margin: 0 auto;
  font: var(--type-eyebrow);
  font-weight: 400;
  color: rgba(255, 255, 255, 0.55);
}
.hv-footer__legal-inner a { color: rgba(255, 255, 255, 0.55); }
.hv-footer__legal-inner a:hover { color: #fff; }

/* ---------- Utilidades de página ---------- */
.hv-container { max-width: var(--container-max); padding: 0 var(--container-pad); margin: 0 auto; }
.hv-section-title {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin: 0 0 1.5rem;
}
.hv-section-title h2 { margin: 0; }
.hv-section-title a { font: var(--type-label); color: var(--text-link); }


/* ============================================================
   Retículas de página y capa responsive
   Breakpoints: 1100 (escritorio compacto) · 920 (tablet) ·
   700 (tablet vertical) · 600 (móvil)
   ============================================================ */
.hv-grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--grid-gap); }
.hv-grid-cats { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--grid-gap); }
.hv-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--grid-gap); }
.hv-layout-side { display: grid; grid-template-columns: 260px 1fr; gap: var(--grid-gap); align-items: start; }
.hv-layout-split { display: grid; grid-template-columns: 1.1fr 1fr; gap: 3rem; align-items: start; }
.hv-layout-aside { display: grid; grid-template-columns: 1fr 360px; gap: var(--grid-gap); align-items: start; }
.hv-form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.hv-table-scroll { overflow-x: auto; }
.hv-cta-row { display: flex; flex-wrap: wrap; gap: 0.75rem; }
.hv-header__burger { display: none; }

/* ---- Escritorio compacto ---- */
@media (max-width: 1100px) {
  .hv-grid-4 { grid-template-columns: repeat(3, 1fr); }
  /* Categorías destacadas: 2×2 simétrico en cuanto no caben las 4 */
  .hv-grid-cats { grid-template-columns: repeat(2, 1fr); }
  .hv-layout-side { grid-template-columns: 220px 1fr; }
}

/* ---- Tablet (≤920) ---- */
@media (max-width: 920px) {
  .hv-layout-side, .hv-layout-split, .hv-layout-aside { grid-template-columns: 1fr; }
  .hv-layout-split { gap: 1.5rem; }
  .hv-layout-aside aside { position: static !important; }
  .hv-grid-3 { grid-template-columns: repeat(3, 1fr); gap: 1rem; }

  /* Header: buscador pasa a línea completa */
  .hv-header__main { flex-wrap: wrap; gap: 0.75rem 1rem; padding: 0.75rem 1rem; }
  .hv-header__logo img { height: 2.25rem; }
  .hv-header__search { flex-basis: 100%; order: 3; max-width: none; }
  .hv-header__actions { margin-left: auto; gap: 0; }
  .hv-preheader__inner { padding: 0.4rem 1rem; }
  .hv-preheader__inner > span:last-child { display: none; }
  .hv-preheader__inner > span:first-child { width: 100%; text-align: center; }

  .hv-footer__inner { grid-template-columns: 1fr 1fr; gap: 2rem 1.5rem; padding: 2rem 1.5rem; }
  .hv-footer__legal-inner { flex-direction: column; align-items: flex-start; gap: 0.5rem; }
}

/* ---- Tablet vertical (≤700) ---- */
@media (max-width: 700px) {
  .hv-grid-4 { grid-template-columns: repeat(2, 1fr); gap: 1rem; }
  .hv-grid-3 { grid-template-columns: 1fr; gap: 1.25rem; }
}

/* ---- Móvil (≤600) ---- */
@media (max-width: 600px) {
  .hv-grid-cats { grid-template-columns: 1fr; }
  :root {
    --text-4xl: 1.875rem;  /* display hero 30 */
    --text-3xl: 1.5rem;    /* h1 24 */
    --text-2xl: 1.25rem;   /* h2 20 */
    --grid-gap: 0.75rem;
  }
  .hv-container { padding-left: 1rem; padding-right: 1rem; }
  .hv-cta-row .hv-btn { flex: 1 1 100%; }
  .hv-btn { white-space: normal; }
  .hv-btn--lg { padding: 0.75rem 1.25rem; font-size: var(--text-base); }
  .hv-form-grid { grid-template-columns: 1fr; }
  .hv-footer__inner { grid-template-columns: 1fr; }

  /* Header móvil: hamburguesa + logo + acciones; menú vertical desplegable */
  .hv-header__burger { display: inline-flex; }
  .hv-header__main { gap: 0.25rem 0.5rem; }
  .hv-header__action-label { display: none; }
  .hv-nav { display: none; }
  .hv-nav.hv-nav--open { display: block; border-bottom: 1px solid var(--border-default); }
  .hv-nav.hv-nav--open .hv-nav__inner { flex-direction: column; gap: 0; padding: 0.25rem 0.5rem 0.5rem; overflow: visible; }
  .hv-nav.hv-nav--open .hv-nav__link {
    width: 100%;
    justify-content: flex-start;
    padding: 0.875rem 0.75rem;
    font-size: var(--text-base);
    border-bottom: 1px solid var(--hv-gris-100);
    border-left: 3px solid transparent;
  }
  .hv-nav.hv-nav--open .hv-nav__link--active { border-left-color: var(--hv-oceano-600); background: var(--hv-oceano-50); }

  /* Tablas de datos: permitir scroll sin romper la página */
  .hv-table-scroll table { min-width: 560px; }
}

/* ===== src/css/07-hummingbird.css ===== */
/* ============================================================
   Harven Surf — Puente con el tema padre (Hummingbird / Bootstrap 5.3.3)
   ------------------------------------------------------------
   Hummingbird compila Bootstrap desde SCSS: en theme.css los
   componentes llevan valores HEX LITERALES, no var(--bs-primary).
   Verificado:
     .btn-primary{--bs-btn-bg:#0b69f6; ...}
   => redefinir --bs-primary en :root NO recolorea los botones.
      Hay que sobrescribir las variables DE COMPONENTE (--bs-btn-*),
      que sí son custom properties y se heredan sin !important.

   Este archivo hace que TODO lo que pinta el tema padre y los
   módulos nativos (formularios, paginación, offcanvas, toasts,
   faceted search, checkout...) hable el idioma de la marca,
   sin tocar ni un archivo de hummingbird.
   ============================================================ */

/* ---- 1. Tokens globales de Bootstrap ---------------------- */
:root,
[data-bs-theme="light"] {
  /* Tipografía: Inter -> Archivo (autoalojada) */
  --bs-body-font-family: var(--font-body);
  --bs-font-monospace: var(--font-mono);
  --bs-body-font-size: var(--text-base);
  --bs-body-font-weight: var(--weight-regular);
  --bs-body-line-height: var(--leading-normal);

  /* Color de marca */
  --bs-primary: var(--action-primary);
  --bs-primary-rgb: 14, 94, 128;
  --bs-secondary: var(--hv-gris-500);
  --bs-secondary-rgb: 110, 123, 133;
  --bs-success: var(--hv-exito);
  --bs-success-rgb: 21, 122, 82;
  --bs-danger: var(--hv-error);
  --bs-danger-rgb: 194, 41, 60;
  --bs-warning: var(--hv-aviso);
  --bs-warning-rgb: 178, 106, 0;
  --bs-info: var(--hv-oceano-500);
  --bs-info-rgb: 23, 110, 146;
  --bs-dark: var(--hv-tinta);
  --bs-dark-rgb: 20, 24, 29;

  /* Texto y superficies */
  --bs-body-color: var(--text-body);
  --bs-body-color-rgb: 20, 24, 29;
  --bs-body-bg: var(--surface-page);
  --bs-emphasis-color: var(--hv-tinta);
  --bs-secondary-color: var(--text-muted);
  --bs-secondary-bg: var(--surface-inset);
  --bs-tertiary-bg: var(--surface-alt);
  --bs-heading-color: var(--text-body);

  /* Enlaces */
  --bs-link-color: var(--text-link);
  --bs-link-color-rgb: 14, 94, 128;
  --bs-link-hover-color: var(--text-link-hover);
  --bs-link-hover-color-rgb: 10, 61, 83;

  /* Bordes y radios: el sistema es plano (4px controles / 8px tarjetas) */
  --bs-border-color: var(--border-default);
  --bs-border-color-translucent: var(--border-default);
  --bs-border-radius: var(--radius-sm);
  --bs-border-radius-sm: var(--radius-sm);
  --bs-border-radius-lg: var(--radius-md);
  --bs-border-radius-xl: var(--radius-md);
  --bs-border-radius-pill: var(--radius-pill);

  /* Sombras y foco */
  --bs-box-shadow-sm: var(--shadow-sm);
  --bs-box-shadow: var(--shadow-md);
  --bs-box-shadow-lg: var(--shadow-lg);
  --bs-focus-ring-color: rgba(14, 94, 128, 0.35);

  /* Contenedor: el mockup trabaja a 1320px */
  --bs-gutter-x: var(--container-pad);
}

/* ---- 2. Botones (variables de componente) ----------------- */
.btn {
  --bs-btn-font-family: var(--font-body);
  --bs-btn-font-weight: var(--weight-semibold);
  --bs-btn-border-radius: var(--radius-sm);
  --bs-btn-focus-box-shadow: var(--focus-ring);
}

/* ⚠️ ENLACES CON ASPECTO DE BOTÓN — no borrar.
 *
 * `05-base.css` declara `a { color: var(--text-link) }` sin capa, y
 * Bootstrap declara `.btn { color: var(--bs-btn-color) }` DENTRO de una
 * capa. Una declaración sin capa gana a cualquiera con capa **sea cual sea
 * la especificidad**, así que nuestro `a` (0,0,1) se imponía sobre `.btn`
 * (0,1,0) y TODO `<a class="btn">` de la tienda salía con color de enlace
 * en vez del color del botón.
 *
 * Se vio en el carrito: "Finalizar compra" es un `<a class="btn btn-primary">`
 * y salía en azul océano sobre fondo azul océano —texto invisible— y casi
 * negro al pasar el ratón. Los `<button>` no estaban afectados, por eso solo
 * fallaban algunos botones.
 *
 * Se restituye la intención de Bootstrap leyendo sus propias variables de
 * componente, así que sigue valiendo para cualquier variante (--primary,
 * --outline-*, --danger…) sin repetir colores.
 */
a.btn { color: var(--bs-btn-color); }
a.btn:hover { color: var(--bs-btn-hover-color); }
a.btn:focus-visible { color: var(--bs-btn-hover-color); }
a.btn:active,
a.btn.active { color: var(--bs-btn-active-color); }
a.btn.disabled { color: var(--bs-btn-disabled-color); }

.btn-primary {
  --bs-btn-color: var(--text-inverse);
  --bs-btn-bg: var(--action-primary);
  --bs-btn-border-color: var(--action-primary);
  --bs-btn-hover-color: var(--text-inverse);
  --bs-btn-hover-bg: var(--action-primary-hover);
  --bs-btn-hover-border-color: var(--action-primary-hover);
  --bs-btn-active-color: var(--text-inverse);
  --bs-btn-active-bg: var(--action-primary-active);
  --bs-btn-active-border-color: var(--action-primary-active);
  --bs-btn-disabled-color: var(--action-disabled-text);
  --bs-btn-disabled-bg: var(--action-disabled-bg);
  --bs-btn-disabled-border-color: var(--action-disabled-bg);
  --bs-btn-focus-shadow-rgb: 14, 94, 128;
}

/* "Tinta": el secundario del sistema es negro logo, no gris Bootstrap */
.btn-secondary {
  --bs-btn-color: var(--text-inverse);
  --bs-btn-bg: var(--action-secondary);
  --bs-btn-border-color: var(--action-secondary);
  --bs-btn-hover-color: var(--text-inverse);
  --bs-btn-hover-bg: var(--action-secondary-hover);
  --bs-btn-hover-border-color: var(--action-secondary-hover);
  --bs-btn-active-bg: var(--action-secondary-hover);
  --bs-btn-active-border-color: var(--action-secondary-hover);
  --bs-btn-disabled-color: var(--action-disabled-text);
  --bs-btn-disabled-bg: var(--action-disabled-bg);
  --bs-btn-disabled-border-color: var(--action-disabled-bg);
}

.btn-outline-primary {
  --bs-btn-color: var(--action-primary);
  --bs-btn-border-color: var(--border-strong);
  --bs-btn-hover-color: var(--text-inverse);
  --bs-btn-hover-bg: var(--action-primary);
  --bs-btn-hover-border-color: var(--action-primary);
  --bs-btn-active-bg: var(--action-primary-active);
  --bs-btn-active-border-color: var(--action-primary-active);
}

.btn-danger {
  --bs-btn-bg: var(--hv-error);
  --bs-btn-border-color: var(--hv-error);
  --bs-btn-hover-bg: #a52133;
  --bs-btn-hover-border-color: #a52133;
}

/* ---- 3. Formularios --------------------------------------- */
.form-control,
.form-select {
  border-color: var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text-body);
}

.form-control:focus,
.form-select:focus {
  border-color: var(--border-focus);
  box-shadow: var(--focus-ring);
}

.form-control::placeholder { color: var(--hv-gris-400); }

.form-label {
  font: var(--type-label);
  color: var(--text-body);
}

.form-check-input:checked {
  background-color: var(--action-primary);
  border-color: var(--action-primary);
}

.form-check-input:focus {
  border-color: var(--border-focus);
  box-shadow: var(--focus-ring);
}

.invalid-feedback,
.form-control.is-invalid { --bs-form-invalid-color: var(--hv-error); --bs-form-invalid-border-color: var(--hv-error); }

/* ---- 4. Otros componentes del padre ----------------------- */
.badge { --bs-badge-border-radius: var(--radius-pill); font-weight: var(--weight-semibold); }

.card {
  --bs-card-border-color: var(--border-default);
  --bs-card-border-radius: var(--radius-md);
  --bs-card-bg: var(--surface-card);
}

.pagination {
  --bs-pagination-color: var(--text-body);
  --bs-pagination-border-color: var(--border-default);
  --bs-pagination-hover-bg: var(--surface-alt);
  --bs-pagination-hover-color: var(--text-link);
  --bs-pagination-active-bg: var(--action-primary);
  --bs-pagination-active-border-color: var(--action-primary);
  --bs-pagination-border-radius: var(--radius-sm);
  --bs-pagination-focus-box-shadow: var(--focus-ring);
}

.alert { --bs-alert-border-radius: var(--radius-sm); }

.dropdown-menu {
  --bs-dropdown-border-color: var(--border-default);
  --bs-dropdown-border-radius: var(--radius-sm);
  --bs-dropdown-link-active-bg: var(--action-primary);
  --bs-dropdown-link-hover-bg: var(--surface-alt);
}

.offcanvas { --bs-offcanvas-bg: var(--surface-page); }

.modal { --bs-modal-border-radius: var(--radius-md); --bs-modal-border-color: var(--border-default); }

.table {
  --bs-table-border-color: var(--border-default);
  --bs-table-striped-bg: var(--surface-alt);
}

/* Contenedor: el mockup trabaja a 1320px, igual que xxl de Bootstrap */
.container,
.container-xxl { max-width: var(--container-max); }

/* ===== src/css/08-chasis.css ===== */
/* ============================================================
   Harven Surf — Chasis (cabecera, navegación, pie, migas, paginación)
   ------------------------------------------------------------
   06-components.css ya trae los componentes .hv-* del design system.
   Este archivo solo hace DOS cosas:
     1. Los pocos añadidos que el mockup no tenía como componente
        (buscador de cabecera, columna de acción icono+etiqueta).
     2. Encajar el marcado que pintan los módulos nativos y el tema
        padre dentro de ese diseño: ps_mainmenu, los bloques del pie,
        las migas y la paginación.
   Sin !important: custom.css ya carga después del padre.
   ============================================================ */

/* ---- 1. Cabecera: columna icono + etiqueta ---------------- */
/* El mockup apila el icono sobre su etiqueta. No existe como opción
   nativa: los bloques del padre son horizontales (icono + título). */
.hv-header__action {
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: 1;
}
.hv-header__action > .hv-iconbtn { text-decoration: none; }
.hv-header__action .dropdown-toggle::after { display: none; }

/* Logo: la plantilla emite width/height reales del archivo (450x106) para
   reservar espacio y evitar saltos de layout (CLS). Pero los atributos
   width/height son "presentational hints" que se mapean a las propiedades
   CSS: si solo fijamos la altura, el ancho usado sigue siendo 450px y el
   logo sale deformado y desbordando en móvil.
   Con width:auto el navegador deriva el ancho de la relación de aspecto. */
.hv-header__logo img {
  width: auto;
  max-width: 100%;
}
.hv-header__h1 { margin: 0; }

/* El design system baja a 2.25rem en tablet (<=920) pero no define móvil */
@media (max-width: 600px) {
  .hv-header__logo img { height: 1.875rem; }
}

/* ---- 2. Buscador de cabecera ------------------------------ */
.hv-search { position: relative; }
.hv-search__form { position: relative; display: flex; }
.hv-search__input { padding-right: 5.5rem; }

.hv-search__submit,
.hv-search__clear {
  position: absolute;
  top: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  color: var(--hv-gris-500);
  cursor: pointer;
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  transform: translateY(-50%);
  transition: color var(--transition-fast);
}
.hv-search__submit { right: 0.25rem; }
.hv-search__clear { right: 2.5rem; }
.hv-search__submit:hover,
.hv-search__clear:hover { color: var(--action-primary); }
.hv-search__submit:focus-visible,
.hv-search__clear:focus-visible { outline: 3px solid var(--border-focus); outline-offset: -3px; }

/* Desplegable de sugerencias */
.hv-search__dropdown {
  position: absolute;
  z-index: 1000;
  top: calc(100% + 0.25rem);
  right: 0;
  left: 0;
  overflow: hidden auto;
  max-height: 60vh;
  background: var(--surface-card);
  border: var(--border-card);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
}
.hv-search__result {
  display: flex;
  gap: 0.75rem;
  align-items: center;
  padding: 0.5rem 0.75rem;
  color: var(--text-body);
  text-decoration: none;
  border-bottom: 1px solid var(--hv-gris-100);
}
.hv-search__result:last-child { border-bottom: none; }
.hv-search__result:hover,
.hv-search__result:focus-visible { background: var(--surface-alt); }
.hv-search__result-image { width: 2.75rem; height: 2.75rem; object-fit: contain; }
.hv-search__result-name { margin: 0; font: var(--type-small); }

/* ---- 3. Navegación: ps_mainmenu dentro de .hv-nav --------- */
/* El megamenú del padre se reutiliza tal cual (mantiene submenús y el
   offcanvas móvil, que el mockup no cubría) y se le da el aspecto plano
   del diseño. El padre lo muestra a partir de xl (1200px); aquí baja a
   la escala del sistema para que la fila de categorías aparezca antes. */
.hv-nav .ps-mainmenu { flex: 1; }
.hv-nav .ps-mainmenu--desktop { display: flex; align-items: center; }

/* ÚNICA excepción a la regla de "cero !important" del proyecto, y hay que
   entender POR QUÉ está escrita así o no funciona.

   El padre marca el menú de escritorio con `.d-none d-xl-block`, y las
   utilidades de Bootstrap son `display: none !important`. Pero además
   Hummingbird organiza su CSS en CAPAS DE CASCADA:

     @layer vendors, bs-base, bs-components, bs-custom-components,
            ps-base, ps-components, ps-pages, ps-modules, utilities;

   y `.d-none` vive en `@layer utilities`. En la cascada, para las
   declaraciones `!important` el orden de capas se INVIERTE: gana la capa
   más temprana, y cualquier `!important` dentro de una capa gana a un
   `!important` SIN capa. Como nuestro custom.css no está en ninguna capa,
   su `!important` pierde siempre contra `.d-none`, tenga la especificidad
   que tenga. (Comprobado: sin la capa, esto no se aplicaba entre 601 y
   1199px y la tienda se quedaba sin menú en tablet.)

   La solución es declarar la regla en una capa ANTERIOR a `utilities`.
   Se usa `ps-base`, que ya existe en el padre. */
@layer ps-base {
  @media (min-width: 601px) {
    .hv-nav .ps-mainmenu__desktop { display: block !important; }
    .hv-nav .ps-mainmenu__mobile-toggle { display: none !important; }
  }
}

/* Móvil: el offcanvas #mobileMenu que pinta ps_mainmenu es DESCENDIENTE de
   .hv-nav, y el design system oculta .hv-nav por debajo de 600px. Si se deja
   así, no solo desaparece la fila de categorías: desaparece el panel del
   menú y no hay forma de abrirlo. Por eso aquí se mantiene .hv-nav en el
   flujo y se oculta únicamente el bloque de escritorio. */
@media (max-width: 600px) {
  .hv-nav { display: block; border-top: none; }
  .hv-nav__inner { padding: 0; }
  .hv-nav .ps-mainmenu--desktop { display: none; }
}

/* Solo el árbol de ESCRITORIO va en horizontal. Ojo: .menu__list es la lista
   del menú MÓVIL y también cuelga de .hv-nav (el offcanvas está dentro), así
   que incluirla aquí ponía las categorías en fila dentro de un panel estrecho
   y solo se veía la primera. Se estila aparte, más abajo. */
.hv-nav .ps-mainmenu__tree {
  display: flex;
  gap: 0.25rem;
  padding: 0;
  margin: 0;
  list-style: none;
}

/* Enlace de primer nivel = .hv-nav__link del mockup */
.hv-nav .ps-mainmenu__tree-link {
  display: inline-flex;
  gap: 0.25rem;
  align-items: center;
  padding: 0.875rem 1rem;
  font: var(--weight-semibold) var(--text-sm) / 1 var(--font-body);
  color: var(--text-body);
  text-decoration: none;
  white-space: nowrap;
  border-bottom: 2px solid transparent;
  transition: color var(--transition-fast);
}
.hv-nav .ps-mainmenu__tree-link:hover { color: var(--hv-oceano-600); }

/* ⚠️ El recuadro que salía al hacer clic en una categoría NO era nuestro.
   El padre lo pinta con `:focus` a secas, no con `:focus-visible`:

     .ps-mainmenu:is(.ps-mainmenu--desktop) .ps-mainmenu__tree>li .ps-mainmenu__tree-link:focus
       { outline: .125rem solid var(--bs-link-color); outline-offset: .125rem }

   `:focus` se activa TAMBIÉN al pulsar con el ratón, así que el anillo
   aparecía en cada clic. Se quita solo en ese caso —`:focus:not(:focus-visible)`—
   y se conserva íntegro para quien navega con el teclado, que es a quien
   sirve de verdad. Quitarlo del todo dejaría el menú sin indicación de foco.

   El padre repite ese mismo `:focus` en tres sitios del megamenú: el enlace
   de categoría, la flecha que abre el submenú y los ítems del desplegable.
   Los tres van aquí, o el recuadro reaparece en cuanto la categoría tenga
   submenú.

   Nuestra regla tiene MENOS especificidad que la del padre (0,4,1 frente a
   0,5,1), pero gana igual porque la del padre vive en `@layer ps-modules` y
   esta no lleva capa. El subrayado del elemento activo lo pone
   `border-bottom` y no se toca. */
.hv-nav .ps-mainmenu__tree > li .ps-mainmenu__tree-link:focus:not(:focus-visible),
.hv-nav .ps-mainmenu__tree > li .ps-mainmenu__tree-dropdown-toggle:focus:not(:focus-visible),
.hv-nav .submenu__left-item:focus:not(:focus-visible) {
  outline: 0;
}
.hv-nav .ps-mainmenu__tree-item-wrapper .current > .ps-mainmenu__tree-link,
.hv-nav .ps-mainmenu__tree-link[aria-current="page"] {
  color: var(--hv-oceano-700);
  border-bottom-color: var(--hv-oceano-600);
}

/* Botón hamburguesa del padre con el aspecto del mockup */
.hv-nav .ps-mainmenu__mobile-toggle .menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  color: var(--text-body);
  text-decoration: none;
}

/* Menú móvil (offcanvas): lista vertical, con el mismo lenguaje que el
   mockup daba a .hv-nav--open (fila a fila, filete inferior y marca de
   activo en el borde izquierdo). */
.ps-mainmenu--mobile { width: min(20rem, 85vw); }
.ps-mainmenu--mobile .menu__list {
  display: flex;
  flex-direction: column;
  padding: 0;
  margin: 0;
  list-style: none;
}
.ps-mainmenu--mobile .menu__link,
.ps-mainmenu--mobile .menu__title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 0.875rem 1rem;
  font: var(--weight-semibold) var(--text-base) / 1.2 var(--font-body);
  color: var(--text-body);
  text-decoration: none;
  border-bottom: 1px solid var(--hv-gris-100);
  border-left: 3px solid transparent;
}
.ps-mainmenu--mobile .menu__link:hover { color: var(--hv-oceano-600); }
.ps-mainmenu--mobile .current > .menu__link {
  color: var(--hv-oceano-700);
  background: var(--hv-oceano-50);
  border-left-color: var(--hv-oceano-600);
}
.ps-mainmenu--mobile .menu__title {
  font: var(--type-eyebrow);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  border-left-color: transparent;
}
/* Botón para abrir el nivel hijo. Hoy no se pinta porque el catálogo no
   tiene subcategorías, pero en cuanto se creen aparece aquí. */
.ps-mainmenu--mobile .menu__toggle-child {
  display: inline-flex;
  align-items: center;
  padding: 0.5rem;
  color: var(--text-muted);
}

/* Submenú desplegable */
.submenu {
  background: var(--surface-card);
  border: var(--border-card);
  box-shadow: var(--shadow-md);
}
.submenu__left-item,
.ps-mainmenu__tree-dropdown-toggle { color: var(--text-body); }

/* ---- 4. Pie: bloques de módulo como columnas -------------- */
/* ps_linklist, ps_customeraccountlinks y ps_contactinfo pintan los tres
   el patrón .footer-block / __title / __list. Hay que neutralizar su
   retícula de Bootstrap (col-md-6 col-lg-3) para que no pelee con la
   nuestra. */
/* El mockup fijaba 4 columnas (2fr 1fr 1fr 1.2fr), pero el número real de
   columnas lo decide el back office: depende de cuántos módulos estén
   enganchados a displayFooter y de si tienen contenido configurado. Se pasa
   a flex para que la retícula aguante de 1 a 4 columnas sin romperse. */
.hv-footer__inner {
  display: flex;
  flex-wrap: wrap;
  gap: 2.5rem;
}
.hv-footer__brand { flex: 2 1 20rem; }
.hv-footer__inner > .footer-block,
.hv-footer__inner > nav.footer-block,
.hv-footer__inner > section.footer-block {
  flex: 1 1 11rem;
  width: auto;
  max-width: none;
  padding: 0;
  margin: 0;
}

/* Títulos de columna: SIEMPRE en blanco y sin aspecto de enlace.
   Se incluye el `a` descendiente por si algún módulo enlaza su título:
   sin esto heredaría el color de enlace de 05-base.css. */
.hv-footer .footer-block__title,
.hv-footer .footer-block__title a {
  margin: 0 0 1rem;
  font: var(--type-eyebrow);
  color: #fff;
  text-decoration: none;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
}

/* Pie SIEMPRE desplegado, también en móvil.
   El padre lo monta como acordeón: los bloques llevan `collapse` de Bootstrap
   y solo los abre a partir de 768px
   (@media(min-width:768px){.footer-block__content.collapse{display:block}}).
   Aquí se anula en todos los tamaños y se retira el botón de plegado.
   No hace falta !important: `.collapse:not(.show)` de Bootstrap tiene
   especificidad 0,2,0 y este selector 0,4,0. */
.hv-footer .footer-block__content.collapse:not(.show) { display: block; }
.hv-footer .footer-block__title--toggle .stretched-link,
.hv-footer .footer-block__title button { display: none; }

.hv-footer .footer-block__list {
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  padding: 0;
  margin: 0;
  list-style: none;
}
.hv-footer .footer-block__list a,
.hv-footer .footer-block__content a,
.hv-footer li { font: var(--type-small); color: rgb(255 255 255 / 75%); }
.hv-footer .footer-block__list a:hover,
.hv-footer .footer-block__content a:hover { color: #fff; }

.hv-footer__logo { display: block; height: 2.5rem; margin-bottom: 1rem; }
.hv-footer__claim { max-width: 36ch; margin: 0; font: var(--type-small); }
.hv-footer__legal-links { display: flex; gap: 1.25rem; }

/* Franja previa al pie: va A SANGRE.
   Cuelga fuera de .hv-footer (sobre el fondo claro de la página) y sus módulos
   —ps_emailsubscription sobre todo— pintan su propio fondo en el <section> con
   un .container dentro. Por eso aquí no hay ni contenedor ni ancho máximo: la
   plantilla ya no los envuelve en .hv-container, que era lo que recortaba el
   fondo del bloque de newsletter al ancho de la retícula.
   El filete blanco que llevaba antes no se ve sobre fondo claro; se deja solo
   en __modules, que sí está dentro del pie oscuro. */
.hv-footer__before { width: 100%; }
/* El .container del módulo sigue la retícula del sitio: 07-hummingbird.css ya
   le pone el ancho máximo, aquí se iguala el margen lateral al de
   .hv-container (--container-pad) para que el texto case con el resto. */
.hv-footer__before .container { padding-inline: var(--container-pad); }

.hv-footer__modules {
  padding: 1.5rem 0;
  border-bottom: 1px solid rgb(255 255 255 / 15%);
}

/* ---- 5. Migas de pan -------------------------------------- */
/* La plantilla del padre vale tal cual; solo hay que vestirla. */
.breadcrumb__wrapper { padding: 1rem 0; }
.breadcrumb {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding: 0;
  margin: 0;
  font: var(--type-small);
  color: var(--text-muted);
  list-style: none;
  background: none;
}
.breadcrumb-item + .breadcrumb-item::before {
  content: "/";
  padding-right: 0.5rem;
  color: var(--hv-gris-400);
}
.breadcrumb-link { color: var(--text-muted); text-decoration: none; }
.breadcrumb-link:hover { color: var(--text-link); }
.breadcrumb-item:last-child > span { color: var(--text-body); }

/* ---- 6. Contenedor ---------------------------------------- */
/* 07-hummingbird.css ya limita .container a --container-max.
   Aquí solo se igualan los que el padre usa con otro sufijo. */
.container-md,
.container-lg,
.container-xl { max-width: var(--container-max); }

/* ===== src/css/09-home.css ===== */
/* ============================================================
   Harven Surf — Home
   ------------------------------------------------------------
   Las retículas (.hv-grid-cats, .hv-grid-3, .hv-grid-4), el contenedor
   y .hv-section-title ya vienen del design system en 06-components.css.
   Aquí solo van las piezas propias de la home: tarjeta de categoría,
   franja alterna, bloque de condiciones y texto SEO. El hero NO está
   aquí: lo pinta el módulo Creative Slider (layerslider) con su propio
   CSS, enganchado a displayHome desde el back office.
   ============================================================ */

/* ---- Ritmo vertical de las secciones ---------------------- */
.hv-section { padding-block: var(--section-gap); }
.hv-band { background: var(--surface-alt); }

/* ---- Tarjeta de categoría ---------------------------------- */
.hv-cat-card {
  display: block;
  overflow: hidden;
  color: inherit;
  text-decoration: none;
  background: var(--surface-card);
  border: var(--border-card);
  border-radius: var(--radius-md);
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}
.hv-cat-card:hover {
  color: inherit;
  border-color: var(--border-strong);
  box-shadow: var(--shadow-sm);
}
.hv-cat-card:focus-visible { outline: 3px solid var(--border-focus); outline-offset: 2px; }

.hv-cat-card__media {
  display: block;
  aspect-ratio: 16 / 9;
  background: var(--surface-inset);
}
.hv-cat-card__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.hv-cat-card__body { display: block; padding: 0.875rem 1rem; }
.hv-cat-card__name {
  display: block;
  font: var(--type-h3);
  font-weight: var(--weight-display);
  text-transform: uppercase;
  letter-spacing: var(--tracking-display);
}
.hv-cat-card__desc {
  display: block;
  margin-top: 0.125rem;
  font: var(--type-small);
  color: var(--text-muted);
}

/* ---- Condiciones B2B --------------------------------------- */
.hv-feature { display: flex; gap: 1rem; align-items: flex-start; }
.hv-feature__icon { font-size: 1.75rem; color: var(--action-primary); }
.hv-feature__title { margin: 0 0 0.25rem; }
.hv-feature__text { margin: 0; font: var(--type-small); color: var(--text-muted); }

/* ---- Bloque SEO -------------------------------------------- */
.hv-prose { max-width: 78ch; }
.hv-prose p { font: var(--type-small); color: var(--text-muted); }
.hv-prose__actions { display: flex; flex-wrap: wrap; gap: 1rem; margin-top: 1rem; }
.hv-prose__actions a { font: var(--type-label); }

/* ---- Bloque de productos de los módulos nativos ------------ */
/* ps_newproducts / ps_featuredproducts traen su propio título y su
   retícula de Bootstrap. Se les da el tratamiento de sección del
   diseño; la miniatura en sí se maqueta en la Fase 3. */
.hv-band .products,
.hv-band .product-list {
  --bs-gutter-x: var(--grid-gap);
  --bs-gutter-y: var(--grid-gap);
}
.hv-band .section-title,
.hv-band .featured-products__title,
.hv-band h2 {
  margin: 0 0 1.5rem;
}

/* ===== src/css/10-producto.css ===== */
/* ============================================================
   Harven Surf — Ficha de producto
   ------------------------------------------------------------
   Los átomos (.hv-badge, .hv-btn) ya vienen del design system.
   Aquí solo va la cabecera de la ficha (marca, nombre, referencia),
   la fila de disponibilidad y el bloque de precio.
   ============================================================ */

/* ---- Cabecera: marca · nombre · referencia ---------------- */
.hv-product__brand {
  font: var(--type-eyebrow);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
}
.hv-product__brand a { color: inherit; text-decoration: none; }
.hv-product__brand a:hover { color: var(--text-link); }

/* El nombre va en caja normal, no en mayúsculas: es un nombre de
   producto, no un titular de sección. */
.product__name.hv-product__name {
  margin: 0.375rem 0;
  font: var(--type-h2);
  text-transform: none;
  letter-spacing: 0;
}

.hv-product__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1rem;
  font: var(--type-ref);
  color: var(--text-subtle);
}
.hv-product__meta-sep { color: var(--hv-gris-300); }

/* ---- Disponibilidad --------------------------------------- */
/* El padre declara .product__availability como flex-direction:column, así que
   hay que fijar `row` explícitamente: si no, el `align-items:center` de abajo
   centra el badge horizontalmente en vez de alinearlo verticalmente. */
.hv-product__availability {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  align-items: center;
  justify-content: flex-start;
  margin-block: 1rem;
  text-align: left;
}
.hv-product__stock-count { font: var(--type-small); color: var(--text-muted); }
.hv-product__delivery { flex-basis: 100%; font: var(--type-small); color: var(--text-muted); }

/* ---- Acciones ---------------------------------------------- */
/* Cantidad + añadir en la misma fila; el botón se come el resto del
   ancho, como en el mockup. */
.hv-product__actions { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center; }
.hv-product__actions .product__add-to-cart { flex: 1 1 12rem; }
.hv-product__actions .product__add-to-cart-button { width: 100%; }

/* ---- Precio ------------------------------------------------ */
/* El precio de la ficha es el dato principal de una tienda B2B:
   se compone con el token de precio, en tinta. */
.product__prices { margin-block: 1rem; }
.product__price {
  font: var(--weight-bold) var(--text-4xl) / 1.1 var(--font-body);
  color: var(--text-price);
}
.product__regular-price {
  font: var(--type-body);
  color: var(--text-pvpr);
  text-decoration: line-through;
}
.product__tax-infos,
.product__taxless-price,
.hv-product__price-gross {
  font: var(--type-small);
  color: var(--text-muted);
}

/* "sin IVA" junto a la cifra: es la unidad del dato, no una nota al pie */
.hv-product__prices .product__prices-inline {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: baseline;
}
.hv-product__price-note {
  font: var(--type-label);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
}

/* ============================================================
   Miniatura de producto (.hv-pcard)
   ------------------------------------------------------------
   El grueso de .hv-pcard ya viene del design system en
   06-components.css. Aquí solo se encaja dentro de la retícula
   de listado del tema padre y se resuelve lo que el mockup no
   tenía (línea de precio bruto de referencia).
   ============================================================ */

/* El padre pinta las miniaturas dentro de .product-miniature con su
   propia caja; al añadir .hv-pcard hay que neutralizar lo suyo para
   que no se dupliquen bordes ni paddings. */
.hv-pcard.product-miniature {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 0;
}
.hv-pcard.product-miniature .product-miniature__inner { display: contents; }

.hv-pcard__media { position: relative; display: block; }
.hv-pcard__media .product-miniature__image {
  display: block;
  width: 100%;
  height: auto;
}

/* El cuerpo crece para que el pie (badge + añadir) quede alineado
   abajo en todas las tarjetas de una fila, tengan el nombre que tengan. */
.hv-pcard__body { flex: 1; }
.hv-pcard__foot { margin-top: auto; }

.hv-pcard__name { margin: 0; }
.hv-pcard__name a { color: inherit; text-decoration: none; }
.hv-pcard__name a:hover { color: var(--text-link); }

/* Precio bruto de referencia junto al neto */
.hv-pcard__pvpr { white-space: nowrap; }
.hv-pcard__regular {
  font: var(--type-small);
  color: var(--text-pvpr);
  text-decoration: line-through;
}

/* Sin selector de cantidad: el formulario es solo el botón */
.hv-pcard__foot .product-miniature__form { display: flex; margin: 0; }

/* ============================================================
   Fase 3 · puntos 3.7, 3.10, 3.12 y 3.13
   Origen de diseño: ui_kits/tienda-b2b/Producto.jsx
   ============================================================ */

/* ---- 3.7 · Galería 52/48 ----------------------------------- */
/* El padre reparte 48% para la galería y el resto para la compra;
   el mockup usa `.hv-layout-split` (1.1fr 1fr), o sea 52/48 al revés.
   Solo cambia la proporción: la retícula ya es un grid del padre. */
.product__container { grid-template-columns: 52% minmax(0, 1fr); gap: var(--grid-gap); }

/* Portada dentro de una tarjeta cuadrada, como en el mockup. */
.product__carousel {
  overflow: hidden;
  background: #fff;
  border: var(--border-card);
  border-radius: var(--radius-md);
}

.product__carousel .carousel-item img { aspect-ratio: 1 / 1; object-fit: cover; }

/* Cinco miniaturas por fila (el padre pone cuatro). */
.product__thumbnails-list { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 0.75rem; }

.product__thumbnail {
  overflow: hidden;
  border: var(--border-card);
  border-radius: var(--radius-sm);
}

.product__thumbnail img { display: block; width: 100%; aspect-ratio: 1 / 1; object-fit: cover; }
/* La miniatura activa NO se marca: quitado a petición del cliente (2026-08-19).
   ⚠️ El recuadro NO lo ponía este tema, sino el padre, y con `outline` sobre la
   IMAGEN, no con `border` sobre el botón:
     .page-product .product__thumbnail.active .product__thumbnail-image
       { outline: .125rem solid var(--bs-primary) }
   Vive en `@layer ps-pages`, así que basta con apagarlo desde aquí (sin capa)
   y sin `!important`. Se deja `transparent` en vez de `none` para no perder el
   hueco reservado por `outline-offset` y que no baile el tamaño. */
.product__thumbnail.active .product__thumbnail-image { outline-color: transparent; }

/* ---- 3.10 · Tallas como botones ---------------------------- */
.hv-variant { padding: 0; margin: 0 0 1rem; border: none; }

.hv-variant__head {
  display: flex;
  gap: 0.5rem;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 0.5rem;
}

.hv-variant__legend { float: none; width: auto; padding: 0; margin: 0; font: var(--type-label); }
.hv-variant__selected { font: var(--type-small); color: var(--text-muted); }
.hv-variant__options { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.hv-variant__option { position: relative; margin: 0; }

/* El radio sigue existiendo —lleva el estado, el foco y el teclado—,
   solo que su cara visible es el `<label>`. No se usa `display:none`:
   eso lo sacaría del orden de tabulación. */
.hv-variant__input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  overflow: hidden;
  clip-path: inset(50%);
}

.hv-variant__button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 3rem;
  height: 2.75rem;
  padding: 0 0.75rem;
  font: var(--type-label);
  color: var(--text-body);
  cursor: pointer;
  background: #fff;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  transition: background var(--transition-fast), border-color var(--transition-fast);
}

.hv-variant__button:hover { border-color: var(--hv-gris-900); }
.hv-variant__input:checked + .hv-variant__button { color: #fff; background: var(--hv-tinta); border-color: var(--hv-tinta); }
.hv-variant__input:focus-visible + .hv-variant__button { outline: 3px solid var(--border-focus); outline-offset: 2px; }

/* ---- 3.12 · Fila de envío ---------------------------------- */
.hv-product__shipping {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.25rem;
  padding: 0;
  margin: 1rem 0 0;
  font: var(--type-small);
  color: var(--text-muted);
  list-style: none;
}

.hv-product__shipping-item { display: inline-flex; gap: 0.375rem; align-items: center; }
.hv-product__shipping-item .material-icons { font-size: 1.125rem; }

/* ---- 3.13 · Descripción y ficha técnica -------------------- */
/* El mockup las pone una al lado de otra y siempre abiertas; el padre las
   monta como acordeón. Se conserva su marcado entero —de él cuelgan
   `js-product-details` (que el JS repinta al cambiar de combinación) y los
   bloques que enganchan los módulos en `extraContent`— y solo se le quita
   el comportamiento de plegado. */
.product__bottom { grid-template-columns: minmax(0, 1fr); }

.product__accordion {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2rem var(--grid-gap);
  align-items: start;
}

.product__accordion .accordion-item { background: none; border: none; }

/* El botón del acordeón pasa a ser el titular de la sección. */
.product__accordion .accordion-button {
  padding: 0 0 0.75rem;
  font: var(--type-h3);
  color: var(--text-body);
  cursor: default;
  background: none;
  pointer-events: none;
  border-bottom: 1px solid var(--border-default);
  box-shadow: none;
}

.product__accordion .accordion-button::after { display: none; }

/* Siempre desplegado: la especificidad (0,3,0) gana a la de Bootstrap
   `.accordion-collapse.collapse:not(.show)` sin necesidad de `!important`. */
.product__accordion .accordion-collapse.collapse:not(.show) { display: block; }
.product__accordion .accordion-body { padding: 1rem 0 0; }

.product__description { font: var(--type-body); color: var(--text-muted); max-width: 65ch; }

/* Ficha técnica: filas etiqueta/valor separadas por línea, como la tabla
   del mockup. */
.product__accordion .details__list { padding: 0; margin: 0; list-style: none; background: none; }

.product__accordion .details__item {
  display: flex;
  gap: 1rem;
  align-items: baseline;
  justify-content: space-between;
  padding: 0.625rem 0;
  font: var(--type-small);
  border-bottom: 1px solid var(--border-default);
}

.product__accordion .details__title { font-weight: var(--weight-semibold); color: var(--text-body); }
.product__accordion .details__right { color: var(--text-muted); text-align: right; }

/* ---- Responsive de la ficha -------------------------------- */
@media (max-width: 920px) {
  .product__container { grid-template-columns: minmax(0, 1fr); }
  .product__accordion { grid-template-columns: minmax(0, 1fr); gap: 1.5rem; }
}

@media (max-width: 600px) {
  .product__thumbnails-list { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.5rem; }
}

/* ===== src/css/11-catalogo.css ===== */
/* ============================================================
   11 · Catálogo — listado de categoría, marca y búsqueda
   Origen de diseño: ui_kits/tienda-b2b/Categoria.jsx
   ------------------------------------------------------------
   El mockup monta la página con `.hv-layout-side` (grid 260px 1fr).
   Aquí NO se usa esa clase: Hummingbird ya sirve la misma retícula
   con `layout-left-column` (#left-column + #center-column dentro de
   una .row de Bootstrap), y ahí es donde los módulos enganchan sus
   hooks. Reescribir la retícula significaría reescribir el layout y
   perder `displayLeftColumn`. Se ajustan las proporciones y punto.
   ============================================================ */

/* ---------- Retícula de dos columnas ---------- */
/* El mockup fija la columna de filtros en 260px; Bootstrap la deja en
   un 25% que a 1320px se va a ~320px. Se corrige por ancho fijo.
   `.col-lg-3` es `flex:0 0 auto;width:25%` dentro de una capa, así que
   estas reglas sin capa ganan sin `!important`. */
@media (min-width: 992px) {
  .layout-left-column #left-column { flex: 0 0 auto; width: 260px; }
  .layout-left-column #center-column { flex: 1 1 0%; width: auto; max-width: none; }
}

@media (min-width: 768px) and (max-width: 991.98px) {
  .layout-left-column #left-column { flex: 0 0 auto; width: 220px; }
  .layout-left-column #center-column { flex: 1 1 0%; width: auto; max-width: none; }
}

/* Si la columna izquierda se queda sin módulos —pasa en el listado de marca,
   donde no hay facetas— no debe reservar 260px de hueco en blanco. `:empty`
   no vale: el contenedor lleva saltos de línea dentro. */
@media (min-width: 768px) {
  .layout-left-column #left-column:not(:has(*)) { display: none; }
}

/* ⚠️ El mockup pasa a una sola columna a 920px, pero el corte real lo
   manda Bootstrap a 768px: por debajo de ahí `#search_filters_wrapper`
   lleva `.d-none .d-md-block` (que es `!important` en la capa
   `utilities`) y los filtros se sirven en el offcanvas. Mover ese corte
   obligaría a pelear con la cascada por capas para nada: entre 768 y
   920px se ven las dos columnas, con la izquierda a 220px. */

/* ---------- Bloques de la columna izquierda ---------- */
/* `.left-block` la ponen tanto ps_categorytree como ps_facetedsearch.
   Es la tarjeta con borde del mockup. */
.layout-left-column .left-block {
  padding: 0.25rem 1rem 1rem;
  background: #fff;
  border: var(--border-card);
  border-radius: var(--radius-md);
}

.layout-left-column .left-block + .left-block { margin-top: var(--grid-gap); }

.layout-left-column .left-block__title {
  margin: 0;
  padding: 0.75rem 0 0;
  font: var(--type-label);
  color: var(--text-body);
}

.layout-left-column .left-block__title-link { color: inherit; }
.layout-left-column .left-block__title-link:hover { color: var(--text-link-hover); }

/* Árbol de categorías: el mockup no lo lleva (navega por el megamenú),
   pero se conserva porque es un módulo que el cliente puede desenganchar
   desde el back office. Se alinea con el resto de la columna. */
.category-tree__list { padding: 0; margin: 0.5rem 0 0; list-style: none; }
.category-tree__list .category-tree__list { padding-left: 0.75rem; }
.category-tree__item-header { padding: 0.25rem 0; }
.category-tree__item-link { font: var(--type-small); color: var(--text-muted); }
.category-tree__item-link:hover { color: var(--text-link-hover); }

/* ---------- Facetas ---------- */
/* Marcado propio en modules/ps_facetedsearch/…/facets.tpl. Conserva
   `#search-filters`, `data-search-url`, `.js-search-link` y
   `.js-search-filters-clear-all`, que es de lo que tira theme.js. */
.hv-facets__head {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 0 0;
}

.hv-facets__title { font: var(--type-label); color: var(--text-body); }

.hv-facets__clear {
  padding: 0;
  font: var(--type-eyebrow);
  color: var(--text-link);
  cursor: pointer;
  background: none;
  border: none;
}

.hv-facets__clear:hover { color: var(--text-link-hover); text-decoration: underline; }


/* El desplegable lo mueve Bootstrap Collapse (`.accordion-collapse`),
   no JS propio: `.hv-facet__list` solo aporta la retícula interior. */
.hv-facet__list { padding: 0; margin: 0.75rem 0 0; list-style: none; }
.hv-facet__list > li { margin: 0; }
.hv-facet__opt { padding: 0.125rem 0; margin: 0; }
.hv-facet__opt a { flex: 1 1 auto; color: inherit; }
.hv-facet__opt a:hover { color: var(--text-link-hover); }
.hv-facet__opt--active a { font-weight: var(--weight-semibold); color: var(--text-body); }

/* Neutralizar el acordeón de Bootstrap.
   `.accordion-item` y `.accordion-button` traen fondo, bordes, padding y
   una flecha en `::after` que aquí sobran: el chevron es un Material
   Icon dentro del botón, como en FacetGroup.jsx. */
.hv-facet.accordion-item { background: none; border: none; border-bottom: 1px solid var(--border-default); border-radius: 0; }
.hv-facet .accordion-button::after { display: none; }
.hv-facet .accordion-button:not(.collapsed) { color: var(--text-body); background: none; box-shadow: none; }
.hv-facet .accordion-button:focus { box-shadow: none; }
.hv-facet .accordion-body { padding: 0; }
.hv-facet.accordion-item:last-child { border-bottom: none; }

/* La opción: input + etiqueta, con el recuento pegado a la derecha. */
.hv-facet__label {
  display: flex;
  flex: 1 1 auto;
  gap: 0.5rem;
  align-items: center;
  margin: 0;
  font: var(--type-small);
  cursor: pointer;
}

.hv-facet__label .hv-facet__count { margin-left: auto; }

/* Muestra de color / textura de los atributos de tipo color. */
.hv-facet__swatch {
  display: inline-block;
  flex-shrink: 0;
  width: 1rem;
  height: 1rem;
  cursor: pointer;
  background-size: cover;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
}

.hv-facet__swatch.active { outline: 2px solid var(--action-primary); outline-offset: 1px; }

/* Rango de precio: lo pinta jQuery UI desde el módulo. Solo se le da aire. */
.hv-facet__slider { padding: 1rem 0.25rem 0.25rem; }
.hv-facet__slider-values { font: var(--type-small); color: var(--text-muted); text-align: center; }

/* ---------- Filtros activos (chips) ---------- */
/* Van sobre la rejilla, no dentro del aside como en el mockup: el
   contenedor `#js-active-search-filters` lo repinta el ajax de
   PrestaShop desde `catalog/listing/product-list.tpl`, que vive en la
   columna central. Mover el bloque obligaría a reescribir el layout. */
.hv-active-filters { margin: 0 0 1rem; }
.hv-active-filters__list { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; padding: 0; margin: 0; list-style: none; }
.hv-active-filters__title { font: var(--type-eyebrow); color: var(--text-muted); }
.hv-active-filters .hv-chip { text-decoration: none; }

/* ---------- Cabecera de la categoría ---------- */
.hv-cat-header { margin: 0 0 1.25rem; }
.hv-cat-header .page-title-section { margin: 0 0 0.5rem; }
.hv-cat-header__intro { max-width: 70ch; margin: 0; font: var(--type-small); color: var(--text-muted); }
.hv-cat-header__intro p:last-child { margin-bottom: 0; }
.hv-cat-header__cover { margin: 1rem 0 0; }
.hv-cat-header__cover img { border-radius: var(--radius-md); }

/* ---------- Barra superior del listado ---------- */
.hv-listing-top {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1rem;
  align-items: center;
  justify-content: space-between;
  margin: 0 0 1rem;
}

/* ⚠️ El padre monta `.products__selection` como GRID y le pone
   `order: -1` a `.products__sort` para que en móvil el orden salga antes
   que el contador. Aquí la barra es flex y el contador va siempre
   primero, como en el mockup, así que hay que reponer el `order`. */
.hv-listing-top__count { order: 0; font: var(--type-small); color: var(--text-muted); }
.hv-listing-top__tools { display: flex; order: 1; gap: 0.75rem; align-items: center; }

/* El orden sigue siendo el dropdown de Bootstrap del padre (lo abre y
   cierra su propio JS); solo se le da el aspecto del `<select>` del
   mockup, chevron incluido. */
.hv-sort { position: relative; width: 220px; }

.hv-sort__button {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  height: 2.75rem;
  padding: 0 0.75rem 0 1rem;
  font: var(--weight-regular) var(--text-base)/1.5 var(--font-body);
  color: var(--text-body);
  text-align: left;
  cursor: pointer;
  background: #fff;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
}

.hv-sort__button::after { display: none; }  /* el caret triangular de Bootstrap */
.hv-sort__button:hover { border-color: var(--hv-gris-400); }
.hv-sort__button .material-icons { font-size: 1.25rem; color: var(--hv-gris-500); }
.hv-sort__menu { min-width: 100%; }
.hv-sort__item.current { font-weight: var(--weight-semibold); }

/* Botón "Filtrar": solo en móvil. El padre lo oculta a partir de 768px
   con `.products__filter-button{display:none}`, pero esa regla vive en
   una capa y `.hv-btn` (sin capa) la gana, así que había que repetir la
   ocultación aquí. A partir de 768px los filtros ya se ven en columna. */
.hv-listing-top__filter { display: inline-flex; gap: 0.375rem; align-items: center; }

@media (min-width: 768px) {
  .hv-listing-top__filter { display: none; }
}

/* ---------- Rejilla de productos ---------- */
/* `.products` es la clase del padre; se le encaja la retícula `.hv-grid-4`
   del sistema, con SUS breakpoints (1100 / 700), no los de Bootstrap.
   A 1320px de contenedor menos 260px de filtros quedan ~1035px: cuatro
   tarjetas de ~247px, que es el ancho con el que están diseñadas. */
.products {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--grid-gap);
}

@media (max-width: 1100px) { .products { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 920px)  { .layout-left-column .products { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 700px)  { .products { grid-template-columns: repeat(2, 1fr); gap: 1rem; } }

/* ---------- Paginación ---------- */
.hv-pagination__wrap {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1rem;
  align-items: center;
  justify-content: space-between;
  margin-top: 1.75rem;
}

.hv-pagination__summary { font: var(--type-small); color: var(--text-muted); }
.hv-pagination { flex-wrap: wrap; margin: 0 auto; }
.hv-pagination__gap { padding: 0 0.25rem; color: var(--text-subtle); }

/* ---------- Texto SEO inferior ---------- */
.hv-cat-footer {
  max-width: 78ch;
  padding-top: 2rem;
  margin-top: 2.5rem;
  border-top: 1px solid var(--border-default);
}

.hv-cat-footer h2 { font: var(--type-h3); letter-spacing: 0; text-transform: none; }
.hv-cat-footer p { font: var(--type-small); color: var(--text-muted); }
.hv-cat-footer > :last-child { margin-bottom: 0; }

/* ---------- Sin resultados ---------- */
.hv-listing-empty { padding: 3rem 0; text-align: center; }

/* ---------- 3.14 · Listado de marcas ---------- */
/* `catalog/brands.tpl` no se sobrescribe: su marcado ya sirve, solo le
   faltaba la retícula y el aspecto de tarjeta del sistema. */
.brand__list {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--grid-gap);
  padding: 0;
  list-style: none;
}

.brand {
  padding: 1.25rem;
  background: #fff;
  border: var(--border-card);
  border-radius: var(--radius-md);
}

.brand:hover { border-color: var(--hv-gris-400); }
.brand__image { display: flex; align-items: center; justify-content: center; min-height: 4.5rem; }
.brand__img { max-height: 4.5rem; width: auto; }
.brand__title { font: var(--type-label); color: var(--text-body); }
.brand__title:hover { color: var(--text-link-hover); }
.brand__products { font: var(--type-small); color: var(--text-muted); }

@media (max-width: 1100px) { .brand__list { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 700px)  { .brand__list { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } }

/* ===== src/css/12-cuenta.css ===== */
/* ============================================================
   12 · Cuenta y alta B2B
   Origen de diseño: ui_kits/tienda-b2b/Registro.jsx y los componentes
   de formulario del sistema (Input/Select/Checkbox/Alert.jsx).
   ------------------------------------------------------------
   El login, "mi cuenta", direcciones y pedidos NO están en el mockup:
   se construyen con los componentes del sistema, en coherencia con el
   alta, que sí está dibujada.
   ============================================================ */

/* ---------- Campos de formulario ---------- */
/* `_partials/form-fields.tpl` emite las clases del sistema JUNTO a las de
   Bootstrap. Nuestras reglas no llevan capa, así que ganan sin
   `!important`; las de Bootstrap siguen ahí por si algún JS las busca. */
.hv-field { margin-bottom: 1rem; }
.hv-field--hidden { margin: 0; }

/* Bootstrap le mete a `.form-check` un padding-left para su check propio.
   Aquí la casilla es un flex item de verdad, así que sobra. */
.hv-check.form-check { padding-left: 0; }
.hv-check .form-check-input { float: none; margin-left: 0; }
.hv-check--inline { display: inline-flex; margin-right: 1.25rem; }
.hv-radio-group { display: flex; flex-wrap: wrap; gap: 0.5rem 0; }

/* El select nativo se estila desde `.hv-select`; el chevron es un
   Material Icon absoluto dentro de `.hv-select-wrap`. Bootstrap pinta el
   suyo como background-image y hay que quitarlo o salen dos. */
.hv-select-wrap .hv-select { padding-right: 2.25rem; background-image: none; }

.hv-birthday { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.hv-birthday .hv-select { width: auto; min-width: 6rem; flex: 1 1 6rem; }

/* Contraseña: campo + botón de ver/ocultar pegados, sin el input-group
   de Bootstrap por medio. */
/* ⚠️ `.hv-input` lleva `width: 100%`, y como no está en ninguna capa gana
   al `width: 1%` que Bootstrap le pone dentro de un `.input-group`: el
   botón se iba a la línea de abajo. Hay que devolver el ancho flexible y
   prohibir el salto de línea. */
.hv-password { display: flex; flex-wrap: nowrap; align-items: stretch; }
.hv-password .hv-input { flex: 1 1 auto; width: 1%; min-width: 0; border-top-right-radius: 0; border-bottom-right-radius: 0; }

.hv-password__toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  color: var(--text-muted);
  cursor: pointer;
  background: var(--surface-alt);
  border: 1px solid var(--border-strong);
  border-left: none;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  transition: color var(--transition-fast);
}

.hv-password__toggle:hover { color: var(--text-body); }

/* Errores: el bloque general arriba, el de campo pegado a su campo. */
.hv-alert__list { padding-left: 1.25rem; margin: 0.25rem 0 0; }
.hv-form > .hv-alert,
.hv-register .hv-alert { margin-bottom: 1.5rem; }

/* ---------- Formularios ---------- */
.hv-form__title { margin: 0 0 1.25rem; font: var(--type-h3); }

/* Retícula de dos columnas del mockup. Qué campos ocupan el ancho
   completo se decide por `data-field`, que pone `form-fields.tpl`: así no
   hay que cablear el orden de los campos, que lo fija
   `CustomerFormatter` y puede cambiar con la configuración de la tienda. */
.hv-form--grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 1.5rem; }

.hv-form--grid > .hv-field--checkbox,
.hv-form--grid > .hv-field--radio-buttons,
.hv-form--grid > .hv-field--textarea,
.hv-form--grid > .hv-field-wrap,
.hv-form--grid > .hv-field[data-field="email"],
.hv-form--grid > .hv-field[data-field="company"] { grid-column: 1 / -1; }

/* Las casillas de consentimiento van juntas y algo separadas del resto. */
.hv-form--grid > .hv-field--checkbox { margin-bottom: 0.75rem; }
.hv-form--grid > .hv-field--checkbox:first-of-type { margin-top: 0.5rem; }

/* Una sola columna estrecha: es lo que aguanta que el formato de dirección
   cambie con el país. Ver customer/_partials/address-form.tpl. */
.hv-form--stack { max-width: 640px; }
.hv-form--stack ~ .hv-form__actions { max-width: 640px; }

.hv-form__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1rem;
  align-items: center;
  margin-top: 1.5rem;
}

.hv-form__actions--end { justify-content: flex-end; }
.hv-form__link { font: var(--type-small); color: var(--text-muted); }
.hv-form__link:hover { color: var(--text-link-hover); }

/* ---------- Tarjeta y caja lateral ---------- */
.hv-card {
  padding: 1.5rem;
  background: #fff;
  border: var(--border-card);
  border-radius: var(--radius-md);
}

.hv-aside-box {
  display: grid;
  gap: 1rem;
  align-content: start;
  padding: 1.5rem;
  background: var(--surface-alt);
  border-radius: var(--radius-md);
}

.hv-aside-box__title { margin: 0; font: var(--type-h3); letter-spacing: 0; text-transform: none; }
.hv-aside-box__text { margin: 0; font: var(--type-small); color: var(--text-muted); }

.hv-aside-box__foot {
  padding-top: 1rem;
  margin: 0;
  font: var(--type-small);
  color: var(--text-muted);
  border-top: 1px solid var(--border-default);
}

/* ---------- Pasos del alta ("Cómo funciona") ---------- */
.hv-steps { display: grid; gap: 1rem; padding: 0; margin: 0; list-style: none; }
.hv-steps__item { display: flex; gap: 0.75rem; align-items: flex-start; }

.hv-steps__num {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  font: var(--type-label);
  color: #fff;
  background: var(--hv-tinta);
  border-radius: 50%;
}

.hv-steps__title { font: var(--type-label); }
.hv-steps__desc { font: var(--type-small); color: var(--text-muted); }

/* ---------- Login y alta ---------- */
.hv-account-page { padding-bottom: 3rem; }
.hv-register__intro { max-width: 60ch; margin: 0 0 1.5rem; color: var(--text-muted); }

/* El mockup limita el formulario a 640px aunque la columna sea más ancha:
   una línea de formulario de 900px es incómoda de leer y de rellenar. */
.hv-register__form { max-width: 680px; }
.hv-login__form { max-width: 520px; align-self: start; }

/* ---------- Mi cuenta: menú lateral ---------- */
/* La estructura la sirve `customer/page.tpl` del padre (una .row de
   Bootstrap con col-lg-3 + col-lg-9). No se reescribe: ahí es donde
   cuelgan los hooks `displayCustomerAccount`. Solo se reestila. */
.account-menu--sidebar {
  padding: 1rem;
  background: #fff;
  border: var(--border-card);
  border-radius: var(--radius-md);
}

.account-menu__title { margin: 0 0 0.75rem; font: var(--type-label); color: var(--text-muted); }
.account-menu__nav { display: grid; gap: 0.125rem; }

.account-menu__link {
  display: flex;
  gap: 0.625rem;
  align-items: center;
  padding: 0.5rem 0.625rem;
  font: var(--type-small);
  color: var(--text-body);
  border-radius: var(--radius-sm);
  transition: background var(--transition-fast);
}

.account-menu__link:hover { color: var(--text-body); background: var(--hv-gris-100); }
.account-menu__link--active { font-weight: var(--weight-semibold); color: #fff; background: var(--hv-tinta); }
.account-menu__link--active:hover { color: #fff; background: var(--hv-tinta); }
.account-menu__link--signout { margin-top: 0.5rem; color: var(--text-muted); border-top: 1px solid var(--border-default); border-radius: 0; }
.account-menu__icon { font-size: 1.125rem; }

/* Rejilla de accesos de la portada de la cuenta. */
.account-menu--main {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--grid-gap);
}

.account-menu--main .account-menu__link {
  flex-direction: column;
  gap: 0.5rem;
  align-items: flex-start;
  padding: 1.25rem;
  font: var(--type-label);
  border: var(--border-card);
  border-radius: var(--radius-md);
}

.account-menu--main .account-menu__icon { font-size: 1.5rem; color: var(--hv-oceano-600); }
.account-menu--main .account-menu__link--signout { margin-top: 0; border-top: var(--border-card); border-radius: var(--radius-md); }

.account-menu__back { margin-bottom: 1.5rem; }

/* ---------- Direcciones ---------- */
.addresses__list { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--grid-gap); }

.address-card {
  padding: 1.25rem;
  background: #fff;
  border: var(--border-card);
  border-radius: var(--radius-md);
}

.address-card__alias { font: var(--type-label); }
.address-card__content { margin: 0.5rem 0 0; font: var(--type-small); color: var(--text-muted); font-style: normal; }
.address-card__actions { display: flex; gap: 1rem; margin-top: 1rem; font: var(--type-small); }
.address-card__delete { color: var(--hv-error); }

.address-card--add-address {
  display: flex;
  gap: 0.75rem;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  border-style: dashed;
}

.address-card--add-address:hover { color: var(--text-link); border-color: var(--action-primary); }
.address-card__add-text { font: var(--type-label); }

/* ---------- Historial de pedidos ---------- */
.order-history { border: var(--border-card); border-radius: var(--radius-md); overflow: hidden; }
.order-history__header { font: var(--type-eyebrow); color: var(--text-muted); background: var(--surface-alt); }
.order-history__row + .order-history__row { border-top: 1px solid var(--border-default); }
.order-history__cell { font: var(--type-small); }
.order-history__cell--reference { font-family: var(--font-mono); }

/* ---------- Responsive ---------- */
@media (max-width: 920px) {
  .account-menu--main { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 700px) {
  .hv-form--grid { grid-template-columns: 1fr; }
  .addresses__list { grid-template-columns: 1fr; }
}

@media (max-width: 600px) {
  .account-menu--main { grid-template-columns: 1fr; }
  .hv-card, .hv-aside-box { padding: 1.25rem; }
  .hv-form__actions--end { justify-content: stretch; }
  .hv-form__actions--end .hv-btn { width: 100%; }
}

/* ===== src/css/13-compra.css ===== */
/* ============================================================
   13 · Compra — carrito, checkout y confirmación
   Origen de diseño: ui_kits/tienda-b2b/Carrito.jsx y Checkout.jsx
   ------------------------------------------------------------
   En esta tienda el carrito no es una compra sino una SOLICITUD que el
   equipo comercial confirma después: de ahí el vocabulario de las
   plantillas ("Pedido en curso", "Resumen de la solicitud").
   ============================================================ */

/* ---------- Carrito ---------- */
.hv-cart-page { align-items: start; padding-bottom: 3rem; }

/* ⚠️ `min-width: 0` es imprescindible. Una columna `1fr` de grid tiene
   `min-width: auto`, o sea que NO se encoge por debajo del ancho de su
   contenido: la tabla del carrito la ensanchaba y el `overflow-x: auto` de
   `.hv-table-scroll` no llegaba a activarse nunca, desbordando la página
   entera en móvil (medido: viewport 500px, scroll 574px). */
.hv-cart-page > * { min-width: 0; }
.hv-cart-page .page-title-section { margin-bottom: 1.25rem; }

.hv-cart__box {
  background: #fff;
  border: var(--border-card);
  border-radius: var(--radius-md);
}

.hv-carttable { width: 100%; margin: 0; border-collapse: collapse; font: var(--type-small); }
.hv-carttable thead th {
  padding: 0.75rem 1rem;
  font: var(--type-label);
  color: var(--text-body);
  text-align: left;
  background: var(--surface-alt);
}

.hv-carttable__num { text-align: right; }
.hv-carttable td { padding: 0.875rem 1rem; vertical-align: middle; }
.hv-carttable tbody tr + tr td { border-top: 1px solid var(--border-default); }

/* Una línea */
.hv-cartline__product { display: flex; gap: 0.75rem; align-items: center; }

.hv-cartline__media {
  flex-shrink: 0;
  width: 3.5rem;
  height: 3.5rem;
  overflow: hidden;
  background: #fff;
  border: 1px solid var(--hv-gris-100);
  border-radius: var(--radius-sm);
}

.hv-cartline__media img { display: block; width: 100%; height: 100%; object-fit: cover; }
.hv-cartline__info { display: grid; gap: 0.125rem; }

.hv-cartline__brand {
  font: var(--type-eyebrow);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
}

.hv-cartline__name { font-weight: var(--weight-medium); color: var(--text-body); }
.hv-cartline__name:hover { color: var(--text-link-hover); }
.hv-cartline__ref-code { font: var(--type-ref); font-size: 0.6875rem; color: var(--text-subtle); }
.hv-cartline__attr { font: var(--type-eyebrow); font-weight: 400; color: var(--text-muted); }
.hv-cartline__delivery { font: var(--type-eyebrow); font-weight: 400; color: var(--text-muted); }

.hv-cartline__stock { font: var(--type-eyebrow); font-weight: 500; color: var(--text-muted); }
.hv-cartline__stock--in_stock { color: var(--hv-exito); }
.hv-cartline__stock--last_remaining_items,
.hv-cartline__stock--available { color: var(--hv-aviso); }
.hv-cartline__stock--unavailable { color: var(--hv-error); }

/* El selector de cantidad, compacto: `qty-input.tpl` le pone al input
   `.form-control` (ancho 100%) y `.mw-100`, que dentro de una celda de tabla
   lo estira hasta ocupar toda la columna. */
.hv-cartline__qty .quantity-button__group { width: max-content; }
.hv-cartline__qty .quantity-button__group .form-control { width: 3.5rem; text-align: center; }
.hv-cartline__unit-net { font-weight: var(--weight-semibold); white-space: nowrap; }
.hv-cartline__unit-old { display: block; font: var(--type-eyebrow); color: var(--text-pvpr); text-decoration: line-through; }
.hv-cartline__unit-full { display: block; font: var(--type-eyebrow); font-weight: 400; color: var(--text-muted); }
.hv-cartline__total { font-weight: var(--weight-semibold); white-space: nowrap; }
.hv-cartline__actions { width: 1%; text-align: right; }
.hv-cartline__remove { color: var(--text-muted); }
.hv-cartline__remove:hover { color: var(--hv-error); }
.hv-cartline__gift { display: inline-flex; gap: 0.375rem; align-items: center; font: var(--type-small); }

.cart__continue-shopping { margin-top: 1rem; }

/* ---------- Resumen de la solicitud ---------- */
.hv-summary {
  position: sticky;
  top: 1rem;
  padding: 1.5rem;
  background: var(--surface-inset);
  border-radius: var(--radius-md);
}

.hv-summary__title { margin: 0 0 1rem; font: var(--type-h3); letter-spacing: 0; text-transform: none; }
.hv-summary__note { margin: 1rem 0 0; font: var(--type-eyebrow); font-weight: 400; color: var(--text-muted); }

/* Las líneas del resumen las pinta el padre (`cart-summary__line`), tanto
   en el carrito como en el aside del checkout. */
.cart-summary__line {
  display: flex;
  gap: 1rem;
  align-items: baseline;
  justify-content: space-between;
  padding: 0.25rem 0;
  font: var(--type-small);
}

.cart-summary__label { color: var(--text-body); }
.cart-summary__value { white-space: nowrap; }

.cart-summary__total .cart-summary__line--bold {
  padding-top: 0.625rem;
  margin-top: 0.5rem;
  font: var(--type-price);
  font-size: 1.125rem;
  border-top: 1px solid var(--border-strong);
}

.cart-summary__actions { margin-top: 1rem; }
.hv-summary .cart-summary__actions .btn { width: 100%; }

/* ---------- Carrito vacío ---------- */
.hv-cart-empty { padding: 3rem 0 4rem; text-align: center; }
.hv-cart-empty__icon { font-size: 3rem; color: var(--hv-gris-300); }
.hv-cart-empty__title { margin: 1rem 0 0.5rem; }
.hv-cart-empty__text { margin: 0 auto 1.5rem; max-width: 46ch; color: var(--text-muted); }

/* ---------- Checkout ---------- */
/* La navegación superior de pasos del padre se conserva TAL CUAL: es la que
   permite volver a un paso ya hecho.
   ⚠️ No tocar `.checkout-steps__number`. El padre lo apila SOBRE la etiqueta
   (`margin-inline:auto` + `margin-block-end`) y traza la línea que une los
   pasos con `::before`/`::after` a `top: .6875rem`, o sea la mitad exacta de
   su altura de 1.5rem. Cambiarle el tamaño o pasarlo a `inline-flex` deja la
   línea cruzando el texto. */
.checkout-steps__list { padding: 0; margin: 0; list-style: none; }

/* Cada paso, una tarjeta con su número. */
.hv-step {
  margin-bottom: 0.75rem;
  background: #fff;
  border: var(--border-card);
  border-radius: var(--radius-md);
}

.hv-step__head {
  display: flex;
  gap: 0.75rem;
  align-items: center;
  padding: 1rem 1.25rem;
}

.hv-step__num {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  font: var(--type-label);
  color: var(--hv-gris-500);
  background: var(--hv-gris-200);
  border-radius: 50%;
}

.hv-step__num .material-icons { font-size: 1rem; }
.hv-step--current .hv-step__num,
.hv-step.step--current .hv-step__num { color: #fff; background: var(--hv-tinta); }
.hv-step.step--complete .hv-step__num { color: #fff; background: var(--hv-exito); }

/* El título del paso: mismo tamaño abierto o cerrado, para que la tarjeta
   no dé un salto al avanzar. El padre lo pinta como `page-title-section`,
   que es el estilo de un h1 de página y aquí resulta enorme. */
.hv-step__title {
  margin: 0;
  font: var(--type-h4);
  color: var(--text-body);
  text-transform: none;
  letter-spacing: 0;
}

.hv-step__edit { margin-left: auto; font: var(--type-eyebrow); color: var(--text-link); }
.hv-step.step--reachable .hv-step__head { cursor: pointer; }
.hv-step__content { padding: 0 1.25rem 1.25rem; }
.hv-step:not(.step--current) .hv-step__content { padding-bottom: 0; }

/* El aside del checkout reutiliza el resumen del carrito. */
.checkout-grid__aside-wrapper .cart-summary { padding: 0; }

/* ---------- Confirmación ---------- */
.hv-confirm__alert { margin: 1.5rem 0; }
.hv-confirm__text { margin: 0.5rem 0 0; }
.hv-confirm__actions { margin-bottom: 2.5rem; }
.hv-confirm__subtitle { font: var(--type-h3); letter-spacing: 0; text-transform: none; }
.hv-confirm__details { margin-bottom: 2rem; }
.hv-confirm__list { padding-left: 1.25rem; font: var(--type-small); color: var(--text-muted); }

/* ---------- Responsive ---------- */
@media (max-width: 920px) {
  .hv-summary { position: static; }
}

@media (max-width: 700px) and (min-width: 601px) {
  .hv-carttable { min-width: 34rem; }  /* la tabla scrollea dentro de su caja */
}

@media (max-width: 700px) {
  .hv-cart-page .cart-grid__aside { margin-top: 1.5rem; }
}

/* En móvil la tabla deja de ser tabla y cada línea pasa a ser una tarjeta.
   Scrollear en horizontal para llegar al botón de eliminar es una mala
   forma de resolverlo: el dato cabe de sobra si se apila.
   Las cabeceras se ocultan (`thead`) y las etiquetas que hacen falta se
   reponen con `::before` desde `content`, así el HTML sigue siendo una
   tabla correcta para un lector de pantalla. */
@media (max-width: 600px) {
  /* ⚠️ El selector lleva `.hv-table-scroll` delante por necesidad: el design
     system trae `.hv-table-scroll table { min-width: 560px }` (0,1,1) para
     que sus tablas scrolleen, y le ganaba a un `.hv-carttable` a secas
     (0,1,0). Ese era el motivo de que la fila siguiera midiendo 560px con
     un viewport de 500 y el botón de eliminar se saliera de la pantalla.
     También pasa a `display: block`: aquí ya no es una tabla, es una lista
     de tarjetas. */
  .hv-table-scroll .hv-carttable { display: block; min-width: 0; }
  .hv-carttable thead { display: none; }
  .hv-carttable tbody,
  .hv-carttable tr,
  .hv-carttable td { display: block; width: auto; }

  /* La fila pasa a ser una retícula: el producto ocupa el ancho completo y
     debajo van cantidad, precios y el botón de eliminar, que queda pegado a
     la derecha sin recurrir a `float` (con float se salía del recuadro). */
  .hv-carttable tbody tr {
    display: grid;
    grid-template-columns: auto auto auto 1fr;
    gap: 0.75rem 1.25rem;
    align-items: center;
    padding: 1rem;
  }
  .hv-carttable tbody tr + tr { border-top: 1px solid var(--border-default); }
  .hv-carttable tbody tr + tr td { border-top: none; }
  .hv-carttable td { padding: 0; }

  /* ⚠️ Estas reglas llevan el `td` delante a propósito: `.hv-carttable td`
     ya declara `display: block` con especificidad (0,1,1) y ganaría a un
     `.hv-cartline__qty` a secas (0,1,0), dejándolo todo apilado. */
  .hv-carttable td.hv-cartline__ref { grid-column: 1 / -1; }
  .hv-carttable td.hv-cartline__unit,
  .hv-carttable td.hv-cartline__total { text-align: left; }
  .hv-carttable td.hv-cartline__actions { justify-self: end; width: auto; }

  .hv-cartline__unit::before,
  .hv-cartline__total::before {
    display: block;
    font: var(--type-eyebrow);
    font-weight: 400;
    color: var(--text-muted);
  }

  .hv-cartline__unit::before { content: "Precio neto"; }
  .hv-cartline__total::before { content: "Total"; }
}

@media (max-width: 600px) {
  .hv-summary, .hv-step__head { padding-inline: 1rem; }
  .hv-step__content { padding-inline: 1rem; }
}

/* ===== src/css/14-alta-b2b.css ===== */
/* ============================================================
   Harven Surf — Solicitud de alta profesional (módulo b2bregistration)
   ------------------------------------------------------------
   El formulario NO lo genera PrestaShop con {form_field}, sino el módulo
   B2B Registration con plantilla propia. El tema la sustituye
   (themes/hvs/modules/b2bregistration/…), así que el marcado ya es el del
   design system y casi todo lo estila 12-cuenta.css. Aquí va solo lo
   específico de esta pantalla.
   ============================================================ */

/* ---- Retícula y orden --------------------------------------
   Los campos personalizados (Nombre comercial, Tipo de negocio, Teléfono,
   C.P., Provincia y Observaciones) los inyecta el módulo TODOS JUNTOS, en un
   bloque, detrás de los campos nativos. Con `display: contents` ese bloque
   deja de pintar caja y sus hijos pasan a ser celdas de la misma retícula que
   el resto, así que el `order` de cada campo —que es su posición en el back
   office— decide dónde cae. Sin esto, el diseño obligaría a parchear el módulo.
   Recordatorio: `display: contents` NO cambia el árbol del DOM, solo la caja;
   por eso las reglas de abajo no pueden usar el selector `>` desde la retícula. */
.hv-b2b-custom { display: contents; }

/* Campos a ancho completo (correo, observaciones, consentimientos). */
.hv-b2b-grid .hv-field--wide,
.hv-b2b-grid .hv-field--textarea,
.hv-b2b-grid .hv-field--checkbox { grid-column: 1 / -1; }

/* Las casillas van juntas y algo separadas del resto, como en el alta normal. */
.hv-b2b-grid .hv-field--checkbox { margin-bottom: 0.75rem; }
.hv-b2b-grid .hv-field--checkbox:first-of-type { margin-top: 0.5rem; }

/* El envoltorio del consentimiento RGPD no pinta etiqueta propia. */
.hv-b2b-grid .hv-field[data-field="gdpr"]:empty { display: none; }

/* ---- Persona de contacto -----------------------------------
   Una etiqueta, dos casillas: el diseño pide "Nombre y apellidos" en un solo
   campo y el módulo necesita first_name y last_name por separado. */
.hv-namepair { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; }

/* ---- Campos del módulo que conservan clases de Bootstrap ----
   La plantilla del módulo (y su JS) marcan el estado con .form-error/.form-ok
   sobre el padre del campo. Se traduce al lenguaje visual del sistema. */
.hv-b2b-form .form-error .hv-input,
.hv-b2b-form .form-error .hv-select { border-color: var(--hv-error); }

/* ---- Pantalla de solicitud enviada ------------------------- */
.hv-register--enviada { max-width: 720px; padding-block: 1rem 3rem; }
.hv-register--enviada .hv-alert p:last-child { margin-bottom: 0; }
.hv-register__enviada-acciones { margin-top: 1.5rem; }

/* ---- Alta de PrestaShop desviada al alta profesional -------- */
.hv-register--desvio { max-width: 640px; padding-block: 0 3rem; }
.hv-register--desvio .hv-cta-row { margin-top: 1.5rem; }

/* ---- Móvil -------------------------------------------------- */
@media (max-width: 600px) {
  .hv-namepair { grid-template-columns: 1fr; }
}

