/* ==========================================================================
   Papelito · el panel
   Maquetado contra el concepto del 17/8. Proporciones medidas sobre ese
   archivo, no estimadas.
   ========================================================================== */

/* Capa de viewport completo, no un bloque en el flujo. Si va en el flujo, se
   apila DEBAJO de la intro mientras las dos conviven: el documento mide dos
   pantallas y el fade in del panel queda fuera de cuadro. */
.board {
  position: fixed;
  inset: 0;
  z-index: 2;
  overflow: hidden;   /* el panel se adapta; la pantalla no scrollea */
  padding: var(--s4);
  background: var(--bg-app);
  opacity: 0;
  transition: opacity 900ms var(--ease-inout);
}

.board[hidden] { display: none; }
.board--visible { opacity: 1; }

.board__panel {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  min-width: 0;
  /* Tope de ancho. Sin él, en un monitor grande las columnas se estiran sin
     límite y los tickets terminan midiendo el doble de lo que deben: el diseño
     se agranda en vez de respirar. Con el tope, la escala se mantiene y el
     sobrante queda como margen. */
  width: 100%;
  max-width: 1400px;
  margin-inline: auto;
  padding: var(--s5) var(--s6) var(--s4);
  /* Dos halos suaves además del color plano. El vidrio de las columnas necesita
     algo que desenfocar: sobre un fondo liso, un backdrop-filter no se nota. */
  background:
    radial-gradient(120% 85% at 12% 0%, rgba(255, 255, 255, 0.95), transparent 55%),
    radial-gradient(90% 75% at 98% 100%, rgba(252, 205, 222, 0.60), transparent 62%),
    var(--panel);
  border-radius: 24px;
  box-shadow: 0 2px 24px -8px rgba(139, 30, 65, 0.10);
}

/* --- Barra superior ------------------------------------------------------ */
.board__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.brand {
  display: flex;
  align-items: center;
  gap: var(--s2);
  font-size: 19px;
  font-weight: var(--w-title);
  letter-spacing: -0.015em;
  color: var(--marca);
}

.brand__icono {
  width: 26px;
  height: 24px;
  flex: none;
}
/* El logo lleva el cuerpo relleno y sin chispas. Las custom properties son la
   única vía para tocar el interior del símbolo (ver el comentario en el HTML). */
.brand__icono { --pl-relleno: rgba(245, 21, 91, 0.09); }

/* Decorativo por decisión de producto: no es un botón, así que no se comporta
   como uno — sin cursor, sin hover, sin foco. Un control que parece clickeable
   y no hace nada se lee como una app rota. */
.board__gear {
  display: grid;
  place-items: center;
  width: 38px;
  aspect-ratio: 1;
  color: var(--marca);
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 2px 10px -2px rgba(139, 30, 65, 0.13);
}
.board__gear svg { width: 17px; height: 17px; }

/* --- Encabezado ---------------------------------------------------------- */
.board__head { margin: var(--s5) 0 var(--s4); }

.board__title {
  display: flex;
  align-items: center;
  gap: var(--s3);
  font-size: 22px;
  font-weight: var(--w-title);
  letter-spacing: -0.02em;
  color: var(--ink);
}
.board__title::after {
  content: '';
  width: 8px;
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--marca);
}

.board__sub {
  margin-top: 4px;
  font-size: 13px;
  color: var(--ink-mute);
}

/* --- La grilla -----------------------------------------------------------
   Tres columnas de tickets + la impresora, y una fila abajo para la consola
   que abarca sólo las tres de tickets. La cuarta columna es 1fr para que las
   de tickets arranquen en la misma línea que el logo y el título. */
.board__cols {
  display: grid;
  /* Las tres columnas se estiran y se reparten el ancho; el ticket las llena.
     Es lo que hace el concepto. Antes las columnas medían lo que medía el
     ticket y el sobrante quedaba como un hueco enorme al costado.
     El ancho real del ticket lo publica el JS en --ticket-w, para que el que
     sale de la boca mida exactamente lo mismo que el de la columna. */
  grid-template-columns: repeat(3, minmax(0, 1fr)) minmax(0, auto);
  gap: var(--s4);
  min-width: 0;
  min-height: 0;
  align-items: stretch;
  flex: 1;
}

/* --- Columnas ------------------------------------------------------------ */
.col {
  position: relative;   /* ancla de la guía de scroll */
  display: flex;
  flex-direction: column;
  /* Piso fijo: la columna mide siempre lo de tres tarjetas, tenga una, tres o
     diez. El valor lo publica el JS midiendo una tarjeta real. Sin este piso el
     tablero crecía de a poco con cada tarjeta y volvía a moverse en la cuarta. */
  min-height: var(--col-alto, 360px);
  min-width: 0;
  overflow: hidden;   /* nada se escapa de la columna */
  padding: var(--s3);
  background: var(--col-bg);
  -webkit-backdrop-filter: blur(18px) saturate(1.8);
          backdrop-filter: blur(18px) saturate(1.8);
  border: 1px solid var(--col-borde);
  border-radius: 16px;
  /* El brillo interior de arriba es lo que hace que se lea como vidrio y no
     como un rectángulo translúcido: simula el canto iluminado de una lámina. */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.95),
    inset 0 -1px 0 rgba(255, 255, 255, 0.30),
    0 8px 24px -14px rgba(139, 30, 65, 0.28);
}

.col__head {
  display: flex;
  align-items: center;
  gap: var(--s2);
  padding: var(--s1) var(--s1) var(--s3);
}

.col__dot {
  width: 8px;
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--col-pend);
}
.col[data-estado='haciendo'] .col__dot { background: var(--col-doing); }
.col[data-estado='listo']    .col__dot { background: var(--col-done);  }

.col__name {
  flex: 1;
  font-size: 11px;
  font-weight: var(--w-bold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
}

.col__count {
  min-width: 22px;
  padding: 2px 7px;
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: center;
  color: var(--col-pend);
  background: var(--col-pend-bg);
  border-radius: var(--r-pill);
}
.col[data-estado='haciendo'] .col__count { color: var(--col-doing); background: var(--col-doing-bg); }
.col[data-estado='listo']    .col__count { color: var(--col-done);  background: var(--col-done-bg);  }

/* El alto máximo lo calcula el JS: exactamente 3 tickets y medio. El medio
   ticket cortado es el que le avisa al ojo que hay más abajo — por eso no lleva
   ningún degradado encima, que taparía justo la señal. */
.col__list {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  /* Puede encogerse pero NO estirarse: en el concepto "+ Nueva tarea" va pegado
     a los tickets, no clavado al pie de la columna. Y al poder encogerse, si la
     pantalla es baja el flex la achica sola y la lista scrollea — sin que haga
     falta calcular nada. */
  flex: 0 1 auto;
  min-height: 8px;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;

  /* Aire para que la sombra del ticket no quede recortada.
     `overflow-y: auto` obliga al eje horizontal a recortar también (no existe
     un eje `visible` con el otro en `auto`), así que la lista es una caja que
     corta por los cuatro lados. La sombra del hover se extiende ~11px a los
     costados y ~18px hacia abajo: hay que darle ese lugar de verdad.
     El margen negativo lateral compensa el padding para que el ticket siga
     midiendo el ancho de la columna. */
  margin-inline: calc(var(--s3) * -1);
  padding-inline: var(--s3);
  padding-block: 6px 20px;
  margin-bottom: -14px;
}
.col__list::-webkit-scrollbar { width: 0; height: 0; }

/* Lo que sobra abajo se desvanece en vez de cortarse de golpe.
   El degradado es CORTO a propósito: con 52px se comía casi la mitad de la
   tercera tarjeta y parecía que la columna mostraba menos de lo que mostraba.
   30px alcanzan para que el borde no sea un tajo y para que el asomo de la
   cuarta se lea como un fantasma. */
.col__list--hay-mas {
  -webkit-mask-image: linear-gradient(#000 calc(100% - 30px), transparent);
          mask-image: linear-gradient(#000 calc(100% - 30px), transparent);
}

/* Nada aparece de la nada: lo que pasa a estar a la vista entra con un fundido
   corto. Suave, no lento — 240ms; más que eso se siente pesado en una lista que
   se reordena seguido. */
.ticket--entra { animation: ticket-entra 240ms var(--ease-inout) both; }

@keyframes ticket-entra {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: none; }
}

/* --- Guía de scroll -------------------------------------------------------
   Aparece recién con la cuarta tarjeta. Es un indicador, no un control: no se
   arrastra, sólo dice cuánto hay y dónde estás. La barra nativa se descarta
   porque ocuparía ancho real y los tickets de una columna con scroll medirían
   distinto que los de una sin scroll. */
.col__guia {
  position: absolute;
  right: 4px;
  width: 3px;
  border-radius: 2px;
  background: rgba(245, 21, 91, 0.10);
  pointer-events: none;
}
.col__guia[hidden] { display: none; }

.col__guia span {
  position: absolute;
  left: 0;
  width: 100%;
  border-radius: 2px;
  background: rgba(245, 21, 91, 0.38);
  transition: top 90ms linear;
}

/* --- Estado vacío -------------------------------------------------------- */
.col__vacio {
  display: flex;
  flex: 1;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: var(--s4) var(--s3);
  text-align: center;
  border: 1.5px dashed rgba(245, 21, 91, 0.16);
  border-radius: 13px;
}
.col--con-tickets .col__vacio { display: none; }

/* Acá sí van las chispas: es la única aparición donde el ícono es ilustración
   y no marca. */
.col__vacio-icono {
  --pl-chispas: block;
  width: 56px;
  height: 51px;
  margin-bottom: var(--s2);
  color: rgba(245, 21, 91, 0.32);
}
.col[data-estado='listo'] .col__vacio-icono { color: rgba(91, 140, 105, 0.38); }

.col__vacio-titulo {
  font-size: 13.5px;
  font-weight: var(--w-bold);
  color: var(--ink);
}
.col__vacio-texto {
  font-size: 12px;
  line-height: 1.45;
  color: var(--ink-mute);
}

/* --- Menú del ticket ------------------------------------------------------
   Los tres puntos del concepto. Por ahora tiene una sola acción: borrar.
   Editar quedó fuera de la v1. */
.ticket__menu {
  position: absolute;
  top: calc(var(--zig-h) + 8px);
  right: 6px;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  color: rgba(245, 21, 91, 0.45);
  border-radius: 8px;
  transition: background var(--t-fast), color var(--t-fast);
}
.ticket__menu:hover,
.ticket__menu[aria-expanded='true'] {
  color: var(--marca);
  background: rgba(245, 21, 91, 0.09);
}
.ticket__menu svg { width: 15px; height: 15px; }

.ticket__acciones {
  position: absolute;
  top: calc(var(--zig-h) + 34px);
  right: 6px;
  z-index: 6;
  min-width: 132px;
  padding: 5px;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 8px 24px -6px rgba(139, 30, 65, 0.26);
}
.ticket__acciones[hidden] { display: none; }

.ticket__accion {
  width: 100%;
  padding: 9px 10px;
  text-align: left;
  font-size: 13.5px;
  font-weight: var(--w-med);
  color: var(--urg-alta);
  border-radius: 8px;
}
.ticket__accion:hover { background: var(--urg-alta-bg); }

/* --- Confirmación de borrado ---------------------------------------------
   Borrar un ticket no tiene deshacer, así que pide confirmación. Va en el
   mismo popover en vez de un diálogo del navegador: no interrumpe, se cancela
   con Escape o tocando afuera, y no saca al usuario de la página. */
.ticket__confirmar { min-width: 168px; padding: 10px; }

.ticket__confirmar-texto {
  padding: 0 2px 8px;
  font-size: 12.5px;
  line-height: 1.35;
  color: var(--ink-mute);
}

.ticket__confirmar-botones { display: flex; gap: 6px; }

.ticket__confirmar-botones button {
  flex: 1;
  padding: 7px 8px;
  font-size: 12.5px;
  font-weight: var(--w-bold);
  border-radius: 8px;
}
.ticket__cancelar { color: var(--ink-mute); background: rgba(15, 10, 12, 0.05); }
.ticket__cancelar:hover { background: rgba(15, 10, 12, 0.09); }
.ticket__borrar-si { color: #fff; background: var(--urg-alta); }
.ticket__borrar-si:hover { filter: brightness(1.08); }

/* --- Sombra y hover del ticket -------------------------------------------
   Va con `drop-shadow` y NO con `box-shadow`: el ticket lleva una `mask` para
   el zigzag, y la máscara recorta también la box-shadow — quedaría un rectángulo
   de sombra cortado contra los dientes. `drop-shadow` sigue la silueta real, así
   que la sombra tiene los dientes.

   El hover es mínimo a propósito: la tarjeta es arrastrable, así que el gesto
   que tiene que anticipar es "esto se puede tomar", no "esto es un botón". */
/* El papel y el fondo de la columna son casi el mismo valor (#FEF9F7 contra
   #FEFAFB), así que la sombra es lo ÚNICO que despega la tarjeta. Con un 10%
   y 1.5px de blur no se veía nada: hace falta que trabaje de verdad. */
.col .ticket {
  filter: drop-shadow(0 2px 3px rgba(139, 30, 65, 0.14));
  transition: filter var(--t-base) var(--ease-inout),
              transform var(--t-base) var(--ease-settle);
}

.col .ticket:hover {
  transform: translateY(-2px);
  filter: drop-shadow(0 7px 11px rgba(139, 30, 65, 0.22));
}

/* --- Arrastre ------------------------------------------------------------- */
.ticket { cursor: grab; touch-action: none; user-select: none; }

.ticket--arrastrando {
  cursor: grabbing;
  pointer-events: none;
  filter: drop-shadow(0 16px 28px rgba(139, 30, 65, 0.22));
  transform: rotate(-1.2deg);
  transition: none;
}

/* El hueco que deja el ticket levantado. No es un fantasma gris: es aire con
   un contorno mínimo, para que la columna no parezca rota mientras arrastrás. */
.hueco {
  flex: none;
  border: 1.5px dashed rgba(245, 21, 91, 0.18);
  border-radius: var(--r-sm);
  background: rgba(245, 21, 91, 0.04);
}

/* --- La columna de la impresora ------------------------------------------
   Al costado va SÓLO la impresora. La escritura vive abajo. */
.consola {
  grid-column: 4;
  grid-row: 1 / span 2;
  position: sticky;
  top: 0;
  justify-self: end;
  align-self: center;
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 700ms var(--ease-inout), transform 800ms var(--ease-settle);
}
.consola--entra { opacity: 1; transform: none; }

/* El ancho sale del token: su boca tiene que medir exactamente lo que mide un
   ticket, para que el papel salga a escala real. */
.printer--panel {
  /* `width: min(..., 100%)` acá colapsa a cero: el 100% se resuelve contra una
     pista `auto` que a su vez se dimensiona por el contenido. Es circular.
     Con max-width la pista mide primero y después se acota. */
  width: var(--impresora-side-w);
  max-width: 100%;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform var(--t-base) var(--ease-settle);
}
.printer--panel:hover { transform: translateY(-5px); }
.printer--panel .papelito { width: 100%; }
.printer--panel .papelito::before { display: none; }   /* sin halo acá */

/* --- La consola de escritura, abajo -------------------------------------- */
.consola__form {
  grid-column: 1 / 4;
  grid-row: 2;
  position: sticky;
  bottom: 0;
  padding-top: var(--s4);
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 700ms var(--ease-inout), transform 800ms var(--ease-settle);
}
.consola__form--entra { opacity: 1; transform: none; }

.pill--console {
  width: 100%;
  gap: var(--s3);
  padding: 6px 6px 6px var(--s3);
  background: #fff;
  border: 1.5px solid rgba(245, 21, 91, 0.18);
  box-shadow: 0 4px 18px -8px rgba(139, 30, 65, 0.16);
}

.pill__icono {
  width: 24px;
  height: 22px;
  flex: none;
  color: rgba(245, 21, 91, 0.45);
}

.btn-print {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  flex: none;
  min-width: 148px;
  padding: var(--s3) var(--s5);
  font-size: 14px;
  font-weight: var(--w-bold);
  color: #fff;
  background: var(--marca-suave);
  border-radius: var(--r-pill);
  box-shadow: 0 4px 14px -4px rgba(245, 21, 91, 0.45);
  transition: background var(--t-fast), transform var(--t-fast) var(--ease-settle);
}
.btn-print:hover  { background: var(--marca); transform: translateY(-1px); }
.btn-print:active { background: var(--marca-press); transform: translateY(0) scale(0.98); }
.btn-print:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }
.btn-print svg { width: 16px; height: 16px; }

/* --- Pie ------------------------------------------------------------------ */
/* Pie y crédito comparten renglón: dos alturas de texto al pie competían entre
   sí y ninguna remataba. Cada parte conserva su color — el mensaje en el rosa
   tenue, la firma en gris y el enlace en el rosa de marca. */
.board__pie {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--s2);
  margin-top: var(--s3);
  font-size: 12.5px;
  font-weight: var(--w-med);
  color: var(--marca-tenue);
}
.board__pie svg { width: 14px; height: 14px; }

.board__pie-sep {
  color: var(--ink-mute);
  opacity: 0.45;
}

.board__credito {
  font-size: 12.5px;
  color: var(--ink-mute);
  opacity: 0.8;
}

.board__credito a {
  color: var(--marca);
  font-weight: var(--w-bold);
  text-decoration: none;
  border-bottom: 1px solid rgba(245, 21, 91, 0.28);
  transition: border-color var(--t-fast), color var(--t-fast);
}
.board__credito a:hover { border-bottom-color: var(--marca); }
.board__credito a:focus-visible { border-radius: 3px; }

/* --- El ticket en vuelo, de la boca a la columna -------------------------- */
.vuelo {
  position: fixed;
  z-index: 40;
  transform-origin: top left;   /* al escalar, la esquina no se mueve */
  pointer-events: none;
  filter: drop-shadow(0 14px 26px rgba(139, 30, 65, 0.20));
}

/* Sin animación de aparición al aterrizar: el ticket no aparece, llega. La
   única vez que se usa es cuando no hubo vuelo (recarga, estado restaurado). */
.ticket--aterriza { animation: ticket-aterriza 300ms var(--ease-settle) both; }

@keyframes ticket-aterriza {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* El sprite de símbolos no ocupa lugar. */
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

/* Menus escape ticket masks and column clipping without changing the paper. */
.ticket__acciones { position: fixed; inset: auto; z-index: 100; max-width: calc(100vw - 16px); }
