/* ── Button ── */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px;
  border-radius: var(--radius-sm);
  font-size: 0.85rem;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  border: 1px solid transparent;
  white-space: nowrap;
  /* `all` animaba tambien lo que no es estado visual (layout, color del rotulo),
     que es lo que hacia que el texto se desvaneciera al pasar el puntero. */
  transition:
    background-color var(--transition),
    border-color var(--transition),
    color var(--transition),
    box-shadow var(--transition),
    transform var(--transition);

  &:active { transform: translateY(1px); }
  &:disabled, &[aria-disabled='true'] {
    cursor: not-allowed;
    opacity: 0.55;
    transform: none;
  }
}

.btn svg { width: 14px; height: 14px; }

/* Cada variante declara su color tambien dentro del hover. No es redundancia:
   `a:hover` de 00-base.css pesa 0,1,1 contra 0,1,0 de `.btn-primary`, asi que
   sin esta linea el rotulo toma --primary-dk justo cuando el fondo tambien paso
   a --primary-dk y el boton queda en blanco. El hover va envuelto en
   @media (hover: hover) para que en tactil no se quede pegado despues de tocar. */
.btn-primary {
  background: var(--primary);
  color: var(--on-primary);
  border-color: var(--primary);

  @media (hover: hover) {
    &:hover {
      background: var(--primary-dk);
      border-color: var(--primary-dk);
      color: var(--on-primary);
    }
  }
}

.btn-outline {
  background: transparent;
  color: var(--text-secondary);
  border-color: var(--border-color);

  @media (hover: hover) {
    &:hover {
      background: var(--bg-hover);
      color: var(--text-primary);
      border-color: var(--text-muted);
    }
  }
}

.btn-sm { padding: 5px 10px; font-size: 0.8rem; }

.btn-danger {
  background: var(--red);
  color: var(--on-primary);
  border-color: var(--red);

  @media (hover: hover) {
    &:hover {
      background: var(--red-dk);
      border-color: var(--red-dk);
    }
  }
}

.btn-ghost {
  background: transparent;
  color: var(--text-secondary);
  border: none;

  @media (hover: hover) {
    &:hover { color: var(--text-primary); background: var(--bg-hover); }
  }
}

/* Estado de carga de los envios (ver admin.js): Naja marca los botones de
   envio del formulario al arrancar la peticion y los libera al terminar. El
   anillo usa currentColor, asi funciona en cualquier variante de boton, y el
   disabled que acompana al estado bloquea el reenvio. */
.btn.is-loading {
  pointer-events: none;
  opacity: 0.8;
}

.btn.is-loading::before {
  content: '';
  width: 13px;
  height: 13px;
  flex: none;
  border-radius: 50%;
  border: 2px solid color-mix(in oklab, currentColor, transparent 65%);
  border-top-color: currentColor;
  animation: giro-boton 0.8s linear infinite;
}

@keyframes giro-boton {
  to { transform: rotate(1turn); }
}

/* ── Campos ─ */
/* La receta unica de los controles. Vive escalada a `.form-grid`, que es el
   unico markup que produce FormGridRenderer, y no al `.nette-modal-body` del
   css del modal como estaba: los mismos campos se renderizan en tarjeta (las
   opciones de un elemento del guion, agregar elemento) y alla no tienen ese
   ancestro, asi que los dibujaba el UA oscuro que activa
   `data-bs-theme="dark"` de Bootstrap. Medido antes del cambio, el mismo
   input de texto: 25 px de alto, borde de 2 px, radio 0 y relleno 0 en la
   pagina contra 40,9 / 1 / 6 / 10x12 en el modal. */
.form-grid input[type="text"],
.form-grid input[type="search"],
.form-grid input[type="url"],
.form-grid input[type="email"],
.form-grid input[type="number"],
.form-grid input[type="tel"],
.form-grid input[type="password"],
.form-grid input[type="date"],
.form-grid input[type="time"],
.form-grid input[type="datetime-local"],
.form-grid input[type="month"],
.form-grid input[type="week"],
.form-grid select,
.form-grid textarea {
  width: 100%;
  padding: .5em 8px;
  background-color: var(--bg-input);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-family: inherit;
  font-size: 0.9rem;
  line-height: 1.2;
  transition: border-color var(--transition);
}

/* Los tres estados del campo van sobre la misma lista excluida: `input`
   tambien es el boton de enviar, y sin el `:not` el hover le pisaria el
   `border-color` de `.btn-primary` (0,3,1 de esta regla contra 0,2,0). */
.form-grid :is(input, select, textarea):not([type="submit"], [type="button"], .btn):hover {
  border-color: color-mix(in oklab, var(--border-color), var(--text-muted) 45%);
}

/* Foco: aqui solo cambia el borde; el anillo se lo deja al `:focus-visible`
   global de 00-base.css. El modal repetia el outline con su propio
   `outline-offset` (1 px contra los 2 px del global) y lo dibujaba tambien al
   hacer click, que es justo lo que el global evita. */
.form-grid :is(input, select, textarea):not([type="submit"], [type="button"], .btn):focus {
  border-color: var(--primary);
}

/* Inerte (`readonlyOnEdit` deshabilita el control). Sin reglas propias el
   modal pintaba un campo deshabilitado igual que uno activo. */
.form-grid :is(input, select, textarea):is(:disabled, [readonly]):not([type="submit"], [type="button"], .btn) {
  background-color: var(--bg-body);
  border-color: var(--border-card);
  color: var(--text-muted);
  cursor: not-allowed;
}

/* La etiqueta acompana al campo: 12 px de aire es (42 - 17,85) / 2, el punto
   en que su linea cae sobre el eje optico del control. Estaba en 8 px y la
   etiqueta flotaba 7,5 px por encima del centro del campo. */
.form-grid__label label {
  display: block;
  padding-top: .5em;
  margin: 0;
  text-align: start;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--text-secondary);
}

.form-grid__row.required .form-grid__label label::after {
  content: " *";
  color: var(--red);
}

.form-grid__help {
  display: block;
  color: var(--text-muted);
  font-size: 0.78rem;
}

/* `ul.error` es el contenedor que Nette usa para los dos niveles: el de la
   propia fila (dentro de `.form-grid__control`) y el del formulario, que cae
   antes del grid y se quedaba sin ninguna regla. */
.form-grid ul.error,
form > ul.error {
  margin: 0 0 14px;
  padding-inline-start: 18px;
  color: var(--red);
  font-size: 0.85rem;
}

/* Desplegable: la flecha del UA se dibuja con el esquema del sistema, ni pesa
   ni cae como los iconos del panel. Con `appearance: none` el chevron pasa a
   ser un fondo propio (el token de 00-base.css). La receta es de los dos unicos
   scopes del panel con un <select>: `.form-grid` y el paginador de Tabulator,
   que se arma su propio `select.tabulator-page-size` fuera de cualquier
   `.form-grid`. Vive escalada a las dos por el mismo motivo que la receta de
   campos de arriba: cuando cada contexto tenia la suya, se separaban. */
.form-grid select,
.tabulator .tabulator-footer .tabulator-page-size {
  -webkit-appearance: none;
  appearance: none;
  background-image: var(--select-chevron);
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 12px 12px;
}

.form-grid select {
  padding-right: 34px;
}

/* La lista desplegada. `appearance: base-select` (Chrome 135+, Safari 26) saca
   el popup del sistema operativo y lo entrega como DOM del documento, que es lo
   unico que permite pintarlo con los tokens: la receta de arriba oscurece la
   caja, pero la lista del paginador seguia abriendo clara sobre el panel
   oscuro. El opt-in tiene que declararse TAMBIEN en `::picker(select)`: con el
   solo en el <select> la caja pasa al documento, pero la fila resaltada la sigue
   pintando el sistema (una banda azul clara sobre la lista oscura). Donde
   todavia no existe la propiedad (Firefox) la declaracion se cae y el control
   conserva `appearance: none` con su popup nativo, o sea lo mismo que habia
   antes. Todo el bloque va dentro de `@supports` para que las reglas de `option`
   no alcancen un popup que no controlamos. */
@supports (appearance: base-select) {
  .form-grid select,
  .tabulator .tabulator-footer .tabulator-page-size {
    appearance: base-select;
  }

  /* La flecha sigue siendo el fondo de la receta, asi que el indicador del UA
     se apaga para no dibujarla dos veces. */
  select::picker-icon {
    display: none;
  }

  /* Mismo dibujo que `.tabulator-edit-list`, el desplegable que Tabulator arma
     para sus editores `list`: ahi ya no hay dos estilos de lista en el panel. */
  ::picker(select) {
    appearance: base-select;
    padding: 4px;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-lg);
    color: var(--text-primary);
  }

  select option {
    padding: 8px 12px;
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
  }

  /* La opcion elegida se marca con el check del UA y sube de texto, no de fondo:
     `--bg-hover` es el mismo oklch que `--bg-input` y un relleno para las dos
     cosas (elegida y subrayada) las dejaba iguales. */
  select option:checked {
    color: var(--text-primary);
  }

  /* `:focus` va en la misma regla que `:hover` porque en el popup abierto la
     opcion resaltada es la que tiene el foco del teclado, no la que esta bajo el
     puntero: con solo `:hover` la fila activa seguia con el dibujo del UA. */
  @media (hover: hover) {
    select option:is(:hover, :focus) {
      background: var(--bg-hover);
      color: var(--text-primary);
    }
  }
}

/* La muestra de color no es una caja de texto: se le deja su cuadro y el
   resto del column queda vacio a proposito. */
.form-grid input[type="color"] {
  width: 60px;
  min-height: 42px;
  padding: 5px;
  background-color: var(--bg-input);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.form-grid input[type="color"]::-webkit-color-swatch-wrapper {
  padding: 0;
}
.form-grid input[type="color"]::-webkit-color-swatch {
  border: none;
  border-radius: 3px;
}

/* Casilla: mismo dibujo que el resto de controles (fondo, borde y radio de
   la receta de campos) en vez del widget del sistema: con `accent-color` el
   check nativo seguia siendo el gris del UA, que sobre el panel oscuro leia
   como desactivado. Marcada, la caja pasa al primario del panel y el tick es
   un SVG en el tono de --on-primary (igual que --select-chevron, el color va
   fijo en el data URI porque un background-image no ve las CSS variables). */
.form-grid input[type="checkbox"] {
  appearance: none;
  width: 18px;
  height: 18px;
  flex: none;
  margin: 0;
  background-color: var(--bg-input);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background-color var(--transition), border-color var(--transition);
}

.form-grid input[type="checkbox"]:hover {
  border-color: color-mix(in oklab, var(--border-color), var(--text-muted) 45%);
}

.form-grid input[type="checkbox"]:checked {
  background-color: var(--primary);
  border-color: var(--primary);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 6.5 5 9l4.5-6' fill='none' stroke='%23241e18' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 12px 12px;
}

.form-grid input[type="checkbox"]:is(:disabled, [readonly]) {
  background-color: var(--bg-body);
  border-color: var(--border-card);
  cursor: not-allowed;
}

/* Nette envuelve la casilla en su propia etiqueta y deja vacia la columna de
   la izquierda; el min-height alinea esa fila con las de los demas campos. */
.form-grid__control label {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 42px;
  font-size: 0.9rem;
  color: var(--text-primary);
  cursor: pointer;
}

/* Archivo: en el modal de elemento el input se oculta y lo sustituye el boton
   del widget de Cloudinary (media-upload.js); esto es para los formularios
   donde el control nativo si se ve. */
.form-grid input[type="file"] {
  width: 100%;
  min-height: 42px;
  padding: 6px 12px;
  background-color: var(--bg-input);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 0.85rem;
}
.form-grid input[type="file"]::file-selector-button {
  margin-inline-end: 10px;
  padding: 3px 10px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  background-color: var(--bg-card-header);
  color: var(--text-primary);
  font: inherit;
  cursor: pointer;
}

/* ── Table ── */
/* Dignidades tabulares: las columnas de fechas, ids y conteos dejan de
   bailar cuando cambia el dato, y las cifras de una columna alinean en peso. */
.table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
  /* Bootstrap da 1 rem de margen inferior a .table: el ritmo vertical del
     panel lo pone el gap de .page-wrapper, y aqui seria una segunda
     separacion encima del hueco real. */
  margin: 0;
}

.table thead th {
  padding: 10px 16px;
  text-align: start;
  font-weight: 600;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border-color);
  background: var(--bg-card-header);
  white-space: nowrap;
  -webkit-user-select: none;
  user-select: none;
}

.table tbody td {
  padding: 12px 16px;
  border-bottom: 1px solid var(--border-color);
  color: var(--text-secondary);
  vertical-align: middle;
}

.table tbody tr { transition: background var(--transition); }

.table tbody tr:hover { background: var(--bg-row-hover); }

.table tbody tr:last-child td { border-bottom: none; }

/* ── Ficha (dl) ── */
/* Lista termino/definicion como grid: reemplazo generico de las tablas de
   pares clave-valor (detalle de una entidad). Los dt/dd van sueltos, como
   hijos directos del dl: cada par cae en una fila de dos columnas y la
   columna de etiquetas comparte ancho entre filas, como el th de una tabla.
   Los valores cortan en cualquier parte para que URLs y slugs largos no
   desborden la tarjeta. */
.ficha {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  column-gap: 16px;
  row-gap: 10px;
  margin: 0;
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
}
.ficha > dt {
  padding: 2px 0;
  font-weight: 600;
  color: var(--text-muted);
  white-space: nowrap;
}
.ficha > dd {
  margin: 0;
  padding: 2px 0;
  color: var(--text-secondary);
  overflow-wrap: anywhere;
  min-width: 0;
}

/* ── Cell classes ── */
.cell-muted {
  color: var(--text-muted);
  font-size: 0.78rem;
}

.cell-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.cell-acciones {
  display: flex;
  gap: 4px;
  justify-content: center;
}

.cell-json {
  display: inline-block;
  max-width: 260px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: middle;
}

/* ── Status badges ── */
.status {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 10px;
  border-radius: 20px;
  font-size: 0.75rem;
  font-weight: 500;
}

.status::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
}

/* Los dos estados pasan a las marcas de la paleta: venian de la tabla flat-UI
   (#2ecc71, #f1c40f) que el panel ya no usa. Medido sobre su propio tinte al 15 %,
   el verde queda en 6,09:1 (antes 6,04) y el amarillo en 6,86:1 (antes 7,11); los
   dos siguen por encima del 4,5:1 que pide AA para texto normal. */
.status-green  { --tint: var(--green); }
.status-yellow { --tint: var(--yellow); }

.status-green,
.status-yellow {
  background: color-mix(in oklab, var(--tint) 15%, transparent);
  color: var(--tint);

  &::before { background: var(--tint); }
}

/* ── Chips ── */
.chip {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 4px;
  font-size: 0.75rem;
  font-weight: 500;
  /* Borde reservado: las variantes de 80-variantes.css solo declaran
     border-color, y sin ancho de borde el chip con marca mediria 2 px menos
     que uno sin ella (desalineacion medida en la tabla de elementos). */
  border: 1px solid transparent;
  /* Scrim neutro, no una marca: blanco al 8 % levanta el chip sobre cualquier
     fondo de tarjeta sin insinuar un estado. */
  background: rgba(255,255,255,.08);
  color: var(--text-secondary);
}

.chip-control { background: color-mix(in oklab, var(--blue) 20%, transparent); color: var(--blue); }

/* ── Alerts (avisos flash del layout) ── */
/* Viven aqui, no en el css del modal: los produce la barra de flash de
   @layout, en la pagina. Bootstrap ya define .alert con su propria caja
   (fondo y margen incluidos); estas reglas sin capa le ganan y el margen se
   anula porque el hueco vertical la pone el gap de .page-wrapper. */
.alert {
  margin: 0;
  padding: 12px 16px;
  border-radius: var(--radius-sm);
  font-size: 0.85rem;
  font-weight: 500;
  border: 1px solid transparent;
}

/* Los tres avisos estaban pintados con la tabla flat-UI (#2ecc71, #e74c3c,
   #f39c12) y no con las marcas del panel. Además del desfase de color, el rojo
   plano fallaba AA: medido sobre el tinte real de la caja, el rótulo de
   `.alert-error` daba 3,69:1 y con `--red` da 4,97:1 (verde 6,06 a 6,15 y amarillo
   5,77 a 6,94). */
.alert-success { --tint: var(--green); }
.alert-error   { --tint: var(--red); }
.alert-warning { --tint: var(--yellow); }
.alert-info    { --tint: var(--blue); }

.alert-success,
.alert-error,
.alert-warning,
.alert-info {
  background: color-mix(in oklab, var(--tint) 15%, transparent);
  border-color: color-mix(in oklab, var(--tint) 30%, transparent);
  color: var(--tint);
}

/* ── Footer ── */
.footer {
  padding: 16px 24px;
  border-top: 1px solid var(--border-color);
  font-size: 0.8rem;
  color: var(--text-muted);
  display: flex;
  justify-content: space-between;
}

/* ── Responsive ── */

@media (max-width: 768px) {
  .sidebar { display: none; }
  .main { margin-inline-start: 0; }
  .page-header-row { flex-direction: column; }
}
