:root {
  --bg: #f7f7f8;
  --card: #ffffff;
  --text: #1c1c1e;
  --muted: #6b7280;
  --border: #e5e7eb;
  --accent: #2563eb;
  --accent-text: #ffffff;
  --danger: #dc2626;
  --danger-text: #ffffff;
  --ok: #16a34a;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #111113;
    --card: #1c1c1f;
    --text: #f2f2f3;
    --muted: #9ca3af;
    --border: #2e2e33;
    --accent: #3b82f6;
    --accent-text: #ffffff;
    --danger: #ef4444;
    --danger-text: #111113;
    --ok: #22c55e;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  line-height: 1.4;
}

.contenedor {
  max-width: 640px;
  margin: 0 auto;
  padding: 16px;
}

header.app {
  padding: 16px;
  text-align: center;
  border-bottom: 1px solid var(--border);
}

header.app h1 {
  font-size: 1.1rem;
  margin: 0;
}

.progreso {
  text-align: center;
  color: var(--muted);
  font-size: 0.9rem;
  margin: 8px 0 16px;
}

.pie-contacto {
  text-align: center;
  color: var(--muted);
  font-size: 0.85rem;
  margin: 24px 0 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

.pie-contacto a {
  color: inherit;
  text-decoration: underline;
}

.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 16px;
  margin-bottom: 16px;
}

.card h2 {
  font-size: 1rem;
  margin: 0 0 12px;
}

.nombre-archivo {
  font-weight: 600;
  word-break: break-word;
  margin-bottom: 4px;
}

.fila-nombre-archivo {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
}

.btn-ignorar-archivo {
  flex: none;
  padding: 6px 12px;
  border-radius: 8px;
  border: 1px solid var(--muted);
  background: var(--card);
  color: var(--muted);
  font-size: 0.8rem;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
  cursor: pointer;
}

.btn-ignorar-archivo.activo {
  border-color: var(--danger);
  background: var(--danger);
  color: #fff;
}

.campo {
  margin-bottom: 12px;
}

.campo label {
  display: block;
  font-size: 0.85rem;
  color: var(--muted);
  margin-bottom: 4px;
}

.stepper {
  display: flex;
  align-items: center;
  gap: 12px;
}

.stepper-btn {
  flex: none;
  width: 44px;
  height: 44px;
  padding: 0;
  font-size: 1.3rem;
  line-height: 1;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--text);
  cursor: pointer;
}

.stepper-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.stepper-valor {
  min-width: 2ch;
  text-align: center;
  font-size: 1.1rem;
  font-weight: 600;
}

.boton-ingresar-cantidad {
  margin-top: 8px;
  padding: 8px 12px;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--accent);
  background: var(--card);
  border: 1px solid var(--accent);
  border-radius: 8px;
  cursor: pointer;
}

.sheet-cantidad {
  padding: 16px;
}

.input-cantidad {
  width: 100%;
  padding: 12px;
  font-size: 1.1rem;
  text-align: center;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--text);
}

[x-cloak] {
  display: none !important;
}

/* Segmented control: todas las opciones visibles de entrada, un tap para
   elegir. Para Tamaño/Faz/Disposición/Calidad — sets chicos donde tiene
   sentido ver todo de una en vez de abrir algo. */
.segmented {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.segmented-opt {
  flex: 1 1 auto;
  min-width: max-content;
  padding: 10px 14px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--text);
  font-size: 0.9rem;
  cursor: pointer;
  text-align: center;
}

.segmented-opt.selected {
  background: var(--accent);
  color: var(--accent-text);
  border-color: var(--accent);
  font-weight: 600;
}

/* Selector "valor actual + Cambiar" que abre una bottom sheet — para Papel y
   Encuadernado, donde puede haber muchas opciones y conviene verlas en una
   lista grande y tocable en vez de un <select> nativo diminuto. */
.campo-bottom-sheet {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  padding: 12px 14px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--text);
  font-size: 0.95rem;
  font-weight: 600;
  cursor: pointer;
}

.campo-bottom-sheet .cambiar {
  color: var(--accent);
  font-weight: 400;
  font-size: 0.85rem;
  flex: none;
}

.sheet-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: flex-end;
  z-index: 50;
}

.sheet {
  width: 100%;
  max-height: 70vh;
  background: var(--card);
  border-radius: 16px 16px 0 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.sheet-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
  font-weight: 600;
  flex: none;
}

.sheet-header button {
  flex: none;
  width: auto;
  padding: 2px 8px;
  border: none;
  background: none;
  color: var(--muted);
  font-size: 1.2rem;
  cursor: pointer;
}

.sheet-opciones {
  overflow-y: auto;
  padding: 6px;
}

.sheet-opcion {
  display: block;
  width: 100%;
  text-align: left;
  padding: 14px 12px;
  border: none;
  border-bottom: 1px solid var(--border);
  background: var(--card);
  color: var(--text);
  font-size: 1rem;
  cursor: pointer;
}

.sheet-opcion:last-child {
  border-bottom: none;
}

.sheet-opcion.selected {
  color: var(--accent);
  font-weight: 600;
}

.sheet-opcion.selected::after {
  content: " ✓";
}

.precio {
  text-align: center;
  font-size: 1.4rem;
  font-weight: 700;
  margin: 12px 0;
}

.precio small {
  display: block;
  font-size: 0.75rem;
  color: var(--muted);
  font-weight: 400;
}

/* Total del pedido mostrado junto al precio de cada archivo mientras se edita
   (wizard) — secundario respecto del precio del archivo actual, que es lo que
   se está tocando en esa pantalla. */
.precio-total {
  font-size: 1rem;
  font-weight: 600;
  color: var(--muted);
  margin-top: -4px;
}

.preview-hojas {
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: wrap;
  margin: 12px 0;
}

.hoja {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px;
  background: var(--bg);
}

/* Tarjeta que gira sola en loop mostrando anverso y reverso, como si diera
   vuelta la hoja. Solo CSS — dos caras superpuestas, la de atrás pre-rotada
   180° y con backface-visibility:hidden para que no se vea "al revés". */
.hoja-flip {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  perspective: 900px;
}

/* Rótulo "Hoja N" — a propósito hermano de .hoja-flip-inner (no adentro):
   así queda fuera de la 3D/animación, quieto, debajo de la tarjeta. Distinto
   del badge "Página N" (ver .hoja-pagina-badge), que sí gira con cada cara. */
.hoja-flip-caption {
  text-align: center;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--muted);
  margin-top: 8px;
}

.hoja-flip-inner {
  position: relative;
  width: 100%;
  transform-style: preserve-3d;
  animation: hoja-flip-loop 6s ease-in-out infinite;
}

.hoja-cara {
  backface-visibility: hidden;
  width: 100%;
  box-sizing: border-box;
}

.hoja-frente {
  position: relative;
}

.hoja-dorso {
  position: absolute;
  top: 0;
  left: 0;
  transform: rotateY(180deg);
}

/* Overlay "Página N" — a propósito ADENTRO de cada cara (.hoja-frente /
   .hoja-dorso), así gira junto con la hoja y cada cara muestra la página que
   realmente le toca (ej. "Página 1" en el anverso, "Página 2" en el reverso
   al dar la vuelta). El pre-rotado de .hoja-dorso ya se encarga de que el
   texto no quede espejado cuando esa cara mira al usuario. Pegado al borde
   inferior de la hoja, centrado. */
.hoja-pagina-badge {
  position: absolute;
  bottom: 6px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--accent);
  color: var(--accent-text);
  font-size: 0.65rem;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 999px;
  white-space: nowrap;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
  z-index: 5;
}

@keyframes hoja-flip-loop {
  0%, 38% { transform: rotateY(0deg); }
  50%, 88% { transform: rotateY(180deg); }
  100% { transform: rotateY(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .hoja-flip-inner,
  .folleto-flip-inner,
  .folleto-mitad-izq,
  .folleto-mitad-der,
  .folleto-mitad-cierre-inner,
  .a5-tijera {
    animation: none;
  }
}

.hoja .etiqueta {
  text-align: center;
  font-size: 0.75rem;
  color: var(--muted);
  margin-bottom: 4px;
}

.hoja-grid {
  display: grid;
  gap: 3px;
}

.hoja-grid.pph-1 { grid-template-columns: 1fr; }
.hoja-grid.pph-2 { grid-template-columns: 1fr 1fr; }
.hoja-grid.pph-4 { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; }

.hoja-grid img {
  width: 100%;
  aspect-ratio: 3/4;
  object-fit: contain;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 3px;
}

/* Hoja en blanco (reverso de simple faz, o página que no existe) — SIEMPRE
   blanco de verdad, no var(--card): en tema oscuro var(--card) es casi negro,
   y una hoja en blanco no puede verse negra. */
.celda-vacia {
  width: 100%;
  aspect-ratio: 3/4;
  background: #ffffff;
  border: 1px solid var(--border);
  border-radius: 3px;
}

.preview-no-disponible {
  display: flex;
  justify-content: center;
  margin: 12px 0;
}

.preview-no-disponible-celda {
  width: 160px;
  max-width: 60%;
  aspect-ratio: 3/4;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 12px;
  border: 2px dashed var(--border);
  border-radius: 8px;
  background: var(--bg);
  color: var(--muted);
  font-size: 0.8rem;
}

/* Preview de folleto/A5: primera hoja física. Dos animaciones en loop
   continuo (alternate, para que la reversa quede prolija sin escribir un
   segundo juego de keyframes):
   - .folleto-flip-inner gira toda la hoja UNA vez (anverso → reverso) y se
     queda ahí (folleto-flip-loop, misma para folleto y A5) — lo que sea que
     "termina" la animación pasa mostrando el reverso, sin volver a mostrar
     el anverso plano antes.
   - Folleto: .folleto-mitad-cierre (mitad izquierda DEL REVERSO) es una
     tarjetita de dos caras — frente=página de adentro (reverso.izquierda),
     dorso=la MISMA página que ya se ve en anverso.derecha — que gira sobre
     su propio lomo, revelando esa página como si el folleto se cerrara
     ahí mismo (ver folleto-cierre-loop).
   - A5: .folleto-mitad-izq/-der (esta vez EN EL REVERSO, no en el anverso)
     se separan en línea recta después de que pasa la tijera (ver
     .a5-tijera / folleto-corte-tijera / folleto-corte-separar-izq/der),
     simulando el corte al medio de la hoja. */
.folleto-flip {
  position: relative;
  width: 100%;
  perspective: 900px;
  margin: 0 auto;
}

.folleto-flip-inner {
  position: relative;
  width: 100%;
  transform-style: preserve-3d;
  animation: folleto-flip-loop 9s ease-in-out infinite alternate;
}

/* Sin transform-style:preserve-3d acá a propósito: combinado con
   backface-visibility:hidden en el mismo elemento, anidado dentro de otro
   preserve-3d (.folleto-flip-inner), Chrome deja de ocultar bien la cara de
   atrás (se ve el reverso espejado incluso con el anverso al frente). El
   preserve-3d que necesita el plegado nested vive en .folleto-mitades, no
   hace falta acá también. */
.folleto-cara {
  backface-visibility: hidden;
  width: 100%;
  box-sizing: border-box;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px;
  background: var(--bg);
}

.folleto-anverso {
  position: relative;
}

.folleto-reverso {
  position: absolute;
  top: 0;
  left: 0;
  transform: rotateY(180deg);
}

.folleto-mitades {
  position: relative;
  display: flex;
  gap: 4px;
  transform-style: preserve-3d;
  /* perspective PROPIA acá, no solo la de .folleto-flip: .folleto-cara (el
     padre) es flat a propósito (ver su comentario — así se soluciona el bug
     de backface-visibility de Chrome), pero eso "aplana" el pliegue en V de
     más abajo si no le da su propia cámara 3D — sin esto, rotateY() en
     .folleto-mitad-izq/der se pinta como un simple scaleX en vez de un
     trapecio con profundidad real, y nunca se llega a ver la V. */
  perspective: 700px;
}

/* Línea de lomo fija (no animada) al medio del spread — marca dónde se
   pliega (folleto) o se corta (A5) la hoja. En folleto y A5 por igual, y en
   las dos caras (anverso y reverso): es donde va el lomo tanto si el
   documento está mostrando el frente como si ya dio vuelta. */
.folleto-flip .folleto-mitades::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  border-left: 2px dashed var(--muted);
  pointer-events: none;
  z-index: 4;
}

.a5-tijera {
  position: absolute;
  left: 50%;
  top: 0;
  font-size: 1.1rem;
  line-height: 1;
  z-index: 6;
  pointer-events: none;
  animation: folleto-corte-tijera 9s ease-in-out infinite alternate;
}

.folleto-mitad {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
}

/* .celda-vacia NO entra acá (aparte, sin background propio): la regla
   general de más arriba ya la deja siempre blanca de verdad, ni siquiera
   var(--card) — ver el comentario de esa regla. Si se suma esta clase
   después con background:var(--card) le gana por especificidad y una hoja
   en blanco vuelve a verse negra en tema oscuro (pasó una vez, ver commit). */
.folleto-mitad img {
  width: 100%;
  aspect-ratio: 3/4;
  object-fit: contain;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 3px;
}

/* .folleto-mitad-izq/-der en sí no necesitan estilo propio para folleto —
   quedan quietas (folleto ya no se pliega en el anverso, ver más arriba).
   Las clases se mantienen en el HTML solo para que A5 las pueda targetear
   más abajo (más específico, .folleto-flip.corte …), sin tocar el anverso
   de folleto. */
.folleto-flip.corte .folleto-mitad-izq {
  animation: folleto-corte-separar-izq 9s ease-in-out infinite alternate;
}

.folleto-flip.corte .folleto-mitad-der {
  animation: folleto-corte-separar-der 9s ease-in-out infinite alternate;
}

/* Mitad IZQUIERDA del REVERSO en folleto: tarjetita de dos caras (reusa
   .hoja-cara/.hoja-frente/.hoja-dorso, mismo mecanismo que .hoja-flip) que
   gira sobre su borde INTERNO (el lomo — su borde derecho, no el centro de
   la propia página) para "cerrar". Pivotar ahí en vez de en el centro no es
   solo estético: la rotación desplaza sola el borde lejano (el izquierdo)
   hasta la posición de la mitad derecha — por eso termina solapando/
   tapando la página del reverso ahí, sin necesitar un translate aparte.

   Tres ajustes hicieron falta para que esa tapada se vea bien, los tres
   comprobados a mano:
   - transform-style:preserve-3d ACÁ (el wrapper), no solo en
     .folleto-mitades y en .folleto-mitad-cierre-inner: sin esto acá, el
     giro de -inner se pinta aplanado (un simple escalado, sin la
     profundidad real) — mismo bug que ya habíamos encontrado y resuelto en
     .folleto-mitades, pero acá en el nivel de adentro. Con esto puesto se
     ve bien la sensación de "levantarse" del borde que gira, igual que en
     .hoja-flip.
   - 178° y no 180° exactos en folleto-cierre-loop (ver más abajo): justo
     en 180 la profundidad 3D del borde que se desplaza vuelve a 0 (empata
     con el plano de la mitad derecha), y ahí el orden de pintado de la
     miniatura no es confiable. Con 2° de menos queda una profundidad real,
     chiquita pero inequívoca, hacia el espectador — el signo (178 y no
     182) importa: es el que corresponde UNA VEZ que este wrapper ya tiene
     preserve-3d puesto (con preserve-3d era al revés).
   - z-index acá Y en la mitad derecha estática (más abajo): el badge es
     position:absolute con su propio z-index, un elemento aparte de la
     miniatura — la profundidad 3D de arriba no alcanza para ordenarlo
     bien solo, hace falta que las DOS mitades tengan z-index explícito
     (no solo esta) para que la comparación entre ambas sea inequívoca en
     vez de caer en "gana el que está después en el HTML". */
.folleto-mitad-cierre {
  transform-style: preserve-3d;
  z-index: 5;
}

.folleto-reverso .folleto-mitad:not(.folleto-mitad-cierre) {
  z-index: 1;
}

.folleto-mitad-cierre-inner {
  position: relative;
  width: 100%;
  transform-style: preserve-3d;
  transform-origin: 100% 50%;
  animation: folleto-cierre-loop 9s ease-in-out infinite alternate;
}

@keyframes folleto-flip-loop {
  0%, 16% { transform: rotateY(0deg); }
  24%, 100% { transform: rotateY(180deg); }
}

@keyframes folleto-cierre-loop {
  0%, 44% { transform: rotateY(0deg); }
  /* 178deg, no 180deg exactos: justo en 180 la profundidad 3D del borde que
     se desplaza vuelve a 0 (empata con el plano de la mitad derecha,
     estática), y ahí el orden de pintado dentro de un contexto preserve-3d
     no es confiable (ni con z-index) — con 2° menos queda una profundidad
     real, chiquita pero inequívoca, hacia el espectador, así el navegador
     ordena bien sin ambigüedad y la página 1 pinta arriba de la 3 sí o sí.
     (Antes era 182° — pero eso era con .folleto-mitad-cierre SIN
     preserve-3d, que aplanaba el giro; al agregarle preserve-3d para que
     se vea la profundidad real del giro — ver ese selector más abajo — el
     sentido que gana el empate se invirtió, así que pasó a ser 178°.) */
  70%, 100% { transform: rotateY(178deg); }
}

/* Timing pensado igual que folleto-cierre-loop (mismos puntos 44%/70%) para
   que folleto y A5 se sientan parte de la misma familia: reverso se
   asienta en 180° a los 24% (folleto-flip-loop) y se queda quieto hasta
   44%, ahí pasa la tijera (44-58%), y de 58 a 70% las mitades se separan,
   quedando así hasta el final del ciclo. */
@keyframes folleto-corte-tijera {
  0%, 40% { opacity: 0; transform: translate(-50%, -12%); }
  44% { opacity: 1; transform: translate(-50%, -12%); }
  58% { opacity: 1; transform: translate(-50%, 104%); }
  62%, 100% { opacity: 0; transform: translate(-50%, 104%); }
}

@keyframes folleto-corte-separar-izq {
  0%, 58% { transform: translateX(0) rotate(0deg); }
  70%, 100% { transform: translateX(-14px) rotate(-3deg); }
}

@keyframes folleto-corte-separar-der {
  0%, 58% { transform: translateX(0) rotate(0deg); }
  70%, 100% { transform: translateX(14px) rotate(3deg); }
}

.aviso {
  font-size: 0.8rem;
  color: var(--muted);
  text-align: center;
  margin: 4px 0 12px;
}

.miniatura-zoomable {
  cursor: zoom-in;
}

.preview-hojas.zoomable {
  cursor: zoom-in;
}

.zoom-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.75);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
  padding: 24px;
  box-sizing: border-box;
}

.zoom-overlay-activo {
  opacity: 1;
  pointer-events: auto;
}

.zoom-content {
  display: flex;
  gap: 24px;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  max-width: 100%;
  max-height: 100%;
  cursor: zoom-out;
  transform: scale(0.85);
  transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.zoom-overlay-activo .zoom-content {
  transform: scale(1);
}

.zoom-img-simple {
  max-width: 90vw;
  max-height: 85vh;
  border-radius: 8px;
  background: var(--card);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.5);
}

/* Vista previa de hoja(s) clonada adentro del zoom, más grande — la animación
   de dar vuelta (hoja-flip-loop) sigue corriendo en el clon, no hace falta
   nada especial para eso. */
.zoom-grande.preview-hojas {
  margin: 0;
}

.zoom-grande .hoja-flip,
.zoom-grande .hoja {
  /* Igual que .zoom-grande.folleto-flip: la base ya es responsive (ocupa el
     ancho disponible de la tarjeta), así que el zoom necesita un tamaño que
     siga siendo más grande que eso en la mayoría de los casos, sin
     desbordar la pantalla — puede haber hasta 2 hojas lado a lado acá. */
  width: min(85vw, 300px);
}

/* .folleto-flip lleva el mismo id que .preview-hojas (es el propio nodo
   clonado), así que acá "zoom-grande" cae en el MISMO elemento — selector
   compuesto, sin espacio — a diferencia de .hoja-flip, que es descendiente
   del nodo clonado (.preview-hojas). */
.zoom-grande.folleto-flip {
  /* La base ya ocupa el ancho de la tarjeta (hasta ~600px en desktop), así
     que acá no alcanza un valor fijo chico — tiene que quedar más grande
     que eso siempre. min(vw, px) para que en el celular use casi toda la
     pantalla y en desktop no crezca sin límite. */
  width: min(92vw, 560px);
  filter: drop-shadow(0 12px 30px rgba(0, 0, 0, 0.5));
}

.zoom-grande .hoja-flip {
  filter: drop-shadow(0 12px 30px rgba(0, 0, 0, 0.5));
}

.zoom-grande .folleto-mitades {
  gap: 6px;
}

.zoom-grande .a5-tijera {
  font-size: 1.8rem;
}

.zoom-grande .hoja-pagina-badge {
  font-size: 0.8rem;
  padding: 3px 12px;
  bottom: 10px;
}

.zoom-grande .hoja-flip-caption {
  font-size: 0.9rem;
  margin-top: 12px;
}

@media (prefers-reduced-motion: reduce) {
  .zoom-overlay, .zoom-content {
    transition: none;
  }
}


.nav-botones {
  display: flex;
  gap: 8px;
  margin-top: 16px;
}

.nav-botones .grupo-principal {
  display: flex;
  gap: 8px;
  flex: 1;
}

button, .boton {
  font-size: 0.95rem;
  padding: 12px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--text);
  cursor: pointer;
  flex: 1;
  text-align: center;
  text-decoration: none;
}

button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.boton-primario {
  background: var(--accent);
  color: var(--accent-text);
  border-color: var(--accent);
}

.boton-peligro {
  background: transparent;
  color: var(--danger);
  border-color: var(--danger);
  flex: none;
  width: auto;
  padding: 12px 16px;
}

.acciones-finales {
  display: flex;
  gap: 8px;
  margin-top: 8px;
}

.notas-cliente {
  margin: 16px 0 12px;
}

.notas-cliente textarea {
  width: 100%;
  min-height: 96px;
  resize: vertical;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--card);
  color: var(--text);
  font: inherit;
}

.notas-cliente textarea:focus {
  border-color: var(--accent);
  outline: 2px solid color-mix(in srgb, var(--accent) 25%, transparent);
  outline-offset: 1px;
}

.centro {
  text-align: center;
  padding: 40px 16px;
}

.centro h1 {
  font-size: 1.3rem;
}

.centro p {
  color: var(--muted);
}

.htmx-request .precio, .htmx-request .preview-hojas {
  opacity: 0.5;
}

/* Área de subida (página "/"): drag & drop con fallback de click, para no
   depender de que el navegador soporte bien el <input type=file> nativo en
   mobile (donde de cualquier forma termina abriendo el picker del SO). */
.dropzone {
  position: relative;
  border: 2px dashed var(--border);
  border-radius: 12px;
  padding: 28px 16px;
  text-align: center;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.dropzone:hover,
.dropzone:focus-visible {
  border-color: var(--accent);
  outline: none;
}

.dropzone-activo {
  border-color: var(--accent);
  background: rgba(37, 99, 235, 0.08);
}

.dropzone-icono {
  font-size: 1.6rem;
  color: var(--accent);
  line-height: 1;
}

.dropzone-texto strong {
  display: block;
  font-size: 0.95rem;
}

.dropzone-texto span {
  display: block;
  font-size: 0.8rem;
  color: var(--muted);
  margin-top: 2px;
}

.dropzone input[type="file"] {
  /* Oculto de verdad (no solo opacity:0 superpuesto): todo el click/drop lo
     maneja el JS de subir.html sobre el div .dropzone. Si el input también
     quedara clickeable/droppable encima, un drop nativo reemplazaría la
     selección entera en vez de sumarse a lo ya elegido (ver agregarArchivos). */
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.lista-archivos {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 10px;
}

.archivo-chip {
  display: flex;
  align-items: center;
  gap: 6px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px 6px 4px 12px;
  font-size: 0.8rem;
  max-width: 100%;
}

.archivo-chip span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 220px;
}

.archivo-chip-quitar,
.archivo-progreso-quitar {
  flex: none;
  padding: 3px 7px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: transparent;
  color: var(--muted);
  font-size: 0.78rem;
  line-height: 1;
  cursor: pointer;
}

.archivo-chip-quitar:hover,
.archivo-chip-quitar:focus-visible,
.archivo-progreso-quitar:hover,
.archivo-progreso-quitar:focus-visible {
  border-color: var(--danger);
  background: color-mix(in srgb, var(--danger) 10%, transparent);
  color: var(--danger);
  outline: none;
}

.archivo-chip-quitar:disabled,
.archivo-progreso-quitar:disabled {
  border-color: transparent;
  background: transparent;
  color: var(--muted);
  cursor: wait;
  opacity: 0.45;
}

.estado-subida {
  min-height: 1.4em;
  margin: 8px 0 12px;
  color: var(--muted);
  font-size: 0.86rem;
}

.archivo-progreso-item {
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: var(--bg);
}

.archivo-progreso-cabecera {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
  font-size: 0.8rem;
}

.archivo-progreso-nombre {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.archivo-progreso-estado {
  flex: none;
  color: var(--muted);
}

.archivo-progreso-pista {
  height: 7px;
  overflow: hidden;
  border-radius: 999px;
  background: var(--border);
}

.archivo-progreso-barra {
  width: 0;
  height: 100%;
  border-radius: inherit;
  background: var(--accent);
  transition: width 120ms linear;
}
