/* ============================================================
   app.css — shell del área autenticada
   ------------------------------------------------------------
   Lo comparten /short, /rentals, /recharge, /history y
   /dashboard: topbar con saldo, sidebar de secciones y el
   contenedor de página. Mismos tokens que styles.css, cero
   colores nuevos.
   ============================================================ */

body.app-page {
  background: var(--ink);
  --rail: 232px;          /* ancho del riel de navegación */
  --bar: 64px;            /* alto de la barra superior */
  --pad: clamp(18px, 2.4vw, 36px);
  --gap: clamp(14px, 1.6vw, 20px);
}

/* ---------- topbar ---------- */
.appbar {
  position: sticky; top: 0; z-index: 40;
  /* Sobre el FONDO de la marca, no sobre el navy de la plataforma: con una
     paleta clara, una barra oscura fija dejaba el nombre de la marca
     (texto oscuro) invisible. El primer background es el respaldo. */
  background: var(--ink);
  background: color-mix(in srgb, var(--ink) 94%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.appbar__in { display: flex; align-items: center; height: var(--bar); }
/* La marca ocupa exactamente la columna del riel y comparte su borde, así
   la línea vertical del panel es una sola de arriba abajo. */
.appbar .brand {
  width: var(--rail); flex: none; height: 100%;
  padding-left: var(--pad); box-sizing: border-box;
  border-right: 1px solid var(--line);
}

.appbar__right { display: flex; align-items: center; gap: 10px; margin-left: auto; }

/* Quién ha entrado. Un correo largo no puede empujar al saldo ni al botón
   de recargar fuera de la barra: se recorta él. */
.whoami {
  font-family: var(--mono); font-size: 11.5px; color: var(--fg-3);
  max-width: 22ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@media (max-width: 720px) { .whoami { display: none; } }

.wallet-chip {
  display: flex; align-items: center; gap: 9px;
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--slate); padding: 7px 12px;
}
.wallet-chip__k {
  font-family: var(--mono); font-size: 10px; color: var(--fg-3);
  text-transform: uppercase; letter-spacing: .1em;
}
.wallet-chip__v { font-family: var(--px); font-size: 12px; color: var(--signal); }
.wallet-chip__v.is-low { color: var(--watt); }

/* ---------- campana ---------- */
.bell { position: relative; }
.bell__btn {
  display: grid; place-items: center; width: 36px; height: 36px;
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--slate); color: var(--fg-2); cursor: pointer;
}
.bell__btn:hover { border-color: var(--line-2); color: var(--fg); }
.bell__btn[aria-expanded="true"] { border-color: var(--signal); color: var(--signal); }
.bell__n {
  position: absolute; top: -5px; right: -5px; min-width: 17px; height: 17px;
  display: grid; place-items: center; padding: 0 4px;
  background: var(--pulse); color: #12030A; border-radius: 9px;
  font-family: var(--mono); font-size: 10px; font-weight: 700;
}

.notif__panel {
  position: absolute; top: calc(100% + 9px); right: 0; z-index: 60;
  width: min(330px, calc(100vw - 32px));
  border: 1px solid var(--line-2); border-radius: var(--r);
  background: var(--slate); box-shadow: 0 14px 40px rgba(0, 0, 0, .5);
  overflow: hidden;
}
.notif__head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 11px 13px; border-bottom: 1px solid var(--line);
}
.notif__head b {
  font-family: var(--mono); font-size: 11px; color: var(--fg-3);
  text-transform: uppercase; letter-spacing: .11em; font-weight: 500;
}
.notif__head button {
  background: none; border: 0; cursor: pointer; padding: 0;
  font-family: var(--mono); font-size: 11px; color: var(--wire);
}
.notif__head button:hover { text-decoration: underline; }

.notif__list { max-height: 330px; overflow-y: auto; }
.notif {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 11px 13px; border-bottom: 1px solid var(--line);
}
.notif:last-child { border-bottom: 0; }
.notif.is-new { background: rgba(53, 240, 160, .05); }
.notif__dot { width: 7px; height: 7px; flex: none; margin-top: 5px; }
.notif__txt { min-width: 0; flex: 1; }
.notif__txt b {
  display: block; font-family: var(--mono); font-size: 12.5px;
  color: var(--fg); font-weight: 500;
}
.notif__txt em {
  display: block; font-style: normal; font-family: var(--mono);
  font-size: 11px; color: var(--fg-3); margin-top: 3px; overflow-wrap: anywhere;
}
.notif time { font-family: var(--mono); font-size: 10.5px; color: var(--fg-3); flex: none; }
.notif__none {
  margin: 0; padding: 26px 16px; text-align: center;
  font-family: var(--mono); font-size: 12px; color: var(--fg-3);
}

/* ---------- logout ---------- */
.side__foot { border-top: 1px solid var(--line); padding-top: 16px; }
.side__out {
  display: flex; align-items: center; gap: 10px; width: 100%;
  background: none; border: 1px solid transparent; border-radius: var(--r);
  font-family: var(--mono); font-size: 13px; color: var(--fg-3);
  padding: 8px 11px; cursor: pointer; text-align: left;
}
.side__out:hover { background: var(--slate); border-color: var(--line); color: var(--pulse); }
.side__out canvas { width: 20px; height: 20px; image-rendering: pixelated; flex: none; }

.appbar .burger { margin-left: 0; }

/* ---------- layout ---------- */
.app {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  align-items: start;
}

/* El riel va pegado al borde izquierdo de la ventana y con su propia
   superficie: es navegación, no una columna de contenido. */
.side {
  position: sticky; top: var(--bar);
  height: calc(100vh - var(--bar));
  display: flex; flex-direction: column;
  background: var(--ink-2);
  border-right: 1px solid var(--line);
  padding: 20px 12px;
  overflow-y: auto;
}
.side__group + .side__group { margin-top: 24px; }
.side__t {
  font-family: var(--mono); font-size: 10px; color: var(--fg-3);
  text-transform: uppercase; letter-spacing: .12em; margin: 0 0 9px;
}
.side a {
  display: flex; align-items: center; gap: 10px;
  font-family: var(--mono); font-size: 13px; color: var(--fg-2);
  padding: 8px 11px; border-radius: var(--r);
  border: 1px solid transparent;
}
.side a:hover { background: var(--slate); color: var(--fg); text-decoration: none; }
.side a[aria-current="page"] {
  background: rgba(53, 240, 160, .10);
  border-color: var(--signal); color: var(--signal);
}
.side canvas { width: 20px; height: 20px; image-rendering: pixelated; flex: none; }

/* El logout cae al fondo del riel, lejos del resto de la navegación.
   Dos clases porque `.side__group + .side__group` también son dos y si no
   gana ella, dejando el botón pegado al último enlace. */
.side__group.side__foot { margin-top: auto; padding-top: 18px; }

.app__main {
  min-width: 0;
  padding: clamp(20px, 2.2vw, 28px) var(--pad) clamp(36px, 4vw, 52px);
}
/* Tope de ancho para que en pantallas muy anchas las tablas y los textos no
   se estiren hasta ser ilegibles. Por debajo de esto no añade margen. */
.app__inner { max-width: 1480px; margin-inline: auto; }

.app__head { margin-bottom: clamp(24px, 3vw, 34px); max-width: 74ch; }
.app__head--tight { margin-bottom: var(--gap); }
.app__head--tight .h2 { margin-bottom: 8px; }
.app__head .h2 { margin-bottom: 12px; }
.app__head .sub { line-height: 1.65; }

/* ---------- order panel ---------- */
.order { display: grid; gap: var(--gap); grid-template-columns: minmax(0, 1fr) 360px; align-items: start; }
/* Sólo los <div> envoltorio se vuelven pila; un <section class="panel"> puesto
   directamente en .order conserva su flujo interno. */
.order > div { display: grid; gap: var(--gap); align-content: start; min-width: 0; }
.order > .panel { align-self: start; }

.panel {
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--slate); padding: clamp(16px, 1.8vw, 22px);
  min-width: 0;
}
.panel__t {
  font-family: var(--mono); font-size: 11px; color: var(--fg-3);
  text-transform: uppercase; letter-spacing: .11em;
  margin: 0 0 16px; padding-bottom: 12px;
  border-bottom: 1px solid var(--line);
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
}
.panel__t span { color: var(--fg-3); letter-spacing: .04em; text-transform: none; font-size: 11px; }

/* service picker */
.picker { position: relative; margin-bottom: 12px; }
.picker input {
  width: 100%; background: var(--ink-2); color: var(--fg);
  border: 1px solid var(--line); border-radius: var(--r);
  font-family: var(--mono); font-size: 14px; padding: 12px 58px 12px 14px;
}
.picker input:focus { outline: none; border-color: var(--signal); }
.picker input::placeholder { color: var(--fg-3); }
.picker kbd {
  position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
  font-family: var(--mono); font-size: 10.5px; color: var(--fg-3);
  border: 1px solid var(--line-2); border-radius: 3px; padding: 2px 6px;
  pointer-events: none;
}

.svcgrid {
  display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(166px, 1fr));
  /* Alto suficiente para ver casi todo el catálogo de una vez, pero atado
     a la altura de la ventana para que en pantallas bajas no se coma la
     página entera. */
  max-height: min(430px, 46vh);
  overflow-y: auto;
  overflow-x: hidden;        /* nada puede salirse a lo ancho */
  padding-right: 10px;
}
.svcgrid:empty::after {
  content: "Nothing matches that."; grid-column: 1 / -1;
  font-family: var(--mono); font-size: 12.5px; color: var(--fg-3);
  padding: 22px 0; text-align: center;
}

/* La tarjeta es una rejilla de una celda con dos ocupantes superpuestos:
   el botón de selección ocupa toda la caja y la estrella se apoya arriba a
   la derecha. Son HERMANOS, no anidados —un <button> dentro de otro es HTML
   inválido y rompe el teclado— y el botón reserva el hueco con padding, así
   un nombre largo envuelve en vez de empujar la estrella fuera. */
.sopt {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--ink-2); min-width: 0;
  transition: border-color .15s var(--ease), transform .15s var(--ease);
}
.sopt:hover { border-color: var(--line-2); transform: translateY(-1px); }
.sopt.on { border-color: var(--signal); background: rgba(53, 240, 160, .10); }

.sopt__pick {
  grid-area: 1 / 1 / 2 / 3;
  display: grid; gap: 10px; align-content: space-between;
  min-width: 0; min-height: 64px;
  background: none; border: 0; cursor: pointer; text-align: left;
  color: var(--fg-2); font-family: var(--mono); font-size: 13px;
  padding: 11px 12px;
}
.sopt--star .sopt__pick { padding-right: 34px; }
.sopt:hover .sopt__pick { color: var(--fg); }
.sopt.on .sopt__pick { color: var(--signal); }
.sopt__pick:focus-visible { outline: 2px solid var(--signal); outline-offset: -2px; border-radius: var(--r); }

.sopt__top { display: flex; align-items: flex-start; gap: 8px; min-width: 0; }
.sopt__dot { width: 8px; height: 8px; flex: none; margin-top: 4px; background: currentColor; }
/* El nombre envuelve; ningún servicio se recorta con puntos suspensivos. */
.sopt__name { min-width: 0; line-height: 1.35; overflow-wrap: anywhere; }
.sopt__price { font-family: var(--px); font-size: 11px; color: var(--fg); }
.sopt.on .sopt__price { color: var(--signal); }
.sopt__price em {
  font-style: normal; font-family: var(--mono); font-size: 10.5px;
  color: var(--fg-3); margin-left: 5px;
}

.sopt__star {
  grid-area: 1 / 2 / 2 / 3; align-self: start; z-index: 1;
  width: 26px; height: 26px; margin: 5px 5px 0 0;
  display: grid; place-items: center;
  border: 0; border-radius: 3px; background: none;
  color: var(--fg-3); font-size: 13px; line-height: 1; cursor: pointer;
}
.sopt__star:hover { color: var(--watt); background: rgba(255, 197, 61, .12); }
.sopt__star.on { color: var(--watt); }
.sopt__star:focus-visible { outline: 2px solid var(--watt); outline-offset: -2px; }

/* provider selector */
.provsel { display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(172px, 1fr)); }
.psel {
  display: flex; align-items: flex-start; gap: 9px; min-width: 0;
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--ink-2); color: var(--fg-2);
  font-family: var(--mono); font-size: 12.5px; padding: 9px 11px; cursor: pointer;
  text-align: left;
}
.psel:hover { border-color: var(--line-2); color: var(--fg); }
.psel.on { border-color: var(--accent, var(--signal)); color: var(--fg); background: var(--slate-2); }
.psel canvas { width: 22px; height: 22px; image-rendering: pixelated; flex: none; }
/* La imagen propia que una marca puso a un proveedor (whitelabel): mismo
   hueco que el sprite, pero SIN pixelar y sin ocultarse en estilo classic
   —el logo de un revendedor no es pixel-art nuestro—. */
.psel .provicon { width: 22px; height: 22px; flex: none; object-fit: contain; border-radius: 3px; }
/* Sin min-width:0 el bloque de texto no encoge y desborda la tarjeta. */
.psel > span { min-width: 0; }
.psel b { overflow-wrap: anywhere; }
.psel em {
  font-style: normal; display: block; font-size: 10.5px;
  color: var(--fg-3); margin-top: 4px; line-height: 1.45;
  overflow-wrap: anywhere;
}
.psel s { color: var(--fg-3); text-decoration: line-through; }
.psel[disabled] { opacity: .45; cursor: not-allowed; }

/* summary / receipt */
.recap { display: grid; gap: 12px; margin-bottom: 18px; }
.recap__r {
  display: flex; justify-content: space-between; gap: 18px;
  font-family: var(--mono); font-size: 12.5px; color: var(--fg-2);
  line-height: 1.5;
}
.recap__r b { color: var(--fg); font-weight: 500; }
.recap__r--tot {
  border-top: 1px solid var(--line); padding-top: 14px; margin-top: 4px;
  font-size: 13.5px;
}
.recap__r--tot b { font-family: var(--px); font-size: 13px; color: var(--signal); }

.hintline { font-family: var(--mono); font-size: 11.5px; color: var(--fg-3); margin: 14px 0 0; line-height: 1.65; }
/* Un payload JSON en línea no trae espacios donde partir y se sale de la
   pantalla en móvil. Los bloques <pre> no se ven afectados: ahí manda
   white-space: pre y overflow-wrap no aplica. */
.app__main code { overflow-wrap: anywhere; }
.hintline b { color: var(--watt); font-weight: 500; }

/* ---------- live order ---------- */
.live { display: grid; gap: 12px; }
.live__row {
  display: flex; align-items: center; gap: 11px;
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--ink-2); padding: 12px 13px;
  font-family: var(--mono); font-size: 12.5px; color: var(--fg-3);
}
.live__row.is-on { border-color: var(--line-2); color: var(--fg-2); }
.live__row.is-done { border-color: var(--signal); color: var(--fg); }
.live__dot {
  width: 9px; height: 9px; flex: none; background: var(--line-2);
}
.live__row.is-on .live__dot { background: var(--watt); animation: pulse 1.1s infinite; }
.live__row.is-done .live__dot { background: var(--signal); animation: none; }
.live__row time { margin-left: auto; color: var(--fg-3); font-size: 11px; }

.numberbox {
  border: 1px solid var(--line-2); border-radius: var(--r);
  background: var(--ink-2); padding: 16px; text-align: center;
}
.numberbox__n {
  font-family: var(--px); font-size: clamp(15px, 3.4vw, 21px); color: var(--fg);
  display: block; margin-bottom: 10px; overflow-wrap: anywhere;
}
.numberbox__a { display: flex; gap: 9px; justify-content: center; flex-wrap: wrap; }

.sms {
  border: 1px solid var(--signal); border-radius: var(--r);
  background: rgba(53, 240, 160, .07); padding: 14px;
}
.sms__from {
  font-family: var(--mono); font-size: 10.5px; color: var(--signal);
  text-transform: uppercase; letter-spacing: .1em; margin: 0 0 8px;
}
.sms__body { font-family: var(--mono); font-size: 13px; color: var(--fg); margin: 0 0 12px; }
.sms__code {
  font-family: var(--px); font-size: clamp(17px, 4vw, 24px); color: var(--signal);
  letter-spacing: .12em; display: block; margin-bottom: 12px;
}
/* Las dos cosas que se pueden querer con un código recién llegado:
   quedárselo, o pedir otro en el mismo número. Van en fila y envuelven
   porque en móvil los dos botones no caben en el ancho de la caja. */
.sms__a { display: flex; flex-wrap: wrap; gap: 9px; }

.emptystate {
  border: 1px dashed var(--line-2); border-radius: var(--r);
  padding: 30px 18px; text-align: center;
  font-family: var(--mono); font-size: 12.5px; color: var(--fg-3);
}

/* ---------- recent / repeat ---------- */
.recent { display: grid; gap: 8px; }
.recent__i {
  display: flex; align-items: center; gap: 11px; width: 100%;
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--ink-2); color: var(--fg-2);
  font-family: var(--mono); font-size: 12.5px; padding: 10px 12px;
  cursor: pointer; text-align: left;
}
.recent__i:hover { border-color: var(--signal); color: var(--fg); }
.recent__i b { font-weight: 500; color: var(--fg); overflow-wrap: anywhere; }
.recent__i span { flex: none; }
.recent__i span { margin-left: auto; color: var(--fg-3); font-size: 11px; }

/* ---------- responsive ---------- */
@media (max-width: 860px) {
  .app { grid-template-columns: 1fr; }
  .side {
    position: sticky; top: var(--bar); z-index: 30;
    height: auto; flex-direction: row; align-items: center;
    gap: 8px; overflow-x: auto;
    border-right: 0; border-bottom: 1px solid var(--line);
    padding: 10px var(--pad);
    -webkit-overflow-scrolling: touch;
  }
  .side__group { margin: 0 !important; display: flex; gap: 8px; }
  /* En el riel horizontal, empujar el logout al final lo dejaba fuera de
     la vista; aquí va detrás del resto, separado por una línea. */
  .side__foot {
    margin: 0 !important; padding: 0 0 0 10px;
    border-top: 0; border-left: 1px solid var(--line);
  }
  .side__t { display: none; }
  .side a, .side__out { white-space: nowrap; border: 1px solid var(--line); }
  .appbar .brand { width: auto; border-right: 0; padding-left: var(--pad); }
}
@media (max-width: 560px) {
  .svcgrid { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); }
  .wallet-chip__k { display: none; }
}

/* ============================================================
   DASHBOARD
   ============================================================ */
.dash { display: grid; gap: var(--gap); min-width: 0; }
/* Un item de grid trae min-width:auto, que es min-content: sin esto la
   tabla de órdenes y las cifras en Press Start 2P estiran la columna
   por encima del ancho de la pantalla en vez de encogerse. */
.dash > *, .dash__cols > *, .statgrid > *, .panel, .order > * { min-width: 0; }

.statgrid { display: grid; gap: var(--gap); grid-template-columns: repeat(4, minmax(0, 1fr)); min-width: 0; }
.stat {
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--slate); padding: 14px clamp(14px, 1.5vw, 18px);
  min-width: 0;
}
.stat__k {
  font-family: var(--mono); font-size: 10px; color: var(--fg-3);
  text-transform: uppercase; letter-spacing: .11em; margin: 0 0 10px;
}
.stat__v {
  font-family: var(--px); font-size: clamp(11px, 1.7vw, 17px); color: var(--fg);
  display: block; overflow-wrap: anywhere;
}
.stat__v.is-signal { color: var(--signal); }
.stat__d { font-family: var(--mono); font-size: 11px; color: var(--fg-3); margin: 8px 0 0; line-height: 1.45; }

.dash__cols { display: grid; gap: var(--gap); grid-template-columns: minmax(0, 1fr) 360px; min-width: 0; align-items: start; }

/* acceso rápido: el flujo principal en 1 clic */
.quick { display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(178px, 1fr)); }
.qbtn {
  display: flex; align-items: flex-start; gap: 9px; text-align: left; min-width: 0;
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--ink-2); color: var(--fg-2);
  font-family: var(--mono); font-size: 13px; padding: 11px 12px; cursor: pointer;
  transition: border-color .15s var(--ease), transform .15s var(--ease);
}
.qbtn:hover { border-color: var(--signal); color: var(--fg); transform: translateY(-1px); }
.qbtn:disabled { opacity: .5; cursor: not-allowed; transform: none; }
.qbtn > span { min-width: 0; overflow-wrap: anywhere; }
.qbtn i { width: 8px; height: 8px; background: var(--signal); flex: none; margin-top: 4px; }
.qbtn b { margin-left: auto; font-family: var(--px); font-size: 10px; font-weight: 400; color: var(--fg-3); }
.qbtn em {
  font-style: normal; display: block; font-size: 10.5px;
  color: var(--fg-3); margin-top: 2px;
}

/* tabla de órdenes */
.otable__scroll { overflow-x: auto; }
.otable { width: 100%; border-collapse: collapse; font-family: var(--mono); font-size: 12.5px; }
.otable th {
  text-align: left; font-weight: 500; color: var(--fg-3);
  font-size: 10px; text-transform: uppercase; letter-spacing: .1em;
  padding: 0 18px 12px 0; white-space: nowrap;
}
.otable th:last-child, .otable td:last-child { padding-right: 0; }
.otable td {
  padding: 13px 18px 13px 0; color: var(--fg-2);
  border-top: 1px solid var(--line); white-space: nowrap;
}
.otable td b { color: var(--fg); font-weight: 500; }
.otable code { font-size: 12px; color: var(--signal); }

.pill {
  display: inline-block; font-size: 9.5px; letter-spacing: .09em;
  text-transform: uppercase; border-radius: 3px; padding: 2px 6px;
  border: 1px solid currentColor;
}
.pill--ok   { color: var(--signal); }
.pill--wait { color: var(--watt); }
.pill--dead { color: var(--fg-3); }

/* En una TABLA todas miden lo mismo. Suelta, una pastilla se ciñe a su
   palabra y está bien; en una columna, doce cajas de anchos distintos
   dibujan un borde serrado en vertical y el ojo lee el contorno antes que
   el estado. El ancho lo fija la etiqueta más larga que puede caer ahí
   —"delivered", "cancelled", "confirmed": nueve caracteres— y se escribe
   en `ch`, que en monoespaciada ES un carácter: sin número mágico que se
   descuadre si cambia la fuente. Los 14px son el padding y el borde, que
   `box-sizing: border-box` mete dentro del min-width, y el .9em el
   letter-spacing de los nueve (.81em) redondeado hacia arriba: al ras
   exacto el navegador calcula `ch` con una centésima menos que el ancho
   real y las de nueve letras se salían por contenido — 73.00 contra
   72.98, invisible pero ya no eran iguales.

   Sólo en tablas: las pastillas sueltas de /rentals y /short van pegadas a
   su número, y ahí estirarlas a un ancho fijo sería dejar un hueco sin
   motivo. */
.otable .pill { min-width: calc(9ch + .9em + 14px); text-align: center; }

/* estado de proveedores */
.pstat { display: grid; gap: 12px; }
/* Flex y no grid: el icono de un proveedor puede no estar —una marca puede
   quitárselo, y en estilo classic los sprites no se pintan—, y una rejilla
   de tres columnas fijas dejaría el nombre apretado en los 22px del hueco
   vacío. En flex, lo que no está simplemente no ocupa. */
.pstat__r { display: flex; gap: 10px; align-items: center; }
.pstat__r > span:first-of-type { flex: 1; min-width: 0; }
.pstat__r canvas { width: 22px; height: 22px; image-rendering: pixelated; flex: none; }
.pstat__r .provicon { width: 22px; height: 22px; flex: none; object-fit: contain; border-radius: 3px; }
.pstat__n { font-family: var(--mono); font-size: 12.5px; color: var(--fg); }
.pstat__bar { display: block; height: 3px; background: var(--line); border-radius: 2px; margin-top: 5px; }
.pstat__bar i { display: block; height: 100%; background: var(--accent, var(--signal)); border-radius: 2px; transition: width .8s var(--ease); }
.pstat__v { font-family: var(--mono); font-size: 11px; color: var(--fg-3); }

@media (max-width: 760px) {
  .statgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .appbar__right { gap: 7px; }
  .wallet-chip { padding: 7px 9px; }
  .appbar__in { gap: 10px; }
  .appbar .brand__txt { display: none; }
  .appbar__right .btn { padding: 9px 11px; }

  /* El panel cuelga del botón (right: 0), y en pantallas estrechas el
     botón no está lo bastante lejos del borde izquierdo: 330px de panel
     se salían 29px fuera de la pantalla. Aquí se ancla al viewport. */
  .notif__panel {
    position: fixed; top: 68px; left: 12px; right: 12px; width: auto;
  }
}

/* ============================================================
   RENTALS
   ============================================================ */
.terms { display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(94px, 1fr)); }
.term {
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--ink-2); color: var(--fg-2);
  padding: 10px 8px; cursor: pointer; text-align: center;
  font-family: var(--mono); min-width: 0;
}
.term:hover { border-color: var(--line-2); color: var(--fg); }
.term.on { border-color: var(--signal); background: rgba(53, 240, 160, .10); color: var(--signal); }
.term b { display: block; font-family: var(--px); font-size: 13px; font-weight: 400; }
.term em { display: block; font-style: normal; font-size: 10px; color: var(--fg-3); margin-top: 4px; }
.term span { display: block; font-size: 11px; margin-top: 6px; }
.term.on em, .term.on span { color: inherit; opacity: .8; }

.rent {
  border: 1px solid var(--line-2); border-radius: var(--r);
  background: var(--ink-2); padding: 14px; min-width: 0;
}
.rent + .rent { margin-top: 10px; }
.rent__top { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.rent__n {
  font-family: var(--px); font-size: clamp(11px, 2.6vw, 14px); color: var(--fg);
  overflow-wrap: anywhere;
}
.rent__m {
  font-family: var(--mono); font-size: 11px; color: var(--fg-3);
  margin: 8px 0 0; overflow-wrap: anywhere;
}
.rent__bar { display: block; height: 4px; background: var(--line); border-radius: 2px; margin: 10px 0 12px; }
.rent__bar i { display: block; height: 100%; background: var(--signal); border-radius: 2px; }
.rent__acts { display: flex; flex-wrap: wrap; gap: 8px; }

.rent__msgs { margin-top: 12px; display: grid; gap: 8px; }

/* ---------- el panel de órdenes activas, paginado ----------
   Lo comparten el "Active rentals" de /rentals y el "Active orders" de
   /short: los dos listan órdenes vivas en la columna estrecha, así que
   los dos tenían el mismo problema — el panel crecía sin tope y la
   columna derecha se estiraba muy por debajo de la izquierda, y el
   desnivel se veía en cuanto pasaban de dos. Se pagina de dos en dos
   (rentals.js / short.js), la lista se queda con el sobrante de la
   columna y el paginador vive anclado al fondo, así que el panel mide lo
   que le toca y no lo que le echen.

   Los nombres son neutros (`olist`/`opager`, de "order") justo porque son
   de las dos: los de antes decían "rent" y en /short se leían mal. */
/* El grid de tarjetas vive aquí — ver `.panel--fill > div > .olist`. */
.olist { min-width: 0; }
.opager {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-top: 12px; padding-top: 12px;
  border-top: 1px solid var(--line);
}
.opager__n {
  font-family: var(--mono); font-size: 11px; color: var(--fg-3);
  overflow-wrap: anywhere;
}
.opager__b { display: flex; gap: 8px; flex: none; align-items: center; }

/* Cuántas filas por página. Vive DENTRO del paginador porque es la misma
   decisión que "página siguiente" vista por el otro lado: el que va a
   pasar de página es justo el que quiere no tener que pasarla. Botones y
   no un <select> por lo de siempre aquí: tres opciones caben a la vista y
   un desplegable esconde dos de las tres. */
.opager__sz { display: flex; align-items: center; gap: 6px; margin-right: 4px; }
.opager__sz em {
  font-style: normal; font-family: var(--mono); font-size: 10px;
  text-transform: uppercase; letter-spacing: .1em; color: var(--fg-3);
}
.opager__sz button {
  font-family: var(--mono); font-size: 11px; color: var(--fg-3);
  background: var(--ink-2); border: 1px solid var(--line); border-radius: var(--r);
  padding: 5px 9px; cursor: pointer; transition: .15s var(--ease);
}
.opager__sz button:hover { color: var(--fg); border-color: var(--line-2); }
.opager__sz button.on {
  background: rgba(53,240,160,.10); border-color: var(--signal); color: var(--signal);
}

/* En estrecho el paginador tiene tres grupos y no caben en una línea: se
   apilan en vez de aplastarse. */
@media (max-width: 620px) {
  .opager { flex-wrap: wrap; }
  /* `flex: none` deja la caja a su ancho de contenido, y en un móvil ese
     ancho —tres tamaños más dos botones de página— es más que el panel: se
     salía por la derecha. Aquí ocupa la línea entera y son sus hijos los
     que rompen. */
  .opager__b { flex: 1 1 100%; flex-wrap: wrap; justify-content: flex-start; }
}

@media (min-width: 981px) {
  /* La lista absorbe el hueco y scrollea SÓLO si las dos tarjetas no caben
     (una renta con códigos es bastante más alta que una recién comprada).
     `min-height: 0` en los DOS: es lo que deja encogerse a un hijo flex, y
     sin él en el wrapper —que por defecto trae `auto`— el contenido vuelve
     a empujar el panel y el paginador acaba fuera de su caja. */
  .panel--fill > div { min-height: 0; }
  .panel--fill > div > .olist {
    flex: 1; min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;        /* nada puede salirse a lo ancho */
    /* El riel se saca al padding del panel en vez de robarle ancho a las
       tarjetas. `.svcgrid` reserva la canaleta con `padding-right` porque
       ahí no hay nada con lo que alinearse; aquí sí: el título del panel y
       el paginador miden el ancho completo, y unas tarjetas 10px más
       estrechas que ellos se ven torcidas. El margen negativo estira la
       caja 10px sobre los 22px de padding del panel — justo donde se pinta
       el riel — y deja el área de contenido intacta. */
    margin-right: -10px;
  }
  .panel--fill > div > .opager { flex: none; }

  /* Y el alto de la fila lo fija la columna IZQUIERDA, no ésta.
     `align-items: stretch` iguala las dos cajas, pero la fila mide lo que
     mida la más alta: con varias rentas la derecha era la que mandaba y la
     izquierda quedaba con medio panel de aire debajo — el desnivel que se
     veía. `height: 0` la saca del cálculo de la fila y `min-height: 100%`
     la estira después hasta el alto ya decidido.

     El suelo de 360px es para el caso contrario: recién entrado, sin
     servicio elegido, los tres pasos de la izquierda miden poco y sin él
     el panel se quedaría demasiado corto para enseñar una tarjeta entera
     con su paginador.

     En /rentals y /short, que son las dos que listan órdenes vivas aquí.
     /recharge también comparte `.order--tall` y se queda fuera: su columna
     derecha no es una lista, es un recibo, y debe crecer con su contenido. */
  [data-page="rentals"] .order--tall > div:last-child,
  [data-page="short"]   .order--tall > div:last-child { height: 0; min-height: 100%; }
  [data-page="rentals"] .order--tall > div:last-child > .panel--fill,
  [data-page="short"]   .order--tall > div:last-child > .panel--fill { min-height: 360px; }
}
.rmsg {
  border: 1px solid var(--signal); border-radius: var(--r);
  background: rgba(53, 240, 160, .07); padding: 11px;
}
.rmsg__f {
  font-family: var(--mono); font-size: 10px; color: var(--signal);
  text-transform: uppercase; letter-spacing: .09em; margin: 0 0 7px;
}
.rmsg__c {
  font-family: var(--px); font-size: clamp(13px, 3vw, 17px); color: var(--signal);
  letter-spacing: .1em; display: block; margin-bottom: 7px; cursor: pointer;
}
.rmsg__c:hover { text-decoration: underline; }
.rmsg__t { font-family: var(--mono); font-size: 12px; color: var(--fg-2); margin: 0; overflow-wrap: anywhere; }

/* Órdenes activas: cada tarjeta se lee sola — la renta es un buzón, la
   orden corta es un número esperando su código. Viven en la columna
   estrecha (314 px útiles), así que el mínimo va con min(): un
   minmax(330px, …) pelado forma igual una pista de 330 px aunque el panel
   mida menos, y la tarjeta se saldría por la derecha.

   El grid va en .olist y NO en el wrapper: desde que el panel se pagina,
   el wrapper tiene dos hijos —la lista y el paginador— y dejarle el grid
   arriba ponía el paginador como una "tarjeta" más y, peor, quitaba la
   separación entre tarjetas (el gap ya no caía entre ellas y la regla de
   abajo anula el margin-top). */
.olist {
  display: grid; gap: var(--gap);
  grid-template-columns: repeat(auto-fill, minmax(min(330px, 100%), 1fr));
  align-items: start; align-content: start;
}
.olist .rent + .rent { margin-top: 0; }

/* ============================================================
   HISTORY
   ============================================================ */
.hfilters { display: grid; gap: 12px; grid-template-columns: minmax(0, 1fr) auto; align-items: center; margin-bottom: 14px; }
.hfilters .seg { margin-bottom: 0; }
.htotals { display: grid; gap: var(--gap); grid-template-columns: repeat(3, minmax(0, 1fr)); margin-bottom: var(--gap); min-width: 0; }

/* El riel de estados. NO tenía regla propia aquí: `.cats` sólo existe en
   services.css, que /history no carga, así que las pastillas caían pegadas
   a la cabecera de la tabla y sin separación entre ellas. Vacío no ocupa —
   con un solo estado el filtro se retira (history.js) y ese hueco de 20px
   dejaría un salto sin nada dentro. */
.cats { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 20px; }
.cats:empty { display: none; }

.hrow { display: none; }
.otable td .sub2 { display: block; color: var(--fg-3); font-size: 11px; margin-top: 5px; }

@media (max-width: 860px) {
  .hfilters { grid-template-columns: 1fr; }
  .hfilters .seg { width: 100%; }
  .hfilters .seg button { flex: 1; }
  .htotals { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ============================================================
   RECHARGE
   ============================================================ */
.picker input[type="number"] { padding-right: 14px; }
/* los spinners nativos estorban en un campo de dinero y no aportan nada */
.picker input[type="number"]::-webkit-outer-spin-button,
.picker input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.picker input[type="number"] { -moz-appearance: textfield; appearance: textfield; }

/* Aviso de que la dirección no es real. Va en magenta, el único color
   del sistema que no significa "todo bien", y con borde sólido: si algo
   tiene que leerse antes de mover dinero, es esto. */
.warnbox {
  border: 1px solid var(--pulse); border-radius: var(--r);
  background: rgba(255, 77, 157, .08); padding: 13px;
  font-family: var(--mono); font-size: 12px; color: var(--fg-2);
  margin-bottom: 12px;
}
.warnbox b {
  display: block; color: var(--pulse); font-weight: 500;
  margin-bottom: 6px; font-size: 12.5px;
}
.warnbox strong { color: var(--fg); font-weight: 500; }

/* El aviso de RED. Va en ámbar y no en el magenta del resto: los dos avisos
   de la factura se leen a la vez, y en el mismo color el ojo los toma por uno
   solo y salta al segundo. Ámbar es además el color que /short y /rentals ya
   usan para "esto es una cuenta atrás, presta atención", frente al magenta de
   "esto ya salió mal". Aquí todavía no ha salido mal: se está a tiempo. */
.warnbox--net {
  border-color: var(--watt); background: rgba(255, 197, 61, .07);
}
.warnbox--net b { color: var(--watt); }

.inv {
  border: 1px solid var(--line-2); border-radius: var(--r);
  background: var(--ink-2); padding: 16px; text-align: center;
}
.inv__k {
  font-family: var(--mono); font-size: 10px; color: var(--fg-3);
  text-transform: uppercase; letter-spacing: .11em; margin: 0 0 8px;
}
.inv__amt {
  display: block; font-family: var(--px); font-size: clamp(13px, 3.2vw, 19px);
  color: var(--signal); margin-bottom: 16px; overflow-wrap: anywhere;
}
.inv__addr {
  display: block; font-family: var(--mono); font-size: 12.5px; color: var(--fg);
  background: var(--slate); border: 1px solid var(--line);
  border-radius: var(--r); padding: 11px; overflow-wrap: anywhere;
  line-height: 1.55;
}

/* ============================================================
   API — panel de desarrollador
   ============================================================ */
.field2 { margin-bottom: 14px; min-width: 0; }
.field2 .lbl { display: block; margin-bottom: 7px; }
.field2--split { display: grid; gap: 12px; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.field2 input[type="text"], .field2 input[type="url"] {
  width: 100%; background: var(--ink-2); color: var(--fg);
  border: 1px solid var(--line); border-radius: var(--r);
  font-family: var(--mono); font-size: 13.5px; padding: 11px 13px;
}
.field2 input:focus { outline: none; border-color: var(--signal); }
.field2 input::placeholder { color: var(--fg-3); }
.field2 .select { width: 100%; }
.field2 .seg { margin-bottom: 0; }
.field2 .field__msg {
  font-family: var(--mono); font-size: 11.5px; margin: 7px 0 0;
  min-height: 15px; color: var(--fg-3);
}

/* scopes y eventos: la misma pastilla conmutable */
.scopes { display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(186px, 1fr)); }
.scope {
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--ink-2); color: var(--fg-2);
  padding: 9px 11px; cursor: pointer; text-align: left; min-width: 0;
}
.scope:hover { border-color: var(--line-2); color: var(--fg); }
.scope.on { border-color: var(--signal); background: rgba(53, 240, 160, .10); }
.scope b {
  display: block; font-family: var(--mono); font-size: 12px;
  font-weight: 500; overflow-wrap: anywhere;
}
.scope.on b { color: var(--signal); }
.scope em {
  display: block; font-style: normal; font-family: var(--mono);
  font-size: 10.5px; color: var(--fg-3); margin-top: 3px;
}

.mkkey { margin-top: 14px; }
.mkkey summary { list-style: none; cursor: pointer; }
.mkkey summary::-webkit-details-marker { display: none; }
.mkkey[open] summary { margin-bottom: 14px; }
.mkkey__body {
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--ink-2); padding: 15px;
}

/* La key completa. Verde y con borde sólido porque es lo único de la
   página que hay que leer AHORA: no se vuelve a mostrar. */
.reveal {
  border: 1px solid var(--signal); border-radius: var(--r);
  background: rgba(53, 240, 160, .07); padding: 14px; margin-bottom: 14px;
}
.reveal__t {
  font-family: var(--mono); font-size: 10.5px; color: var(--signal);
  text-transform: uppercase; letter-spacing: .1em; margin: 0 0 9px;
}
.reveal__k {
  display: block; font-family: var(--mono); font-size: 13px; color: var(--fg);
  background: var(--ink); border: 1px solid var(--line-2); border-radius: var(--r);
  padding: 11px; overflow-wrap: anywhere; line-height: 1.6;
}

.verb {
  font-family: var(--mono); font-size: 10px; font-weight: 700;
  letter-spacing: .06em; border: 1px solid currentColor;
  border-radius: 3px; padding: 2px 5px;
}
.verb--get { color: var(--wire); }
.verb--post { color: var(--signal); }
.verb--delete { color: var(--pulse); }

.tag {
  display: inline-block; font-family: var(--mono); font-size: 10px;
  color: var(--fg-3); border: 1px solid var(--line-2); border-radius: 3px;
  padding: 2px 5px; margin: 0 4px 4px 0;
}

.otable tr.is-off td { opacity: .5; }

.code__out {
  margin: 0; padding: 18px; overflow-x: auto;
  font-family: var(--mono); font-size: 12.5px; line-height: 1.8;
  color: var(--fg-2); white-space: pre;
}
.code__out code { font: inherit; color: inherit; white-space: pre; }

.hookout {
  border: 1px solid var(--line-2); border-radius: var(--r);
  background: var(--ink-2); padding: 13px; margin-top: 12px;
}
.hookout__t {
  font-family: var(--mono); font-size: 10.5px; color: var(--wire);
  text-transform: uppercase; letter-spacing: .09em; margin: 0 0 9px;
  overflow-wrap: anywhere;
}
.hookout__b {
  margin: 0; padding: 11px; overflow-x: auto;
  background: var(--ink); border: 1px solid var(--line); border-radius: var(--r);
  font-family: var(--mono); font-size: 11.5px; line-height: 1.65; color: var(--fg-2);
}

/* La referencia embebida: un <details> por endpoint (y por evento de
   webhook), con su petición, su respuesta de ejemplo y su tabla de
   errores. La misma receta de summary sin marcador que .mkkey. */
.endp {
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--ink-2); margin-bottom: 10px;
}
.endp summary {
  list-style: none; cursor: pointer; display: flex; align-items: center;
  gap: 10px; padding: 11px 13px; min-width: 0; flex-wrap: wrap;
}
.endp summary::-webkit-details-marker { display: none; }
.endp summary:hover { background: rgba(255, 255, 255, .02); }
.endp summary > code {
  font-family: var(--mono); font-size: 12.5px; color: var(--fg);
  overflow-wrap: anywhere;
}
.endp__what {
  font-family: var(--mono); font-size: 11px; color: var(--fg-3);
  margin-left: auto; text-align: right;
}
.endp[open] > summary { border-bottom: 1px solid var(--line); }
.endp__body { padding: 13px; }
.endp__body > p {
  font-size: 13.5px; color: var(--fg-2); line-height: 1.7; margin: 0 0 4px;
}
.endp__body > p code, .endp__body td code {
  font-family: var(--mono); font-size: 12px; color: var(--watt);
  overflow-wrap: anywhere;
}
.endp__t {
  font-family: var(--mono); font-size: 10px; color: var(--fg-3);
  text-transform: uppercase; letter-spacing: .11em; margin: 14px 0 8px;
}
.endp__pre {
  margin: 0; padding: 11px; overflow-x: auto;
  background: var(--ink); border: 1px solid var(--line); border-radius: var(--r);
  font-family: var(--mono); font-size: 11.5px; line-height: 1.65; color: var(--fg-2);
}
.endp__pre code { font: inherit; color: inherit; white-space: pre; }

@media (max-width: 560px) {
  .field2--split { grid-template-columns: 1fr; }
  .scopes { grid-template-columns: 1fr; }
  .endp__what { display: none; }
}

/* ============================================================
   RESPONSIVE — al final a propósito
   ------------------------------------------------------------
   .dash__cols se define en la sección del dashboard, más abajo que
   el bloque de layout; una media query colocada arriba perdía por
   orden de cascada y la columna lateral seguía ocupando 360px en
   móvil. Los overrides de ancho van aquí, después de todo.
   ============================================================ */
@media (max-width: 980px) {
  .order, .dash__cols { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 760px) {
  .statgrid, .htotals { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* A 375px dos columnas siguen siendo legibles y ahorran media pantalla de
   scroll; la columna única se reserva para pantallas realmente estrechas. */
@media (max-width: 360px) {
  .statgrid, .htotals { grid-template-columns: minmax(0, 1fr); }
}

/* ============================================================
   SCROLLBARS
   ------------------------------------------------------------
   Las nativas de Windows son gruesas, claras y redondeadas: en un
   panel casi negro se ven como un parche pegado encima. Estas
   siguen el sistema —cuadradas, de 1px de línea, del color de los
   bordes— y sólo se destacan al pasar por encima.
   ============================================================ */
.svcgrid,
.olist,
.otable__scroll,
.qt__scroll,
.notif__list,
.code__out,
.hookout__b,
.side,
.cats,
.hfilters,
.seg,
.modal__body {
  scrollbar-width: thin;
  scrollbar-color: var(--line-2) transparent;
}

.svcgrid::-webkit-scrollbar,
.olist::-webkit-scrollbar,
.otable__scroll::-webkit-scrollbar,
.qt__scroll::-webkit-scrollbar,
.notif__list::-webkit-scrollbar,
.code__out::-webkit-scrollbar,
.hookout__b::-webkit-scrollbar,
.side::-webkit-scrollbar,
.modal__body::-webkit-scrollbar {
  width: 10px; height: 10px;
}

.svcgrid::-webkit-scrollbar-track,
.olist::-webkit-scrollbar-track,
.otable__scroll::-webkit-scrollbar-track,
.qt__scroll::-webkit-scrollbar-track,
.notif__list::-webkit-scrollbar-track,
.code__out::-webkit-scrollbar-track,
.hookout__b::-webkit-scrollbar-track,
.side::-webkit-scrollbar-track,
.modal__body::-webkit-scrollbar-track {
  background: transparent;
}

/* El borde transparente deja el pulgar en 4px reales y centrado: un
   riel fino que no compite con el contenido. */
.svcgrid::-webkit-scrollbar-thumb,
.olist::-webkit-scrollbar-thumb,
.otable__scroll::-webkit-scrollbar-thumb,
.qt__scroll::-webkit-scrollbar-thumb,
.notif__list::-webkit-scrollbar-thumb,
.code__out::-webkit-scrollbar-thumb,
.hookout__b::-webkit-scrollbar-thumb,
.side::-webkit-scrollbar-thumb,
.modal__body::-webkit-scrollbar-thumb {
  background: var(--line-2);
  border: 3px solid transparent;
  background-clip: content-box;
  border-radius: 0;
}
.svcgrid::-webkit-scrollbar-thumb:hover,
.olist::-webkit-scrollbar-thumb:hover,
.otable__scroll::-webkit-scrollbar-thumb:hover,
.qt__scroll::-webkit-scrollbar-thumb:hover,
.notif__list::-webkit-scrollbar-thumb:hover,
.code__out::-webkit-scrollbar-thumb:hover,
.hookout__b::-webkit-scrollbar-thumb:hover,
.side::-webkit-scrollbar-thumb:hover,
.modal__body::-webkit-scrollbar-thumb:hover {
  background: var(--signal);
  background-clip: content-box;
}

.svcgrid::-webkit-scrollbar-corner,
.otable__scroll::-webkit-scrollbar-corner,
.qt__scroll::-webkit-scrollbar-corner,
.code__out::-webkit-scrollbar-corner {
  background: transparent;
}

/* Los rieles de pastillas (riel lateral en móvil, filtros, segmentos) no
   necesitan barra visible: se arrastran. */
.side::-webkit-scrollbar,
.cats::-webkit-scrollbar,
.hfilters::-webkit-scrollbar,
.seg::-webkit-scrollbar { height: 0; }
@media (min-width: 861px) {
  .side::-webkit-scrollbar { width: 10px; }
}

/* ---------- ficha de API del dashboard ---------- */
/* Filas etiqueta/valor, no columnas. En una columna de 360px el grid de
   `auto-fit` no daba para dos, y encima `.panel--fill > div` (flex,
   column, más abajo) le ganaba en especificidad y lo volvía tres campos
   estirados: la ficha acababa cien píxeles por debajo de la tabla de al
   lado. Tres filas miden lo que miden, y la ficha ya no lleva
   `panel--fill`: no tiene nada que llenar. */
.apistrip__in { display: grid; gap: 0; }
.apistrip__f {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 14px; padding: 11px 0; min-width: 0;
  border-top: 1px solid var(--line);
}
.apistrip__f:first-child { border-top: 0; padding-top: 0; }
.apistrip__f span {
  font-family: var(--mono); font-size: 10px; color: var(--fg-3);
  text-transform: uppercase; letter-spacing: .11em; flex: none;
}
.apistrip__f b {
  font-family: var(--mono); font-size: 12.5px; font-weight: 500; color: var(--fg);
  text-align: right; overflow-wrap: anywhere; min-width: 0;
}
/* Un valor que todavía no existe se apaga en vez de leerse como dato. */
.apistrip__f b.is-dim { color: var(--fg-3); }

/* El cuadrito del webhook es el mismo de `.qbtn i` y `.live__dot`: sin él
   "not set" se lee igual que cualquier otro valor, y es lo único de la
   ficha sobre lo que hay algo que hacer.
   La URL se recorta en una línea con puntos suspensivos —el title lleva la
   entera—: un webhook largo repartido en tres renglones a la derecha de la
   etiqueta desmonta la ficha, y lo que se reconoce de un vistazo es el
   host, que es justo lo que queda. */
.apistrip__f b.is-set, .apistrip__f b.is-off {
  display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.apistrip__f b.is-set::before, .apistrip__f b.is-off::before {
  content: ''; display: inline-block; width: 7px; height: 7px; margin-right: 7px;
}
.apistrip__f b.is-set::before { background: var(--signal); }
.apistrip__f b.is-off { color: var(--fg-3); }
.apistrip__f b.is-off::before { background: var(--line-2); }


/* ============================================================
   PANELES A TODO EL ANCHO
   ------------------------------------------------------------
   Cuando un panel deja de vivir en una columna estrecha, su
   contenido tiene que aprovechar el ancho en vez de estirarse en
   una tira. Si no, el hueco no desaparece: se muda dentro del
   panel.
   ============================================================ */

/* Órdenes recientes para repetir: en fila, no una debajo de otra. */
.recent { grid-template-columns: repeat(auto-fill, minmax(248px, 1fr)); }

/* Factura: aviso arriba a todo el ancho, y debajo dirección y progreso
   en paralelo. */
.invsplit { display: grid; gap: var(--gap); align-items: stretch; }
/* Los tres pasos se reparten el alto de la caja de la dirección en vez de
   apelotonarse arriba: queda una línea de tiempo, no un hueco debajo. */
@media (min-width: 861px) {
  .invsplit > .live { align-content: space-between; }
}

@media (min-width: 861px) {
  .invsplit { grid-template-columns: minmax(0, 1fr) minmax(0, 380px); }

}

/* La columna de resumen acompaña al scroll.
   ------------------------------------------------------------
   En un formulario de dos columnas la de la derecha —precio y botón—
   siempre acaba antes que la de entradas. En vez de dejar ese hueco
   muerto, el resumen se queda pegado arriba mientras se recorre el
   resto: el precio y el botón siguen a la vista, que es justo lo que
   se quiere mirar mientras se elige. Sólo a partir de 981px, que es
   donde el layout deja de ser una sola columna. */
@media (min-width: 981px) {
  .order > *:last-child { position: sticky; top: calc(var(--bar) + var(--gap)); }
}

/* Columna derecha que llena el alto de la izquierda.
   ------------------------------------------------------------
   El sketch pide confirmar al lado de servicio+proveedor y tan alto como
   los dos juntos. Con filas auto/1fr, el resumen conserva su alto natural
   y el panel de la orden en vivo absorbe el resto: donde antes quedaba un
   vacío ahora está el sitio donde va a aparecer el número.
   Dentro del @media a propósito: suelto ganaría por cascada al bloque de
   una sola columna y estiraría paneles también en el móvil. */
@media (min-width: 981px) {
  /* .order trae align-items:start, que deja cada columna con su alto
     natural; sin estirarla, el 1fr de abajo no tiene sobrante que repartir. */
  .order--tall, .dash__cols--tall { align-items: stretch; }

  /* Sólo la derecha reparte el sobrante. Si la izquierda también lo hiciera,
     al crecer la orden en vivo se estirarían servicio y proveedor, metiendo
     el hueco dentro de esos paneles en vez de quitarlo. */
  .order--tall > div:first-child { align-content: start; }
  /* .order > .panel lleva align-self:start; aquí queremos lo contrario. */
  .order--tall > .panel { align-self: stretch; }
  .order--tall > div:last-child {
    align-content: stretch;
    grid-template-rows: auto minmax(0, 1fr);
  }
  /* y el resumen no se pega al scroll aquí: ya llena su columna */
  .order--tall > *:last-child { position: static; }

  /* Un .panel--fill suelto en .order--tall (sin panel debajo que absorba)
     estira el propio resumen: cifras arriba, botón anclado al fondo. */
  .order--tall > .panel--fill .recap { margin-bottom: auto; }

  .panel--fill { display: flex; flex-direction: column; }
  .panel--fill > div { flex: 1; display: flex; flex-direction: column; }
  .panel--fill .emptystate { flex: 1; display: grid; place-content: center; }
  /* Mismo trato para la orden en vivo: el panel llena la columna y las dos
     cajas se quedan en el medio en vez de flotar sobre el hueco. */
  .panel--fill .livemin { flex: 1; align-content: center; }

  /* EL SOBRANTE LO ABSORBE LA IZQUIERDA, NUNCA LA DERECHA.
     ------------------------------------------------------------
     La fila mide lo que la columna más alta. Antes la que repartía ese
     sobrante era la derecha, y con ella más alta que la izquierda el
     hueco caía DEBAJO de la tabla de órdenes: la ficha de API terminaba
     cien píxeles por debajo, en escalón. Las dos situaciones no se ven
     igual —una columna lateral que acaba antes es lo normal en un panel;
     una que sobresale se lee como rota—, así que estira sólo la izquierda
     y sólo su ÚLTIMO panel: la tabla, que es lo que puede crecer sin que
     se le vea el hueco (el estado vacío se centra por `panel--fill`, y
     con filas la tabla deja sitio a las que faltan). Los de arriba
     conservan su alto, que era la razón de no estirar esta columna: el
     hueco no se mete en "Order in one click".
     Al revés que `.order--tall` justo aquí encima, y a propósito: allí la
     columna que crece es la de la orden en vivo, que es donde el usuario
     está mirando. */
  .dash__cols--tall > div { display: flex; flex-direction: column; }
  .dash__cols--tall > div:first-child > :last-child { flex: 1; }
}

/* ---------- modal de la orden ---------- */
/* El proceso de compra se mudó aquí: la subasta, la compra del número y la
   espera del SMS ocupan el centro de la pantalla mientras duran. El panel
   de la página se queda sólo con lo que se vuelve a mirar después.
   Cerrarlo NO cancela nada — la orden sigue viva y el panel la reabre. */
.modal {
  position: fixed; inset: 0; z-index: 120;
  display: grid; place-items: center; padding: var(--pad);
}
.modal[hidden] { display: none; }
.modal__scrim { position: absolute; inset: 0; background: rgba(5, 6, 11, .74); }
.modal__card {
  position: relative; z-index: 1;
  width: min(440px, 100%); max-height: calc(100vh - var(--pad) * 2);
  display: flex; flex-direction: column;
  border: 1px solid var(--line-2); border-radius: var(--r);
  background: var(--slate); box-shadow: 0 18px 60px rgba(0, 0, 0, .6);
  animation: rise .22s var(--ease);
}
.modal__head {
  display: flex; align-items: center; gap: 12px; flex: none;
  padding: 13px 14px; border-bottom: 1px solid var(--line);
}
.modal__head b {
  font-family: var(--mono); font-size: 11px; color: var(--fg-3);
  text-transform: uppercase; letter-spacing: .11em; font-weight: 500;
}
.modal__head em {
  font-style: normal; font-family: var(--mono); font-size: 11px;
  color: var(--fg-3); margin-left: auto; text-align: right; overflow-wrap: anywhere;
}
.modal__x {
  flex: none; width: 26px; height: 26px; display: grid; place-items: center;
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--slate-2); color: var(--fg-3);
  font-family: var(--mono); font-size: 13px; line-height: 1; cursor: pointer;
}
.modal__x:hover { border-color: var(--line-2); color: var(--fg); }
.modal__body { padding: 14px; overflow-y: auto; }
/* El pie lleva la explicación y, cuando la orden ya terminó, el botón de
   salir. La tarjeta del diálogo tapa la rejilla de servicios, así que un
   final sin salida evidente se lee como "la página se colgó": el clic cae
   en la tarjeta y no pasa nada. */
.modal__foot {
  flex: none; padding: 11px 14px; border-top: 1px solid var(--line);
  display: flex; align-items: center; gap: 12px;
  font-family: var(--mono); font-size: 11px; color: var(--fg-3);
}
.modal__foot span { flex: 1; min-width: 0; }
.modal__foot .btn { flex: none; }
/* el fondo no se mueve detrás del diálogo */
body.is-modal { overflow: hidden; }

/* ---------- orden en vivo, versión mínima ---------- */
/* Ya no narra el proceso: eso es cosa del diálogo. Aquí sólo el número y,
   cuando llega, el código. Mientras no llegan, un pendiente que gira para
   que se note que la orden sigue viva y no colgada. */
.livemin { display: grid; gap: 12px; }
.livemin__f {
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--ink-2); padding: 15px 14px; text-align: center;
}
.livemin__f.is-live { border-color: var(--signal); background: rgba(53, 240, 160, .07); }
.livemin__k {
  font-family: var(--mono); font-size: 10.5px; color: var(--fg-3);
  text-transform: uppercase; letter-spacing: .11em; margin: 0 0 10px;
}
.livemin__f.is-live .livemin__k { color: var(--signal); }
.livemin__v {
  font-family: var(--px); font-size: clamp(14px, 3.2vw, 19px); color: var(--fg);
  margin: 0 0 11px; overflow-wrap: anywhere;
}
.livemin__f.is-live .livemin__v { color: var(--signal); letter-spacing: .1em; }
.livemin__wait {
  display: inline-flex; align-items: center; gap: 9px; margin: 0;
  font-family: var(--mono); font-size: 12px; color: var(--watt);
}
.livemin__meta {
  font-family: var(--mono); font-size: 11px; color: var(--fg-3);
  margin: 0; text-align: center; overflow-wrap: anywhere;
}
.livemin__more {
  background: none; border: 0; padding: 0; cursor: pointer;
  font-family: var(--mono); font-size: 11px; color: var(--wire);
}
.livemin__more:hover { text-decoration: underline; }

/* Cuadrado que gira a saltos, no un aro que barre: el resto de la interfaz
   está hecha de píxeles y una animación continua aquí desentonaría. */
.pxspin { width: 11px; height: 11px; flex: none; position: relative; }
.pxspin::before {
  content: ""; position: absolute; inset: 0; background: currentColor;
  clip-path: polygon(0 0, 50% 0, 50% 50%, 0 50%);
  animation: spin 640ms steps(4) infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- estados muertos de la orden ---------- */
/* El paso donde murió (timeout o compra fallida) y la caja que dice por
   qué. Magenta y no ámbar: no es "espera", es "esto ya no va a pasar". */
.live__row.is-fail { border-color: var(--pulse); color: var(--fg-2); }
.live__row.is-fail .live__dot { background: var(--pulse); animation: none; }
.deadbox {
  border: 1px solid var(--pulse); border-radius: var(--r);
  background: rgba(255, 77, 157, .07); padding: 13px 14px;
  font-family: var(--mono); font-size: 12.5px; color: var(--fg);
  overflow-wrap: anywhere;
}
.livemin__f.is-dead { border-color: rgba(255, 77, 157, .55); }
.livemin__f.is-dead .livemin__k { color: var(--pulse); }
.livemin__dead {
  font-family: var(--mono); font-size: 12px; color: var(--pulse); margin: 0;
}

/* ---------- el bot de la orden ---------- */
/* El estado de una orden se lee antes en una cara que en una línea de
   texto: el bot cambia de humor con el evento (comprando, esperando el
   SMS, código, timeout) y la frase de al lado lo cuenta con palabras.
   Es el mismo bicho del registro a propósito — /signup y /short tienen
   que sentirse la misma web.

   `data-mood` en el contenedor tiñe lo destacado de la frase con el
   color que ya usa la página para ese estado: ámbar mientras se espera,
   magenta cuando la ventana se cerró vacía. */
.botline {
  display: flex; align-items: center; gap: 12px; flex: none;
  padding: 12px 14px; border-bottom: 1px solid var(--line);
  background: var(--ink-2);
}
/* 96 lógicos a 96 CSS: escala 1:1, la única que no parte píxeles. */
#omBotCv { width: 96px; height: 96px; flex: none; image-rendering: pixelated; }
.botsay {
  position: relative; flex: 1; min-width: 0; margin: 0;
  border: 1px solid var(--line-2); border-radius: var(--r);
  background: var(--slate-2); padding: 11px 13px;
  font-family: var(--mono); font-size: 12px; line-height: 1.6;
  color: var(--fg-2); overflow-wrap: anywhere;
}
/* el pico apunta al bot, no hacia arriba: están uno al lado del otro */
.botsay::after {
  content: ""; position: absolute; left: -7px; top: 50%; margin-top: -6px;
  width: 6px; height: 12px; background: var(--slate-2);
  border-top: 1px solid var(--line-2); border-bottom: 1px solid var(--line-2);
  clip-path: polygon(0 50%, 100% 0, 100% 100%);
}
.botsay b { color: var(--signal); font-weight: 500; }
.botline[data-mood="wait"] .botsay b { color: var(--watt); }
.botline[data-mood="sad"] .botsay b,
.botline[data-mood="error"] .botsay b { color: var(--pulse); }

/* En apaisado de móvil el diálogo entero mide menos que el bot: ahí manda
   la orden, y la frase sigue estando en la caja del estado muerto. */
@media (max-height: 520px) {
  .botline { display: none; }
}

/* ---------- salidas del estado muerto ---------- */
/* Un timeout no es el final del camino: el número murió, pero el servicio
   sigue elegido y hay otros proveedores con stock. Los botones son de
   compra —cobran— así que llevan el precio escrito, no un "reintentar"
   a ciegas. */
.deadbox p { margin: 0; }
.deadbox__a {
  display: flex; flex-wrap: wrap; gap: 9px; margin-top: 12px;
}

/* ============================================================
   ADMIN  (/admin)
   ------------------------------------------------------------
   Casi todo se reusa tal cual: `.panel`, `.otable`, `.pill`,
   `.stat`, `.seg`, `.chip`, `.opager` y `.modal` son los mismos
   que en /history y /rentals — un panel de administracion que
   invente su propio lenguaje visual se lee como otra aplicacion.

   Lo que si es propio son las tres cosas que no existian: un
   bloque de ACCION (un campo, su boton y la frase que explica
   que va a pasar), la ficha de un PROVEEDOR con sus dos fees
   editables, y la tarjeta de un PAR del pool de depositos, que
   ademas de enseñar filtra la tabla de abajo. Eso es lo unico
   que hay aqui abajo.
   ============================================================ */
.adm__sec[hidden] { display: none; }

/* ---------- gráfica de barras (Dashboard) ----------
   Barras y no una línea: cada barra es un periodo cerrado, y una línea
   entre dos días insinúa que hubo algo entre medias.

   SIN EJE Y, a propósito. Un eje con tres marcas ocupa una columna entera
   para decir menos que la lectura de arriba, que da la cifra exacta de la
   barra donde está el cursor y, en reposo, la del periodo en curso. El
   pico y la media van a su lado y son las dos referencias que hacen falta
   para saber si una barra es alta.

   Cada barra es un `<button>` de verdad: así se alcanza con el tabulador y
   se lee con el teclado, no solo con el ratón. */
.chart { padding-bottom: 26px; }

/* "Per month" no se parte en dos lineas: son tres etiquetas de dos
   palabras y partidas dejan de leerse como un mismo control. */
#sUnitSeg button { white-space: nowrap; }

.chart__read {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
  margin: 0 0 14px; font-family: var(--mono); font-size: 11.5px; color: var(--fg-2);
}
.chart__read b {
  font-family: var(--px); font-size: 18px; color: var(--signal); font-weight: 400;
  line-height: 1.1;
}
/* El resumen de la ventana se va al otro extremo: es contexto, no la
   lectura, y pegado a la cifra competiría con ella. */
.chart__read em {
  font-style: normal; color: var(--fg-3); margin-left: auto; text-align: right;
}

.chart__cols {
  display: flex; align-items: flex-end; gap: 3px;
  height: 168px; min-width: 0;
}
.chart__col {
  position: relative; flex: 1 1 0; min-width: 0; height: 100%;
  display: flex; flex-direction: column; justify-content: flex-end;
  background: none; border: 0; padding: 0; cursor: default;
  border-radius: 2px;
}
/* La barra. `min-height` para que un cero siga dibujando una marca: sin
   ella el eje se corta y parece que falta el dato en vez de valer cero. */
.chart__col b {
  display: block; width: 100%; min-height: 2px;
  background: var(--wire); border-radius: 2px 2px 0 0;
  transition: background .15s var(--ease);
}
.chart__col:hover b, .chart__col:focus-visible b { background: var(--signal); }
.chart__col:focus-visible { outline: 2px solid var(--wire); outline-offset: 2px; }

/* El periodo EN CURSO va rayado: no es una barra baja, es una barra a
   medias, y sin decirlo se lee como una caída justo el día que se mira. */
.chart__col.is-now b {
  background: repeating-linear-gradient(
    135deg, var(--wire) 0 3px, rgba(76, 201, 240, .3) 3px 7px);
}
.chart__col.is-now:hover b, .chart__col.is-now:focus-visible b {
  background: repeating-linear-gradient(
    135deg, var(--signal) 0 3px, rgba(53, 240, 160, .3) 3px 7px);
}

/* La cifra encima de la barra. Solo se pinta cuando caben (12 barras, no
   30): amontonadas no se lee ninguna y la lectura de arriba ya las da. */
.chart__col i {
  font-style: normal; font-family: var(--mono); font-size: 10px; color: var(--fg-3);
  text-align: center; margin-bottom: 4px; line-height: 1;
}

/* La fecha, fuera del alto de la gráfica para que no le robe sitio a las
   barras y siga cuadrada con su columna. */
.chart__col em {
  position: absolute; top: calc(100% + 7px); left: 50%; transform: translateX(-50%);
  font-style: normal; font-family: var(--mono); font-size: 9.5px; color: var(--fg-3);
  white-space: nowrap; display: none;
}
.chart__col.is-tick em { display: block; }

@media (max-width: 640px) {
  .chart__cols { height: 132px; gap: 2px; }
  .chart__col i { font-size: 9px; }
  .chart__read em { margin-left: 0; width: 100%; text-align: left; }
}

/* ---------- bloque de accion ---------- */
.admact {
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--ink-2); padding: 14px; margin-bottom: 12px;
}
.admact__t {
  font-family: var(--mono); font-size: 10px; color: var(--fg-3);
  text-transform: uppercase; letter-spacing: .11em; margin: 0 0 10px;
}
.admact__row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.admact__in {
  flex: 0 1 190px; min-width: 0;
  background: var(--slate); border: 1px solid var(--line); border-radius: var(--r);
  color: var(--fg); font-family: var(--mono); font-size: 12.5px; padding: 9px 11px;
}
.admact__in--wide { flex: 1 1 240px; }
.admact__in:focus { outline: none; border-color: var(--wire); }
.admact__in::placeholder { color: var(--fg-3); }
/* Un campo deshabilitado tiene que LEERSE deshabilitado: si no, un fee
   que se esta guardando parece un fee editable que no responde. */
.admact__in:disabled { opacity: .5; cursor: progress; }
.admact__d {
  font-family: var(--mono); font-size: 11px; color: var(--fg-3);
  margin: 10px 0 0; line-height: 1.55;
}

/* ---------- bitacora de una cuenta ---------- */
.admlog { display: grid; gap: 8px; }
.admlog__r {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 4px 10px;
  align-items: baseline;
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--slate); padding: 9px 11px;
  font-family: var(--mono); font-size: 11.5px;
}
.admlog__r b { color: var(--wire); font-weight: 500; }
.admlog__r span { color: var(--fg-2); overflow-wrap: anywhere; }
.admlog__r time { color: var(--fg-3); font-size: 10.5px; white-space: nowrap; }
/* El motivo ocupa la fila entera: es texto libre y en una columna estrecha
   se corta justo donde esta la explicacion. */
.admlog__r em {
  grid-column: 1 / -1; font-style: normal; color: var(--fg-3);
  font-size: 11px; overflow-wrap: anywhere;
}

/* ---------- proveedores ---------- */
.provgrid { display: grid; gap: var(--gap); grid-template-columns: repeat(2, minmax(0, 1fr)); }
.prov {
  border: 1px solid var(--line-2); border-radius: var(--r);
  background: var(--ink-2); padding: 14px; min-width: 0;
}
.prov__top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.prov__top b { font-family: var(--px); font-size: 12px; color: var(--fg); font-weight: 400; }
/* La pastilla es el interruptor: el estado y el sitio donde se cambia son
   el mismo objeto, que es como se lee sin leyenda. */
.prov__sw { background: none; cursor: pointer; font-family: var(--mono); }
.prov__sw:hover { background: rgba(233, 237, 247, .06); }
.prov__sw:disabled { opacity: .5; cursor: progress; }
.prov__id {
  font-family: var(--mono); font-size: 11px; color: var(--fg-3);
  margin: 8px 0 12px; overflow-wrap: anywhere;
}
.prov__ok { color: var(--signal); }
.prov__no { color: var(--pulse); }

.prov__fees { display: grid; gap: 8px; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.prov__fee {
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--slate); padding: 9px 10px; min-width: 0;
}
.prov__fee span {
  display: block; font-family: var(--mono); font-size: 9.5px; color: var(--fg-3);
  text-transform: uppercase; letter-spacing: .1em; margin-bottom: 6px;
}
.prov__fee input {
  width: 100%; background: none; border: 0; border-bottom: 1px solid var(--line-2);
  color: var(--fg); font-family: var(--px); font-size: 12px; padding: 2px 0 5px;
}
.prov__fee input:focus { outline: none; border-bottom-color: var(--signal); }
.prov__fee input::placeholder { font-family: var(--mono); font-size: 11px; color: var(--fg-3); }
.prov__fee input:disabled { opacity: .5; cursor: progress; }
.prov__fee em {
  display: block; font-style: normal; font-family: var(--mono);
  font-size: 10.5px; color: var(--fg-3); margin-top: 6px;
}
/* Un namespace que ese proveedor no vende: la casilla se enseña apagada en
   vez de desaparecer, para que las dos fichas se lean en la misma retícula
   y se vea que la ausencia es una decisión, no un hueco. */
.prov__fee.is-off { opacity: .45; }
.prov__fee.is-off em { color: var(--fg-3); }

.prov__cat {
  font-family: var(--mono); font-size: 10.5px; color: var(--fg-3);
  margin-top: 10px; overflow-wrap: anywhere;
}
.prov__cat b { display: block; color: var(--fg-2); font-weight: 500; }

/* ---------- pool de direcciones de depósito ---------- */
/* Una tarjeta por PAR (moneda + cadena). Se parece a `.prov` a propósito
   —son la misma clase de objeto: una ficha con su estado y sus cifras— pero
   es un `<button>`, porque aquí la tarjeta ADEMÁS filtra la tabla de abajo.
   Que sea un botón de verdad y no un div con un `click` es lo que la deja
   alcanzable con el tabulador y anunciada con su `aria-pressed`. */
.poolgrid { display: grid; gap: var(--gap); grid-template-columns: repeat(3, minmax(0, 1fr)); }
.pool {
  display: block; width: 100%; text-align: left; cursor: pointer;
  border: 1px solid var(--line-2); border-radius: var(--r);
  background: var(--ink-2); padding: 14px; min-width: 0;
  color: inherit; font: inherit;
  transition: border-color .18s var(--ease), background .18s var(--ease);
}
.pool:hover { border-color: var(--wire); }
.pool:focus-visible { outline: 2px solid var(--wire); outline-offset: 2px; }
/* El par elegido: el borde en señal, igual que un chip encendido. */
.pool.on { border-color: var(--signal); background: rgba(53, 240, 160, .05); }

.pool__top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.pool__top b { font-family: var(--px); font-size: 12px; color: var(--fg); font-weight: 400; }
.pool__top em {
  font-style: normal; font-family: var(--mono); font-size: 10.5px; color: var(--fg-3);
  text-align: right; overflow-wrap: anywhere;
}

/* La cifra que se viene a leer: cuántas quedan libres. Las otras tres son
   contexto y van pequeñas debajo. */
.pool__n {
  display: block; font-family: var(--px); font-size: 20px; color: var(--signal);
  margin: 12px 0 0; line-height: 1.1;
}
.pool__n i {
  font-style: normal; font-family: var(--mono); font-size: 10px; color: var(--fg-3);
  text-transform: uppercase; letter-spacing: .11em; margin-left: 8px;
}
.pool__r {
  display: flex; flex-wrap: wrap; gap: 4px 12px; margin-top: 8px;
  font-family: var(--mono); font-size: 10.5px; color: var(--fg-3);
}
.pool__acc {
  display: block; font-family: var(--mono); font-size: 10.5px; color: var(--fg-3);
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line);
  overflow-wrap: anywhere;
}
/* Índices reservados sin documento: el hueco que deja una pasada caída a
   mitad (wallet/pool.js). No es un error —un hueco no cuesta nada— así que
   se marca en ámbar y no en rojo. */
.pool__gap { font-style: normal; color: var(--watt); }
.pool__no { font-style: normal; color: var(--pulse); }

/* La dirección ES el botón de copiar: sin caja, sin subrayado y con la
   tipografía de la celda, para que la columna se siga leyendo como una
   columna de texto y no como una fila de botones. */
.addrcopy {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; color: var(--fg); text-align: left;
}
.addrcopy:hover { color: var(--signal); }
.addrcopy:focus-visible { outline: 2px solid var(--wire); outline-offset: 2px; border-radius: 2px; }

@media (max-width: 1100px) {
  .poolgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .poolgrid { grid-template-columns: 1fr; }
}

@media (max-width: 860px) {
  .provgrid { grid-template-columns: 1fr; }
  .admact__in, .admact__in--wide { flex: 1 1 100%; }
  .admact__row .btn { width: 100%; }
}

/* La ficha de una cuenta no es un aviso de dos líneas como los demás
   diálogos de la app: lleva cuatro cifras, dos bloques de acción, una tabla
   de órdenes y una bitácora. En los 440px del `.modal__card` de serie todo
   eso entra en columna de uno. Se ensancha SOLO aquí. */
#uModal .modal__card { width: min(660px, 100%); }

/* Y aun así, cuatro columnas de `.statgrid` no caben: la tipografía de las
   cifras es de píxel y ancha, y a ese ancho parte el importe por la mitad
   ("$41." / "80") — justo donde una cifra de dinero no se puede partir. Dos
   filas de dos, y en pantalla estrecha una sola columna. */
#uModal .statgrid { grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); }
#uModal .stat__v { font-size: clamp(11px, 1.35vw, 14px); }


/* ---------- aviso de correo sin confirmar ----------
   Ámbar y no magenta, por la misma razón que .warnbox--net: magenta es el
   estado que ya salió mal (la orden cuyo código no va a llegar), y esto es
   lo contrario — algo que el usuario resuelve en dos clics y a tiempo.
   Ocupa el ancho del contenido y empuja al resto hacia abajo en vez de
   flotar encima: un aviso que tapa contenido se cierra sin leerlo. */
.verifybar {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin-bottom: var(--gap);
  padding: 14px 16px;
  border: 1px solid var(--watt); border-radius: var(--r);
  background: rgba(255, 197, 61, .07);
}
.verifybar__txt { min-width: 0; flex: 1 1 320px; font-size: 14px; line-height: 1.55; color: var(--fg-2); }
.verifybar__txt b { color: var(--watt); font-weight: 500; }
.verifybar__txt code { font-family: var(--mono); font-size: 12.5px; color: var(--fg); }
.verifybar__act { margin-left: auto; }
/* La nota de resultado cae debajo, a lo ancho: en línea empujaría el botón
   fuera de la vista en un móvil justo cuando hay algo que leer. */
.verifybar__note { flex: 1 0 100%; margin: 2px 0 0; font-family: var(--mono); font-size: 12.5px; color: var(--fg-2); }

/* ---------- recargas (admin): valores largos que se copian ----------
   Una direccion o un txid no caben en una celda: se enseñan recortados y
   el valor entero va en el `title` y al portapapeles con un clic. Es un
   boton y no un span para que se pueda enfocar con el teclado. */
.copyable {
  background: none; border: 0; padding: 0; margin: 0;
  color: inherit; font: inherit; cursor: copy;
  text-decoration: underline dotted var(--fg-3); text-underline-offset: 3px;
}
.copyable:hover, .copyable:focus-visible { color: var(--fg); outline: none; text-decoration-color: var(--wire); }
.admact__link {
  float: right; text-transform: none; letter-spacing: 0; font-size: 11px;
  color: var(--wire); text-decoration: none;
}
.admact__link:hover { text-decoration: underline; }
