/* MiratechSpA — Admin forms (Productos, Envíos, Usuarios: CRUD compartido) */

.upload-zone {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  padding: 36px 20px; text-align: center; border: 1.5px dashed var(--border-default);
  border-radius: 12px; background: var(--surface-sunken); cursor: pointer; color: var(--text-subtle);
  transition: border-color 120ms, background 120ms;
}
.upload-zone:hover { border-color: var(--steel-500); background: var(--surface-accent-soft); }
.upload-zone .lucide, .upload-zone i { width: 30px; height: 30px; }
.upload-zone p { font-size: var(--fs-sm); color: var(--text-body); margin: 0; }
.upload-zone .mono { font-family: var(--font-mono); font-size: var(--fs-2xs); color: var(--text-subtle); }
.upload-zone.small { padding: 20px; }
.upload-zone.small .lucide, .upload-zone.small i { width: 22px; height: 22px; }

.pf-row { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; align-items: start; }
.pf-row.three { grid-template-columns: 1fr 1fr 1fr; }
/* four: para las cards a ancho completo (envío), donde caben los cuatro datos del
   despacho en una sola fila. Colapsa a dos columnas antes que a una. */
.pf-row.four { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1100px) { .pf-row.four { grid-template-columns: 1fr 1fr; } }
/* Toggle vía JS cuando el segundo campo de la fila se oculta entero (ej. RUT solo
   en factura, ver facturacion.js): el primero pasa a ocupar todo el ancho. */
.pf-row.pf-row-solo { grid-template-columns: 1fr; }
.pf-field { display: grid; gap: 7px; margin-bottom: 18px; }
/* [hidden] tiene que ganarle al display:grid de arriba: sin esto, un campo que
   el template o el JS ocultan con el atributo (ej. #campo-unidades-caja cuando
   el producto se vende por unidad) seguía visible — el display de la clase pesa
   igual que el del atributo y se declara después. Mismo problema que ya estaba
   resuelto en .combo-item[hidden] (admin-shell.css). */
.pf-field[hidden] { display: none; }
.pf-field label { font-size: var(--fs-xs); font-weight: var(--fw-semibold); color: var(--text-body); }
.pf-field label .req { color: var(--danger); }
.pf-help { font-size: var(--fs-2xs); color: var(--text-subtle); font-weight: var(--fw-regular); margin-top: -1px; }

.pf-field input,
.pf-field select,
.pf-field textarea {
  width: 100%; padding: 11px 14px; border-radius: var(--radius-md); font: inherit; font-size: var(--fs-sm);
  border: 1.5px solid var(--border-default); background: var(--surface-card); color: var(--text-strong);
  transition: border-color 120ms, box-shadow 120ms;
}
.pf-field input::placeholder, .pf-field textarea::placeholder { color: var(--text-subtle); }
.pf-field input:hover, .pf-field select:hover, .pf-field textarea:hover { border-color: var(--border-strong); }
.pf-field input:focus, .pf-field select:focus, .pf-field textarea:focus {
  outline: none; border-color: var(--focus-ring); box-shadow: var(--shadow-focus);
}
.pf-field textarea { resize: vertical; min-height: 72px; font-family: inherit; }

/* Campo calculado (ej. la unidad de peso que no se está editando): se ve como
   dato de solo lectura, no como un campo roto. */
.pf-field input:disabled {
  background: var(--surface-sunken); color: var(--text-muted);
  border-color: var(--border-subtle); cursor: not-allowed;
}
.pf-field input:disabled:hover { border-color: var(--border-subtle); }

/* Editor TinyMCE: reemplaza in-place el <textarea>, solo calzamos borde/radius con el DS */
.tox-tinymce { border-radius: var(--radius-md) !important; border-color: var(--border-default) !important; }

.pf-field select:not([multiple]) {
  appearance: none; padding-right: 38px; cursor: pointer;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%236B7B88' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 13px center;
}
.pf-field select[multiple] {
  padding: 6px; background-image: none;
}
.pf-field select[multiple] option { padding: 7px 9px; border-radius: 6px; }
.pf-field select[multiple] option:checked { background: var(--surface-brand-soft); color: var(--marine-700); }

/* Estado de error: el input marca su propio borde, no solo el texto de abajo */
.pf-field:has(.form-error) input,
.pf-field:has(.form-error) select,
.pf-field:has(.form-error) textarea {
  border-color: var(--danger);
}
.pf-field:has(.form-error) input:focus,
.pf-field:has(.form-error) select:focus,
.pf-field:has(.form-error) textarea:focus {
  box-shadow: 0 0 0 3px rgba(214,69,69,.16);
}
.form-error {
  display: flex; align-items: center; gap: 5px;
  font-size: var(--fs-2xs); color: var(--red-600); font-weight: var(--fw-medium);
}

/* Checkbox de forms admin (ej. "Zona activa") — switch custom, no el nativo del navegador */
.pf-check { display: inline-flex; align-items: center; gap: 11px; font-weight: var(--fw-medium); font-size: var(--fs-sm); color: var(--text-body); cursor: pointer; }
.pf-check input {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
.pf-check-track {
  position: relative; flex: none; width: 42px; height: 24px; border-radius: 999px;
  background: var(--slate-300); transition: background 160ms;
}
.pf-check-track::after {
  content: ''; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px;
  border-radius: 50%; background: #fff; box-shadow: var(--shadow-sm);
  transition: transform 160ms var(--ease-out, ease);
}
.pf-check input:checked + .pf-check-track { background: var(--steel-500); }
.pf-check input:checked + .pf-check-track::after { transform: translateX(18px); }
.pf-check input:focus-visible + .pf-check-track { box-shadow: var(--shadow-focus); }

/* Radio nativo (ej. unidad de peso g/kg): estilo mínimo sobre el input real,
   no un custom-radio — el navegador ya lo valida/marca bien con :invalid. */
.pf-radio-row { display: flex; gap: 18px; margin-top: 2px; }
.pf-radio {
  display: inline-flex; align-items: center; gap: 8px; font-size: var(--fs-sm);
  font-weight: var(--fw-medium); color: var(--text-body); cursor: pointer;
}
.pf-radio input[type="radio"] { width: 17px; height: 17px; accent-color: var(--steel-500); cursor: pointer; }

@media (max-width: 720px) {
  .pf-row, .pf-row.three, .pf-row.four { grid-template-columns: 1fr; }
}

/* Guardado por card (producto_form.html) */
.adm-section .ord-actions { justify-content: flex-start; align-items: center; }
.card-saved {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--green-600); font-size: var(--fs-xs); font-weight: var(--fw-semibold);
}
.card-saved .lucide, .card-saved i { width: 14px; height: 14px; }

/* Ficha resumen solo-lectura (card_*_vista.html): label estrecho + valor pegado a él */
.adm-kv { display: grid; gap: 0; }
.adm-kv .row {
  display: grid; grid-template-columns: 160px 1fr; align-items: baseline; gap: 20px;
  padding: 11px 0; border-bottom: 1px solid var(--border-subtle);
}
.adm-kv .k {
  color: var(--text-subtle); font-size: var(--fs-2xs); font-weight: var(--fw-medium);
  text-transform: uppercase; letter-spacing: var(--ls-wide);
}
.adm-kv .v { color: var(--text-strong); font-weight: var(--fw-semibold); font-size: var(--fs-sm); }
.adm-kv .v.tipo-v { display: inline-flex; align-items: center; gap: 6px; }
.adm-kv .v.tipo-v svg { width: 15px; height: 15px; color: var(--steel-600); }
.adm-kv .v.empty { color: var(--text-subtle); font-weight: var(--fw-regular); }

/* Descripción + especificaciones (card_descripcion_vista/form): tabs propios,
   independientes de Datos básicos. */
.pd-admin-desc-tabs { display: flex; gap: 24px; border-bottom: 1px solid var(--border-subtle); margin-top: 6px; margin-bottom: 22px; }
.pd-admin-desc-tabs .pd-tab { position: relative; padding: 11px 0; font-size: var(--fs-sm); font-weight: var(--fw-medium); color: var(--text-muted); background: none; border: none; cursor: pointer; }
.pd-admin-desc-tabs .pd-tab.active { color: var(--text-strong); font-weight: var(--fw-bold); }
.pd-admin-desc-tabs .pd-tab.active::after { content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; background: var(--brand-navy); border-radius: 2px; }
.pd-admin-desc-panel { display: none; padding-top: 4px; }
.pd-admin-desc-panel.active { display: block; }
/* Los dos botones "Editar" del header (uno por pestaña, ver
   card_descripcion_vista.html) se alternan con el atributo hidden — sin esto
   .btn (display:inline-flex) le gana y ambos quedan visibles a la vez. Mismo
   problema ya resuelto en .pf-field[hidden] más arriba en este archivo. */
[data-editar-desc][hidden], [data-editar-specs][hidden] { display: none; }

.pd-admin-spec-row {
  display: grid; grid-template-columns: 1fr 1fr auto; gap: 10px; align-items: end;
  margin-bottom: 14px;
}
.pd-admin-spec-list { display: grid; gap: 0; margin-top: 6px; }
.pd-admin-spec-list .row { display: grid; grid-template-columns: 1fr 1fr auto; gap: 10px; align-items: center; padding: 10px 0; border-bottom: 1px solid var(--border-subtle); }
.pd-admin-spec-list .row:last-child { border-bottom: none; }
.pd-admin-spec-list .k { color: var(--text-muted); font-size: var(--fs-sm); }
.pd-admin-spec-list .v { color: var(--text-strong); font-weight: var(--fw-semibold); font-size: var(--fs-sm); }
.pd-admin-spec-empty { color: var(--text-muted); font-size: var(--fs-sm); }

@media (max-width: 640px) {
  .pd-admin-spec-row { grid-template-columns: 1fr; }
  .pd-admin-spec-list .row { grid-template-columns: 1fr; gap: 4px; }
}

/* Estado (vista): aire entre el badge y el texto de ayuda */
#card-estado .st-badge { margin-bottom: 12px; }

/* Aviso "faltan datos para publicar" junto al título de una card (precio-stock,
   estado): mismo tono ámbar que .st-badge.low, sin fondo (va inline en el h2). */
/* Aviso de "falta esto para publicar" en el título del card. display:inline-block
   es lo que lo mantiene en la misma línea que el texto: lucide.createIcons()
   reemplaza el <i> por un <svg>, que por defecto es display:block y saltaba de
   línea dejando el ícono suelto debajo del título. */
.pd-card-alerta {
  display: inline-block; width: 16px; height: 16px;
  color: var(--amber-600); vertical-align: -3px; margin-left: 6px;
}

/* ===== Galería de imágenes (producto_form.html) ===== */
.pd-admin-gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 14px; margin-bottom: 18px; }
.pd-admin-thumb {
  position: relative; border-radius: var(--radius-md); overflow: hidden;
  border: 1px solid var(--border-subtle); background: var(--surface-card); aspect-ratio: 1;
  /* Mismo 6% de aire que la tienda: el admin ve el encuadre real del cliente. */
  padding: 6%;
}
.pd-admin-thumb-zoom { display: block; width: 100%; height: 100%; cursor: zoom-in; }
/* contain y fondo blanco, igual que la tienda: el admin debe ver el mismo encuadre
   que verá el cliente, si no aprueba una foto que después se muestra distinta. */
.pd-admin-thumb-zoom img { width: 100%; height: 100%; object-fit: contain; display: block; background: var(--surface-card); transition: transform 200ms; }
.pd-admin-thumb-zoom:hover img { transform: scale(1.05); }
.pd-admin-thumb-badge {
  position: absolute; top: 8px; left: 8px;
  font-size: var(--fs-2xs); font-weight: var(--fw-semibold); color: #fff;
  background: rgba(27,58,82,.85); padding: 3px 9px; border-radius: 999px;
  pointer-events: none;
}
.pd-admin-thumb-badge--error { background: var(--danger); right: 8px; left: 8px; text-align: center; }
.pd-admin-thumb-zoom[disabled] { cursor: not-allowed; display: flex; align-items: center; justify-content: center; color: var(--danger); }
.pd-admin-thumb-zoom[disabled] i { width: 32px; height: 32px; }
.pd-admin-thumb-actions {
  position: absolute; inset: auto 0 0 0; display: flex; gap: 4px; padding: 8px;
  background: linear-gradient(0deg, rgba(17,42,61,.72), transparent);
}
.pd-admin-thumb-actions form { flex: 1; }
.pd-admin-thumb-actions .btn { width: 100%; padding: 0; height: 30px; }
.pd-admin-thumb-actions .btn.btn-outline { background: rgba(255,255,255,.92); }
.pd-admin-thumb-actions .btn:disabled { opacity: .4; cursor: not-allowed; }

.pd-admin-upload { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.pd-admin-upload .file-drop { max-width: 260px; }

/* ===== Vista previa del carrusel de banners (banners.html) ===== */
/* Sin altura fija: la preview debe mostrar el banner igual que la tienda (completo,
   sin recortar), si no el admin aprueba una imagen que en el sitio se ve distinta. */
.banner-preview { border-radius: var(--radius-md); overflow: hidden; }

/* ===== Lightbox de imagen (clic en miniatura) ===== */
.img-lightbox {
  position: fixed; inset: 0; z-index: 200; display: none;
  align-items: center; justify-content: center; padding: 40px;
  background: rgba(17,42,61,.82); backdrop-filter: blur(3px);
}
.img-lightbox.open { display: flex; }
.img-lightbox img { max-width: 100%; max-height: 100%; border-radius: var(--radius-md); box-shadow: var(--shadow-xl); }
.img-lightbox-close {
  position: absolute; top: 22px; right: 22px; width: 42px; height: 42px; border-radius: 50%;
  background: rgba(255,255,255,.12); color: #fff; display: flex; align-items: center; justify-content: center;
  transition: background 120ms;
}
.img-lightbox-close:hover { background: rgba(255,255,255,.22); }
.img-lightbox-close .lucide, .img-lightbox-close i { width: 20px; height: 20px; }

/* ===== Layout de ficha de producto (dos columnas parejas: identidad+precio-stock+
   presentación | imágenes+estado+medidas; descripción va abajo a ancho completo) ===== */
.pd-detalle-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: start; margin-bottom: 20px; }
.pd-detalle-col { display: grid; gap: 20px; align-content: start; }
.pd-detalle-col > .adm-section, .pd-detalle-col > form { margin-bottom: 0; }
@media (max-width: 960px) { .pd-detalle-grid { grid-template-columns: 1fr; } }

/* Descripción/specs necesitan más aire que la bitácora de al lado (contenido
   rico + tabla de specs vs. una lista compacta de eventos). */
.pd-detalle-grid.pd-detalle-grid-desc { grid-template-columns: 2fr 1fr; }
@media (max-width: 960px) { .pd-detalle-grid.pd-detalle-grid-desc { grid-template-columns: 1fr; } }

/* ===== Bitácora de cambios (card_historial_cambios.html) =====
   Antes era una tabla .inv: con pocas columnas de texto corto se veía como una
   hoja de cálculo perdida en la card, mucho más ancha que alta. Una lista tipo
   línea de tiempo (punto + texto en una sola línea por evento) se lee más
   rápido y ocupa el espacio real que necesita. */
.pd-bitacora { display: grid; gap: 2px; }
.pd-bitacora-item {
  display: grid; grid-template-columns: 15px 1fr auto; gap: 10px; align-items: start;
  padding: 9px 0; border-bottom: 1px solid var(--border-subtle); font-size: var(--fs-sm);
}
/* [hidden] tiene que ganarle al display:grid de arriba: la paginación client-side
   de historial-bitacora.js oculta filas con el atributo, y sin esto quedaban
   igual de visibles (mismo bug ya resuelto en .pf-field[hidden] más arriba). */
.pd-bitacora-item[hidden] { display: none; }
.pd-bitacora-item:last-child { border-bottom: none; }
.pd-bitacora-punto {
  width: 7px; height: 7px; border-radius: 50%; background: var(--steel-400);
  margin-top: 6px; justify-self: center;
}
.pd-bitacora-linea { color: var(--text-body); line-height: 1.5; }
.pd-bitacora-linea b { font-weight: var(--fw-semibold); }
.pd-bitacora-meta { color: var(--text-muted); font-size: var(--fs-xs); margin-top: 1px; }

/* Cabecera de la card con el selector de tamaño de página (5/10), y botón de
   detalle por fila + modal de detalle: ver card_historial_cambios.html y
   historial-bitacora.js (paginación 100% client-side). */
.pd-bitacora-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.pd-bitacora-head h2 { margin: 0; }
.pd-bitacora-tam {
  display: flex; align-items: center; gap: 6px;
  color: var(--text-muted); font-size: var(--fs-xs);
}
.pd-bitacora-tam select {
  border: 1px solid var(--border-default); border-radius: var(--radius-sm);
  padding: 3px 6px; font-size: var(--fs-xs); color: var(--text-body); background: var(--surface-card);
}
.pd-bitacora-detalle {
  width: 26px; height: 26px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%; color: var(--text-subtle); transition: background 120ms, color 120ms;
}
.pd-bitacora-detalle:hover { background: var(--surface-sunken); color: var(--text-strong); }
.pd-bitacora-detalle .lucide, .pd-bitacora-detalle i { width: 15px; height: 15px; }
.pd-bitacora-paginacion {
  display: flex; align-items: center; justify-content: center; gap: 14px;
  margin-top: 14px; font-size: var(--fs-xs); color: var(--text-muted);
}
.pd-bitacora-paginacion .btn { padding: 0 14px; height: 32px; font-size: var(--fs-xs); }
.pd-bitacora-paginacion .btn:disabled { opacity: .45; pointer-events: none; }
.pd-bitacora-modal-meta {
  display: flex; gap: 10px; flex-wrap: wrap; color: var(--text-muted); font-size: var(--fs-xs);
  margin-bottom: 16px;
}
.pd-bitacora-modal-valor {
  color: var(--text-body); font-size: var(--fs-sm); line-height: 1.5;
  background: var(--surface-sunken); border-radius: var(--radius-sm); padding: 8px 10px;
  white-space: pre-wrap; word-break: break-word;
}

/* ===== Modal genérico (ej. crear producto caja) =====
   overflow-y + align-items: flex-start en el contenedor, con margin: auto en el card:
   así el card queda centrado cuando cabe (el auto se reparte arriba/abajo) y, cuando es
   más alto que el viewport, no se recorta por arriba y se puede scrollear hasta el fondo
   (con align-items: center un card alto queda cortado y no llega a los botones). */
.adm-modal {
  position: fixed; inset: 0; z-index: 200; display: none;
  align-items: flex-start; justify-content: center; padding: 20px; overflow-y: auto;
  background: rgba(17,42,61,.55); backdrop-filter: blur(3px);
}
.adm-modal.open { display: flex; }
.adm-modal-card {
  width: 100%; max-width: 460px; margin: auto; background: var(--surface-card);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-xl); padding: 24px;
  max-height: calc(100vh - 40px); overflow-y: auto;
  /* container-type para que las .pf-row de adentro colapsen según el ancho del
     CARD, no del viewport (ver @container más abajo): un modal de 460px con dos
     columnas queda apretado aunque la ventana sea ancha, y al revés, un modal
     .ancho en una ventana de 800px sí tiene espacio para las dos. El breakpoint
     de viewport no sabía distinguir esos dos casos. */
  container-type: inline-size;
}
.adm-modal-card h2 { font-size: var(--fs-md); font-weight: var(--fw-bold); margin-bottom: 6px; }
/* Header con X: el título/ayuda quedan con aire a la derecha para no pasar por
   debajo del botón, que se posiciona flotando en la esquina en vez de ir en el
   flujo — así no empuja el título cuando el texto es largo (ej. "Reemplazar
   documento"). */
.adm-modal-card-head { position: relative; padding-right: 36px; margin-bottom: 20px; }
.adm-modal-card-head h2 { margin-bottom: 4px; }
.adm-modal-card-head .pf-help { margin: 0; }
.adm-modal-close {
  position: absolute; top: -4px; right: -4px; width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%; color: var(--text-subtle); transition: background 120ms, color 120ms;
}
.adm-modal-close:hover { background: var(--surface-sunken); color: var(--text-strong); }
.adm-modal-close .lucide, .adm-modal-close i { width: 18px; height: 18px; }
/* Footer de modal: Cancelar (outline) primero a la izquierda, la acción
   primaria al final a la derecha — orden inverso al de .ord-actions normal
   (paneles de pedido), que no se toca porque lo usan pantallas sin modal. */
.adm-modal-actions { display: flex; justify-content: flex-end; gap: 10px; flex-wrap: wrap; margin-top: 18px; }
.adm-modal-actions .btn { padding: 0 16px; height: 38px; font-size: var(--fs-xs); }
/* Modal "ancho": para forms con muchos campos (crear producto). clamp() se ajusta
   al viewport en vez de un ancho fijo — a 1196px aprovecha la pantalla, a 520px cae
   a 1fr (ver @media abajo) igual que el modal chico. Los otros dos modales
   (caja_modal.html, paso_documento.html) tienen pocos campos y se quedan en 460px:
   estirarlos también se vería ridículo con dos-tres inputs sueltos. */
.adm-modal-card.ancho {
  max-width: min(920px, calc(100vw - 40px));
}
.adm-modal-card.ancho .pf-row { grid-template-columns: 1fr 1fr; }
/* Un input por fila cuando el card mismo queda angosto, sin importar el tamaño
   de la ventana. Reemplaza al @media (max-width: 720px) que había acá: ese medía
   el viewport, así que un modal de 460px en una pantalla grande se quedaba con
   dos columnas apretadas (era justo el caso del modal de crear producto), y no
   había forma de distinguirlo de un .ancho con espacio real.
   560px es el punto donde dos inputs + el gap de 18px dejan de ser cómodos. */
@container (max-width: 560px) {
  .adm-modal-card .pf-row,
  .adm-modal-card.ancho .pf-row,
  .adm-modal-card .pf-row.three,
  .adm-modal-card .pf-row.four { grid-template-columns: 1fr; }
}
@media (max-width: 480px) {
  .adm-modal { padding: 10px; }
  .adm-modal-card { max-height: calc(100vh - 20px); }
  .adm-modal-card.ancho { max-width: calc(100vw - 20px); }
}

/* Confirmación breve tras "Guardar y crear otro" (producto-modal.js). */
.np-aviso {
  position: fixed; bottom: 24px; right: 24px; z-index: 300;
  background: var(--success-soft); color: var(--green-600); border: 1px solid #A9D9C2;
  border-radius: var(--radius-lg); box-shadow: var(--shadow-xl);
  padding: 12px 18px; font-size: var(--fs-sm); font-weight: var(--fw-medium);
}

/* Guía de medida al subir imágenes de producto + aviso si la elegida no es cuadrada
   (la tienda las muestra completas: una foto apaisada queda con espacio a los lados). */
.img-guia {
  display: flex; align-items: flex-start; gap: 9px; margin-bottom: 16px;
  padding: 11px 13px; border-radius: 10px;
  background: var(--surface-accent-soft); border: 1px solid var(--steel-200);
  font-size: var(--fs-xs); line-height: var(--lh-snug); color: var(--text-muted);
}
.img-guia .lucide, .img-guia i { width: 16px; height: 16px; flex: none; margin-top: 1px; color: var(--steel-600); }
.img-guia strong { color: var(--text-strong); font-weight: var(--fw-semibold); }
.img-aviso {
  flex-basis: 100%; margin: 8px 0 0; padding: 10px 12px; border-radius: 9px;
  background: var(--warning-soft); border: 1px solid var(--amber-500);
  color: var(--amber-600); font-size: var(--fs-xs); line-height: var(--lh-snug);
}

/* Buscador de la presentación equivalente (card Presentación). Reemplaza al <select>
   plano: con cientos de productos había que scrollear una lista enorme. */
.busc-input {
  width: 100%; padding: 11px 14px; border-radius: var(--radius-md); font: inherit; font-size: var(--fs-sm);
  border: 1.5px solid var(--border-default); background: var(--surface-card); color: var(--text-strong);
}
.busc-input:focus { outline: none; border-color: var(--focus-ring); box-shadow: var(--shadow-focus); }
.busc-results {
  list-style: none; margin: 8px 0 0; padding: 4px; border-radius: var(--radius-md);
  border: 1.5px solid var(--border-default); background: var(--surface-card);
  max-height: 240px; overflow-y: auto; display: grid; gap: 2px;
}
.busc-result {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 9px 11px; border-radius: 6px; font-size: var(--fs-sm); color: var(--text-body); cursor: pointer;
}
.busc-result:hover { background: var(--surface-brand-soft); color: var(--marine-700); }
.busc-result-sku { font-size: var(--fs-2xs); color: var(--text-subtle); flex: none; }
.busc-result-empty { padding: 10px; font-size: var(--fs-xs); color: var(--text-subtle); }
.busc-chip {
  display: inline-flex; align-items: center; gap: 8px; margin-bottom: 10px;
  padding: 8px 12px; border-radius: var(--radius-pill);
  background: var(--surface-brand-soft); color: var(--marine-700);
  font-size: var(--fs-sm); font-weight: var(--fw-medium);
}
.busc-chip .lucide, .busc-chip i { width: 15px; height: 15px; }
.busc-chip .mono { font-size: var(--fs-2xs); color: var(--text-subtle); }
.busc-chip button { display: inline-flex; color: var(--text-subtle); }
.busc-chip button:hover { color: var(--red-600); }

/* Campo que no aplica por otra opción del formulario (ej. Stock cuando el producto es
   "bajo pedido"): se deja visible pero apagado, así se entiende que existe y por qué no
   se pide, en vez de desaparecer sin explicación. El input ya se ve gris por
   .pf-field input:disabled; acá se apaga el label y se oculta el asterisco de
   obligatorio, que dejaría de ser cierto. El motivo lo escribe el template en .pf-help. */
.pf-field.campo-no-aplica label { color: var(--text-subtle); }
.pf-field.campo-no-aplica label .req { display: none; }

/* Línea de detalle del documento suelto (/gestion/facturacion/): descripción +
   cantidad + precio + botón quitar, sin fila aparte para buscar el producto —
   el campo de descripción ES el buscador (ver comentario en
   facturacion_nueva_form.html), su dropdown de resultados (.busc-results,
   reusado tal cual del buscador de presentación) cuelga debajo anclado a
   .fact-desc-wrap. Columna final angosta en .fact-linea-campos a diferencia
   de .pf-row.four (que reparte todo en partes iguales), porque el botón "x"
   no necesita el mismo ancho que un input. */
.fact-linea { margin-bottom: 14px; padding-bottom: 14px; border-bottom: 1px solid var(--border-subtle); }
.fact-linea:last-child { border-bottom: none; padding-bottom: 0; }
.fact-desc-wrap { position: relative; }
.fact-desc-wrap .busc-results { position: absolute; z-index: 5; top: 100%; left: 0; width: 100%; margin-top: 4px; }
.fact-linea-campos {
  display: grid; grid-template-columns: 2fr 1fr 1fr auto; gap: 12px; align-items: center;
}
/* Angosto: la descripción ocupa toda la fila arriba (con "1 / -1" alcanza,
   grid manda el resto solo a la fila siguiente) y cantidad/precio/botón
   quedan juntos abajo — antes se repartían en un grid de 2 columnas parejas
   y la descripción quedaba cortada a la mitad del ancho, ilegible. */
@media (max-width: 700px) {
  .fact-linea-campos { grid-template-columns: 1fr 1fr auto; }
  .fact-desc-wrap { grid-column: 1 / -1; }
}

/* ===== Documento de factura/boleta en el modal (facturacion_detalle.html,
   facturacion_nueva_revisar.html): un solo bloque .fact-doc, no piezas sueltas
   de .pf-field/table.inv/.ord-totals reusadas fuera de su contexto — acá se
   quiere leer como una factura real, con su propio marco recto (sin los radios
   de card que table.inv trae para verse como listado) uniendo encabezado,
   líneas y totales en una sola pieza visual. */
.fact-doc { border: 1px solid var(--border-default); border-radius: var(--radius-md); overflow: hidden; }

/* Encabezado: folio/fecha + emisor/receptor. Reemplaza el label uppercase de
   .pf-field (vocabulario de formulario editable) por un rótulo de factura:
   mismo tratamiento pequeño y discreto, pero dentro del marco del documento. */
.fact-doc-head { padding: 16px 18px; border-bottom: 1px solid var(--border-default); background: var(--surface-sunken); }
.fact-doc-folio { display: flex; gap: 16px; flex-wrap: wrap; font-size: var(--fs-xs); color: var(--text-muted); margin-bottom: 14px; }
.fact-doc-folio strong { color: var(--text-strong); font-family: var(--font-mono); }
.fact-doc-partes { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.fact-doc-parte-k { font-size: var(--fs-2xs); font-weight: var(--fw-semibold); color: var(--text-subtle); text-transform: uppercase; letter-spacing: var(--ls-wide); margin-bottom: 4px; }
.fact-doc-parte-n { font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--text-strong); line-height: var(--lh-snug); }
.fact-doc-parte-meta { font-family: var(--font-mono); font-size: var(--fs-2xs); color: var(--text-subtle); margin-top: 2px; }
@media (max-width: 560px) { .fact-doc-partes { grid-template-columns: 1fr; } }

/* Líneas: tabla propia, no table.inv — compacta y con grilla vertical + horizontal
   real (celdas separadas en los cuatro lados, look de factura impresa), en vez
   de la fila-tipo-lista del listado de productos. */
.fact-doc-lineas { width: 100%; border-collapse: collapse; }
.fact-doc-lineas th {
  font-family: var(--font-mono); font-size: var(--fs-2xs); font-weight: var(--fw-medium);
  letter-spacing: var(--ls-wide); text-transform: uppercase; color: var(--text-subtle);
  text-align: left; padding: 8px 12px; background: var(--surface-sunken);
  border-bottom: 1px solid var(--border-default);
}
.fact-doc-lineas td { padding: 8px 12px; font-size: var(--fs-sm); color: var(--text-body); border-bottom: 1px solid var(--border-subtle); }
.fact-doc-lineas th.num, .fact-doc-lineas td.num { text-align: right; font-family: var(--font-mono); white-space: nowrap; }
.fact-doc-lineas th + th, .fact-doc-lineas td + td { border-left: 1px solid var(--border-subtle); }
.fact-doc-lineas tbody tr:last-child td { border-bottom: none; }

/* Totales: continuación de la misma pieza, no una sección aparte — mismo fondo
   sunken que el header para que folio/partes y totales enmarquen las líneas.
   Subtotales (Neto/IVA) van compactos y discretos; el Total se separa con su
   propio bloque de mayor peso — antes las tres líneas se leían como una sola
   lista plana, sin distinguir "lo que se suma" de "el resultado". */
.fact-doc-totales { padding: 12px 18px; background: var(--surface-sunken); }
.fact-doc-totales .ord-total-row {
  padding: 5px 0; font-size: var(--fs-xs);
}
.fact-doc-totales .ord-total-row span:last-child { font-family: var(--font-mono); }
.fact-doc-totales .ord-total-row.total {
  margin-top: 10px; padding-top: 14px; border-top: 1.5px solid var(--border-default);
}

/* Header de /gestion/facturacion/: dos botones separados ("Crear boleta"/"Crear
   factura"), cada uno abre su propio modal (#modalNuevaBoleta/#modalNuevaFactura
   en facturacion.html) — no un botón único con un paso de "elegir tipo" dentro
   de un modal compartido. */
.fact-crear-group { display: flex; gap: 10px; }
@media (max-width: 480px) { .fact-crear-group { flex-direction: column; width: 100%; } }

/* Paginador de /gestion/facturacion/: mismo componente visual que .pager del
   catálogo público (templates/catalog/partials/resultados.html), pero copiado acá
   en vez de cargar tienda.css entero en el dashboard — esa hoja trae reglas de la
   tienda pública (grillas de producto, etc.) que no aplican en /gestion/. */
.pager { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px; margin-top: 16px; }
.pager-btn {
  display: inline-grid; place-items: center; min-width: 40px; height: 40px; padding: 0 12px;
  border-radius: 10px; border: 1px solid var(--border-subtle); background: var(--surface-card);
  font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--text-body);
  transition: border-color 120ms, background 120ms, color 120ms;
  /* Son <a> sin href (van solo por hx-get): el navegador no les pone cursor
     pointer automático como a un link real, hay que declararlo a mano. */
  cursor: pointer;
}
.pager-btn i, .pager-btn .lucide { width: 17px; height: 17px; }
@media (hover: hover) and (pointer: fine) {
  a.pager-btn:hover { border-color: var(--steel-300); color: var(--brand-navy); background: var(--surface-sunken); }
}
.pager-btn.is-current { background: var(--brand-navy); border-color: var(--brand-navy); color: #fff; cursor: default; }
.pager-gap { padding: 0 4px; color: var(--text-subtle); font-weight: var(--fw-semibold); }

/* Fila clickeable del listado de /gestion/facturacion/ (abre el modal de detalle):
   cursor y foco visibles, ya que table.inv no marca sus filas como interactivas
   por defecto (las de productos no lo son, ahí el clic va en un botón aparte). */
/* Paginador de /gestion/facturacion/: el link inerte del extremo (ya en la primera o
   última página) queda visible pero sin poder interactuar, en vez de desaparecer. */
.pager-btn.is-disabled { pointer-events: none; cursor: default; }

/* Mientras se carga la página pedida (hx-indicator apunta a #fact-tabla-carga,
   que htmx marca .htmx-request durante la petición): todo el paginador se
   deshabilita, así un segundo clic no dispara otra página a mitad de la primera. */
#fact-tabla-carga.htmx-request + .pager { pointer-events: none; opacity: .6; cursor: wait; }

/* Tabla de /gestion/facturacion/ mientras el paginador recarga por HTMX (hx-indicator
   apunta acá): se atenúa la que ya está en pantalla en vez de vaciarla, así el
   usuario ve que algo está pasando sin un salto en blanco a mitad de carga. */
#fact-tabla-carga.htmx-request { opacity: .5; pointer-events: none; }

/* ===== Modal "Prompt IA" (/gestion/banners/) ===== */
/* Textarea readonly con look de bloque de código: se selecciona/copia entero,
   no se edita ahí (el ajuste, si hace falta, se hace en la propia herramienta
   de IA al pegar el prompt). */
.ia-prompt-texto {
  width: 100%; padding: 14px 16px; border-radius: var(--radius-md);
  border: 1.5px solid var(--border-default); background: var(--surface-sunken);
  color: var(--text-body); font-family: var(--font-mono); font-size: var(--fs-xs);
  line-height: var(--lh-relaxed); resize: vertical; margin-bottom: 10px;
}
.ia-prompt-texto:focus { outline: none; border-color: var(--focus-ring); box-shadow: var(--shadow-focus); }

/* Guía visual ✅/❌: dos columnas que se leen como una comparación directa,
   para juzgar el resultado de la IA de un vistazo antes de subirlo. */
.ia-prompt-guia { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.ia-prompt-ok, .ia-prompt-mal { list-style: none; margin: 0; padding: 14px 16px; border-radius: var(--radius-md); display: grid; gap: 8px; }
.ia-prompt-ok { background: var(--success-soft); }
.ia-prompt-mal { background: var(--danger-soft); }
.ia-prompt-ok li, .ia-prompt-mal li { display: flex; align-items: flex-start; gap: 8px; font-size: var(--fs-xs); line-height: var(--lh-snug); }
.ia-prompt-ok li { color: var(--green-600); }
.ia-prompt-mal li { color: var(--red-600); }
.ia-prompt-ok li::before { content: '✓'; font-weight: var(--fw-bold); flex: none; }
.ia-prompt-mal li::before { content: '✕'; font-weight: var(--fw-bold); flex: none; }
@media (max-width: 640px) { .ia-prompt-guia { grid-template-columns: 1fr; } }
