/* ============================================================================
   Remate v2 — Sistema de diseño DUAL-THEME — "MT Bold" (Modern Tool, paleta legacy)
   Light "legacy Morales Colombo" + Dark "verde casi negro + dorado" + toggle.
   Un único set de tokens semánticos; :root=light, [data-theme="dark"] los pisa.
   Sidebar verde oscuro + dorado · contenido claro · sans + mono · densidad de datos.
   ============================================================================ */

/* ── Fuentes self-hosteadas (antes Google Fonts CDN) ──────────────────────────
   Hanken Grotesk (UI) y Geist Mono (números) son fuentes VARIABLES: un solo woff2
   por familia cubre todo el rango de peso. Subset latin (cubre español). Se sirven
   desde el mismo origen (pasa el CSP 'self') con caché de 1 año (.htaccess).
   font-display: swap → el texto se ve con la fallback y cambia al cargar la fuente. */
@font-face {
  font-family: 'Hanken Grotesk';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('/assets/fonts/hanken-grotesk.woff2') format('woff2');
}
@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('/assets/fonts/geist-mono.woff2') format('woff2');
}

:root {
  color-scheme: light;

  /* ── MARCA verde — escala legacy Morales Colombo ──────────────── */
  --green-900:   #08120a;
  --green-850:   #0c1a0c;
  --green-800:   #111e11;   /* sidebar legacy */
  --green-700:   #11440d;   /* green-dark legacy */
  --green-600:   #236e43;   /* green-primary legacy (PRIMARIO) */
  --green-500:   #1e8048;
  --green-400:   #27ae60;   /* success legacy (verde vivo) */
  --green-300:   #5fcf8c;
  --green-glow:  rgba(39,174,96,.18);

  /* ── DORADO legacy — el acento característico ──────────────────── */
  --gold:        #c4993a;   /* accent legacy */
  --gold-2:      #a87d2a;   /* accent-hover legacy */
  --gold-soft:   #fff8e1;
  --gold-glow:   rgba(196,153,58,.35);

  /* ── SUPERFICIES (LIGHT = paleta legacy) ──────────────────────── */
  --bg:          #f2f5f2;   /* body-bg legacy (verde-grisáceo claro) */
  --surface:     #ffffff;   /* cards/panels */
  --surface-2:   #f6faf6;   /* surface elevada / thead / footers */
  --line:        #dde8dd;   /* borde suave legacy */
  --line-strong: #cbddcb;   /* borde definido (inputs, chips) */

  /* ── TINTA (LIGHT) ────────────────────────────────────────────── */
  --ink:         #1a1f1a;   /* texto principal legacy */
  --ink-2:       #3a463f;   /* secundario */
  --ink-3:       #5d6c5d;   /* muted (AA 5.07:1 sobre el bg claro) */
  --ink-4:       #69716b;   /* faint / placeholders / iconos (AA 4.58:1) */

  /* ── SIDEBAR (verde oscuro) ───────────────────────────────────── */
  --sidebar-bg:  linear-gradient(178deg, var(--green-800), var(--green-900));
  --sidebar-accent: var(--green-glow);       /* radial dorado tenue del mockup */
  --side-ink:    #bcd0c6;   /* texto nav inactivo */
  --side-ink-2:  #d9e6df;   /* texto general sidebar */
  --side-ink-3:  #7c9a8b;   /* iconos/sublabels */
  --side-ink-4:  #7c9a8b;   /* nav-label (era #5d7a6c: 3.67:1, abajo de AA) */
  --side-hover:  rgba(255,255,255,.08);
  --side-line:   rgba(255,255,255,.06);

  /* ── HOVER AFFORDANCE (tinte verde perceptible para superficies interactivas) ── */
  --row-hover:   color-mix(in srgb, var(--green-400) 9%, var(--surface));   /* hover de fila de tabla */
  --ctrl-hover:  color-mix(in srgb, var(--green-600) 9%, var(--surface));   /* hover de controles ghost/secundarios */

  /* ── ESTADOS (5 del remate + delta) ───────────────────────────── */
  /* color-base que el badge mezcla; light = legible sobre fondo claro */
  --st-preparando: #a07010;   /* ámbar/dorado tostado */
  --st-listo:      #1e8048;   /* verde medio */
  --st-programado: #2563c9;   /* azul */
  --st-activo:     #0f6c47;   /* verde fuerte (con dot que late) */
  --st-cerrado:    #5b6b78;   /* slate */
  --st-delta-dn:   #c0533f;   /* delta negativo */

  /* ── TIPO DE REMATE (vivo / online) ───────────────────────────── */
  /* A proposito FUERA de la paleta de estado: ahi verde/ambar/azul/slate ya
     quieren decir otra cosa, y dos idiomas de color en la misma fila se pisan. */
  --mod-vivo:   #8a6a1f;   /* bronce: el martillo de la casa */
  --mod-online: #6244b8;   /* violeta: no se usa en ningun otro lado */

  /* fondos de estado pre-mezclados (mockup) */
  --amber-bg:    #fff8e1;
  --blue-bg:     #e4ecfb;
  --slate-bg:    #eceff1;
  --activo-bg:   #e6f7ee;
  --listo-bg:    #e8f6ef;

  /* ── RADIOS ───────────────────────────────────────────────────── */
  --radius:      12px;   /* cards, panels, modal */
  --radius-sm:   8px;    /* chips, badges, botones de fila */
  --radius-pill: 999px;

  /* ── SOMBRAS ──────────────────────────────────────────────────── */
  --shadow-card: 0 1px 2px rgba(17,30,17,.06), 0 1px 0 rgba(17,30,17,.03);
  --shadow-pop:  0 12px 32px -12px rgba(17,30,17,.28);
  --shadow-lg:   0 24px 60px -24px rgba(17,30,17,.4);

  /* ── FOCUS RING (verde de marca, preservar accesibilidad) ─────── */
  --ring:        0 0 0 3px var(--green-glow);

  /* ── EASINGS (preservar: la app los usa en transiciones) ──────── */
  --spring:      cubic-bezier(.34,1.56,.64,1);
  --smooth:      cubic-bezier(.22,.61,.36,1);
  --ease:        cubic-bezier(.22,.68,0,1);
  --transition:  all .16s var(--smooth);

  /* ── FUENTES ──────────────────────────────────────────────────── */
  --sans:        'Hanken Grotesk', system-ui, sans-serif;
  --mono:        'Geist Mono', ui-monospace, monospace;

  --sidebar-w:   248px;

  /* ════════════════════════════════════════════════════════════════
     ALIAS de compatibilidad — nombres VIEJOS → nuevos.
     OBLIGATORIO: el CSS/JS sin migrar los usa. NO borrar.
     ════════════════════════════════════════════════════════════════ */
  --bone:        var(--bg);
  --bg-canvas:   var(--bg);
  --bg-canvas-2: var(--surface-2);
  --paper:       var(--surface);
  --paper-2:     var(--surface-2);
  --text:        var(--ink);
  --text-soft:   var(--ink-2);
  --text-faint:  var(--ink-3);
  --muted:       var(--ink-3);
  --border:      var(--line);          /* OJO: antes era ink fuerte; ahora suave (mejor) */
  --border-soft: var(--line);
  --hairline:    rgba(17,30,17,.10);
  --green:       var(--green-600);     /* primario ahora = legacy 236e43 */
  --green-deep:  var(--green-700);
  --green-bright:var(--green-400);
  --green-ink:   var(--green-600);     /* verde para texto/links/borde */
  --green-light: #e8f6ef;
  --on-green:    #ffffff;              /* texto sobre verde = blanco (no crema) */
  --brass:       var(--gold);          /* brass legacy → dorado */
  --bronze:      var(--gold);
  --bronze-lt:   var(--gold);
  --bronze-lite: var(--gold);
  --brass-soft:  var(--gold-soft);
  --emerald-glow:var(--green-400);
  --input-border:var(--line-strong);
  --input-bg:    var(--surface);
  --search-bg:   var(--surface);
  --r-sm:        var(--radius-sm);
  --r-md:        var(--radius);
  --r-lg:        var(--radius);
  --r-pill:      var(--radius-pill);
  --pill:        var(--radius-pill);
  --radius-hard: var(--radius);
  --radius-lg:   var(--radius);
  --shadow-sm:   var(--shadow-card);
  --shadow:      var(--shadow-card);
  --shadow-md:   var(--shadow-card);
  --shadow-lift: var(--shadow-pop);
  --elev-card:   var(--shadow-card);
  --danger:      #c0392b;
  --danger-soft: #fbeae7;
  --pend:        #a8590d;
  --pend-soft:   #fbf0e2;
  --success:     var(--green-400);
  --serif:       var(--sans);          /* mata cualquier serif residual sin romper var() */
  /* alias de estados viejos del editorial (por si quedan referencias) */
  --st-delta-up: var(--green-400);
  --marker-fg:   #ffffff;
}

/* Spring nativo cuando el browser soporta linear() */
@supports (animation-timing-function: linear(0,1)) {
  :root { --spring: linear(0,0.55,1.04,0.98,1.008,0.997,1); }
}

[data-theme="dark"] {
  color-scheme: dark;

  /* DARK refinado — superficies neutras (croma bajo, un solo hue ~152°); el verde
     de marca vive en los ACENTOS. Toda la familia verde alineada al esmeralda 152°. */
  --green-900:   #08110d;
  --green-850:   #0c1511;
  --green-800:   #121a16;
  --green-700:   #0f5236;   /* esmeralda profundo (era el oliva turbio #11440d) */
  --green-600:   #2e9e63;   /* primario esmeralda, limpio (era #2f8a55, verde semáforo) */
  --green-500:   #268a57;
  --green-400:   #3ad07f;   /* verde vivo, acento */
  --green-300:   #62d894;
  --green-glow:  rgba(58,208,127,.20);

  --gold:        #d8b878;   /* dorado más claro para legibilidad en dark */
  --gold-2:      #c4993a;
  --gold-glow:   rgba(216,184,120,.32);   /* halo más contenido sobre superficies limpias */

  --bg:          #0b110e;   /* neutro oscuro, subtono verde mínimo */
  --surface:     #121a16;   /* cards: neutro verdoso, croma bajo (era #111e11 verde puro) */
  --surface-2:   #1a241f;   /* elevada — salto de luz limpio sobre surface */
  --line:        rgba(255,255,255,.08);
  --line-strong: rgba(180,210,195,.14);

  --ink:         #eaf3ee;   /* crema verdosa */
  --ink-2:       #c2d2c8;
  --ink-3:       #93a89b;   /* muted dark (AA) */
  --ink-4:       #789184;   /* faint dark (AA 4.62:1 sobre surface-2) */

  --sidebar-bg:  linear-gradient(178deg, #0d1512, #070d0b);
  --sidebar-accent: rgba(216,184,120,.10);
  --side-ink:    #aec4ba;
  --side-ink-2:  #d9e6df;
  --side-ink-3:  #7c9a8b;
  --side-ink-4:  #7c9a8b;   /* idem: 3.77:1 → 5.78:1 */
  --side-hover:  rgba(255,255,255,.09);
  --side-line:   rgba(255,255,255,.07);

  /* HOVER AFFORDANCE dark — el verde vivo (#34c476) al % más alto para perciba sobre #111e11 */
  --row-hover:   color-mix(in srgb, var(--green-400) 12%, var(--surface));
  --ctrl-hover:  color-mix(in srgb, var(--green-400) 14%, var(--surface));

  --st-preparando: #cda255;
  --st-listo:      #3ad07f;
  --st-programado: #5b95ef;
  --st-activo:     #45e08c;
  --st-cerrado:    #8a958c;
  --mod-vivo:   #d8b878;
  --mod-online: #a78bfa;
  --st-delta-dn:   #d98b6a;

  --amber-bg:    rgba(199,154,75,.12);
  --blue-bg:     rgba(91,149,239,.12);
  --slate-bg:    rgba(255,255,255,.05);
  --activo-bg:   rgba(61,220,132,.10);
  --listo-bg:    rgba(52,196,118,.10);

  --shadow-card: 0 1px 2px rgba(0,0,0,.5), 0 1px 0 rgba(0,0,0,.3);
  --shadow-pop:  0 18px 40px -20px rgba(0,0,0,.8);
  --shadow-lg:   0 30px 60px -28px rgba(0,0,0,.9);

  --ring:        0 0 0 3px var(--green-glow);

  /* re-mapear aliases que dependen del valor (los var()-of-var() ya se actualizan
     solos; solo redefinir los de color literal) */
  --green-light: rgba(47,138,85,.18);
  --on-green:    #06100a;          /* texto sobre verde claro dark = oscuro */
  --green-ink:   #4fb37a;          /* verde legible para links/borde en dark */
  --emerald-glow:#34c476;
  --danger:      #e0796a;
  --danger-soft: rgba(224,121,106,.16);
  --pend:        #e0a95c;
  --pend-soft:   rgba(224,169,92,.15);
  --hairline:    rgba(255,255,255,.08);
  --input-bg:    rgba(255,255,255,.04);
  --marker-fg:   #ffffff;
}

/* ── Base / body — plano, sin aurora ni grano ───────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
/* Reserva siempre la barra de scroll: evita el flicker/salto al pasar de una
   vista o tab alta (con scroll) a una corta (sin scroll) — p. ej. las tabs de la
   cuenta corriente del cliente. overflow-y:scroll fija el track siempre (fiable
   en todos los navegadores); scrollbar-gutter cubre los de scrollbar overlay. */
html { font-size: 16px; overflow-y: scroll; scrollbar-gutter: stable; }
body {
  font-family: var(--sans);
  background: var(--bg);                 /* plano — sin radiales editoriales */
  color: var(--ink);
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  letter-spacing: -.01em;
}
.mono { font-family: var(--mono); font-feature-settings: "tnum" 1; letter-spacing: -.02em; }
.tnum { font-variant-numeric: tabular-nums; }

a { color: var(--green-ink); text-decoration: none; }
a:hover { text-decoration: underline; }
input, select, textarea, button { font-family: inherit; font-size: inherit; }

:focus-visible { outline: none; box-shadow: var(--ring); border-radius: var(--radius-sm); }
.btn:focus-visible, .nav-item a:focus-visible, .search:focus-visible { box-shadow: var(--ring); }

/* ── App shell ──────────────────────────────────────────────────────────────── */
.app-shell { display: flex; min-height: 100vh; position: relative; }
/* min-width: 0 NO es decorativo: un item de flex arranca en `min-width: auto`, o
   sea que NO puede achicarse más que su hijo más ancho. Con una tira de filtros
   o una tabla adentro, el layout entero se estiraba a ~700px en un celular de
   390 y la página se iba de lado (todo el trabajo responsive de abajo quedaba
   fuera de pantalla). Con 0, el contenido se banca achicarse y cada bloque
   resuelve su propio scroll. */
.main-content { margin-left: var(--sidebar-w); flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 100vh; background: var(--bg); }

/* ── Sidebar — verde oscuro + acento DORADO ─────────────────────────────────── */
.sidebar {
  width: var(--sidebar-w);
  background:
    radial-gradient(120% 60% at 0% 0%, var(--sidebar-accent), transparent 55%),
    var(--sidebar-bg);
  color: var(--side-ink-2);
  display: flex; flex-direction: column;
  position: fixed; inset: 0 auto 0 0; z-index: 100;
  padding: 18px 14px 14px;
  border-right: 1px solid var(--side-line);
  transition: transform .22s ease;
}
.sidebar-backdrop { display: none; }

/* Brand: mark dorado + nombre (ver layout.js §4) */
.sidebar-logo { display: flex; align-items: center; gap: 11px; padding: 8px 8px 18px; text-decoration: none; }
/* .sidebar-logo ES un link real (navega a "/"): afford honesto y sutil al hover sin subrayar el wordmark */
.sidebar-logo:hover { text-decoration: none; }
.sidebar-logo:hover .sidebar-logo-text { color: #fff; }
.sidebar-logo:hover .mark { filter: brightness(1.06); box-shadow: 0 0 0 1px rgba(196,153,58,.45), 0 6px 18px -6px var(--gold-glow); }
.sidebar-logo .mark {
  width: 34px; height: 34px; border-radius: 9px; flex: none;
  background: linear-gradient(150deg, var(--gold), var(--gold-2));
  display: grid; place-items: center;
  color: #11240f; font-weight: 800; font-size: 15px;
  box-shadow: 0 0 0 1px rgba(196,153,58,.3), 0 6px 16px -6px rgba(196,153,58,.55);
  transition: filter .14s ease, box-shadow .14s ease;
}
.sidebar-logo .mark svg { width: 21px; height: 21px; display: block; }
.sidebar-logo-text { color: #fff; font-size: 14.5px; font-weight: 700; letter-spacing: -.02em; line-height: 1.15; font-family: var(--sans); transition: color .14s ease; }
.sidebar-logo-sub { color: var(--side-ink-3); font-size: 11px; font-weight: 500; letter-spacing: .02em; margin-top: 2px; text-transform: none; }

.sidebar-nav { flex: 1; padding: 6px 0; overflow-y: auto; position: relative; }
.sidebar-nav ul { list-style: none; }
.nav-label {
  font-size: 10.5px; font-weight: 700; letter-spacing: .13em; text-transform: uppercase;
  color: var(--side-ink-4); padding: 16px 10px 7px;
}

/* Nav-item: reusar markup <li class="nav-item"><a> */
.nav-item a {
  position: relative; z-index: 1;
  display: flex; align-items: center; gap: 11px;
  padding: 8.5px 10px; border-radius: 9px;
  color: var(--side-ink); font-size: 13.5px; font-weight: 500;
  transition: background .14s ease, color .14s ease;
}
.nav-item a i { width: 16px; text-align: center; font-size: 13.5px; color: var(--side-ink-3); transition: color .14s ease; }
.nav-item a:hover { background: var(--side-hover); color: #eaf4ef; text-decoration: none; }
.nav-item a:hover i { color: var(--side-ink); }

/* ACTIVO: realce dorado del mockup. El nav-marker es solo el filete dorado lateral. */
.nav-item a.active {
  color: #fff; font-weight: 600;
  background: linear-gradient(90deg, rgba(196,153,58,.20), rgba(196,153,58,.05));
  box-shadow: inset 0 0 0 1px rgba(196,153,58,.2);
}
.nav-item a.active i { color: var(--gold); }

/* contador opcional (.count) si se usa */
.nav-item .count {
  margin-left: auto; font-size: 11px; font-weight: 600;
  background: rgba(255,255,255,.08); color: #cfe0d7;
  padding: 1px 7px; border-radius: 20px;
}
.nav-item a.active .count { background: var(--gold); color: #11240f; }

/* Nav-marker: filete dorado deslizante (preserva el JS de layout.js). El relleno
   lo da .nav-item a.active / :hover; el marker mueve solo el ::before lateral. */
.nav-marker {
  position: absolute; top: 0; left: 14px; right: 14px; height: 40px;
  border-radius: 9px; background: transparent;   /* el fondo lo da .active ahora */
  box-shadow: none; z-index: 0; pointer-events: none; opacity: 0;
  transition: transform .45s var(--spring), height .25s var(--smooth), opacity .2s;
}
.nav-marker::before {
  content: ""; position: absolute; left: -14px; top: 50%; transform: translateY(-50%);
  width: 3px; height: 18px; border-radius: 0 3px 3px 0;
  background: var(--gold); box-shadow: 0 0 12px 1px var(--gold-glow);
}

/* Footer / user / toggles */
.sidebar-footer { margin-top: auto; padding: 14px 6px 0; border-top: 1px solid var(--side-line); }
.sidebar-user { display: flex; align-items: center; gap: 10px; padding: 7px 4px; margin-bottom: 10px; }
.sidebar-user-avatar {
  width: 32px; height: 32px; border-radius: 8px; flex: none;
  background: linear-gradient(140deg, #2a5546, #143a2c);
  color: #bfe8d4; display: grid; place-items: center; font-weight: 700; font-size: 12.5px;
  font-family: var(--sans);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.07);
}
.sidebar-user-name { color: #eaf3ee; font-size: 12.5px; font-weight: 600; }
.sidebar-user-role { color: var(--side-ink-3); font-size: 11px; text-transform: capitalize; }

.btn-theme, .btn-logout {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; padding: 8px 12px; margin-bottom: 8px;
  background: transparent; border: 1px solid var(--side-line);
  border-radius: var(--radius-sm); cursor: pointer;
  font-size: 12.5px; font-weight: 600; font-family: var(--sans);
  transition: background .14s ease, border-color .14s ease, color .14s ease;
}
.btn-theme { color: var(--side-ink); }
.btn-theme:hover { border-color: var(--gold); color: #fff; background: var(--side-hover); }
.btn-theme i { transition: transform .4s var(--spring); }
.btn-theme:hover i { transform: rotate(-20deg) scale(1.1); color: var(--gold); }
.btn-logout { color: #d99; }
.btn-logout:hover { background: rgba(192,57,43,.14); border-color: rgba(192,57,43,.5); color: #f0b8b0; }

/* ── Topbar — limpia ────────────────────────────────────────────────────────── */
.topbar {
  height: 64px; flex: none;
  display: flex;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 20;
}
/* El fondo/borde de la barra ocupa todo el ancho, pero su CONTENIDO se alinea
   a la misma columna centrada que .content-area (así en pantallas anchas la
   fecha no queda colgada del borde). */
.topbar-inner {
  width: 100%; max-width: 1340px; margin-inline: auto;
  height: 100%; display: flex; align-items: center; gap: 18px; padding: 0 28px;
}
.topbar-left { display: flex; align-items: center; gap: 14px; min-width: 0; }
.topbar-title { font-family: var(--sans); font-size: 19px; font-weight: 700; letter-spacing: -.03em; color: var(--ink); }
.topbar-date { font-size: 13px; color: var(--ink-4); font-weight: 500; }
.topbar-date::before { content: none; }   /* SACAR el filete bronce editorial */
.topbar-hamburger {
  display: none; align-items: center; justify-content: center;
  width: 40px; height: 40px; flex-shrink: 0;
  background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm); color: var(--green-ink); font-size: 1.05rem; cursor: pointer;
  transition: var(--transition);
}
.topbar-hamburger:hover { background: var(--ctrl-hover); border-color: var(--green-ink); color: var(--green-ink); }
.content-area { flex: 1; padding: 28px; max-width: 1340px; width: 100%; margin-inline: auto; }

/* ── Página / card ──────────────────────────────────────────────────────────── */
.page { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-card); padding: 22px 24px; }
[data-theme="dark"] .page { backdrop-filter: none; }   /* SACAR blur editorial */
.page-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; gap: 14px; flex-wrap: wrap; }
.page-header h1 { font-family: var(--sans); font-size: 19px; font-weight: 700; letter-spacing: -.02em; color: var(--ink); }
.page-sub, .page-nav a { font-size: 13px; color: var(--ink-4); }
.page-nav a { color: var(--green-ink); font-weight: 600; transition: color .14s ease; }
/* breadcrumb "← Inicio"/"← Remates": hover crisp (verde más vivo + subrayado intencional) */
.page-nav a:hover { color: var(--green-500); text-decoration: underline; text-decoration-thickness: 1.5px; text-underline-offset: 3px; }
[data-theme="dark"] .page-nav a:hover { color: color-mix(in srgb, var(--green-ink) 82%, #fff); }
.toolbar { display: flex; gap: 10px; margin-bottom: 16px; flex-wrap: wrap; align-items: center; }
/* Toolbar con campos etiquetados (label arriba): alinear los controles ABAJO para
   que el buscador (sin label) quede parejo con los selects (con label encima). */
.toolbar--fields { align-items: flex-end; }
.toolbar-spacer { flex: 1; }
/* Search FOLIO: lupa embebida (SVG en background; no puede leer var(), por eso color fijo neutro
   ≈ --ink-4 que funciona en ambos temas) + halo dorado al focus. Markup intacto: <input class="search">. */
/* Sitio Web mete el buscador junto a los chips, fuera de una .toolbar. */
.toolbar .search,
.web-filtros .search {
  flex: 1 1 240px; max-width: 420px; height: 40px; padding: 0 14px 0 38px;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  font: inherit; font-size: 13.5px; background: var(--surface-2); color: var(--ink);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='%23789184' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.2-3.2'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: 13px 50%; background-size: 15px;
  transition: border-color .18s ease, box-shadow .18s ease, background-color .18s ease;
}
.toolbar .search::placeholder,
.web-filtros .search::placeholder { color: var(--ink-4); }
.toolbar .search:focus,
.web-filtros .search:focus {
  outline: none;
  border-color: color-mix(in srgb, var(--gold) 55%, transparent);
  box-shadow: 0 0 0 3px var(--gold-glow);
}
/* Loader inicial del SPA (app.html, antes de que arranque). ANTES estaba en un <style>
   inline en app.html, pero el CSP (style-src 'self', sin unsafe-inline) BLOQUEA los
   <style>/style="" inline → se veía "Cargando…" pelado en el hard reload. Al estar acá
   (app.css es 'self' y render-blocking) queda estilizado desde el primer paint. */
.app-loading { min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 15px; background: var(--bg); }
.app-loading__spin {
  width: 34px; height: 34px; border-radius: 50%;
  border: 3px solid color-mix(in srgb, var(--ink-4) 40%, transparent);
  border-top-color: var(--green-600); animation: app-spin .7s linear infinite;
}
.app-loading__txt { margin: 0; font-family: system-ui, -apple-system, 'Segoe UI', sans-serif; font-size: 13px; font-weight: 600; letter-spacing: .05em; color: var(--ink-3); }
@keyframes app-spin { to { transform: rotate(360deg); } }

/* Estado "subiendo…" de botones/labels de upload (fotos, archivos): spinner
   chico heredando el color del texto + bloqueo de más clicks mientras procesa. */
.upload-spin {
  display: inline-block; width: 14px; height: 14px; vertical-align: -2px;
  border: 2px solid color-mix(in srgb, currentColor 30%, transparent);
  border-top-color: currentColor; border-radius: 50%;
  animation: app-spin .7s linear infinite;
}
label.subiendo { pointer-events: none; opacity: .75; }
@media (prefers-reduced-motion: reduce) { .app-loading__spin { animation-duration: 2.4s; } }

/* Loader de vistas (mientras la vista trae sus datos). Antes era texto pelado feo;
   ahora un spinner centrado + el texto. Lo usan clientes/ventas/remates/home/etc. */
.loading {
  color: var(--ink-3); font-size: 13px; font-weight: 600; letter-spacing: .04em;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 13px; min-height: 160px; padding: 2rem 0; text-align: center;
}
.loading::before {
  content: ""; width: 32px; height: 32px; border-radius: 50%;
  border: 3px solid color-mix(in srgb, var(--ink-4) 40%, transparent);
  border-top-color: var(--green-600); animation: loading-spin .7s linear infinite;
}
@keyframes loading-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .loading::before { animation-duration: 2.4s; } }

/* ── Skeleton loaders (shimmer) — placeholders con la estructura mientras carga ──── */
:root { --sk-base: #e4ebe4; --sk-hi: #f3f7f3; }
[data-theme="dark"] { --sk-base: #202d27; --sk-hi: #2c3d34; }
/* IMPORTANTE: el CSP bloquea los `style` inline puestos por innerHTML, así que TODO el
   tamaño/estructura del skeleton va por CLASES (nunca style="..."). */
.skel { display: block; position: relative; overflow: hidden; background: var(--sk-base); border-radius: 6px; }
.skel::after {
  content: ""; position: absolute; inset: 0; transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--sk-hi) 92%, transparent), transparent);
  animation: sk-shimmer 1.35s ease-in-out infinite;
}
@keyframes sk-shimmer { 100% { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) { .skel::after { animation-duration: 2.6s; } }
.sk-line { height: 11px; border-radius: 5px; width: 100%; }
.sk-circle { border-radius: 50%; width: 30px; height: 30px; flex: none; }
.sk-btn { height: 30px; width: 74px; border-radius: var(--radius-sm); flex: none; }
/* TABLA (encabezado + filas). */
.skel-table { padding: 2px 2px 4px; }
.skel-thead, .skel-tr { display: flex; align-items: center; gap: 16px; }
.skel-thead { padding: 12px 18px; border-bottom: 1px solid var(--line-strong); }
.skel-tr { padding: 15px 18px; border-bottom: 1px solid var(--line); }
.skel-tr:last-child { border-bottom: 0; }
.skel-thead > .skel, .skel-tr > .skel { flex: 1; height: 11px; border-radius: 5px; min-width: 0; }
.skel-main { flex: 1.7; display: flex; align-items: center; gap: 11px; min-width: 0; }
.skel-main .sk-circle { flex: none; }
.skel-main .sk-line { flex: 1; }
.skel-tr > .sk-btn { flex: 0 0 74px; height: 30px; }
/* CARDS (objetos). Nombre propio para no chocar con el .skel-card legacy (height:120px). */
.skel-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 14px; }
.skel-cardbox { border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 14px; display: flex; flex-direction: column; gap: 11px; }
.skel-cardbox > .skel { flex: none; height: 11px; }
.skel-cardbox > .sk-thumb { height: 78px; border-radius: 6px; }
.skel-cardbox > .sk-w70 { width: 70%; }
.skel-cardbox > .sk-w45 { width: 45%; }
/* DASHBOARD stat-cards (card propia sobre --surface para que el shimmer contraste). */
.skel-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 16px; margin-bottom: 20px; }
.skel-stat { border: 1px solid var(--line); border-radius: 12px; background: var(--surface); padding: 20px; display: flex; flex-direction: column; gap: 11px; }
.skel-stat > .skel { flex: none; border-radius: 5px; }
.skel-stat > .skel:nth-child(1) { height: 11px; width: 50%; }
.skel-stat > .skel:nth-child(2) { height: 26px; width: 60%; border-radius: 6px; }
.skel-stat > .skel:nth-child(3) { height: 11px; width: 40%; }
.skel-panel-title { display: block; height: 15px; width: 190px; border-radius: 5px; margin: 4px 0 14px; }
.skel-seg { display: block; height: 42px; width: 340px; max-width: 100%; border-radius: 10px; margin-bottom: 18px; }

/* ═══ Dashboard rework: KPIs accionables + actividad por mes (tabs + barras) ═══ */
/* Selector de moneda: escopea todo el panel a una moneda (pesos/dólares no se suman). */
.dash-moneda { display: flex; align-items: center; gap: 8px; margin-bottom: 16px; flex-wrap: wrap; }
.dash-moneda-lbl { font-size: 12px; font-weight: 600; color: var(--ink-3); text-transform: uppercase; letter-spacing: .04em; }
.dash-moneda-btn {
  appearance: none; cursor: pointer; font-family: inherit; font-size: 13px; font-weight: 600;
  padding: 6px 14px; border-radius: 999px; border: 1px solid var(--line);
  background: var(--surface); color: var(--ink-2); transition: border-color .16s, color .16s, background .16s;
}
.dash-moneda-btn:hover { border-color: var(--green-600); color: var(--ink); }
.dash-moneda-btn.on { background: var(--green-600); border-color: var(--green-600); color: #fff; }

.stats.dash-kpis { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1100px) { .stats.dash-kpis { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .stats.dash-kpis { grid-template-columns: 1fr; } }
/* Skeleton del dashboard (matchea el rework: 4 KPIs + tabs + barras + tabla). */
.skel-stats.skel-kpis4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1100px) { .skel-stats.skel-kpis4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .skel-stats.skel-kpis4 { grid-template-columns: 1fr; } }
.skel-dash { padding: 16px 18px 18px; }
.skel-dash-tabs { display: flex; gap: 18px; padding: 6px 0 14px; border-bottom: 1px solid var(--line); margin-bottom: 18px; }
.skel-dtab { height: 14px; width: 90px; border-radius: 5px; }
.skel-dash-chart { display: flex; align-items: flex-end; gap: 10px; height: 172px; border-top: 1px dashed var(--line); padding-top: 8px; }
.skel-dcol { flex: 1; display: flex; align-items: flex-end; justify-content: center; height: 100%; }
.skel-dbar { width: 100%; max-width: 48px; border-radius: 6px 6px 3px 3px; }
.skel-dcol:nth-child(1) .skel-dbar { height: 20%; }
.skel-dcol:nth-child(2) .skel-dbar { height: 34%; }
.skel-dcol:nth-child(3) .skel-dbar { height: 26%; }
.skel-dcol:nth-child(4) .skel-dbar { height: 58%; }
.skel-dcol:nth-child(5) .skel-dbar { height: 82%; }
.skel-dcol:nth-child(6) .skel-dbar { height: 48%; }
.stat.gold { border-color: color-mix(in srgb, var(--gold) 42%, var(--line)); position: relative; overflow: hidden; }
.stat.gold::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 3px; background: var(--gold); }
.stat.gold .ico { background: color-mix(in srgb, var(--gold) 18%, transparent); color: var(--gold); }
.stat.green { border-color: color-mix(in srgb, var(--green-600) 40%, var(--line)); position: relative; overflow: hidden; }
.stat.green::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 3px; background: var(--green-600); }
.stat.green .ico { background: color-mix(in srgb, var(--green-600) 16%, transparent); color: var(--green-ink); }
.dash-trend { font-weight: 700; display: inline-flex; align-items: center; gap: 3px; }
.dash-trend.up { color: var(--green-ink); }
.dash-trend.down { color: #d98a8a; }
.dash-trend.flat { color: var(--ink-4); }
.dash-tabs { display: flex; gap: 2px; padding: 4px 6px 0; border-bottom: 1px solid var(--line); flex-wrap: wrap; }
.dash-tab { appearance: none; background: none; border: 0; color: var(--ink-3); font-family: inherit; font-size: 13px; font-weight: 600; padding: 10px 13px 13px; cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px; display: inline-flex; align-items: center; gap: 7px; transition: color .18s; }
.dash-tab .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--dc, var(--ink-4)); opacity: .5; transition: opacity .18s; }
.dash-tab:hover { color: var(--ink-2); }
.dash-tab.on { color: var(--ink); border-bottom-color: var(--dc, var(--green-600)); }
.dash-tab.on .dot { opacity: 1; }
.dash-tab:focus-visible { outline: 2px solid var(--green-600); outline-offset: -2px; border-radius: 4px; }
.dash-body { padding: 18px 18px 20px; }
.dash-summary { display: flex; align-items: flex-end; gap: 26px; margin-bottom: 24px; flex-wrap: wrap; }
.dash-summary .big { font-family: var(--mono); font-size: 32px; font-weight: 600; letter-spacing: -.02em; line-height: 1; font-variant-numeric: tabular-nums; }
.dash-summary .big small { font-size: 18px; color: var(--ink-3); }
.dash-summary .big { line-height: 1.05; }
.dash-summary .cap { font-size: 12px; color: var(--ink-3); margin-top: 9px; }
.dash-summary .aside { text-align: right; }
.dash-summary .aside.first { margin-left: auto; }
.dash-summary .aside .n { font-family: var(--mono); font-size: 17px; font-weight: 600; font-variant-numeric: tabular-nums; }
.dash-summary .aside .l { font-size: 11px; color: var(--ink-4); }
/* Gráfico de barras: la ALTURA y el COLOR (--barc) se setean por JS (element.style),
   NO por style="" inline → compatible con el CSP (style-src 'self'). */
.dash-chart { display: flex; align-items: flex-end; gap: 10px; height: 172px; padding-top: 8px; border-top: 1px dashed var(--line); }
.dash-col { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 8px; height: 100%; justify-content: flex-end; min-width: 0; }
.dash-barwrap { width: 100%; max-width: 48px; height: 100%; display: flex; align-items: flex-end; justify-content: center; }
.dash-bar { width: 100%; border-radius: 6px 6px 3px 3px; background: linear-gradient(180deg, var(--barc, var(--green-600)), color-mix(in srgb, var(--barc, var(--green-600)) 45%, transparent)); min-height: 3px; transition: height .5s cubic-bezier(.4, 0, .2, 1); }
.dash-bar.cur { outline: 2px solid color-mix(in srgb, var(--barc, var(--green-600)) 55%, transparent); outline-offset: 2px; }
.dash-col .ml { font-size: 11px; color: var(--ink-4); font-weight: 600; text-transform: uppercase; letter-spacing: .03em; }
.dash-col .mv { font-family: var(--mono); font-size: 11px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.dash-col:hover .mv { color: var(--ink); }
@media (prefers-reduced-motion: reduce) { .dash-bar { transition: none; } }
@media (max-width: 720px) { .dash-summary { gap: 16px; } .dash-chart { gap: 5px; } .dash-col .mv { display: none; } }

/* HISTORIAL (ficha + tabs de rol + saldo + subtabs + tabla). */
.skel-hist-title { height: 22px; width: 280px; border-radius: 6px; margin-bottom: 16px; }
.skel-hist-card { display: flex; align-items: center; gap: 16px; padding: 18px; border: 1px solid var(--line); border-radius: 12px; background: var(--surface); margin-bottom: 16px; }
.skel-hist-card .sk-circle { width: 56px; height: 56px; }
.skel-hist-lines { display: flex; flex-direction: column; gap: 9px; flex: 1; }
.skel-hist-lines > .skel { flex: none; height: 11px; border-radius: 5px; }
.skel-hist-lines > .skel:nth-child(1) { width: 40%; height: 15px; }
.skel-hist-lines > .skel:nth-child(2) { width: 55%; }
.skel-hist-lines > .skel:nth-child(3) { width: 30%; }
.skel-hist-row { display: flex; gap: 10px; margin-bottom: 14px; }
.skel-hist-row > .skel { flex: none; height: 38px; width: 130px; border-radius: 8px; }
.skel-hist-band { height: 74px; border-radius: 12px; margin-bottom: 16px; }
.skel-hist-subrow { display: flex; gap: 10px; margin-bottom: 12px; }
.skel-hist-subrow > .skel { flex: none; height: 30px; width: 150px; border-radius: 8px; }
.skel-hist-tablewrap { border: 1px solid var(--line); border-radius: 12px; background: var(--surface); overflow: hidden; }
/* MODAL (campos de formulario/detalle que cargan async). */
.skel-modal-body { display: flex; flex-direction: column; gap: 16px; }
.skel-modal-field { display: flex; flex-direction: column; gap: 8px; }
.skel-modal-field > .skel { flex: none; border-radius: 5px; }
.skel-modal-field > .skel:nth-child(1) { height: 11px; width: 35%; }
.skel-modal-field > .skel:nth-child(2) { height: 40px; width: 100%; border-radius: 8px; }

.muted { color: var(--ink-3); font-size: .88rem; }
/* Deuda del cliente en la lista: roja cuando debe (al día va con .muted "—"). */
.cliente-deuda { color: var(--danger); font-weight: 600; font-variant-numeric: tabular-nums; }
.section-title { font-family: var(--sans); font-size: 15px; font-weight: 700; color: var(--ink); margin: 6px 0 4px; display: flex; align-items: center; gap: 12px; }
.section-title::after { content: ''; flex: 1; height: 1px; background: var(--line); }

/* ── Botones ────────────────────────────────────────────────────────────────── */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 7px; height: 38px; padding: 0 16px; border-radius: var(--radius-sm); border: 1px solid transparent; cursor: pointer; font-size: 13.5px; font-weight: 600; font-family: var(--sans); letter-spacing: -.01em; transition: var(--transition); white-space: nowrap; }
.btn:disabled { opacity: .55; cursor: not-allowed; }
.btn:active:not(:disabled) { transform: translateY(1px); }
.btn-sm { height: 30px; padding: 0 12px; font-size: 12.5px; }

.btn-primary {
  color: #fff; border: none;
  background: linear-gradient(180deg, var(--green-500), var(--green-600));
  box-shadow: 0 1px 0 rgba(255,255,255,.18) inset, 0 6px 16px -8px rgba(35,110,67,.7);
  transition: transform .12s ease, box-shadow .14s ease, filter .14s ease;
}
.btn-primary:hover:not(:disabled) { filter: brightness(1.06); transform: translateY(-1px); box-shadow: 0 1px 0 rgba(255,255,255,.2) inset, 0 10px 22px -8px rgba(35,110,67,.75); }
.btn-primary:active:not(:disabled) { transform: translateY(0); }
[data-theme="dark"] .btn-primary { background: linear-gradient(180deg, var(--green-500), var(--green-600)); box-shadow: 0 1px 0 rgba(255,255,255,.10) inset, 0 6px 16px -8px rgba(0,0,0,.6); }

.btn-secondary { color: var(--ink-2); border: 1px solid var(--line-strong); background: var(--surface); }
.btn-secondary:hover:not(:disabled) { background: var(--ctrl-hover); border-color: var(--green-ink); color: var(--green-ink); }

.btn-danger { color: var(--danger); border: 1px solid color-mix(in srgb, var(--danger) 45%, transparent); background: transparent; }
.btn-danger:hover:not(:disabled) { background: var(--danger); color: #fff; border-color: var(--danger); }

.btn-warning { background: var(--gold); color: #11240f; border: none; }
.btn-warning:hover:not(:disabled) { filter: brightness(1.08); box-shadow: 0 4px 12px -6px var(--gold-glow); }

/* ── Data table — look FOLIO (variante A del mockup modales-listas) ──────────── */
.table-wrap { overflow-x: auto; }
.data-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }

/* Header: mono mayúscula + hairline DORADA con glow tenue por debajo */
.data-table thead th {
  position: relative;
  text-align: left; font-family: var(--mono); font-size: 10px; font-weight: 500;
  letter-spacing: .15em; text-transform: uppercase;
  color: var(--ink-3); padding: 12px 18px; background: var(--surface-2);
  border-bottom: 1px solid var(--gold); white-space: nowrap;
}
.data-table thead th::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: linear-gradient(90deg, transparent, var(--gold-glow), transparent);
}
.data-table thead th.col-actions { text-align: right; }

/* Filas: tinte verde plano y continuo al hover + acento dorado a la izquierda.
   OJO: el acento NO va con ::before sobre el <tr> — eso genera una celda-tabla
   anónima y corre todas las columnas. Va como box-shadow inset en la 1ra celda. */
.data-table tbody td { padding: 15px 18px; border-bottom: 1px solid var(--line); vertical-align: middle; color: var(--ink-2); transition: background .18s ease, color .18s ease, box-shadow .18s ease; }
.data-table tbody tr:last-child td { border-bottom: none; }
.data-table tbody tr:hover td {
  background: var(--row-hover);
  color: var(--ink);
}
.data-table tbody tr:hover td:first-child { box-shadow: inset 3px 0 0 var(--gold); }

/* números/dinero/documento/teléfono en mono */
.data-table .num, .data-table .money { font-family: var(--mono); font-variant-numeric: tabular-nums; font-weight: 600; letter-spacing: -.02em; }
.data-table .money.muted { color: var(--ink-4); font-weight: 500; }

/* Acciones de fila: mini-botones GHOST con ícono (hairline al reposo, dorado al hover) */
.data-table .col-actions { text-align: right; white-space: nowrap; }
.data-table .col-actions .btn,
.data-table .col-actions .btn-secondary,
.data-table .col-actions .btn-danger {
  /* Más angosto que un .btn-sm suelto: con cuatro por fila (Lotes,
     Publicación, Sala, Acciones) la columna se comía 380 px y la grilla de
     Remates no entraba en la pantalla del operador. Se achica el aire, no el
     texto: las acciones siguen diciendo lo que hacen. */
  height: 30px; padding: 0 8px; margin-left: 4px; gap: 5px;
  font-family: var(--sans); font-size: 11.5px; font-weight: 600;
  border-radius: var(--radius-sm); border: 1px solid var(--line-strong);
  background: transparent; color: var(--ink-2);
  transition: color .16s ease, background .16s ease, border-color .16s ease, box-shadow .16s ease, transform .12s ease;
}
.data-table .col-actions .btn i { font-size: 11px; opacity: .85; }
.data-table .col-actions .btn-secondary:hover {
  color: var(--ink);
  border-color: color-mix(in srgb, var(--gold) 45%, transparent);
  background: color-mix(in srgb, var(--gold) 8%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--gold) 14%, transparent);
}
.data-table .col-actions .btn-danger { color: var(--ink-2); }
.data-table .col-actions .btn-danger:hover {
  color: color-mix(in srgb, var(--danger) 35%, var(--ink));
  border-color: color-mix(in srgb, var(--danger) 50%, transparent);
  background: color-mix(in srgb, var(--danger) 12%, transparent);
  box-shadow: none;
}
.data-table .col-actions .btn:active:not(:disabled) { transform: translateY(1px); }
/* Los rótulos de los botones de acción se ven SIEMPRE: hubo una versión que
   en pantallas medianas los escondía y dejaba los íconos solos, y el usuario
   la devolvió («deben ser texto porque si no el cliente se va a marear»).
   Antes texto claro que cero scroll; abajo de 768px manda el modo tarjeta. */
.data-table .empty { text-align: center; color: var(--ink-3); padding: 8px; }

/* Footer: contador con N en dorado + pager prolijo con chevrons */
.table-footer { display: flex; align-items: center; justify-content: space-between; margin-top: 16px; flex-wrap: wrap; gap: 8px; padding-top: 4px; }
.table-info { font-family: var(--mono); font-size: 11px; letter-spacing: .04em; color: var(--ink-3); }
.table-info b, .table-info strong { color: var(--gold); font-weight: 500; }
.table-pager, .pager { display: flex; gap: 8px; }
.table-pager .btn, .pager .btn {
  height: 32px; padding: 0 13px; gap: 6px; font-size: 12px;
  background: var(--surface-2); color: var(--ink-2); border: 1px solid var(--line-strong);
}
.table-pager .btn i, .pager .btn i { font-size: 9px; }
.table-pager .btn:hover:not(:disabled), .pager .btn:hover:not(:disabled) {
  color: var(--ink);
  border-color: color-mix(in srgb, var(--gold) 40%, transparent);
}

/* ── Badges + 5 estados (reusa badge--prep/listo/prog/activo/cerrado de util.js) ── */
.badge {
  --c: var(--st-listo);
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px 4px 9px; border-radius: var(--radius-sm);
  font-size: 12px; font-weight: 600; letter-spacing: -.005em; white-space: nowrap;
  color: color-mix(in srgb, var(--c) 82%, var(--ink));
  background: color-mix(in srgb, var(--c) 13%, var(--surface));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c) 35%, transparent);
  border: none;
}
[data-theme="dark"] .badge { color: var(--c); background: color-mix(in srgb, var(--c) 16%, transparent); }
.badge i { font-size: .82em; }

.badge--prep    { --c: var(--st-preparando); }
.badge--listo   { --c: var(--st-listo); }
.badge--prog    { --c: var(--st-programado); }
.badge--activo  { --c: var(--st-activo); }
.badge--cerrado { --c: var(--st-cerrado); }

/* ── Marca del tipo de remate ────────────────────────────────────────────────
   Va al lado del badge de estado y se lee de corrido: «Activo, en vivo».
   Deliberadamente mas chica y mas callada que el badge: el estado manda, el
   tipo acompania. Sin texto — el icono es el significado. */
.mod {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; flex-shrink: 0;
  border-radius: var(--radius-sm); font-size: 11px; line-height: 1;
  color: var(--c);
  background: color-mix(in srgb, var(--c) 14%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c) 32%, transparent);
}
.mod--vivo   { --c: var(--mod-vivo); }
.mod--online { --c: var(--mod-online); }
.mod i { font-size: inherit; }

/* La leyenda: una sola vez, arriba de la lista. Es un recordatorio, no un
   decodificador — sin ella el icono se sigue entendiendo. */
.mod-leyenda {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px;
  margin: 0; font-size: 12px; color: var(--muted);
}
.mod-leyenda-it { display: inline-flex; align-items: center; gap: 7px; }

/* Estado + tipo en la misma celda, sin que el tipo empuje la fila. */
.cel-estado { display: inline-flex; align-items: center; gap: 7px; }


/* Solo para lectores de pantalla: el icono no dice nada en voz alta. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Chip slate — Retiro en Boletas de Salida. Neutral sobre ambos temas via tokens. */
/* ── Aviso de lote sin piso ──────────────────────────────────────────────────
   Ambar, no rojo: no es un error, es una consecuencia que hay que ver antes de
   publicar. Rojo se lee como "esto esta roto" y se aprende a ignorar. */
/* .pubweb-aviso: el mismo ámbar para los otros avisos de «antes de publicar»
   (lotes sin título, lotes con lo del ingreso sin revisar). */
.lote-sin-piso, .pubweb-sin-piso, .pubweb-aviso {
  display: flex; align-items: flex-start; gap: 8px;
  margin: 8px 0 0; padding: 9px 11px;
  border-radius: var(--radius-sm);
  font-size: 12.5px; line-height: 1.45;
  color: color-mix(in srgb, var(--st-preparando) 88%, var(--ink));
  background: color-mix(in srgb, var(--st-preparando) 12%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--st-preparando) 30%, transparent);
}
[data-theme="dark"] .lote-sin-piso, [data-theme="dark"] .pubweb-sin-piso, [data-theme="dark"] .pubweb-aviso {
  color: var(--st-preparando);
}
.lote-sin-piso i, .pubweb-sin-piso i, .pubweb-aviso i { margin-top: 2px; flex-shrink: 0; font-size: .95em; }
.lote-sin-piso[hidden] { display: none; }

/* ── Lo que el lote trajo del INGRESO ─────────────────────────────────────────
   Azul, el color de «de dónde vino» (el mismo de los chips de origen de las
   ofertas): no es un error, es una procedencia. El estimado del ingreso es lo
   que se le dijo al remitente y al publicar lo ve el público, así que se dice
   al lado del campo. Ámbar solo cuando NO se trajo (otra moneda, una pieza sin
   estimado): eso sí es algo que hay que resolver antes de publicar. */
.del-ingreso-nota {
  display: flex; align-items: flex-start; gap: 8px;
  margin: 6px 0 0; padding: 8px 10px;
  border-radius: var(--radius-sm);
  font-size: 12px; line-height: 1.45; color: var(--ink-2);
  background: color-mix(in srgb, var(--st-programado) 9%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--st-programado) 28%, transparent);
}
.del-ingreso-nota[hidden] { display: none; }
.del-ingreso-nota > i { margin-top: 2px; flex-shrink: 0; color: var(--st-programado); }
.del-ingreso-nota b { color: var(--ink); }
.del-ingreso-nota .btn { margin-left: auto; flex: none; align-self: center; }
.del-ingreso-nota--aviso {
  color: color-mix(in srgb, var(--st-preparando) 88%, var(--ink));
  background: color-mix(in srgb, var(--st-preparando) 12%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--st-preparando) 30%, transparent);
}
[data-theme="dark"] .del-ingreso-nota--aviso { color: var(--st-preparando); }
.del-ingreso-nota--aviso > i { color: inherit; }

/* Sub-grupo dentro de una seccion: etiqueta y aire, SIN marco propio. Una caja
   con borde adentro de otra caja con borde se lee como dos niveles que no son. */
.pubweb-sub { margin-top: 12px; }
.pubweb-sub-tit {
  margin: 0 0 6px;
  font-family: var(--sans); font-size: 12.5px; font-weight: 700; color: var(--ink);
}


/* Utilidad de centrado (evita style="text-align:center" inline, que el CSP bloquea). */
.text-center { text-align: center; }
/* Salidas: estilos que antes iban inline (los bloqueaba el CSP style-src 'self'). */
.sl-kpi-meta { margin-top: 8px; }
.sl-kpi-chip { font-size: 11px; padding: 3px 9px; }
.sl-mot-cell { display: inline-flex; align-items: flex-start; gap: 8px; }
.sl-mot-badge { flex-shrink: 0; font-size: 11px; padding: 3px 9px; }
.sl-mot-txt { font-size: 12px; color: var(--ink-3); padding-top: 1px; }
.sl-chip--slate {
  --c: color-mix(in srgb, var(--ink-3) 80%, var(--surface));
  color: color-mix(in srgb, var(--ink-3) 90%, var(--ink));
  background: color-mix(in srgb, var(--ink-3) 10%, var(--surface));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink-3) 28%, transparent);
}

/* ── Boletas de Salida · modal "Nueva salida" (multi-selección con cantidades) ── */
/* Datos de la salida (motivo + remitente): arriba, antes de elegir piezas. */
.sl-nueva .sl-datos {
  display: grid; grid-template-columns: 1fr 1fr; gap: 14px;
  padding-bottom: 12px; border-bottom: 1px solid var(--line);
}
.sl-nueva .sl-datos textarea { min-height: 60px; }
@media (max-width: 560px) { .sl-nueva .sl-datos { grid-template-columns: 1fr; } }

/* Buscador (matchea objeto o remitente en una sola lista). */
.sl-nueva .sl-buscar {
  width: 100%; padding: 9px 12px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--ink); font-size: 13px; transition: var(--transition);
}
.sl-nueva .sl-buscar::placeholder { color: var(--ink-4); }
.sl-nueva .sl-buscar:focus { outline: none; border-color: var(--green-400); box-shadow: var(--ring); }

/* Lista de piezas — ALTO FIJO: la caja mide siempre lo mismo (no salta al buscar/paginar);
   scroll propio, encabezado pegajoso y gutter estable para que el scrollbar no corra el layout. */
.sl-nueva .sl-list {
  height: 336px; overflow-y: auto; scrollbar-gutter: stable;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.sl-nueva .sl-hint { margin: 0; padding: 40px 16px; text-align: center; font-size: 13px; color: var(--ink-3); }

/* Tabla de piezas seleccionables (encabezado pegajoso en el scroll de la lista). */
.sl-piezas-tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
.sl-piezas-tbl thead th {
  position: sticky; top: 0; z-index: 1; text-align: left; padding: 9px 12px;
  background: var(--surface-2); color: var(--ink-4);
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  border-bottom: 1px solid var(--line);
}
.sl-piezas-tbl tbody td { padding: 8px 12px; border-bottom: 1px solid var(--line); color: var(--ink-2); vertical-align: middle; }
.sl-piezas-tbl tbody tr:last-child td { border-bottom: none; }
.sl-piezas-tbl tbody tr:hover { background: var(--row-hover); }
.sl-piezas-tbl .sl-col-check { width: 34px; }
.sl-piezas-tbl .sl-col-num { width: 56px; text-align: right; font-family: var(--mono); color: var(--ink-3); }
.sl-piezas-tbl .sl-col-cant { width: 100px; }
.sl-piezas-tbl .sl-check { width: 17px; height: 17px; accent-color: var(--green-600); cursor: pointer; }
.sl-piezas-tbl .sl-obj-nom { font-weight: 600; color: var(--ink); }
.sl-piezas-tbl .sl-obj-id { font-size: 11.5px; }
.sl-piezas-tbl .sl-cant {
  width: 100%; padding: 6px 8px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--ink); font-family: var(--mono); text-align: center; font-size: 13px;
  transition: var(--transition);
}
.sl-piezas-tbl .sl-cant:disabled { opacity: .45; cursor: not-allowed; }
.sl-piezas-tbl .sl-cant:focus { outline: none; border-color: var(--green-400); box-shadow: var(--ring); }

/* Pie: paginador (izq) + contador de selección (der). Altura fija para no desplazar. */
.sl-nueva .sl-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 32px;
}
.sl-nueva .sl-pager { display: flex; align-items: center; gap: 10px; }
.sl-nueva .sl-pg {
  display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px;
  border: 1px solid var(--line-strong); border-radius: 6px; cursor: pointer;
  background: var(--surface); color: var(--ink-2); transition: var(--transition);
}
.sl-nueva .sl-pg:hover:not(:disabled) { color: var(--ink); border-color: var(--green-400); }
.sl-nueva .sl-pg:disabled { opacity: .4; cursor: not-allowed; }
.sl-nueva .sl-pg-info { font-size: 12px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.sl-selc { font-size: 12px; font-weight: 600; color: var(--ink-3); }

/* dot "en vivo" del estado Activo (badgeEstado lo inyecta para estado 3) */
.badge-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--c); flex-shrink: 0; animation: badgePulse 1.9s ease-out infinite; }
@keyframes badgePulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--c) 50%, transparent); }
  70%  { box-shadow: 0 0 0 5px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}
@media (prefers-reduced-motion: reduce) { .badge-dot { animation: none; } }

/* ── Formularios / inputs / select (chevron propio) ─────────────────────────── */
.form { display: flex; flex-direction: column; gap: 14px; }
.form-group { display: flex; flex-direction: column; gap: 6px; }
/* Mismo motivo que `.web-switch[hidden]`: sin esto, un `.form-group` con el
   atributo `hidden` (ej. `data-grupo-extension`, `data-grupo-cierre` del modal
   de Publicación) queda visible igual, porque el `display:flex` de arriba es
   CSS de autor y le gana al `display:none` de la hoja del navegador. */
.form-group[hidden] { display: none; }
.form-group label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-4); }

/* Texto de ayuda bajo el label (opcional, minúsculas). */
.field-hint { font-size: 11.5px; font-weight: 400; text-transform: none; letter-spacing: 0; line-height: 1.35; }
.form-nota { font-size: 12px; color: var(--ink-3); margin: -4px 0 14px; }

/* Checkbox con label a la derecha (toggle en una fila, no columna). */
.form-check .form-check-label { display: flex; flex-direction: row; align-items: center; gap: 9px; cursor: pointer; text-transform: none; letter-spacing: 0; font-size: 13.5px; font-weight: 500; color: var(--ink-2); }
.form-check input[type="checkbox"] { width: 17px; height: 17px; flex: none; accent-color: var(--green-600); cursor: pointer; }
.form-group input, .form-group select, .form-group textarea {
  padding: 10px 13px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--ink); font-size: 13.5px; transition: var(--transition); width: 100%;
}
.form-group textarea { resize: vertical; min-height: 72px; }
.form-group select {
  appearance: none; -webkit-appearance: none; padding-right: 38px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%236b7c6b' stroke-width='1.6'%3E%3Cpath d='M2 4l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 13px center;
}
[data-theme="dark"] .form-group select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%2393a89b' stroke-width='1.6'%3E%3Cpath d='M2 4l4 4 4-4'/%3E%3C/svg%3E");
}
.form-group input[type="date"]::-webkit-calendar-picker-indicator { opacity: .55; cursor: pointer; }
.form-group input:focus, .form-group select:focus, .form-group textarea:focus { outline: none; border-color: var(--green-400); box-shadow: var(--ring); }
.form .req { color: var(--danger); }
.field-error { color: var(--danger); font-size: 11.5px; font-weight: 600; }
.confirm-body .confirm-msg { margin: 0; }
.confirm-body .confirm-detail { margin: 8px 0 0; font-size: 13px; line-height: 1.5; color: var(--ink-3); }
.form-actions, .confirm-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 14px; padding-top: 16px; border-top: 1px solid var(--line); }
/* Aviso dentro de un modal cuando falta un dato imprescindible para la acción
   (ej. "Escribirle" sin mail cargado): mismo tinte dorado que .co-falta-url,
   pero sin depender de un padre grid. */
.msj-sin-mail {
  margin: 0; display: flex; gap: 8px; align-items: flex-start;
  padding: 10px 12px; border-radius: var(--radius-sm);
  border: 1px solid color-mix(in srgb, var(--gold) 45%, transparent);
  background: color-mix(in srgb, var(--gold) 9%, transparent);
  font-size: .85rem; line-height: 1.45; color: var(--ink-2);
}
.msj-sin-mail i { color: var(--gold); margin-top: 2px; flex: 0 0 auto; }
.sena-head { display: flex; justify-content: space-between; align-items: center; gap: .5rem; }
.sena-modo { display: flex; gap: .25rem; }

/* ── Modal — look "DATA REFINADA" (variante B del mockup): sheet sobria
   Linear/Vercel, hairline dorada superior, cabecera con kicker mono, secciones
   por divisores sutiles, inputs con FOCO VERDE y footer claro ──────────────── */
.modal-overlay { position: fixed; inset: 0; background: rgba(17,30,17,.45); backdrop-filter: blur(4px); display: flex; align-items: center; justify-content: center; padding: 1rem; z-index: 1000; }
[data-theme="dark"] .modal-overlay { background: rgba(0,0,0,.62); }
.modal {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  width: 100%; max-width: 480px; max-height: min(90vh, 760px);
  display: flex; flex-direction: column; overflow: hidden;
}
/* Variante ancha: para modales con tablas o contenido que no entra en 480px. */
.modal.modal-wide { max-width: 720px; }
/* ════════════════════════════════════════════════════════════════════════════
   DARK · Modales "Variante C": panel MÁS CLARO (#222b26) y aireado. SOLO dark.
   Subir el panel obliga a re-derivar la ESCALA DE ELEVACIÓN local: las superficies
   internas usaban tokens pensados para un panel oscuro y, sobre #222b26, se invertían:
   - "elevadas" (footer, close, botón 2º, thead) iban con --surface-2 #1a241f →
     quedaban MÁS oscuras que el panel (se hundían) → suben a #2e3833.
   - "campos/pozos" (inputs, metric, selected, obs) iban con --bg #0b110e → agujeros
     negros sobre el panel claro → suben a #161e19 (pozo coherente, ~1 paso bajo el panel).
   En vez de ~20 selectores sueltos se re-mapean los TOKENS scopeados a .modal y las
   reglas existentes cascadean (incluye --ink-4: así la ✕ del close y el nº del step-dot
   pasan AA sobre lo elevado). Light mode intacto: TODO bajo [data-theme="dark"]. */
[data-theme="dark"] .modal {
  backdrop-filter: none;
  background: #222b26;                 /* panel elevado y aireado (variante C) */
  --bg: #161e19;                       /* pozo: inputs, metric, selected-item, obs-item (antes #0b110e = agujero negro) */
  --surface: #1c2521;                  /* nivel medio: foco de input, step-dot idle, lote-foto, inputs anidados */
  --surface-2: #2e3833;                /* elevado: footer, close, botón 2º, thead (antes #1a241f → se hundía bajo el panel) */
  --ctrl-hover: #36413b;               /* hover de controles, un paso sobre lo elevado */
  --row-hover: color-mix(in srgb, var(--green-400) 12%, #222b26);  /* hover de fila SOBRE el panel (antes oscurecía) */
  --line: rgba(255,255,255,.12);       /* divisores reforzados (el .08 se borraba sobre el panel claro) */
  --ink-4: #93a89b;                    /* tinta muted re-derivada → ✕ del close y nº del step-dot pasan AA */
}
/* Header: el velo verde 5% casi desaparece sobre el panel claro → 8%; divisor reforzado. */
[data-theme="dark"] .modal-header {
  background: linear-gradient(180deg, color-mix(in srgb, var(--green-400) 8%, transparent), transparent);
  border-bottom-color: rgba(180,210,195,.20);
}
/* Hairline dorada superior: el glow translúcido se diluye sobre fondo claro → más opacidad. */
[data-theme="dark"] .modal::before { opacity: .92; }
/* Campos con borde firme verdoso (gana al --line del modal). */
[data-theme="dark"] .modal .form-group input,
[data-theme="dark"] .modal .form-group select,
[data-theme="dark"] .modal .form-group textarea { border-color: var(--line-strong); }
/* Scrollbar del cuerpo: el thumb llevaba borde de --surface para fundirse; con el body
   en #222b26 el borde debe ser el panel, si no queda un halo oscuro alrededor del thumb. */
[data-theme="dark"] .modal-body::-webkit-scrollbar-thumb { border-color: #222b26; }
/* hairline dorada superior */
.modal::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 1px; z-index: 3; pointer-events: none;
  background: linear-gradient(90deg, transparent, var(--gold-glow) 18%, var(--gold) 50%, var(--gold-glow) 82%, transparent);
  opacity: .8;
}

.modal-header {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 12px;
  padding: 16px 20px 14px;
  border-bottom: 1px solid var(--line);
  background: linear-gradient(180deg, color-mix(in srgb, var(--green-400) 5%, transparent), transparent);
}
.modal-header-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
/* kicker mono opcional ("MORALES COLOMBO · REMATE") */
.modal-kicker {
  font-family: var(--mono); font-size: 10px; font-weight: 500;
  letter-spacing: .18em; text-transform: uppercase; color: var(--gold);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.modal-title { font-family: var(--sans); font-size: 16px; font-weight: 700; letter-spacing: -.01em; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.modal-close {
  margin-left: auto; flex: 0 0 auto;
  width: 32px; height: 32px; display: grid; place-items: center;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-sm);
  color: var(--ink-4); font-size: 1.25rem; line-height: 1; cursor: pointer;
  transition: var(--transition);
}
.modal-close:hover { color: var(--ink); border-color: var(--line-strong); background: var(--ctrl-hover); }
.modal-body { flex: 1 1 auto; min-height: 0; padding: 24px; overflow-y: auto; }
/* scrollbar fino y discreto del cuerpo */
.modal-body { scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent; }
.modal-body::-webkit-scrollbar { width: 10px; }
.modal-body::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 99px; border: 3px solid var(--surface); background-clip: padding-box; }
/* Footer del form dentro del modal: pegado abajo, claro, con divisor; siempre
   visible mientras el cuerpo scrollea */
.modal .form-actions { position: sticky; bottom: -24px; margin: 18px -24px -24px; padding: 14px 24px; background: var(--surface-2); border-top: 1px solid var(--line); }

/* ── Forms DENTRO del modal: labels más sobrias (peso medio, sin grito) ─────── */
.modal .form-group label { font-weight: 600; letter-spacing: .02em; text-transform: none; font-size: 11.5px; color: var(--ink-3); }
/* Más aire entre campos y secciones dentro del modal (look respirado). */
.modal-body .form { gap: 18px; }
.modal .form-group { gap: 7px; }
.modal-body .section-title { margin: 18px 0 12px; }
.modal-body > .form > .section-title:first-child,
.modal-body > .section-title:first-child { margin-top: 0; }
.modal .form-group input, .modal .form-group select, .modal .form-group textarea { background: var(--bg); border-color: var(--line); }
.modal .form-group input:hover, .modal .form-group select:hover, .modal .form-group textarea:hover { border-color: var(--line-strong); }
/* FOCO VERDE (anillo var(--green-glow)) — superficie levantada al enfocar */
.modal .form-group input:focus, .modal .form-group select:focus, .modal .form-group textarea:focus { border-color: var(--green-600); background: var(--surface); box-shadow: var(--ring); }

/* ── Botones DENTRO del modal (NO el .btn global de toda la app) ────────────── */
.modal .btn-secondary { background: var(--surface-2); }
.modal .btn-secondary:hover:not(:disabled) { background: var(--ctrl-hover); border-color: var(--line-strong); color: var(--ink); }

/* ── Modal de Saldo (cobro por cliente en un remate) ────────────────────────── */
.saldo-modal .saldo-info { font-size: 13px; margin: 0 0 14px; color: var(--ink-2); }
.saldo-modal .saldo-boletas td { vertical-align: middle; }
/* Con la columna Comisión son 7 columnas: no entran en los 720px del modal
   wide y aparecía scroll horizontal que tapaba los botones S/T. Se ensancha
   el modal y se compacta el padding para que la tabla entre completa. */
.modal:has(.saldo-modal) { max-width: 860px; }
.saldo-modal .saldo-boletas th,
.saldo-modal .saldo-boletas td { padding-left: 11px; padding-right: 11px; }
.saldo-modal .cobro-input { width: 110px; padding: 6px 9px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--surface); color: var(--ink); font-size: 13px; text-align: right; }
.saldo-modal .saldo-total { text-align: right; font-size: 14px; margin: 14px 0; color: var(--ink-2); }
.saldo-modal .saldo-total strong { color: var(--green-ink); font-size: 16px; }
[data-theme="dark"] .saldo-modal .saldo-total strong { color: var(--gold); }

/* ── Stepper (modal de estado del remate) ───────────────────────────────────── */
.estado-modal { display: flex; flex-direction: column; gap: 22px; }
.stepper { display: flex; align-items: flex-start; overflow-x: auto; padding-bottom: 4px; }
.step { display: flex; flex-direction: column; align-items: center; gap: 8px; flex: 0 0 70px; text-align: center; }
.step-dot { width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center; font-size: .8rem; background: var(--surface); color: var(--ink-4); border: 1px solid var(--line-strong); transition: var(--transition); }
.step-label { font-size: 11.5px; letter-spacing: .02em; color: var(--ink-4); line-height: 1.2; }
.step-line { flex: 1 1 auto; min-width: 12px; height: 2px; background: var(--line); border-radius: 2px; margin-top: 15px; }
.step-line--done { background: var(--green-500); }
.step--done .step-dot { background: var(--listo-bg); color: var(--green-600); border-color: transparent; }
.step--current .step-dot { background: var(--green-600); color: #fff; border-color: var(--green-600); box-shadow: 0 0 0 4px var(--green-glow); }
.step--current .step-label { color: var(--ink); font-weight: 700; }
.estado-actions { display: flex; flex-direction: column; gap: 10px; padding-top: 16px; border-top: 1px solid var(--line); }
.estado-actions .btn { width: 100%; }
/* Stepper vertical en móvil (no se corta) */
@media (max-width: 480px) {
  .stepper { flex-direction: column; align-items: stretch; overflow-x: visible; gap: 4px; }
  .step { flex-direction: row; gap: 12px; flex: none; text-align: left; }
  .step-label { font-size: .8rem; }
  .step-line { display: none; }
}

/* ── Toast ──────────────────────────────────────────────────────────────────── */
/* ABAJO A LA DERECHA, no arriba: arriba a la derecha vive la campanita, y el
   toast la tapaba justo cuando mas se la quiere tocar (llega una oferta, salta
   el aviso, y hay que esperar a que se vaya para poder abrir la cola). Los
   avisos son de lectura; los controles del encabezado son de accion, y la
   accion no puede quedar debajo de la lectura.

   Y el contenedor no intercepta clicks: solo los toast en si. Sin esto, la
   columna vacia entre dos avisos sigue robando el click de lo que haya debajo. */
.toast-container {
  position: fixed; bottom: 22px; right: 22px; z-index: 1100;
  display: flex; flex-direction: column-reverse; gap: 10px;
  pointer-events: none;
}
.toast { pointer-events: auto; }
.toast { display: flex; align-items: center; gap: 11px; padding: 13px 16px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm); box-shadow: var(--shadow-lg); border-left: 3px solid var(--green-400); min-width: 240px; max-width: 360px; font-size: 13px; font-weight: 500; color: var(--ink); opacity: 0; transform: translateX(18px); transition: opacity .25s, transform .25s; }
.toast-show { opacity: 1; transform: translateX(0); }
.toast-ok { border-left-color: var(--green-400); } .toast-ok i { color: var(--green-400); }
.toast-error { border-left-color: var(--danger); } .toast-error i { color: var(--danger); }
.toast-info i { color: var(--green-ink); }

/* ── Welcome / dashboard fallback ───────────────────────────────────────────── */
.welcome { text-align: center; padding: 64px 20px; }
.welcome-icon { font-size: 3rem; color: var(--gold); margin-bottom: 18px; }
.welcome h2 { font-family: var(--sans); font-size: 1.7rem; font-weight: 700; color: var(--ink); margin-bottom: 10px; letter-spacing: -.02em; }
.welcome p { color: var(--ink-3); font-size: .95rem; }

/* ── Dashboard — stat-cards + panel (markup nuevo en home.js) ───────────────── */
.stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-bottom: 24px; }
.stat { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 18px 18px 16px; position: relative; overflow: hidden; box-shadow: var(--shadow-card); cursor: default; transition: border-color .16s ease, box-shadow .16s ease; }
/* PROBLEMA 3: la KPI card NO es clickeable — hover honesto sin lift (border + sombra suave), cursor default */
.stat:hover { border-color: var(--line-strong); box-shadow: var(--shadow-pop); }
.stat.accent { border-color: color-mix(in srgb, var(--green-400) 45%, var(--line)); }
.stat.accent::after { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: linear-gradient(180deg, var(--green-400), var(--green-600)); }
.stat .top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.stat .label { font-size: 12.5px; font-weight: 600; color: var(--ink-3); }
.stat .ico { width: 30px; height: 30px; border-radius: 8px; display: grid; place-items: center; font-size: 13px; color: var(--green-600); background: var(--listo-bg); border: 1px solid color-mix(in srgb, var(--green-500) 22%, transparent); }
.stat .value { font-family: var(--mono); font-size: 34px; font-weight: 600; letter-spacing: -.045em; line-height: 1; color: var(--ink); font-variant-numeric: tabular-nums; }
.stat .value small { font-size: 18px; font-weight: 600; color: var(--ink-3); }
.stat .trend { display: flex; align-items: center; gap: 6px; margin-top: 11px; font-size: 12px; font-weight: 600; }
.stat .trend.up { color: var(--green-500); }
.stat .trend .sub { color: var(--ink-4); font-weight: 500; }
@media (max-width: 980px) { .stats { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .stats { grid-template-columns: 1fr; } }

/* Panel que envuelve la tabla del dashboard (estilo mockup .panel) */
.panel { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-card); overflow: hidden; }
.panel-head { display: flex; align-items: center; gap: 12px; padding: 16px 20px; border-bottom: 1px solid var(--line); }
.panel-head h2 { font-family: var(--sans); font-size: 15px; font-weight: 700; letter-spacing: -.02em; color: var(--ink); }
.panel-head .sub { font-size: 12.5px; color: var(--ink-4); font-weight: 500; }
.panel-head .actions { margin-left: auto; display: flex; gap: 8px; }
.panel-foot { display: flex; align-items: center; justify-content: space-between; padding: 13px 20px; border-top: 1px solid var(--line); background: var(--surface-2); }
.panel-foot .info { font-size: 12.5px; color: var(--ink-4); font-weight: 500; }
.panel-foot a { font-size: 13px; font-weight: 600; color: var(--green-600); display: inline-flex; align-items: center; gap: 6px; transition: color .14s ease; }
.panel-foot a i { transition: transform .14s var(--smooth); }
[data-theme="dark"] .panel-foot a { color: var(--green-ink); }
/* CTA de pie de panel ("Ver todos los remates"): hover crisp — shift de color + flecha que avanza */
.panel-foot a:hover { color: var(--green-500); text-decoration: none; }
.panel-foot a:hover i { transform: translateX(3px); }
[data-theme="dark"] .panel-foot a:hover { color: color-mix(in srgb, var(--green-ink) 82%, #fff); }

/* ── Atajos (dashboard) — grilla de accesos directos a acciones frecuentes ──── */
.shortcuts-panel { margin-bottom: 24px; }
.shortcuts { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; padding: 18px 20px; }
.shortcut { display: flex; align-items: center; gap: 13px; padding: 14px 15px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface-2); color: var(--ink); transition: border-color .16s ease, box-shadow .16s ease, transform .16s ease, background .16s ease; }
.shortcut:hover { border-color: color-mix(in srgb, var(--green-500) 45%, var(--line)); box-shadow: var(--shadow-pop); transform: translateY(-2px); text-decoration: none; background: var(--surface); }
.shortcut .sc-ico { flex: 0 0 auto; width: 38px; height: 38px; border-radius: 10px; display: grid; place-items: center; font-size: 15px; color: var(--green-600); background: var(--listo-bg); border: 1px solid color-mix(in srgb, var(--green-500) 22%, transparent); transition: background .16s ease, color .16s ease; }
.shortcut:hover .sc-ico { background: linear-gradient(150deg, var(--green-500), var(--green-600)); color: #fff; border-color: transparent; }
.shortcut .sc-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.shortcut .sc-text b { font-size: 13.5px; font-weight: 700; letter-spacing: -.01em; color: var(--ink); }
.shortcut .sc-text small { font-size: 11.5px; color: var(--ink-4); font-weight: 500; }
.shortcut .sc-arrow { margin-left: auto; font-size: 12px; color: var(--ink-4); transition: transform .16s var(--smooth), color .16s ease; }
.shortcut:hover .sc-arrow { color: var(--green-600); transform: translateX(3px); }
[data-theme="dark"] .shortcut .sc-ico { color: var(--green-ink); }
/* En dark el dorado (#d8b878) sí es limpio → se mantiene el pop dorado en hover;
   en light queda verde (el ocre #c4993a se veía muddy). */
[data-theme="dark"] .shortcut:hover .sc-ico { background: linear-gradient(150deg, var(--gold), var(--gold-2)); color: #11240f; }
[data-theme="dark"] .shortcut:hover .sc-arrow { color: var(--gold); }
@media (max-width: 980px) { .shortcuts { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .shortcuts { grid-template-columns: 1fr; } }

/* ── Auth (login) — dos paneles: paño verde + formulario ────────────────────── */
.auth { min-height: 100vh; display: grid; grid-template-columns: 1.05fr 1fr; }
.auth-brand { position: relative; overflow: hidden; display: flex; flex-direction: column; justify-content: center; padding: 64px 56px; color: #f3efe3;
  background: radial-gradient(900px 520px at 18% 0%, var(--gold-glow), transparent 60%), linear-gradient(155deg, #0c1a0c, #111e11 55%, #0a120a); }
.auth-brand::before { content: ''; position: absolute; inset: 22px; border: 1px solid rgba(196,153,58,.26); border-radius: 6px; pointer-events: none; }
.auth-brand-inner { position: relative; z-index: 2; animation: fadeUp .7s var(--ease) both; }
.auth-mark { width: 62px; height: 62px; border-radius: 14px; display: grid; place-items: center; font-family: var(--sans); font-weight: 800; font-size: 1.5rem; color: #11240f; background: linear-gradient(150deg, var(--gold), var(--gold-2)); box-shadow: 0 10px 26px rgba(0,0,0,.32); margin-bottom: 30px; }
.auth-logo-card { display: inline-flex; padding: 20px 26px; background: #fff; border-radius: 16px; box-shadow: 0 18px 40px -16px rgba(0,0,0,.55), 0 0 0 1px rgba(196,153,58,.25); margin-bottom: 26px; }
.auth-logo { display: block; width: 210px; max-width: 58vw; height: auto; }
.auth-wordmark { font-family: var(--sans); font-weight: 800; font-size: 3rem; line-height: .98; letter-spacing: -.03em; }
.auth-tag { font-family: var(--sans); font-size: 1.1rem; color: #d8c39a; margin-top: 16px; font-weight: 500; }
.auth-estab { font-size: .64rem; letter-spacing: .26em; text-transform: uppercase; color: rgba(196,153,58,.85); margin-top: 22px; }
.auth-flourish { position: absolute; right: -34px; bottom: -36px; font-size: 16rem; color: rgba(196,153,58,.07); transform: rotate(-14deg); z-index: 1; }
.auth-panel { display: flex; align-items: center; justify-content: center; padding: 40px 28px; background: var(--surface); }
.auth-form { width: 100%; max-width: 380px; display: flex; flex-direction: column; gap: 16px; animation: fadeUp .6s var(--ease) .08s both;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 34px 32px; box-shadow: var(--shadow-pop); }
[data-theme="dark"] .auth-form { background: var(--surface-2); box-shadow: var(--shadow-lg); }
.auth-form-head h2 { font-family: var(--sans); font-size: 1.7rem; font-weight: 700; letter-spacing: -.02em; color: var(--ink); }
.auth-form-head p { color: var(--ink-3); font-size: .9rem; margin: 4px 0 8px; }
.auth-field { display: flex; flex-direction: column; gap: 6px; }
.auth-field label { font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-4); }
.auth-field input { width: 100%; padding: 12px 14px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); font-size: .95rem; background: var(--surface); color: var(--ink); transition: var(--transition); }
.auth-field input:focus { outline: none; border-color: var(--green-400); background: var(--surface); box-shadow: var(--ring); }
.pw-wrap { position: relative; display: flex; align-items: center; }
.pw-wrap input { padding-right: 44px; }
.pw-toggle { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); width: 32px; height: 32px; display: grid; place-items: center; background: transparent; border: none; border-radius: 8px; color: var(--ink-4); cursor: pointer; transition: var(--transition); }
.pw-toggle:hover { color: var(--green-ink); background: var(--ctrl-hover); }
.auth-submit { width: 100%; padding: 13px; font-size: .95rem; margin-top: 6px; height: auto; }
.auth-error { background: var(--danger-soft); border: 1px solid color-mix(in srgb, var(--danger) 40%, transparent); color: var(--danger); padding: 10px 14px; border-radius: var(--radius-sm); font-size: .85rem; }

@media (max-width: 820px) {
  .auth { grid-template-columns: 1fr; }
  .auth-brand { padding: 36px 30px; min-height: 210px; justify-content: flex-end; }
  .auth-brand::before { inset: 14px; }
  .auth-mark { width: 50px; height: 50px; font-size: 1.25rem; margin-bottom: 18px; }
  .auth-wordmark { font-size: 2.2rem; }
  .auth-tag { font-size: 1rem; }
  .auth-flourish { font-size: 9rem; right: -16px; bottom: -8px; }
}

/* ── Stock: galería de objetos ──────────────────────────────────────────────── */
.obj-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 16px; }
/* Encabezado de sección (Disponibles / Agotados) en "Todos": ocupa todo el ancho de la grilla. */
.obj-group-h { grid-column: 1 / -1; display: flex; align-items: center; gap: 10px; margin: 10px 2px 0; font-family: var(--mono); font-size: 10.5px; font-weight: 500; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-3); }
.obj-group-h:first-child { margin-top: 0; }
.obj-group-h .obj-group-n { flex: none; font-weight: 600; color: var(--ink-4); }
.obj-group-h::after { content: ''; flex: 1; height: 1px; background: var(--line); }
.obj-card { position: relative; display: flex; flex-direction: column; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-card); transition: var(--transition); }
.obj-card:hover { box-shadow: var(--shadow-pop); transform: translateY(-2px); border-color: var(--line-strong); }
.obj-photo-btn { position: relative; display: block; width: 100%; padding: 0; border: none; background: none; cursor: pointer; aspect-ratio: 4 / 3; overflow: hidden; }
/* contain, NO cover: la foto del objeto se ve COMPLETA. Con cover, una pieza
   alta (un cuchillo, un cuadro) se recortaba por los costados y desde la grilla
   no se distinguia de otra. El alto lo fija .obj-photo-btn (aspect 4/3), asi que
   todas las cards siguen midiendo igual; las bandas toman el fondo neutro. */
.obj-photo { width: 100%; height: 100%; object-fit: contain; display: block; background: var(--surface-2); }
.obj-photo--empty { display: flex; align-items: center; justify-content: center; background: var(--surface-2); color: var(--ink-4); }
.obj-photo--empty i { font-size: 2.4rem; color: var(--line-strong); }
.obj-photo-cta { position: absolute; inset: auto 0 0 0; display: flex; align-items: center; justify-content: center; gap: 7px; padding: 9px; font-size: 12px; font-weight: 600; color: #fff; background: linear-gradient(transparent, rgba(17,30,17,.78)); opacity: 0; transform: translateY(6px); transition: var(--transition); }
.obj-photo-btn:hover .obj-photo-cta, .obj-photo-btn:focus-visible .obj-photo-cta { opacity: 1; transform: translateY(0); }
.obj-photo--empty + .obj-photo-cta { opacity: 1; transform: none; background: none; color: var(--green-ink); }
/* Miniatura del objeto en el detalle de la boleta de entrada (por clase: el CSP
   bloquea el style inline). */
.be-obj-thumb { width: 44px; height: 44px; object-fit: cover; border-radius: 6px; display: block; border: 1px solid var(--line); }
/* Valor estimado como rango (Desde / Hasta) en el alta/edición de objeto. */
.objeto-valor-rango { display: flex; gap: 8px; }
.objeto-valor-rango input { flex: 1; min-width: 0; }
/* Barra de acciones del detalle de la boleta de entrada (botón Imprimir/PDF). */
.be-detalle-toolbar { display: flex; justify-content: flex-end; margin-bottom: 12px; }
.obj-remove { position: absolute; top: 10px; right: 10px; z-index: 2; width: 30px; height: 30px; display: grid; place-items: center; border: none; border-radius: 50%; background: color-mix(in srgb, var(--surface) 92%, var(--bg)); backdrop-filter: blur(4px); color: var(--danger); cursor: pointer; box-shadow: var(--shadow-card); opacity: 0; transition: var(--transition); }
.obj-card:hover .obj-remove, .obj-remove:focus-visible { opacity: 1; }
.obj-remove:hover { background: var(--danger); color: #fff; }
.obj-body { padding: 13px 15px 15px; display: flex; flex-direction: column; gap: 7px; flex: 1; }
.obj-name { font-family: var(--sans); font-size: 14px; font-weight: 700; line-height: 1.3; letter-spacing: -.01em; color: var(--ink); }
.obj-desc { font-size: 12.5px; color: var(--ink-3); line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.obj-meta { margin-top: auto; display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
.obj-val { font-family: var(--mono); font-size: 14px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--green-ink); white-space: nowrap; }
[data-theme="dark"] .obj-val { color: var(--gold); }
/* El lapiz va PEGADO al valor estimado, y siempre visible (no en hover como el
   de quitar foto). En Stock no habia forma de editar ese numero y el cliente lo
   busco justo ahi: esconderlo detras de un hover era repetir el problema. */
.obj-val-wrap { display: inline-flex; align-items: center; gap: 7px; flex: none; }
.obj-editar { width: 26px; height: 26px; flex: none; display: grid; place-items: center; padding: 0; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--surface-2); color: var(--ink-3); font-size: 11px; cursor: pointer; transition: var(--transition); }
.obj-editar:hover { background: var(--ctrl-hover); color: var(--ink); border-color: var(--green-500); }
.chip { display: inline-flex; align-items: center; gap: 7px; height: 26px; padding: 0 11px; border-radius: var(--radius-sm); font-size: 12px; font-weight: 600; background: var(--listo-bg); color: var(--green-600); border: 1px solid color-mix(in srgb, var(--green-500) 25%, transparent); }
[data-theme="dark"] .chip { color: var(--st-listo); }
.chip--out { background: var(--danger-soft); color: var(--danger); border-color: color-mix(in srgb, var(--danger) 30%, transparent); }

/* Venta anulada: badge propio + fila atenuada con el monto tachado, para que se
   lea de un vistazo que esa fila NO cuenta (sigue visible: la exige el municipal). */
.badge--anulada { --c: var(--danger); }
.vt-fila-anulada td { opacity: .5; }
.vt-fila-anulada .vt-money { text-decoration: line-through; }
.vt-fila-anulada .badge--anulada { opacity: 1; }
/* El panel de cierre online atenúa el lote que ya tiene boleta de pista: no es
   más un pendiente de trabajo (llamar, cargar), es historia. */
.vt-fila-vendida td { opacity: .6; }

/* Traza del objeto: en qué remate/lote están sus unidades comprometidas. */
.obj-trazas { display: flex; flex-direction: column; gap: 4px; margin-top: 9px; padding-top: 9px; border-top: 1px dashed var(--line); }
.obj-traza { font-size: 12px; color: var(--ink-3); line-height: 1.35; }
.obj-traza i { font-size: 10px; margin-right: 4px; color: var(--green-600); }
[data-theme="dark"] .obj-traza i { color: var(--gold); }
.obj-traza b { color: var(--ink-2); font-weight: 600; }

/* Chips de filtro (clickeables, con estado activo) — p. ej. estado en Remates */
.filter-chips { display: flex; flex-wrap: wrap; gap: 7px; margin: 0 0 14px; }
.filter-chip { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 13px; border-radius: 999px; font-family: var(--sans); font-size: 12.5px; font-weight: 600; background: var(--surface); color: var(--ink-2); border: 1px solid var(--line-strong); cursor: pointer; transition: background-color .14s ease, color .14s ease, border-color .14s ease; }
.filter-chip:hover { border-color: var(--green-ink); color: var(--green-ink); }
.filter-chip.is-active { background: var(--green-600); color: #fff; border-color: var(--green-600); }
[data-theme="dark"] .filter-chip.is-active { background: var(--gold); color: #1a1a1a; border-color: var(--gold); }

/* ── Empty state + paginador ────────────────────────────────────────────────── */
.empty-state { text-align: center; padding: 48px 24px; color: var(--ink-3); border: 1px dashed var(--line-strong); border-radius: var(--radius); background: var(--surface-2); animation: popIn .4s var(--ease) both; }
.data-table .empty-state { border: none; background: none; padding: 40px 16px; }
.empty-state i { font-size: 2.4rem; color: var(--ink-4); }
.empty-state h3 { font-family: var(--sans); font-size: 15px; font-weight: 700; color: var(--ink); margin: 14px 0 6px; }
.empty-state p { font-size: 12.5px; margin-bottom: 16px; }
.pager { align-items: center; justify-content: center; gap: 16px; margin-top: 24px; }
.pager-info { font-size: 12.5px; color: var(--ink-4); }

/* ── Ventas: layout main+aside, saldos, progress, captions ──────────────────── */
.toolbar-field { margin: 0; min-width: 200px; }
/* Filtro compacto (selects de pocas opciones, p.ej. perfil/estado en Usuarios) */
.toolbar-field--sm { min-width: 140px; flex: 0 0 auto; }
.toolbar-field > label { display: block; font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-3); margin-bottom: 4px; }
/* ════════ Ventas / Boleta de Pista — KPIs + pestañas (rediseño) ════════ */
/* Tira de KPIs (siempre visible) */
.vt-kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-card); margin-bottom: 20px; }
.vt-kpi { background: var(--surface); padding: 16px 18px; }
.vt-kpi--accent { background: var(--surface-2); }
.vt-kpi .k-top { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.vt-kpi .k-ico { width: 28px; height: 28px; border-radius: var(--radius-sm); display: grid; place-items: center; flex: none; background: var(--surface-2); border: 1px solid var(--line); color: var(--green-ink); font-size: 13px; }
.vt-kpi--amber .k-ico { color: var(--gold); }
.vt-kpi .k-label { font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); font-weight: 600; }
.vt-kpi .k-val { font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 24px; font-weight: 600; letter-spacing: -.02em; color: var(--ink); line-height: 1; }
.vt-kpi .k-val small { font-size: 14px; color: var(--ink-4); font-weight: 500; }
.vt-kpi--amber .k-val { color: var(--gold); }
.vt-kpi .k-meta { margin-top: 8px; font-size: 12px; color: var(--ink-4); }
.vt-kpi .k-meta b { font-family: var(--mono); color: var(--ink-2); font-weight: 500; }

/* Barra de control: segmented + filtro */
.vt-controls { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 16px; flex-wrap: wrap; }
.vt-seg { display: inline-flex; background: var(--surface); border: 1px solid var(--line-strong); border-radius: 11px; padding: 4px; gap: 2px; box-shadow: var(--shadow-card); position: relative; }
.vt-seg button { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; border: none; background: transparent; border-radius: 8px; padding: 8px 15px; font-family: var(--sans); font-size: 13.5px; font-weight: 600; color: var(--ink-3); transition: color .18s; position: relative; z-index: 1; }
.vt-seg button i { font-size: 13px; opacity: .85; }
.vt-seg button .seg-count { font-family: var(--mono); font-size: 11px; font-weight: 600; background: var(--surface-2); color: var(--ink-4); border: 1px solid var(--line); border-radius: 6px; padding: 1px 6px; }
.vt-seg button:hover { color: var(--ink-2); }
.vt-seg button.on { color: var(--on-green); }
.vt-seg button.on .seg-count { background: rgba(255,255,255,.2); color: var(--on-green); border-color: rgba(255,255,255,.25); }
.vt-seg .vt-glider { position: absolute; top: 4px; bottom: 4px; left: 4px; border-radius: 8px; background: var(--green-600); box-shadow: 0 1px 3px rgba(17,68,13,.3); transition: transform .3s var(--smooth), width .3s var(--smooth); z-index: 0; }

/* Paneles (una pestaña a la vez) */
.vt-tabpanel { display: none; }
.vt-tabpanel.on { display: block; animation: vt-rise .35s var(--smooth) both; }
@keyframes vt-rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
/* Sub-tabs anidadas (dentro de un .vt-tabpanel) — mismo swap que las tabs principales. */
.vt-subpanel { display: none; }
.vt-subpanel.on { display: block; animation: vt-rise .3s var(--smooth) both; }
/* Barra del sub-seg: alineado a la IZQUIERDA (convención del proyecto). */
.vt-subseg-bar { display: flex; justify-content: flex-start; padding: 0 20px; border-bottom: 1px solid var(--line); }
.vt-panel { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-card); overflow: hidden; }
/* Identidad por rol (Comprador/Vendedor): borde superior de color + tinte ambiental
   + marca de agua GRANDE, para saber en qué vista estás SIN leer. Dorado = Comprador
   (paga) · verde = Vendedor (cobra). Colores por tema (--rc) para que se vea bien en
   claro Y oscuro. Todo detrás del contenido (border + capas de background). */
.vt-panel.role-comprador { --rc: #a87d2a; }
.vt-panel.role-vendedor  { --rc: #1e8048; }
[data-theme="dark"] .vt-panel.role-comprador { --rc: #d8b878; }
[data-theme="dark"] .vt-panel.role-vendedor  { --rc: #56c98a; }

.vt-panel.role-comprador, .vt-panel.role-vendedor {
  border-top: 4px solid var(--rc);
  background: var(--surface);
}
.vt-panel .table-wrap { border: none; border-radius: 0; box-shadow: none; }
/* Diferenciador FUERTE por rol: el recuadro del SALDO (banda grande y prominente) se
   tiñe entero del color del rol → inconfundible de un vistazo. Usa --rc (por tema). */
.vt-panel.role-comprador .hist-saldo-head, .vt-panel.role-vendedor .hist-saldo-head {
  background: color-mix(in srgb, var(--rc) 16%, var(--surface));
  border-bottom-color: color-mix(in srgb, var(--rc) 44%, var(--line));
}
.vt-panel.role-comprador .hist-saldo-ico, .vt-panel.role-vendedor .hist-saldo-ico {
  background: color-mix(in srgb, var(--rc) 24%, var(--surface));
  border-color: color-mix(in srgb, var(--rc) 50%, transparent);
  color: var(--rc);
}
.vt-panel.role-comprador .hist-saldo-val, .vt-panel.role-vendedor .hist-saldo-val { color: var(--rc); }
.vt-panel.role-comprador .hist-saldo-label, .vt-panel.role-vendedor .hist-saldo-label {
  color: color-mix(in srgb, var(--rc) 66%, var(--ink-2));
}
/* Sub-tabs (Cuenta corriente / Cierre): el SUBRAYADO del activo toma el color del rol
   (dorado Comprador / verde Vendedor). Van dentro del panel → heredan --rc. */
.vt-panel.role-comprador .vt-subseg button.on, .vt-panel.role-vendedor .vt-subseg button.on {
  color: var(--rc);
}
.vt-panel.role-comprador .vt-subseg button.on .seg-count,
.vt-panel.role-vendedor .vt-subseg button.on .seg-count { color: var(--rc); }
/* Tab principal activa: cuando Comprador está activo, el glider (píldora) se vuelve
   DORADO con texto oscuro. Vendedor queda verde (default). El seg vive fuera del panel,
   así que uso :has() para saber qué tab está seleccionada. */
#hist-seg:has(button[data-tab="comprador"].on) .vt-glider {
  background: var(--gold); box-shadow: 0 1px 3px rgba(140,100,20,.35);
}
#hist-seg:has(button[data-tab="comprador"].on) button.on { color: #1a140a; }
#hist-seg:has(button[data-tab="comprador"].on) button.on .seg-count {
  background: rgba(0,0,0,.14); color: #1a140a; border-color: rgba(0,0,0,.18);
}
/* El glider principal ya desliza (transform/width); sumo background para que el cambio
   de color dorado↔verde al cambiar de rol también anime. */
#hist-seg .vt-glider { transition: transform .3s var(--smooth), width .3s var(--smooth), background .3s var(--smooth); }
.vt-panel-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 15px 20px; border-bottom: 1px solid var(--line); background: var(--surface-2); }
.vt-panel-head h2 { font-size: 14.5px; font-weight: 700; letter-spacing: -.01em; color: var(--ink); margin: 0; }
.vt-panel-head .ph-sub { font-size: 12.5px; color: var(--ink-4); font-weight: 400; }
.vt-panel-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 13px 20px; border-top: 1px solid var(--line); background: var(--surface-2); font-size: 13px; color: var(--ink-3); }
.vt-panel-foot b { font-family: var(--mono); color: var(--ink); font-weight: 600; }

/* Celdas del rediseño */
.vt-buyer { display: flex; align-items: center; gap: 10px; }
.vt-av { width: 32px; height: 32px; border-radius: var(--radius-sm); flex: none; display: grid; place-items: center; font-family: var(--mono); font-size: 12px; font-weight: 600; color: #fff; background: linear-gradient(150deg, var(--green-500), var(--green-700)); }
.vt-buyer b { font-weight: 600; color: var(--ink); font-size: 14px; }
.vt-buyer small { display: block; color: var(--ink-4); font-size: 11.5px; }
.vt-lote { display: inline-flex; align-items: center; gap: 8px; font-weight: 600; color: var(--ink); }
.vt-lote .hash { font-family: var(--mono); font-size: 12px; color: var(--green-ink); background: var(--green-light); border: 1px solid var(--line-strong); border-radius: 6px; padding: 2px 7px; }
.vt-money { font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 14px; font-weight: 600; color: var(--ink); }
.vt-num { font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--ink-2); }
.vt-num.saldo { color: var(--gold); font-weight: 600; }
.vt-cobrar { display: inline-flex; align-items: center; gap: 7px; cursor: pointer; border-radius: var(--radius-sm); font-size: 13px; font-weight: 700; padding: 7px 14px; border: 1px solid var(--gold-2); background: var(--gold); color: #11240f; transition: var(--transition); }
.vt-cobrar:hover { background: var(--gold-2); }
.vt-atday { font-size: 12.5px; color: var(--green-ink); font-weight: 600; display: inline-flex; align-items: center; gap: 6px; }
.vt-cobrar i { font-size: 12px; }
.vt-acciones { display: inline-flex; align-items: center; gap: 8px; justify-content: flex-end; flex-wrap: wrap; }
.vt-liquidar { display: inline-flex; align-items: center; gap: 7px; cursor: pointer; border-radius: var(--radius-sm); font-size: 13px; font-weight: 700; padding: 7px 14px; border: 1px solid var(--border); background: transparent; color: var(--ink); transition: var(--transition); }
.vt-liquidar:hover { border-color: var(--gold-2); color: var(--gold-2); }
.vt-liquidar i { font-size: 12px; }
.vt-liquidado { font-size: 12.5px; color: var(--muted); font-weight: 600; display: inline-flex; align-items: center; gap: 6px; }

/* Combobox de cliente (Boleta de Pista): dropdown propio, estilado e integrado al
   tema (reemplaza el datalist nativo, que flotaba aparte y sin estilo). */
.vt-combo { position: relative; }
.vt-combo-list {
  list-style: none; margin: 0; padding: 5px;
  position: absolute; top: calc(100% + 5px); left: 0; right: 0; z-index: 50;
  max-height: 280px; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-lg);
}
.vt-combo-list[hidden] { display: none; }
.vt-combo-list li {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 9px; border-radius: 7px; cursor: pointer;
  font-size: 13.5px; font-weight: 500; color: var(--ink-2);
  transition: background-color .12s ease, color .12s ease;
}
.vt-combo-list li:hover,
.vt-combo-list li.active { background: var(--surface-2); color: var(--ink); }
.vt-combo-list .vt-av { width: 26px; height: 26px; min-width: 26px; font-size: 10.5px; }
.vt-combo-list .combo-empty {
  cursor: default; color: var(--ink-4); justify-content: center;
  font-style: italic; font-weight: 400;
}
.vt-combo-list .combo-empty:hover { background: transparent; color: var(--ink-4); }

/* Alta de cliente inline en el form de venta (Boleta de Pista): fila selector +
   botón "Nuevo", y panel plegable con los campos mínimos del cliente. */
.vta-comprador-row { display: flex; gap: 8px; align-items: flex-end; }
.vta-comprador-row .form-group { flex: 1; min-width: 0; }
/* Remitente + el botón "Nuevo" al lado. align-items:flex-end para que el botón
   quede a la altura del INPUT y no del label, que es lo que pasa con center. */
.be-cli-row { display: flex; gap: 8px; align-items: flex-end; }
.be-cli-row .vt-combo { flex: 1; min-width: 0; }
.be-cli-row .btn { flex: none; }

.vta-facturar-row { display: flex; gap: 8px; align-items: center; }
.vta-facturar-row select { flex: 1; min-width: 0; }
.vta-facturar-row .btn { flex: none; }
.vta-facturar-row select[hidden] { display: none; }
.vta-ne-panel { margin-top: 10px; }
.vta-nc-panel {
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 13px 15px; display: flex; flex-direction: column; gap: 12px;
  background: var(--surface-2);
}
.vta-nc-panel[hidden] { display: none; }
.vta-nc-titulo { margin: 0; font-weight: 600; font-size: 13px; color: var(--ink-2); }
.vta-nc-acciones { display: flex; justify-content: flex-end; gap: 8px; }

/* ── Sala: crear la ficha del comprador sin salir de la pista ──────────────
   Va DESTACADO y arriba del buscador porque es el camino esperado: si el que
   gano tiene cuenta web y todavia no es cliente, crearle la ficha con lo que
   ya sabemos es lo que se va a hacer nueve de cada diez veces. El buscador
   queda abajo, para el caso raro de que la persona ya tenga otra ficha. */
.sala-nc {
  margin: 0 0 14px;
  padding: 12px 14px;
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  background: var(--surface-2);
}
.sala-nc-titulo { margin: 0 0 4px; font-size: 13px; font-weight: 700; color: var(--ink-1); }
.sala-nc-datos { margin: 0 0 10px; font-size: 12.5px; line-height: 1.45; color: var(--ink-3); }
.sala-nc-o { margin: 10px 0 0; font-size: 12px; color: var(--ink-4); }

/* Panel "Saldos por lote" — SIEMPRE visible (no es pestaña): el inventario de avance
   del remate. Tabla con estado + barra de avance contenida + footer con el resumen. */
/* «Este remate ya cerró, la caja sigue abierta.» Va arriba de los KPIs porque
   cambia el significado de todo lo de abajo: son los números de un remate
   terminado que todavía se está facturando. Alto FIJO en una línea de texto: la
   tira no puede crecer al cambiar de remate y empujar la grilla. */
.vt-aviso-caja {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 14px; margin-bottom: 14px;
  border: 1px solid var(--line); border-left: 3px solid var(--st-programado);
  border-radius: var(--radius); background: var(--amber-bg);
}
.vt-aviso-caja > i { color: var(--st-programado); font-size: 16px; flex: 0 0 auto; }
.vt-aviso-caja-txt { flex: 1 1 auto; font-size: 12.5px; line-height: 1.45; color: var(--ink-2); }
.vt-aviso-caja-txt b { display: block; color: var(--ink); }
.vt-aviso-caja .btn { flex: 0 0 auto; }
@media (max-width: 920px) {
  .vt-aviso-caja { flex-wrap: wrap; }
  .vt-aviso-caja .btn { margin-left: auto; }
}

.vt-kpis--3 { grid-template-columns: repeat(3, 1fr); }
/* KPIs de Boleta de Pista compactos (eran innecesariamente altos). */
.vt-kpis--3 .vt-kpi { padding: 10px 16px; }
.vt-kpis--3 .vt-kpi .k-top { margin-bottom: 5px; }
.vt-kpis--3 .vt-kpi .k-ico { width: 25px; height: 25px; }
.vt-kpis--3 .vt-kpi .k-val { font-size: 20px; }
.vt-kpis--3 .vt-kpi .k-val small { font-size: 12px; }
.vt-kpis--3 .vt-kpi .k-meta { margin-top: 3px; font-size: 11.5px; }
/* La tabla de Saldos ahora va al pie (debajo de Ventas): sin margen inferior extra. */
.vt-saldos { margin-top: 18px; margin-bottom: 0; }
.vt-saldos .vt-panel-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; }
.vt-saldos .vt-panel-head h2 { display: flex; align-items: center; gap: 9px; }
.vt-saldos .vt-panel-head h2 i { color: var(--gold); font-size: 14px; }
.vt-saldos .th-r, .vt-saldos .td-r { text-align: right; }
.vt-saldos .th-c, .vt-saldos .td-c { text-align: center; }
.sl-head-tot { display: flex; align-items: center; gap: 16px; flex-shrink: 0; }
.sl-head-tot > div { text-align: right; }
.sl-tot-lab { display: block; font-family: var(--mono); font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-4); margin-bottom: 2px; }
.sl-tot-val { font-family: var(--mono); font-size: 22px; font-weight: 700; color: var(--ink); letter-spacing: -.03em; line-height: 1; }
.sl-tot-val--gold { color: var(--gold); }
.sl-tot-sep { width: 1px; height: 32px; background: var(--line-strong); }
.sl-num { font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 13.5px; font-weight: 600; color: var(--ink-2); letter-spacing: -.02em; }
.sl-num--ok { color: var(--green-ink); }
.sl-saldo { font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 15px; font-weight: 700; color: var(--gold); letter-spacing: -.02em; }
.sl-saldo--zero { color: var(--ink-4); font-weight: 500; font-size: 13.5px; }
.sl-prog { display: flex; align-items: center; gap: 9px; }
.sl-bar-wrap { width: 120px; flex: none; }
.sl-bar-wrap .progress { height: 6px; background: var(--line-strong); border-radius: 99px; overflow: hidden; }
.sl-bar-wrap .progress-bar { height: 100%; border-radius: 99px; transition: width .5s var(--smooth); }
.sl-bar--parcial { background: linear-gradient(90deg, color-mix(in srgb, var(--gold) 75%, var(--green-700)), var(--gold)); }
.sl-bar--casi { background: linear-gradient(90deg, var(--green-600), var(--green-400)); }
.sl-pct { font-family: var(--mono); font-size: 11.5px; font-weight: 600; color: var(--ink-3); flex: none; min-width: 30px; }
.sl-foot { display: flex; align-items: center; justify-content: flex-start; gap: 18px; flex-wrap: wrap; }
.sl-foot span { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--ink-4); }
.sl-foot span i { font-size: 11px; }
.sl-foot b { font-family: var(--mono); font-size: 13px; font-weight: 600; color: var(--ink-2); }
.sl-foot-ok i, .sl-foot-ok b { color: var(--green-ink); }
.sl-foot-alert i, .sl-foot-alert b { color: var(--gold); }

/* Avatares con variación de color por comprador */
.vt-av--1 { background: linear-gradient(150deg, var(--green-400), var(--green-700)); }
.vt-av--2 { background: linear-gradient(150deg, #4a7fb0, #2f5a86); }
.vt-av--3 { background: linear-gradient(150deg, #c39a4a, #9a6b16); }
.vt-av--4 { background: linear-gradient(150deg, #9b6fb0, #6e3a86); }
/* Alineación derecha en celdas numéricas del rediseño */
.vt-panel td.vt-r, .vt-panel th.vt-r { text-align: right; }
/* Donut del KPI % vendido */
.vt-kpi { position: relative; overflow: hidden; }
.vt-donut { position: absolute; top: 50%; right: 18px; transform: translateY(-50%); width: 50px; height: 50px; border-radius: 50%; display: grid; place-items: center; background: conic-gradient(var(--green-500) calc(var(--p, 0) * 1%), var(--line-strong) 0); }
.vt-donut::after { content: ""; position: absolute; width: 37px; height: 37px; border-radius: 50%; background: var(--surface); }
.vt-donut span { position: relative; z-index: 1; font-family: var(--mono); font-size: 11px; font-weight: 600; color: var(--green-ink); }

/* KPI Saldo clickeable (Historial · Cuenta corriente): toggle que filtra la tabla
   a remates con deuda. Pista de que es clickeable + realce dorado cuando está activo.
   El realce usa box-shadow inset (no exterior) porque .vt-kpi tiene overflow:hidden. */
.vt-kpi--clickable { cursor: pointer; transition: background-color .16s ease, box-shadow .16s ease; }
.vt-kpi--clickable:hover { background: var(--surface-2); }
.vt-kpi--clickable:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--gold); }
.vt-kpi--clickable .k-meta i { margin-right: 4px; color: var(--gold); font-size: 10px; }
.vt-kpi--clickable.is-on { background: var(--gold-glow); box-shadow: inset 0 0 0 2px var(--gold); }
.vt-kpi--clickable.is-on .k-meta { color: var(--gold); font-weight: 600; }
.section-title { font-family: var(--sans); font-size: 14px; font-weight: 700; letter-spacing: -.01em; color: var(--ink); margin: 0 0 12px; }
.table-caption { font-size: 12.5px; color: var(--ink-3); margin: 0 0 10px; }
.table-caption strong, .table-caption b { color: var(--green-ink); font-weight: 700; }
.table-caption--row { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.empty-state--compact { padding: 28px 18px; }

/* Historial de cliente: separación entre secciones (consignaciones/compras/retiros) */
.hist-sec { margin-top: 26px; }
.hist-sec .section-title .muted { font-weight: 400; }
.empty-state--compact i { font-size: 1.8rem; }
.empty-state--compact h3 { font-size: 13.5px; margin: 10px 0 4px; }
.empty-state--compact p { font-size: 12px; margin-bottom: 0; }
.progress { height: 7px; border-radius: var(--radius-pill); background: var(--line-strong); overflow: hidden; }
.progress-bar { height: 100%; border-radius: var(--radius-pill); background: linear-gradient(90deg, var(--green-600), var(--green-400)); transition: width .3s var(--smooth); }
.progress-label { display: inline-block; margin-top: 4px; font-size: 11px; font-weight: 600; color: var(--ink-3); font-family: var(--mono); }
@media (max-width: 920px) { .vt-kpis { grid-template-columns: repeat(2, 1fr); } }
/* La tira de pestañas (Todos / Preparando / Listo / …) no entra en un celular y
   es lo que estiraba la página entera: acá scrollea DENTRO de su propio ancho.
   El glider es absolute y viaja con el scroll, así que sigue marcando bien. */
@media (max-width: 768px) {
  .vt-controls { flex-wrap: wrap; }
  .vt-controls > * { min-width: 0; max-width: 100%; }
  .vt-seg { display: flex; max-width: 100%; overflow-x: auto; scrollbar-width: none; }
  .vt-seg::-webkit-scrollbar { display: none; }
  .vt-seg button { flex: none; }
}

/* Preview de cierre de remate: resumen en mini-cards (look refinado) */
.cierre-resumen { display: grid; grid-template-columns: repeat(auto-fit, minmax(116px, 1fr)); gap: 10px; margin-bottom: 14px; }
.metric { position: relative; display: flex; flex-direction: column; gap: 4px; padding: 11px 12px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg); overflow: hidden; }
.metric::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 2px; background: linear-gradient(180deg, var(--green-400), var(--green-700)); opacity: .55; }
.metric-label { font-family: var(--mono); font-size: 9.5px; font-weight: 500; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-4); }
.metric-value { font-family: var(--mono); font-size: 18px; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.cierre-aviso { margin: 0 0 14px; }

/* ── Liquidación en el modal de cierre ──────────────────────────────────────── */
.cierre-liq { margin: 16px 0; padding: 14px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg); }
.cierre-liq-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
.cierre-liq-head h3 { margin: 0; font-size: 15px; }
.cierre-liq-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.cierre-liq-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.cierre-liq-col h4 { margin: 0 0 6px; font-size: 13px; }
.cierre-liq-col table { width: 100%; }
@media (max-width: 640px) { .cierre-liq-cols { grid-template-columns: 1fr; } }

/* ── Cierre compacto: tira de resumen + boletas colapsables ────────────────── */
/* Ancho amplio: la pestaña Compradores completa (con comisiones editables) entra
   cómoda. Se acota al viewport para no desbordar en pantallas chicas. */
.modal:has(.cierre-preview) { max-width: min(96vw, 1000px); }
/* Tira de resumen: reemplaza las 5 tarjetas KPI por una línea escaneable. */
.cierre-strip { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; margin-bottom: 14px; padding: 11px 14px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg); font-size: 12.5px; color: var(--ink-3); }
.cierre-strip b { font-family: var(--mono); font-size: 15px; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.cierre-strip-x { color: var(--line-strong); }
/* Boletas colapsables: el detalle no compite con la liquidación. */
.cierre-acc { margin-bottom: 14px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg); }
.cierre-acc > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 10px; padding: 11px 14px; font-size: 13px; font-weight: 600; color: var(--ink); }
.cierre-acc > summary::-webkit-details-marker { display: none; }
.cierre-acc > summary:focus-visible { box-shadow: var(--ring); border-radius: var(--radius-sm); }
.cierre-acc-chev { font-size: 11px; color: var(--ink-3); transition: transform .2s var(--smooth); }
.cierre-acc[open] .cierre-acc-chev { transform: rotate(90deg); }
.cierre-acc #cierre-boletas { padding: 0 14px 12px; }
/* La liquidación ahora lidera: sin margen superior extra. */
.cierre-liq { margin: 0; }
/* Comisiones por comprador: dos inputs editables (compr/vend) + impuesto solo-lectura. */
.comis { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; }
.comis-pair { display: flex; align-items: center; gap: 10px; }
.comis-row { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; color: var(--ink-3); white-space: nowrap; }
.comis-input { width: 58px; padding: 3px 6px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--surface); color: var(--ink); font-size: 12px; text-align: right; font-variant-numeric: tabular-nums; }

/* Ajuste del lado vendedor: tabla compacta dentro del modal (6 columnas con
   inputs). Sin esto entra en scroll horizontal aunque el modal sea wide. */
.aj-tabla { table-layout: auto; font-size: 13px; }
/* Especificidad extra: .data-table thead th define su propio padding y gana por
   orden; acá se necesita más compacto para que las 6 columnas entren sin scroll. */
.data-table.aj-tabla thead th,
.data-table.aj-tabla tbody td { padding: 8px 6px; white-space: nowrap; }
.aj-tabla .aj-monto { width: 92px; }
.aj-tabla .aj-pct { width: 62px; }
.aj-tabla small.muted { display: block; font-size: 10.5px; line-height: 1.2; }
.aj-nota { margin: 0 0 14px; }
.comis-input:focus { border-color: var(--green-600); background: var(--surface); box-shadow: var(--ring); outline: none; }
.comis-ro { font-size: 11px; color: var(--ink-2); white-space: nowrap; }
.comis-ro b { font-variant-numeric: tabular-nums; }
.comis-imp { font-size: 10.5px; }

/* ── Modal de cierre: filas más compactas y prolijas ─────────────────────────── */
/* Todo centrado verticalmente para que las celdas cortas (plata) no floten arriba. */
.modal:has(.cierre-preview) .cierre-liq td,
.modal:has(.cierre-preview) .cierre-liq th { vertical-align: middle; }
.modal:has(.cierre-preview) .cierre-liq tbody td { padding-top: 9px; padding-bottom: 9px; }
/* Comisiones: más finas y juntas para no estirar la fila. */
.cierre-liq .comis { gap: 3px; }
.cierre-liq .comis-row { font-size: 10.5px; gap: 4px; }
.cierre-liq .comis-input { width: 50px; padding: 2px 5px; font-size: 11.5px; }
.cierre-liq .comis-imp { font-size: 10px; }
/* Acciones en UNA línea: botones chicos + "Liquidado" como check compacto (el
   texto se oculta, queda el ícono con su tooltip). Evita el salto a 2 filas. */
.cierre-liq .vt-acciones { display: inline-flex; flex-wrap: nowrap; justify-content: flex-end; align-items: center; gap: 5px; white-space: nowrap; }
.cierre-liq .vt-cobrar, .cierre-liq .vt-liquidar { font-size: 11px; padding: 5px 9px; }
.cierre-liq .vt-cobrar i, .cierre-liq .vt-liquidar i { font-size: 10px; }
.cierre-liq .vt-liquidado { font-size: 0; padding: 5px 7px; gap: 0; }
.cierre-liq .vt-liquidado i { font-size: 13px; }
.cierre-liq .comis-pair { gap: 8px; }
/* Imprimir solo-ícono (botón cuadrado). */
.cierre-liq .vt-liquidar.vt-icono { padding: 5px 8px; }
.cierre-liq .vt-liquidar.vt-icono i { font-size: 12px; }
/* Sin avatar del comprador en el cierre: solo el nombre. */
.cierre-liq .vt-buyer .vt-av { display: none; }
.cierre-liq .vt-buyer { gap: 0; }
.print-boleta .pb-bloque { font-size: 13pt; margin: 18px 0 6px; }

/* ── Sección / filas de objetos / lotes ─────────────────────────────────────── */
.objeto-row { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; align-items: center; }
.objeto-row input[name="nombre"] { flex: 1 1 100%; }
/* Ancho completo (línea propia, como nombre) y alto fijo en filas: este texto
   termina en la columna Observaciones del catálogo impreso, así que necesita
   lugar de verdad. resize:vertical es la única forma de crecer, y es a mano,
   nunca automática al tipear (regla del cliente: nada de saltos de tamaño). */
.objeto-row textarea[name="descripcion"] { flex: 1 1 100%; resize: vertical; }
.objeto-row input[name="cantidad"] { flex: 1 1 70px; min-width: 0; }
.objeto-row input[name="valor_esperado"] { flex: 1 1 90px; min-width: 0; }
.objeto-row > button { flex: 0 0 auto; }
.objeto-row input, .objeto-row textarea { padding: 9px 11px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); font: inherit; background: var(--surface); color: var(--ink); }
.objeto-row input:focus, .objeto-row textarea:focus { outline: none; border-color: var(--green-400); box-shadow: var(--ring); }
.objeto-foto { flex: 0 0 auto; width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; border: 1px dashed var(--line-strong); border-radius: var(--radius-sm); color: var(--ink-3); cursor: pointer; overflow: hidden; transition: var(--transition); }
.objeto-foto:hover { border-color: var(--green-ink); color: var(--green-ink); background: var(--ctrl-hover); }
.objeto-foto.has-img { border-style: solid; }
.objeto-foto.has-img > i { display: none; }
.objeto-foto-preview { width: 100%; height: 100%; object-fit: cover; }
@media (max-width: 480px) { .objeto-row > input { flex: 1 1 100%; } }

.lotes-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 30px 40px; align-items: start; justify-items: center; }
/* Modo arrastre: apaga transiciones/hover de las otras cards (evita el jank de fotos
   que hacen zoom y barras que aparecen al pasar el cursor durante el reflow).
   is-busy bloquea interacción mientras se persiste el nuevo orden. */
.lotes-grid.is-dragging .lote-card:not(.dragging) * { transition: none !important; pointer-events: none; }
.lotes-grid.is-busy { pointer-events: none; opacity: .6; }

/* ── Reordenar lotes (enfoque B): lista vertical 1D, drag estable ───────────── */
.demo-badge { font-family: var(--mono); font-size: 10px; font-weight: 600; letter-spacing: .12em;
  color: var(--gold); background: color-mix(in srgb, var(--gold) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--gold) 38%, transparent); border-radius: var(--radius-pill);
  padding: 3px 9px; vertical-align: middle; margin-left: 10px; }
.reorder-panel { max-width: 560px; margin-top: 18px; }
.lote-reorder { padding: 12px; display: flex; flex-direction: column; gap: 8px; user-select: none; }
.lote-reorder-row { display: flex; align-items: center; gap: 12px; padding: 11px 13px;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-sm);
  cursor: grab; transition: border-color .15s ease, box-shadow .15s ease, opacity .15s ease; }
.lote-reorder-row:hover { border-color: var(--line-strong); }
.lote-reorder-row.dragging { cursor: grabbing; border-style: dashed; border-color: var(--gold);
  background: color-mix(in srgb, var(--gold) 9%, var(--surface-2)); box-shadow: 0 0 0 3px var(--gold-glow); }
.lote-reorder-row.dragging > * { opacity: .35; } /* placeholder = slot limpio (sin doble texto con el ghost) */
.lr-grip { flex: none; color: var(--ink-4); font-size: 17px; line-height: 1; letter-spacing: -3px; cursor: grab; }
.lote-reorder-row:hover .lr-grip { color: var(--gold); }
.lr-folio { flex: none; width: 34px; font-family: var(--mono); font-size: 13px; font-weight: 600; color: var(--gold); }
.lr-ttl { flex: 1; min-width: 0; font-size: 13.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lr-ttl small { display: block; font-weight: 400; font-size: 11px; color: var(--ink-4); }
.lote-reorder-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 13px 16px; border-top: 1px solid var(--line); }
.lote-reorder-foot .muted { font-size: 12px; }
/* Dentro de un modal la lista usa el padding del cuerpo (no doble). */
.modal-body .lote-reorder { padding: 2px 0 0; }
.reorder-hint { margin: -2px 0 14px; }
/* Demo a escala (muchos lotes): buscador, lista scrolleable, "mover a #", flash. */
.reorder-tools { display: flex; align-items: center; gap: 12px; padding: 14px 16px 10px; }
.reorder-search { flex: 1; position: relative; display: flex; align-items: center; }
.reorder-search > i { position: absolute; left: 12px; color: var(--ink-4); font-size: 12px; pointer-events: none; }
.reorder-search input { width: 100%; padding: 9px 12px 9px 32px; background: var(--bg); border: 1px solid var(--line-strong); border-radius: var(--radius-sm); color: var(--ink); font: inherit; font-size: 13px; }
.reorder-search input:focus { outline: none; border-color: var(--green-600); box-shadow: var(--ring); }
.reorder-count { flex: none; font-size: 12px; white-space: nowrap; }
.lote-reorder--scroll { max-height: 52vh; overflow-y: auto; }
.lr-jump { cursor: pointer; border: 1px solid transparent; background: none; padding: 2px 6px; border-radius: 6px; transition: background .14s ease, border-color .14s ease; }
.lr-jump:hover { background: var(--bg); border-color: var(--line-strong); }
.lr-folio-input { width: 54px; text-align: center; padding: 3px 4px; border: 1px solid var(--green-600); border-radius: 6px; background: var(--bg); color: var(--gold); font-family: var(--mono); font-size: 13px; font-weight: 600; }
.lr-folio-input:focus { outline: none; box-shadow: var(--ring); }
.lote-reorder-row.is-hidden { display: none; }
/* Filtro client-side genérico: oculta filas que no matchean el buscador */
.data-table tbody tr.is-hidden { display: none; }
.lote-reorder-row.lr-flash { border-color: var(--green-400); box-shadow: 0 0 0 3px var(--green-glow); }
.lote-reorder.is-filtering .lr-grip { opacity: .3; cursor: default; }
/* En el modal: el buscador usa el padding del cuerpo (no doble) y la lista se acota
   para que el buscador quede fijo arriba mientras la lista scrollea sola. */
.modal-body .reorder-tools { padding: 0 0 12px; }
.modal-body .lote-reorder--scroll { max-height: 42vh; }

/* ── Tarjeta de lote — "Folio de Remate" (etiqueta de subasta) · ALTO FIJO ── */
/* Alto SIEMPRE constante (tenga 0 o muchos objetos/fotos): hilo y pie fijos,
   el cuerpo rellena y scrollea internamente si el contenido excede. */
.lote-card { --t-perf: var(--line-strong); position: relative; width: 100%; max-width: 340px; height: 520px; display: flex; flex-direction: column; isolation: isolate; overflow: hidden; font-family: var(--sans); color: var(--ink); border: 1px solid var(--line-strong); border-radius: var(--radius);
  background: radial-gradient(120% 80% at 88% -10%, var(--green-glow), transparent 55%), linear-gradient(180deg, var(--surface-2), var(--surface));
  box-shadow: 0 1px 0 rgba(255,255,255,.04) inset, 0 18px 40px -22px rgba(0,0,0,.55), 0 2px 8px -4px rgba(0,0,0,.4); }
.lote-card[draggable="true"] { cursor: grab; -webkit-user-select: none; user-select: none; }
/* Las <img> son draggable por defecto y secuestran el gesto (se arrastra la foto en
   vez de la card) → neutralizadas. */
.lote-card img { -webkit-user-drag: none; user-drag: none; }
/* Drag tipo Trello: la card arrastrada se COLAPSA a un placeholder fino. Clave anti-
   parpadeo: así insertarla ya no reflowea el grid de 520px bajo el cursor (era el
   lazo layout→reinserción→layout que hacía oscilar). El cálculo la ignora (:not). */
.lote-card.dragging { cursor: grabbing; height: 90px; min-height: 0; overflow: hidden; background: var(--surface-2); outline: 2px dashed var(--gold); outline-offset: -2px; box-shadow: 0 0 0 4px var(--gold-glow); }
.lote-card.dragging > * { opacity: 0; }
.lote-card.dragging * { pointer-events: none; } /* opacity no quita hit-testing → esto sí */

/* hilo + ojal de la etiqueta colgante */
.folio-thread { position: relative; height: 26px; flex: none; display: flex; align-items: center; justify-content: center; }
.folio-thread::before { content: ""; position: absolute; top: -13px; left: 50%; transform: translateX(-50%); width: 108px; height: 30px; border: 1.5px solid var(--gold); border-bottom: none; border-radius: 60px 60px 0 0; opacity: .55; filter: drop-shadow(0 0 4px var(--gold-glow)); }
.folio-eyelet { position: relative; width: 16px; height: 16px; border-radius: 50%; background: radial-gradient(circle at 35% 30%, var(--gold-soft), var(--gold) 45%, var(--gold-2) 100%); box-shadow: 0 0 0 3px var(--green-900), 0 0 10px var(--gold-glow); }
.folio-eyelet::after { content: ""; position: absolute; inset: 0; margin: auto; width: 5px; height: 5px; border-radius: 50%; background: var(--green-900); }

/* cuerpo — rellena el alto fijo y scrollea si el contenido excede */
.folio-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 12px 18px 6px; scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent; }
.folio-body::-webkit-scrollbar { width: 6px; }
.folio-body::-webkit-scrollbar-track { background: transparent; }
.folio-body::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 3px; }

/* encabezado: folio + estado */
.folio-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.folio-folio { font-family: var(--mono); font-size: 11px; letter-spacing: .16em; text-transform: uppercase; color: var(--muted); display: flex; align-items: baseline; gap: 7px; min-width: 0; }
.folio-folio b { font-size: 24px; letter-spacing: .01em; line-height: 1; color: var(--gold); font-weight: 600; }
.folio-gav { color: var(--green-400); font-size: 13px; align-self: center; }
.folio-status { display: inline-flex; align-items: center; gap: 6px; font-family: var(--mono); font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: var(--green-300); padding: 5px 9px; border: 1px solid color-mix(in srgb, var(--green-400) 35%, transparent); border-radius: var(--radius-pill); background: color-mix(in srgb, var(--green-400) 10%, transparent); white-space: nowrap; flex: none; }
.folio-status::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--green-400); box-shadow: 0 0 8px var(--green-400); }
/* moneda del lote: chip junto al número (gold). --propia = el lote pisa la del remate. */
.folio-moneda { align-self: center; display: inline-flex; align-items: center; gap: 5px; font-family: var(--mono); font-size: 9.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--gold); padding: 2px 7px; border: 1px solid color-mix(in srgb, var(--gold) 32%, transparent); border-radius: var(--radius-pill); background: color-mix(in srgb, var(--gold) 9%, transparent); white-space: nowrap; }
.folio-moneda--propia::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: var(--gold); box-shadow: 0 0 7px var(--gold); }
/* Renglones de plata por moneda (remate mixto): una línea por moneda apiladas. */
.vt-cur { white-space: nowrap; }
.vt-cur + .vt-cur { margin-top: 3px; }
/* Resumen contable por moneda: columnas de importes alineadas a la derecha. */
.rc-num { text-align: right; white-space: nowrap; }
/* KPI con más de una moneda: en vez del número grande, líneas apiladas por moneda. */
.k-val--multi { font-size: 1.15rem; line-height: 1.3; }
.k-val--multi .vt-cur { font-weight: 700; }
.folio-title { margin: 11px 0 0; font-size: 17px; line-height: 1.22; font-weight: 600; color: var(--ink); letter-spacing: -.01em; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.folio-title--empty { opacity: .6; font-style: italic; font-weight: 500; }
/* Sin título y todavía editable: el catálogo lo va a mostrar como «Lote 12».
   Se dice en ámbar (algo que resolver antes de publicar), en letra de frase. */
.folio-title--falta { opacity: 1; font-style: normal; font-weight: 600; font-size: 13.5px; line-height: 1.35;
                      color: color-mix(in srgb, var(--st-preparando) 88%, var(--ink)); }
[data-theme="dark"] .folio-title--falta { color: var(--st-preparando); }
.folio-title--falta i { font-size: .9em; }
/* El bloque de plata de la card: base, estimado y el ritmo propio si lo hay.
   En FILAS con etiqueta y no todo en un renglon separado por puntos: apretado
   se leia como un amasijo y encima se partia en dos lineas. Cada dato en su
   fila se escanea de un vistazo y el bloque respira.

   Es un BOTON aunque parezca una ficha: el dato mismo es el cartel que indica
   donde se edita. Antes, para saber en cuanto arrancaba un lote habia que abrir
   un modal, lote por lote, en un remate de 183. */
/* El aire esta calculado: la card tiene alto FIJO y un lote con base, estimado y
   ritmo propio son TRES filas. Con mas padding la tercera desbordaba y aparecia
   una barra de scroll dentro de la card. */
.folio-plata { position: relative; display: flex; flex-direction: column; gap: 4px;
               width: 100%; margin: 8px 0 0; padding: 8px 32px 8px 11px;
               border: 1px solid transparent; border-radius: 9px; background: var(--surface-2);
               font-family: var(--sans); text-align: left; cursor: pointer;
               transition: border-color .15s, background .15s; }
.folio-plata:hover { border-color: var(--line-strong); background: var(--ctrl-hover); }
.folio-plata-fila { display: flex; align-items: baseline; gap: 8px; }
/* La etiqueta en chico y apagada: esta para ubicar, no para leerse. */
.folio-plata-k { flex: none; min-width: 66px; font-size: 10.5px; font-weight: 700; text-transform: uppercase;
                 letter-spacing: .05em; color: var(--ink-4); }
.folio-plata-v { font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 12.5px;
                 font-weight: 700; color: var(--ink); }
/* El lapiz arriba a la derecha, fuera del camino de los datos. */
.folio-plata > i { position: absolute; top: 9px; right: 10px; font-size: 11px; color: var(--ink-4); }
.folio-plata:hover > i { color: var(--ink-2); }
/* Sin base = sin piso: la primera oferta puede entrar en cualquier monto. */
.folio-plata-falta { color: var(--st-anulada, var(--ink-4)); font-weight: 600; }
/* El lote se sale del ritmo del remate: es la excepcion y hay que verla. */
.folio-plata-propio { color: var(--st-programado); }
/* El mínimo interno: se ve en la grilla de la casa, con candado, y en un gris
   que no se lee como «el precio del lote». */
.folio-plata-secreto { color: var(--ink-3); }
.folio-plata-secreto i { font-size: .85em; }
/* «Del ingreso»: el estimado es la propuesta que trajo la pieza y nadie la
   revisó. Pastilla chica pegada al número, que no agrega una fila (la card
   tiene alto fijo). */
.folio-ingreso { display: inline-flex; align-items: center; gap: 4px; margin-left: 6px; padding: 1px 6px;
                 font-family: var(--sans); font-size: 9.5px; font-weight: 700; letter-spacing: .05em;
                 text-transform: uppercase; white-space: nowrap; vertical-align: 1px;
                 color: var(--st-programado); border-radius: var(--radius-pill);
                 background: color-mix(in srgb, var(--st-programado) 12%, transparent);
                 box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--st-programado) 32%, transparent); }
.folio-ingreso i { font-size: .95em; }
/* No se trajo (otra moneda, una pieza sin estimado): se dice en la fila del
   estimado, en letra de frase y no de número. */
.folio-plata-nota { font-family: var(--sans); font-size: 11.5px; font-weight: 600; line-height: 1.3;
                    color: color-mix(in srgb, var(--st-preparando) 88%, var(--ink)); }
[data-theme="dark"] .folio-plata-nota { color: var(--st-preparando); }
.folio-plata-nota i { font-size: .9em; }

.folio-desc { margin: 7px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--ink-2); display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

/* etiqueta de sección (Fotos) + botones claros Asignar / Agregar foto */
.folio-sec-h { display: flex; align-items: center; justify-content: space-between; margin: 14px 0 8px; font-family: var(--mono); font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-4); }
.folio-sec-add { display: inline-flex; align-items: center; gap: 5px; font-family: var(--sans); font-size: 11px; font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--ink-2); background: transparent; border: 1px dashed var(--line-strong); border-radius: var(--radius-sm); padding: 3px 8px; cursor: pointer; transition: var(--transition); }
.folio-sec-add i { font-size: 10px; color: var(--ink-4); transition: color .18s; }
.folio-sec-add:hover { border-color: var(--green-400); border-style: solid; color: var(--green-400); background: var(--green-glow); }
.folio-sec-add:hover i { color: var(--green-400); }
.folio-sec-right { display: inline-flex; align-items: center; gap: 8px; }

/* fotos — grilla de 3 con acciones al hover */
.folio-photos { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
/* Grilla: solo la foto principal + contador "+N". La galería completa está en el modal. */
.folio-photos--mini { grid-template-columns: 1fr; max-width: 168px; }
.folio-photo-more { position: absolute; right: 6px; bottom: 6px; padding: 3px 8px; border-radius: 999px; background: rgba(0,0,0,.72); color: #fff; font-size: 11px; font-weight: 700; line-height: 1; pointer-events: none; }
.folio-empty-fotos { margin: 0; }
.folio-photo { position: relative; margin: 0; aspect-ratio: 4 / 3; overflow: hidden; border-radius: var(--radius-sm); border: 1px solid var(--line); background: var(--green-900); }
/* contain: la foto del lote entera, igual que en el catalogo publico. Con cover
   una pieza alta se recortaba y desde la grilla no se sabia que era. */
.folio-photo img { width: 100%; height: 100%; object-fit: contain; display: block; filter: saturate(.92) brightness(.94); transition: transform .5s cubic-bezier(.2,.7,.2,1); }
.folio-photo:hover img { transform: scale(1.06); }
.folio-photo.is-principal { border-color: var(--gold); box-shadow: inset 0 0 0 1px var(--gold); }
.folio-photo-actions { position: absolute; inset: auto 0 0 0; display: flex; justify-content: flex-end; gap: 3px; padding: 4px; background: linear-gradient(to top, rgba(0,0,0,.6), transparent); opacity: 0; transition: opacity .14s; }
.folio-photo:hover .folio-photo-actions, .folio-photo:focus-within .folio-photo-actions { opacity: 1; }
.folio-photo-act { width: 22px; height: 22px; display: inline-flex; align-items: center; justify-content: center; font-size: 9px; color: #fff; background: rgba(255,255,255,.18); border: 0; border-radius: 5px; cursor: pointer; transition: background .14s; }
.folio-photo-act:hover { background: rgba(255,255,255,.34); }
.folio-photo-act:disabled { color: var(--gold); background: rgba(255,255,255,.12); cursor: default; }
.folio-photo-act--danger:hover { background: var(--danger); }
/* La foto de la card es clickeable: abre el modal en la galería (ver todas + ordenar). */
.folio-photo[data-ver-fotos] { cursor: pointer; }
.folio-photo-view { position: absolute; top: 6px; left: 6px; width: 24px; height: 24px; display: grid; place-items: center; border-radius: 7px; color: #fff; font-size: 10px; background: rgba(0,0,0,.5); backdrop-filter: blur(3px); opacity: 0; transform: scale(.9); transition: opacity .16s var(--smooth), transform .16s var(--smooth); pointer-events: none; }
.folio-photo:hover .folio-photo-view, .folio-photo:focus-within .folio-photo-view { opacity: 1; transform: scale(1); }

/* contenido / objetos */
.folio-objs { margin-top: 14px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: rgba(0,0,0,.1); overflow: hidden; }
.folio-objs-h { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px 11px; border-bottom: 1px solid var(--line); font-family: var(--mono); font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-4); }
.folio-assign { display: inline-flex; align-items: center; gap: 5px; color: var(--green-400); cursor: pointer; border: none; background: none; font: inherit; letter-spacing: .08em; }
.folio-assign:hover { color: var(--green-300); }
.folio-obj { display: flex; align-items: center; gap: 9px; padding: 8px 11px; font-size: 12.5px; color: var(--ink-2); border-top: 1px dotted var(--line); }
.folio-obj:first-child { border-top: none; }
.folio-obj-box { color: var(--gold-2); font-size: 11px; width: 14px; text-align: center; flex: none; }
.folio-obj-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.folio-qty { font-family: var(--mono); font-size: 11px; font-weight: 600; color: var(--ink); padding: 2px 7px; border-radius: var(--radius-pill); background: var(--surface-2); border: 1px solid var(--line-strong); flex: none; }
/* Acciones por objeto SIEMPRE visibles (editar cantidad / quitar), no en hover */
.folio-obj-actions { flex: none; display: flex; gap: 3px; opacity: .85; transition: opacity .14s; }
.folio-obj:hover .folio-obj-actions, .folio-obj:focus-within .folio-obj-actions { opacity: 1; }
.folio-obj-act { width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center; font-size: 10px; color: var(--ink-4); background: transparent; border: 1px solid var(--line); border-radius: 6px; cursor: pointer; transition: var(--transition); }
.folio-obj-act:hover { color: var(--green-400); border-color: var(--green-400); background: var(--green-glow); }
.folio-obj-act--danger:hover { color: var(--gold); border-color: var(--gold-2); background: rgba(216,184,120,.08); }
.folio-objs .lote-empty { margin: 8px; background: transparent; border: none; padding: 4px; }

/* línea perforada del stub */
.folio-tear { position: relative; height: 16px; flex: none; }
.folio-tear::before { content: ""; position: absolute; left: 14px; right: 14px; top: 50%; border-top: 2px dashed var(--t-perf); }
.folio-tear::after { content: ""; position: absolute; top: 50%; left: -9px; width: 18px; height: 18px; border-radius: 50%; background: var(--bg); transform: translateY(-50%); box-shadow: calc(100% + 18px) 0 0 var(--bg); border: 1px solid var(--line-strong); }

/* stub: acciones tipo recibo */
.folio-stub { flex: none; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 4px 14px 16px; }
.folio-edit { flex: 1 1 auto; white-space: nowrap; display: inline-flex; align-items: center; justify-content: center; gap: 8px; height: 40px; padding: 0 12px; border: none; cursor: pointer; border-radius: var(--radius-sm); font-family: var(--sans); font-size: 13px; font-weight: 600; letter-spacing: .01em; color: var(--green-900); background: linear-gradient(180deg, var(--green-400), var(--green-600)); box-shadow: 0 0 0 1px color-mix(in srgb, var(--green-400) 40%, transparent) inset, 0 6px 16px -8px var(--green-400); transition: transform .15s, box-shadow .25s, filter .2s; }
/* El candado "Vendido — no editable" baja a su propia línea: no compite con los botones. */
.folio-locked { flex-basis: 100%; }
.folio-edit:hover { filter: brightness(1.06); box-shadow: 0 0 0 1px color-mix(in srgb, var(--green-400) 60%, transparent) inset, 0 8px 20px -8px var(--green-400); }
.folio-edit:active { transform: translateY(1px); }
.folio-edit--sec { background: var(--surface-2); color: var(--ink-2); box-shadow: none; border: 1px solid var(--line-strong); flex: 0 1 auto; }
.folio-edit--sec:hover { color: var(--green-ink); border-color: var(--green-ink); background: var(--ctrl-hover); transform: none; }
.folio-icon { width: 40px; height: 40px; flex: none; display: grid; place-items: center; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--surface-2); color: var(--ink-2); cursor: pointer; transition: color .2s, border-color .2s, background .2s; }

/* Variante secundaria del botón del talón (Web): presente pero sin competir
   con el primario Editar lote. */

/* Pastilla de estado web en la cabecera de la card: el dato que antes no se
   veía sin abrir el modal. Clickeable → abre Publicación web del lote. */
.web-pill { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 700; padding: 3px 10px; border-radius: 99px; border: none; cursor: pointer; font-family: var(--sans); letter-spacing: .01em; transition: filter .2s, border-color .2s; }
.web-pill--on { color: var(--st-activo); background: var(--green-glow); }
.web-pill--on:hover { filter: brightness(1.15); }
.web-pill--off { color: var(--ink-4); background: var(--surface-2); border: 1px solid var(--line); }
.web-pill--off:hover { color: var(--ink-2); border-color: var(--line-strong); }
.web-pill i { font-size: .9em; }
.folio-icon:hover { color: var(--gold); border-color: var(--gold); background: rgba(216,184,120,.06); }

/* menú ⋮ — el JS togglea .lote-menu-pop por click (atributo hidden) */
.lote-menu { position: relative; flex: none; }
/* POSITION: FIXED, no absolute. La .lote-card recorta (overflow:hidden, lo
   necesita por el alto fijo y las esquinas redondeadas), y el popup se abre
   hacia la IZQUIERDA desde un boton que no llega a estar a 158px del borde
   izquierdo de la card: se comia 21.6px, justo la columna de los iconos, que
   salian cortados al medio. Sacandolo del contexto de recorte deja de pasar.
   El left/top los pone ubicarMenu() en lotes.js, que ademas lo voltea si no
   entra arriba y lo mete adentro de la ventana. */
.lote-menu-pop { position: fixed; left: 0; top: 0; min-width: 158px; background: var(--surface-2); border: 1px solid var(--line-strong); border-radius: var(--radius-sm); box-shadow: 0 14px 30px -14px rgba(0,0,0,.6); padding: 5px; display: flex; flex-direction: column; z-index: 50; animation: popIn .16s var(--ease) both; }
.lote-menu-pop[hidden] { display: none; }
.lote-menu-item { width: 100%; display: flex; align-items: center; gap: 9px; padding: 8px 9px; border: none; background: none; cursor: pointer; border-radius: 6px; font-family: var(--sans); font-size: 12.5px; color: var(--ink-2); text-align: left; transition: background .12s, color .12s; }
.lote-menu-item i { width: 14px; text-align: center; color: var(--ink-4); font-size: 11px; }
.lote-menu-item:hover:not(:disabled) { background: var(--ctrl-hover); color: var(--ink); }
.lote-menu-item:disabled { opacity: .4; cursor: not-allowed; }
.folio-menu-danger { color: var(--gold); }
.folio-menu-danger:hover:not(:disabled) { background: rgba(216,184,120,.08); color: var(--gold); }
.folio-menu-danger i { color: var(--gold-2); }
.lote-menu-sep { height: 1px; margin: 4px 6px; background: var(--line); }
.lote-empty { display: flex; align-items: center; gap: 8px; margin: 0; padding: 8px 10px; font-size: 12px; color: var(--muted); background: var(--surface-2); border: 1px dashed var(--line-strong); border-radius: var(--radius-sm); }
.lote-empty i { font-size: 1rem; color: var(--ink-4); flex-shrink: 0; }

/* 4) Galería de fotos del lote (modal "Editar lote"): reorden por arrastre.
      El orden = prioridad; la primera es la portada. Los tiles se arrastran con
      pointer events (la foto se "levanta" y sigue al cursor) — ver lotes.js. */
.lote-galeria-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(116px, 1fr)); gap: 10px; }
.lg-hint { display: flex; align-items: center; gap: 8px; margin: 0 0 13px; font-size: 12.5px; color: var(--ink-3); }
.lg-hint i { color: var(--gold); font-size: 12px; }
.lg-hint b { color: var(--ink-2); font-weight: 600; }
.lg-vacia { margin: 12px 0 0; font-size: 12.5px; }

.lg-tile {
  position: relative; margin: 0; aspect-ratio: 4 / 3; border-radius: var(--radius-sm); overflow: hidden;
  border: 1px solid var(--line-strong); background: var(--surface);
  cursor: grab; user-select: none; touch-action: none;
  transition: border-color .15s var(--smooth), box-shadow .15s var(--smooth);
}
.lg-tile:hover { border-color: var(--gold); box-shadow: 0 10px 24px -14px rgba(0,0,0,.7); }
/* contain: aca se elige la portada arrastrando ("la cambio de lugar y se cambia
   la portada", dijo el cliente). Recortadas no se distingue una foto de otra, que
   es justamente lo unico que importa en esta grilla. */
.lg-tile img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; display: block; pointer-events: none; }

/* La foto AGARRADA: levantada, sigue al cursor (position:fixed la pone el JS). El
   z-index la deja por encima del modal-overlay (1000) y del toast (1100). */
.lg-tile.lg-lifting {
  cursor: grabbing; z-index: 1200; border-color: var(--gold);
  box-shadow: 0 26px 54px -14px rgba(0,0,0,.78), 0 0 0 2px var(--gold);
  filter: brightness(1.06) saturate(1.04);
}
/* El hueco donde va a caer */
.lg-tile.lg-placeholder { background: var(--gold-glow); border: 1.6px dashed var(--gold); box-shadow: none; cursor: default; }

.lg-grip {
  position: absolute; top: 7px; left: 7px; width: 24px; height: 24px; border-radius: 7px;
  display: grid; place-items: center; color: #fff; font-size: 11px; pointer-events: none;
  background: rgba(8,14,10,.5); backdrop-filter: blur(4px); opacity: .82;
}
.lg-num, .lg-portada { position: absolute; bottom: 7px; border-radius: 7px; backdrop-filter: blur(4px); font-size: 10px; font-weight: 600; padding: 2px 7px; pointer-events: none; }
.lg-num { right: 7px; font-family: var(--mono); background: rgba(8,14,10,.6); color: var(--ink-2); }
.lg-portada { left: 7px; display: inline-flex; align-items: center; gap: 4px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: #1a1206; background: var(--gold); box-shadow: 0 2px 8px rgba(0,0,0,.4); }
.lg-portada i { font-size: 9px; }

.lg-del {
  position: absolute; top: 7px; right: 7px; width: 24px; height: 24px; border-radius: 7px; border: none;
  display: grid; place-items: center; color: #fff; font-size: 12px; cursor: pointer;
  background: rgba(8,14,10,.55); backdrop-filter: blur(4px); opacity: 0;
  transition: opacity .15s var(--smooth), background .15s var(--smooth);
}
.lg-tile:hover .lg-del, .lg-tile:focus-within .lg-del { opacity: 1; }
.lg-del:hover { background: var(--danger); }

.lg-add {
  display: grid; place-items: center; gap: 5px; aspect-ratio: 4 / 3; border-radius: var(--radius-sm);
  border: 1.5px dashed var(--line-strong); color: var(--ink-3); cursor: pointer;
  background: color-mix(in srgb, var(--ink) 1.5%, transparent); transition: var(--transition);
}
.lg-add:hover { border-color: var(--green-600); color: var(--green-400); background: var(--green-glow); }
.lg-add i { font-size: 1.2rem; }
.lg-add span { font-size: 11px; }

/* Buscador + multi-selección de objetos al asignar (dentro del modal) */
.search-results { list-style: none; margin: 0 0 12px; padding: 0; max-height: 200px; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; }
.search-results li { margin: 0; }
.search-results .btn { width: 100%; justify-content: flex-start; }
.selected-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.selected-item { display: flex; align-items: center; gap: 8px; padding: 8px 9px 8px 11px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg); transition: border-color .16s var(--smooth); }
.selected-item:focus-within { border-color: var(--green-600); }
.selected-item > span { flex: 1 1 auto; min-width: 0; font-size: 13px; color: var(--ink); }
.selected-item input[type="number"] { width: 72px; flex: 0 0 auto; padding: 6px 8px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface); color: var(--ink); font-family: var(--mono); text-align: center; transition: var(--transition); }
.selected-item input[type="number"]:focus { outline: none; border-color: var(--green-600); box-shadow: var(--ring); }
/* ── Asignar objeto(s) al lote: elegir VIENDO la pieza ─────────────────────────
   Un remate de platería son cientos de piezas de nombre corto y parecido
   ("rastra", "mate", "taba"): sin la foto, armar el lote es adivinar.

   La miniatura entra SIN que el modal cambie de alto. El alto lo fija el modal
   (`height`, no el `max-height` elástico de .modal), el cuerpo va sin scroll y
   scrollean por dentro los resultados y los seleccionados. Así da lo mismo si la
   búsqueda trae uno o cincuenta, y agregar o quitar seleccionados no mueve nada.

   Todo va scopeado a `.asignar-obj`: `.search-results` y `.selected-list` son de
   este modal y de ningún otro lugar, y las clases nuevas (.ao-*) no rozan el
   `.obj-photo` de Stock. */
/* El tope de 700px solo manda en pantallas grandes. La máquina del que opera es
   de 1365×768, o sea un viewport de ~1347×672: ahí reparte el vh, y con 88vh la
   lista de resultados quedaba en 165px (dos filas). 92vh todavía deja ~27px de
   aire arriba y abajo, así que el modal entero sigue entrando en la pantalla. */
.modal:has(.asignar-obj) { height: min(92vh, 700px); max-height: none; }
.modal:has(.asignar-obj) .modal-body { overflow: hidden; }
/* Cuatro filas: buscador, resultados (lo que sobra), seleccionados y pie. */
.modal-body .asignar-obj {
  height: 100%; min-height: 0; gap: 14px;
  display: grid; grid-template-rows: auto minmax(0, 1fr) auto auto;
}
/* Con el alto ya fijado el pie no necesita ser sticky: es una fila más del grid.
   Los márgenes negativos siguen calibrados contra el padding 24px del cuerpo. */
.modal .asignar-obj .form-actions { position: static; margin: 0 -24px -24px; padding: 14px 24px; }

.asignar-obj .search-results { margin: 0; max-height: none; min-height: 0; gap: 6px; padding-right: 5px; }
/* Alto fijo, no `max-height`: si creciera con los ítems, el pie se movería al
   agregar el primero. Cede en pantallas bajas, nunca por contenido, y el aire
   que suelta se lo lleva la lista de resultados: en 1347×672 esto reservaba
   141px para confirmar lo ya elegido y dejaba 165px para elegir, que es al
   revés de lo que hace falta. El piso de 98px son dos filas justas (2×46 + 6). */
.asignar-obj .selected-list { height: clamp(98px, 16vh, 148px); overflow-y: auto; gap: 6px; padding-right: 5px; }
/* Sin nada elegido el hueco reservado se dibuja: si no, se lee como un bache. */
.asignar-obj .selected-list:has(.muted) {
  display: grid; place-items: center;
  border: 1.5px dashed var(--line); border-radius: var(--radius-sm);
}
.asignar-obj .search-results,
.asignar-obj .selected-list { scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent; }
.asignar-obj .search-results::-webkit-scrollbar,
.asignar-obj .selected-list::-webkit-scrollbar { width: 8px; }
.asignar-obj .search-results::-webkit-scrollbar-thumb,
.asignar-obj .selected-list::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 99px; }

/* Filas de alto fijo (el .btn traía 38px y no entra la miniatura). */
.asignar-obj .ao-item { width: 100%; height: 56px; padding: 0 12px 0 8px; gap: 10px; justify-content: flex-start; }
/* `flex: 0 0 auto`: son hijos directos de un flex column con alto fijo y, sin
   esto, el tercer seleccionado achica a los tres en vez de aparecer el scroll. */
.asignar-obj .selected-item { flex: 0 0 auto; height: 46px; padding: 0 9px; gap: 9px; }

/* La foto no se encoge (`flex: 0 0 auto`) y el hueco del objeto SIN foto mide
   igual: la fila no puede depender de si la pieza tiene foto o no. */
.asignar-obj .ao-thumb {
  flex: 0 0 auto; width: 40px; height: 40px; display: block;
  object-fit: cover; border-radius: 6px; border: 1px solid var(--line); background: var(--surface-2);
}
.asignar-obj .ao-thumb--mini { width: 30px; height: 30px; border-radius: 5px; }
.asignar-obj .ao-thumb--vacia { display: grid; place-items: center; color: var(--ink-4); }
.asignar-obj .ao-thumb--vacia i { font-size: 14px; }
.asignar-obj .ao-thumb--mini.ao-thumb--vacia i { font-size: 11px; }

/* `min-width: 0` + ellipsis: el nombre largo trunca en vez de empujar la foto. */
.asignar-obj .ao-txt { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; text-align: left; }
.asignar-obj .ao-nombre,
.asignar-obj .ao-meta { display: block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.asignar-obj .ao-nombre { font-size: 13px; font-weight: 600; line-height: 1.3; color: var(--ink); }
.asignar-obj .ao-meta { font-size: 11.5px; font-weight: 500; line-height: 1.3; color: var(--ink-3); }
.asignar-obj .ao-mas { flex: 0 0 auto; font-size: 12px; color: var(--ink-4); }
.asignar-obj .ao-item:hover:not(:disabled) .ao-nombre,
.asignar-obj .ao-item:hover:not(:disabled) .ao-mas { color: var(--green-ink); }

/* Modal de edición de lote: imágenes + observaciones por objeto.
   Secciones separadas por divisor sutil + label de sección mono mayúscula. */
.modal:has(.lote-edit) { max-width: 560px; }

/* Modal dedicado de fotos del lote (ver + ordenar). Más ancho que el de edición
   para que la galería respire (4–5 columnas). */
.modal:has(.lote-galeria-modal) { max-width: 620px; }
.lote-galeria-modal { display: flex; flex-direction: column; gap: 4px; }
.lote-galeria-modal .lote-galeria { margin: 2px 0 0; }
.lote-galeria-modal .form-actions { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line); }
.lote-edit { display: flex; flex-direction: column; }
.lote-edit-sec { display: flex; flex-direction: column; gap: 12px; padding: 18px 0; }
.lote-edit-sec:first-child { padding-top: 2px; }
.lote-edit-sec + .lote-edit-sec { border-top: 1px solid var(--line); }
.lote-edit-titulo {
  display: flex; align-items: center; gap: 9px; margin: 0;
  font-family: var(--mono); font-size: 11px; font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase; color: var(--ink-2);
}
.lote-edit-titulo i {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: 6px;
  display: grid; place-items: center; font-size: 11px;
  color: var(--green-400); background: var(--green-glow); border: 1px solid var(--line-strong);
}
/* ════════════════════════════════════════════════════════════════════════════
   MOTION — sobrio, sin ornamentos editoriales
   ════════════════════════════════════════════════════════════════════════════ */
@keyframes fadeUp   { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes fadeIn   { from { opacity: 0; } to { opacity: 1; } }
@keyframes popIn    { from { opacity: 0; transform: translateY(8px) scale(.98); } to { opacity: 1; transform: none; } }
@keyframes shimmer  { from { background-position: -180% 0; } to { background-position: 180% 0; } }

/* Reveal escalonado al entrar a cada vista */
/* Las secciones entran INSTANTÁNEAS (sin fade ni desplazamiento): toda animación
   de entrada deja un instante en blanco al reemplazar el contenido, que se percibe
   como salto (con movimiento) o pestañeo (con fade). Las animaciones quedan a nivel
   de interacción: pestañas (glider), modales, hover, estados vacíos. */

/* Skeletons con shimmer (estados de carga) */
.skeleton, .skel-line {
  background: linear-gradient(100deg, var(--surface-2) 30%, color-mix(in srgb, var(--ink) 6%, var(--surface-2)) 50%, var(--surface-2) 70%);
  background-size: 220% 100%; animation: shimmer 1.3s linear infinite; border-radius: var(--radius-sm);
}
.skel-line { height: 12px; margin: 9px 0; }
.skel-card { height: 120px; border-radius: var(--radius); }
.skel-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 16px; }

/* Modal / overlay: entrada con resorte suave */
.modal-overlay { animation: fadeIn .2s var(--ease) both; }
.modal { animation: popIn .26s var(--ease) both; }

/* ── Móvil / tablet: sidebar como drawer con hamburguesa + backdrop ─────────── */
@media (max-width: 768px) {
  /* visibility saca el drawer cerrado del orden de tabulacion. El delay iguala
     la transicion del transform: si no, al cerrar desaparece de golpe en vez
     de deslizarse. Al abrir no hay delay (0s) para que aparezca ya. */
  .sidebar {
    transform: translateX(-100%); box-shadow: var(--shadow-lg);
    visibility: hidden; transition: transform .22s ease, visibility 0s linear .22s;
  }
  .app-shell.nav-open .sidebar {
    transform: translateX(0);
    visibility: visible; transition: transform .22s ease, visibility 0s linear 0s;
  }
  .main-content { margin-left: 0; }

  .topbar-hamburger { display: inline-flex; }
  .topbar-inner { padding: 0 20px; }
  .topbar-title { font-size: 1.1rem; }
  .content-area { padding: 20px; }

  /* Backdrop: solo visible con el drawer abierto */
  .app-shell.nav-open .sidebar-backdrop { display: block; position: fixed; inset: 0; z-index: 90; background: rgba(17,30,17,.42); backdrop-filter: blur(1px); }
}

/* ── Tablas → TARJETAS en móvil (responsive real en cada listado) ──────────── */
@media (max-width: 768px) {
  .data-table thead { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
  .data-table, .data-table tbody, .data-table tbody tr, .data-table tbody td { display: block; width: 100%; }
  .data-table tbody tr { border: 1px solid var(--line); border-radius: var(--radius); margin-bottom: 12px; background: var(--surface); box-shadow: var(--shadow-card); overflow: hidden; }
  .data-table tbody tr:hover td { background: transparent; }
  .data-table tbody td { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 11px 15px; border-bottom: 1px dashed var(--line); text-align: right; }
  .data-table tbody tr td:last-child { border-bottom: none; }
  .data-table tbody td::before { content: attr(data-label); font-family: var(--sans); font-size: .62rem; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-4); font-weight: 700; text-align: left; flex-shrink: 0; }
  .data-table td.col-actions { flex-wrap: wrap; justify-content: flex-end; }
  .data-table td.col-actions .btn { margin: 3px 0 3px 6px; }
  .data-table td.empty { justify-content: center; }
  .data-table td.empty::before { content: none; }
  .table-footer { flex-direction: column; gap: 12px; }
  /* La tabla anidada dentro de un lote se mantiene compacta, no como tarjeta global */
  .lote-card .data-table tbody td { border-bottom: 1px dashed var(--line); }

  /* La tabla del CIERRE NO se vuelve tarjetas: el card-mode global la rompe (filas-detalle
     anidadas + celda del caret). Se mantiene TABLA y scrollea horizontal dentro del wrap. */
  .hist-cierre { padding: 12px 10px; }
  .hist-cierre > .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .hist-cierre-table { min-width: 660px; }
  .hist-cierre-table, .hist-cierre-table tbody, .hist-cierre-table tbody tr, .hist-cierre-table tbody td { display: revert; }
  .hist-cierre-table thead { position: static; width: auto; height: auto; clip: auto; overflow: visible; border: 0; }
  .hist-cierre-table tbody tr { border: 0; border-radius: 0; margin: 0; background: none; box-shadow: none; }
  .hist-cierre-table tbody td::before { content: none; }
  .hist-cierre-detwrap { padding: 8px 8px 12px 12px; }
  .hist-cierre-detwrap .table-wrap { overflow-x: auto; }
  .hist-cierre-detwrap .hist-table { min-width: 320px; }
}

/* ── Historial: anchos de columna FIJOS en desktop ──────────────────────────────
   table-layout:fixed → el ancho de las columnas NO depende de las filas visibles,
   así al filtrar (KPI Saldo) o paginar las columnas no saltan. SOLO en desktop:
   en ≤768px las .data-table pasan a modo tarjeta (display:block) y fixed no aplica.
   Scopeado a .hist-table → no afecta Clientes ni otras vistas. */
.hist-subhead { margin: 18px 0 8px; font-size: 13px; font-weight: 700; color: var(--ink-2, var(--ink)); }
.hist-subhead .muted { font-weight: 400; }

@media (min-width: 769px) {
  .hist-table { table-layout: fixed; }
  /* Columnas de texto variable: truncar con ellipsis en vez de expandir la columna. */
  .hist-table td, .hist-table th { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* Las celdas de monto/acciones no deben truncar su contenido (entra completo). */
  .hist-table td.vt-r, .hist-table th.vt-r,
  .hist-table td.col-actions, .hist-table th.col-actions { overflow: visible; }

  /* Cuenta corriente: Remate(flex) · Estado(140) · Comprado/Vendido/Pagado/Saldo(120 c/u) */
  .hist-table--cc th:nth-child(2), .hist-table--cc td:nth-child(2) { width: 140px; }
  .hist-table--cc th:nth-child(n+3), .hist-table--cc td:nth-child(n+3) { width: 120px; }

  /* Ventas: Fecha(110) · Remate(flex) · Lote(22%) · Objeto(s)(flex) · Monto(130) */
  .hist-table--ventas th:nth-child(1), .hist-table--ventas td:nth-child(1) { width: 110px; }
  .hist-table--ventas th:nth-child(3), .hist-table--ventas td:nth-child(3) { width: 22%; }
  .hist-table--ventas th:nth-child(5), .hist-table--ventas td:nth-child(5) { width: 130px; }

  /* Compras: Fecha(110) · Remate(flex) · Lote(flex) · Cant.(90) · Monto(130) */
  .hist-table--compras th:nth-child(1), .hist-table--compras td:nth-child(1) { width: 110px; }
  .hist-table--compras th:nth-child(4), .hist-table--compras td:nth-child(4) { width: 90px; }
  .hist-table--compras th:nth-child(5), .hist-table--compras td:nth-child(5) { width: 130px; }

  /* Recibos: N.º(100) · Fecha(120) · Remate(flex) · Monto(130) · acciones(140) */
  .hist-table--recibos th:nth-child(1), .hist-table--recibos td:nth-child(1) { width: 100px; }
  .hist-table--recibos th:nth-child(2), .hist-table--recibos td:nth-child(2) { width: 120px; }
  .hist-table--recibos th:nth-child(4), .hist-table--recibos td:nth-child(4) { width: 130px; }
  .hist-table--recibos th:nth-child(5), .hist-table--recibos td:nth-child(5) { width: 140px; }
}

@media (max-width: 560px) {
  .obj-grid { grid-template-columns: repeat(2, 1fr); gap: 12px; }
  .page { padding: 18px 16px; }
  .topbar-date { display: none; }
}

/* ── Cross-fade entre vistas (View Transitions API) ─────────────────────────── */
::view-transition-old(root),
::view-transition-new(root) { animation-duration: .32s; animation-timing-function: var(--smooth); }
/* Durante el fade, la vista nueva aparece en su estado final (no re-anima la entrada) */
html.vt #view > *,
html.vt .obj-card, html.vt .lote-card, html.vt .estado-modal {
  animation: none !important; opacity: 1 !important; transform: none !important;
}

/* ── Transición suave de tema (solo durante el toggle) ──────────────────────── */
html.theme-anim, html.theme-anim *, html.theme-anim *::before, html.theme-anim *::after {
  transition: background-color .3s var(--smooth), color .3s var(--smooth),
              border-color .3s var(--smooth), fill .3s var(--smooth) !important;
}

/* ── Respeto total a quien prefiere menos movimiento ────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ── Boleta de salida imprimible (Morales Colombo) ──────────────────────────── */
/* En pantalla nunca se ve: solo existe para el diálogo de impresión. */
@media screen {
  .print-boleta { display: none; }
}

/* Margen de PÁGINA en cero para los nueve impresos. Nunca había un @page acá,
   así que la paginación real dependía de lo que trajera puesto el diálogo de
   impresión del navegador (o el default sin pedir nada, que en Chrome headless
   ronda 1 pulgada) — un margen que se SUMA al padding que ya trae cada
   encabezado (24mm en los seis papeles verticales, 12mm/14mm en catálogo y
   pre-ofertantes). Es la causa del defecto del reporte municipal: con pocos
   lotes el contenido entra sobrado con margen de página CERO, pero con
   cualquier margen que el navegador agregue arriba, el pie se corre solo a una
   segunda hoja casi en blanco. Mismo criterio que ya usaban las etiquetas
   térmicas («el aire va en el padding, no en el margen de página») — acá se
   generaliza a los nueve. No puede ir con selector de clase (@page no se
   condiciona por eso), así que aplica a TODOS los documentos por igual; el
   apaisado del catálogo sigue viviendo aparte, por CSSOM (ver catalogo-print.js),
   y se combina bien con este margen: son propiedades distintas del mismo @page. */
@page { margin: 0; }

@media print {
  /* Un solo tamaño de logo para los nueve impresos (pedido textual del dueño:
     «los logos, más grande siempre y consistente a todos recibos»). Antes eran
     DOS tamaños distintos (40px en los seis papeles verticales, 14px en el
     catálogo apaisado) y ninguno de los dos era este. Una sola variable: el
     día de mañana que cambie, se toca ACÁ y no en tres reglas sueltas que se
     pueden desincronizar. 56px es 40% más grande que el anterior (40px) y
     entra sin agrandar la única cabecera de un renglón (el catálogo, ver
     `.cat-head` más abajo) ni sacarle una página a ningún documento — medido
     con los nueve PDF reales antes/después de este cambio. */
  :root { --logo-h: 56px; }

  /* Ocultar TODA la app: los hermanos del contenedor de impresión salen de FLUJO
     (display:none), no solo visibility:hidden. Si solo se ocultan con visibility,
     siguen ocupando alto y generan páginas en blanco antes/después del recibo. */
  body > *:not(.print-boleta) { display: none !important; }
  .print-boleta,
  .print-boleta * { visibility: visible; }

  .print-boleta {
    display: block;
    position: static;
    margin: 0;
    padding: 24mm 20mm;
    width: 100%;
    background: #fff;
    color: #000;
    /* Sans-serif de sistema: más legible en recibos que la serif. Números
       tabulares + lining → misma altura y ancho (antes Georgia usaba figuras
       "oldstyle" con alturas distintas). */
    font-family: "Segoe UI", "Helvetica Neue", Arial, system-ui, sans-serif;
    font-variant-numeric: tabular-nums lining-nums;
    font-size: 12pt;
    line-height: 1.5;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  /* Los importes tabulares (columnas y totales) heredan lining-nums del contenedor. */
  .print-boleta .pb-num,
  .print-boleta .pb-total,
  .print-boleta .pb-total-sub,
  .print-boleta .pb-saldo { font-variant-numeric: tabular-nums lining-nums; }

  /* Línea de retención (impuesto municipal) sobre el total del vendedor. */
  .print-boleta .pb-total-sub { margin: 0 0 2px; font-size: 11px; color: #555; text-align: right; }

  /* ── Catálogo del remate: la hoja del estrado ────────────────────────────
     No es un recibo de una página: son 183 lotes. Márgenes más chicos, tipo más
     chica y la cabecera de la tabla repetida en cada hoja, porque si no a partir
     de la segunda no se sabe qué columna es cuál. Y ninguna fila partida al
     medio entre dos páginas. */
  .print-catalogo { padding: 12mm 10mm; font-size: 9.5pt; line-height: 1.3; }
  /* Cabecera de la hoja del estrado: la casa a la izquierda, título+sello a la
     derecha. Sigue siendo UN SOLO renglón horizontal (no se repite por
     página, y no le come aire a los 183 lotes), pero con el logo grande
     (var(--logo-h), igual que los otros ocho papeles) hacía falta reacomodar,
     no solo agrandar la imagen:
       · el logo YA NO comparte línea de base con el título — antes (14px) los
         tres elementos eran casi del mismo alto y "una fila de texto con un
         ícono" alcanzaba; con el logo a --logo-h ese armado dejaba un texto
         chiquito perdido al lado de un logo grande, muy desbalanceado;
       · título y sello ahora van APILADOS en un bloque a la derecha
         (.cat-head-info), no repartidos en los extremos del renglón: así el
         bloque de texto compite en peso visual con el logo en vez de flotar
         solo, y el título subió un punto (12pt → 13pt) para acompañar.
     Se midió que esto NO le agrega página a ninguno de los dos documentos que
     usan esta cabecera (catálogo de 183 lotes, hoja de pre-ofertantes). */
  .print-catalogo .cat-head {
    display: flex;
    align-items: center;
    gap: 14px;
    border-bottom: 1.5px solid #000;
    padding-bottom: 6px;
    margin-bottom: 8px;
  }
  .print-catalogo .cat-logo { display: block; height: var(--logo-h); width: auto; }
  /* margin-left: auto empuja el bloque de texto al extremo derecho (el logo
     no tiene ancho fijo, así que justify-content: space-between no alcanza
     con solo dos hijos flex). align-items: flex-end para que título y sello
     queden alineados contra el borde derecho, como en la hoja de la casa. */
  .print-catalogo .cat-head-info { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; margin-left: auto; }
  .print-catalogo .cat-titulo { font-weight: 700; font-size: 13pt; }
  .print-catalogo .cat-sello { font-size: 8.5pt; color: #444; }
  .print-catalogo .cat-remate { margin: 0 0 2px; font-size: 10pt; font-weight: 600; }
  .print-catalogo .cat-resumen { margin: 0 0 8px; font-size: 8.5pt; color: #444; }
  /* Las columnas de plata van VACIAS cuando no hay dato: son el renglon donde el
     martillero escribe a mano arriba del estrado, asi que necesitan aire y los
     cuatro bordes visibles. */
  .print-catalogo .cat-plata { border-left: 1px solid #999; min-width: 22mm; }
  /* La paleta va DEBAJO del monto y mas chica: identifica a quien llamar cuando
     el lote entra a venta, sin robarle el lugar al numero. */
  .print-catalogo .cat-paleta { display: block; font-size: 7.5pt; font-weight: 400; color: #555; }

  /* ── Agenda de llamadas (pre-ofertantes) ─────────────────────────────────
     Va VERTICAL: son seis columnas pero angostas, sin el parrafo de
     observaciones. Cada lote agrupa hasta N renglones (N lo elige quien
     imprime, en la ventanita previa), y una linea mas marcada arriba del
     primero separa un lote del otro: leyendo de corrido, sin esa linea, no se
     sabe donde termina un lote y empieza el siguiente. */
  .print-preofertantes { padding: 14mm 12mm; }
  .print-preofertantes .cat-grupo td { border-top: 1.5px solid #000; }
  .print-preofertantes .cat-tabla th:nth-child(2) { width: 46mm; }
  .print-preofertantes .cat-tabla th:nth-child(3) { width: 16mm; }
  .print-preofertantes .cat-tabla th:nth-child(5) { width: 34mm; }
  /* El telefono es lo que se marca: tabular y sin partirse a mitad de numero. */
  .print-preofertantes .cat-tel { font-variant-numeric: tabular-nums; white-space: nowrap; }

  .print-catalogo .cat-tabla { width: 100%; border-collapse: collapse; }
  .print-catalogo .cat-tabla thead { display: table-header-group; } /* se repite por página */
  .print-catalogo .cat-tabla tr { break-inside: avoid; page-break-inside: avoid; }
  .print-catalogo .cat-tabla th,
  .print-catalogo .cat-tabla td { border-bottom: 1px solid #bbb; padding: 4px 6px; vertical-align: top; }
  .print-catalogo .cat-tabla th { border-bottom: 1.5px solid #000; text-align: left; font-size: 9pt; text-transform: uppercase; letter-spacing: .03em; }
  /* Las observaciones son largas y se comen la hoja: se les da el ancho que
     sobra y se acotan las demás columnas. */
  .print-catalogo .cat-tabla th:nth-child(1) { width: 12mm; }
  .print-catalogo .cat-tabla th:nth-child(2) { width: 42mm; }
  .print-catalogo .cat-tabla th:nth-child(4),
  .print-catalogo .cat-tabla th:nth-child(5),
  .print-catalogo .cat-tabla th:nth-child(6) { width: 26mm; }
  .print-catalogo .cat-obs { font-size: 9pt; color: #333; }

  /* Modo multi-recibo (cierre): un recibo por página. El padding de página lo
     pone cada .print-page (el contenedor no agrega el suyo). */
  .print-boleta--multi { padding: 0; }
  .print-boleta--multi .print-page {
    padding: 24mm 20mm;
    break-after: page;
    break-inside: avoid;
  }
  .print-boleta--multi .print-page:last-child { break-after: auto; }

  .print-boleta .pb-head {
    text-align: center;
    border-bottom: 2px solid #000;
    padding-bottom: 10px;
    margin-bottom: 18px;
  }
  /* El logo REEMPLAZA al "MORALES COLOMBO" de texto (ya lo dice el propio
     isologo): mismo lugar, mismo peso visual, para no empujar el resto del
     recibo a una hoja más. Alto fijo + ancho automático: no se estira ni
     deforma la imagen, y las ocho hojas quedan con el mismo tamaño de marca. */
  .print-boleta .pb-logo {
    display: block;
    height: var(--logo-h);
    width: auto;
    margin: 0 auto;
  }
  .print-boleta .pb-sub {
    margin: 6px 0 0;
    font-size: 11pt;
    font-style: italic;
    letter-spacing: 1px;
  }

  .print-boleta .pb-meta {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: 18px;
    font-size: 11pt;
  }
  .print-boleta .pb-nro { font-weight: 700; }

  .print-boleta .pb-campos {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: 36px;
  }
  .print-boleta .pb-campos th,
  .print-boleta .pb-campos td {
    text-align: left;
    vertical-align: top;
    padding: 9px 10px;
    border: 1px solid #000;
  }
  .print-boleta .pb-campos th {
    width: 28%;
    font-weight: 700;
    background: #f0f0f0;
    text-transform: uppercase;
    font-size: 10pt;
    letter-spacing: .5px;
  }

  /* Tabla de ítems del recibo por cliente (varias líneas de compra). Comparten
     esta tabla la boleta de entrada, la liquidación, el recibo y el reporte
     municipal (y también el catálogo, vía .cat-tabla, que ya traía su propia
     protección — ver más abajo). */
  .print-boleta .pb-items {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: 16px;
  }
  /* Ninguna fila se parte al medio entre dos páginas. Sin esto, una
     descripción larga (p. ej. un artículo con varias líneas de texto) podía
     cortarse a mitad de oración en el borde de la hoja, con el resto
     arrancando solo en la página siguiente y SIN repetir el nombre del
     artículo ni las columnas de cantidad/valor — se verificó con la boleta
     de entrada 20001 (64 artículos), donde la fila «Acordeón» se partía así.
     El Reporte de piezas (.pzp-row/.pzp-detail) ya traía esta protección;
     acá le faltaba. */
  .print-boleta .pb-items tr { break-inside: avoid; page-break-inside: avoid; }
  .print-boleta .pb-items th,
  .print-boleta .pb-items td {
    padding: 7px 9px;
    border: 1px solid #000;
    font-size: 11pt;
    vertical-align: top;
  }
  .print-boleta .pb-items thead th {
    background: #f0f0f0;
    text-transform: uppercase;
    font-size: 9pt;
    letter-spacing: .5px;
  }
  .print-boleta .pb-num { text-align: right; white-space: nowrap; }
  .print-boleta .pb-totales {
    margin: 0 0 36px;
    text-align: right;
  }
  .print-boleta .pb-total,
  .print-boleta .pb-sena {
    margin: 0 0 4px;
    font-size: 12pt;
    font-weight: 400;
  }
  .print-boleta .pb-saldo {
    margin: 6px 0 0;
    padding-top: 6px;
    border-top: 1px solid #000;
    font-size: 13pt;
    font-weight: 700;
  }
  /* Encabezado de moneda en el remate mixto. Sin aire arriba, el «USD» quedaba
     pegado al «Total a cobrar» del bloque en pesos y se leía como parte de ese
     total. Al primero no se le pone aire: ya viene despegado de la tabla. */
  .print-boleta .pb-cur-h {
    margin: 18px 0 6px;
    font-size: 12pt;
    letter-spacing: 1px;
  }
  .print-boleta .pb-cur-h:first-child { margin-top: 0; }

  /* Dos firmas lado a lado (remitente + casa) en la boleta de entrada. */
  .print-boleta .pb-firmas {
    display: flex;
    gap: 48px;
    margin-top: 56px;
  }
  .print-boleta .pb-firmas .pb-firma { flex: 1; margin-top: 0; }
  .print-boleta .pb-firma {
    margin-top: 48px;
    text-align: center;
  }
  .print-boleta .pb-firma-line {
    display: block;
    width: 60%;
    margin: 0 auto 6px;
    border-top: 1px solid #000;
  }
  .print-boleta .pb-firma-label {
    font-size: 10pt;
    letter-spacing: .5px;
  }

  .print-boleta .pb-foot {
    margin-top: 30px;
    padding-top: 8px;
    border-top: 1px solid #999;
    text-align: center;
    font-size: 9pt;
    color: #333;
  }

  /* ── Resumen contable (impreso) ────────────────────────────────────────── */
  .print-boleta .rc-items .rc-fuerte th,
  .print-boleta .rc-items .rc-fuerte td { font-weight: 700; font-size: 12pt; }
  .print-boleta .pb-nota {
    margin: 4px 0 24px;
    font-size: 9.5pt;
    font-style: italic;
    color: #333;
  }

  /* ── Reporte de piezas (impreso) — layout editorial propio (clases .pzp-*) ── */
  .print-piezas { color: #1a1a1a; font-family: Georgia, 'Times New Roman', serif; }
  .print-piezas .pzp-head { text-align: center; margin-bottom: 22px; }
  /* Mismo alto que .pb-logo (var(--logo-h)): es el mismo isologo, y el cliente
     lo pidió parejo en todos los papeles, no un tamaño distinto por hoja. */
  .print-piezas .pzp-logo { display: block; height: var(--logo-h); width: auto; margin: 0 auto; }
  .print-piezas .pzp-sub { margin: 5px 0 0; font-size: 10pt; font-style: italic; color: #555; letter-spacing: .5px; }

  .print-piezas .pzp-meta {
    display: flex; justify-content: space-between; align-items: flex-end;
    border-top: 2px solid #1a1a1a; border-bottom: 1px solid #ccc;
    padding: 11px 2px; margin-bottom: 20px;
  }
  .print-piezas .pzp-title { margin: 0; font-size: 8.5pt; font-weight: 700; text-transform: uppercase; letter-spacing: 1.5px; color: #666; }
  .print-piezas .pzp-consig { margin: 5px 0 0; font-size: 15pt; font-weight: 700; }
  .print-piezas .pzp-meta-r { text-align: right; }
  .print-piezas .pzp-date { margin: 0; font-size: 10.5pt; font-weight: 600; }
  .print-piezas .pzp-count { margin: 3px 0 0; font-size: 9.5pt; color: #666; }

  /* Banda de resultado: tira de celdas con la plata YA REALIZADA del
     consignante (liquidado, a cobrar, cobrado, % vendido). El valor esperado
     no tiene celda acá: es interno, no sale en el papel del consignante. */
  .print-piezas .pzp-inv { display: flex; border: 1px solid #ccc; margin-bottom: 22px; }
  .print-piezas .pzp-inv-cell {
    flex: 1; padding: 9px 13px; border-right: 1px solid #e2e2e2;
    display: flex; flex-direction: column; gap: 2px;
  }
  .print-piezas .pzp-inv-cell:last-child { border-right: none; }
  .print-piezas .pzp-inv-lbl { font-size: 7.5pt; text-transform: uppercase; letter-spacing: .6px; color: #777; }
  .print-piezas .pzp-inv-val { font-size: 13pt; font-weight: 800; line-height: 1.1; }
  .print-piezas .pzp-inv-sub { font-size: 7.5pt; color: #888; font-style: italic; }
  .print-piezas .pzp-vend { font-weight: 700; }

  .print-piezas .pzp-table { width: 100%; border-collapse: collapse; }
  .print-piezas .pzp-table thead th {
    font-size: 8pt; text-transform: uppercase; letter-spacing: .8px; color: #666;
    font-weight: 700; padding: 0 8px 7px; border-bottom: 1.5px solid #1a1a1a; text-align: right;
  }
  .print-piezas .pzp-table .pzp-th-name { text-align: left; }
  .print-piezas .pzp-n { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums lining-nums; }

  .print-piezas .pzp-row td { padding: 9px 8px 3px; font-size: 11pt; border-bottom: none; }
  .print-piezas .pzp-row .pzp-name { font-weight: 700; }
  .print-piezas .pzp-row .pzp-cant { font-weight: 700; }
  .print-piezas .pzp-zero { color: #bbb; }

  .print-piezas .pzp-detail td { padding: 0 8px 9px; border-bottom: 1px solid #e2e2e2; }
  .print-piezas .pzp-row--solo td { border-bottom: 1px solid #e2e2e2; padding-bottom: 9px; }
  .print-piezas .pzp-loc { list-style: none; margin: 0; padding: 0; }
  .print-piezas .pzp-loc li { font-size: 9.5pt; color: #444; padding: 1px 0; break-inside: avoid; }
  .print-piezas .pzp-loc-n { font-weight: 600; color: #1a1a1a; }
  .print-piezas .pzp-loc-sep { color: #aaa; margin: 0 6px; }
  .print-piezas .pzp-loc em { font-style: italic; color: #777; }

  /* .pzp-totales es una <tr> más del <tbody> (no un <tfoot>): un <tfoot> se
     repite solo al pie de cada página impresa y el total dejaba de ser el
     total para pasar a "lo que se ve en esta hoja nada más". Ver el
     comentario en piezas-print.js. */
  .print-piezas .pzp-table .pzp-totales td {
    padding: 11px 8px 4px; border-top: 1.5px solid #1a1a1a; font-weight: 800; font-size: 11pt;
  }
  .print-piezas .pzp-table .pzp-totales .pzp-name { text-transform: uppercase; letter-spacing: 1px; font-size: 9.5pt; }
  .print-piezas .pzp-row, .print-piezas .pzp-detail, .print-piezas .pzp-totales { break-inside: avoid; }

  .print-piezas .pzp-empty { text-align: center; padding: 24px; color: #666; font-style: italic; }
  .print-piezas .pzp-note { margin: 15px 0 0; font-size: 8.5pt; font-style: italic; color: #777; }
  .print-piezas .pzp-foot {
    margin-top: 26px; padding-top: 8px; border-top: 1px solid #ccc;
    text-align: center; font-size: 8.5pt; color: #888; letter-spacing: .5px;
  }

  /* ── Reporte municipal (impreso) ─────────────────────────────────────────── */
  /* .rm-totales es una <tr> más del <tbody> (no un <tfoot>): con pocos lotes
     el <tfoot> mandaba el pie de la hoja solo a una segunda página casi en
     blanco. Ver el comentario en reporte-municipal-print.js. */
  .print-boleta .rm-items .rm-totales th,
  .print-boleta .rm-items .rm-totales td { font-weight: 700; background: #f0f0f0; }
  .print-boleta .rm-anulada td { color: #666; text-decoration: line-through; }

  /* ── Etiquetas ────────────────────────────────────────────────────────
     TODAS LAS QUE ENTREN EN LA HOJA. Antes iba una por pagina: 34 articulos
     eran 34 hojas con la etiqueta arriba y el resto en blanco. Textual del
     usuario, con las 34 en la mano: «la idea es que por papel se impriman
     todas las que puedan».

     Rejilla que se adapta al papel que haya: en A4 entran dos columnas, en un
     rollo de 80 mm queda una sola y fluye. No se fija el tamaño de pagina a
     proposito, justamente para que sirva en los dos.

     Cada etiqueta lleva su guia de corte punteada: sin una linea no se puede
     cortar derecho, y son piezas que se pegan una por una. */
  .print-boleta--etiquetas {
    /* El aire va ACA y no en el margen de pagina: el margen reserva una banda
       de la hoja (y encima Chrome dibuja ahi su encabezado). Con el margen en
       cero y el aire adentro, las 34 etiquetas pasaron de 2 paginas a 1. */
    padding: 8mm;
    display: grid;
    /* ANCHO FIJO, no estirado. Con `1fr` cada etiqueta se comia todo el ancho
       sobrante y una que dice «M&C · LOTE 1» quedaba flotando en un rectangulo
       de media hoja: el contenido esta centrado, pero la caja es tan grande que
       se lee torcida. Una etiqueta es una pegatina fisica y tiene su tamaño.
       Con `auto-fill` entran las que entren y el sobrante queda a la derecha. */
    grid-template-columns: repeat(auto-fill, 90mm);
    justify-content: start;
    gap: 3mm;
    align-content: start;
  }
  .print-boleta--etiquetas .print-page {
    box-sizing: border-box;
    width: 100%;
    padding: 3mm;
    text-align: center;
    border: 1px dashed #999;   /* por donde se corta */
    /* Lo unico que se prohibe es que una etiqueta quede partida entre dos
       hojas: media etiqueta no sirve para nada. El salto de pagina lo decide
       el flujo, no una regla por etiqueta. */
    break-inside: avoid;
  }

  .print-boleta--etiquetas .etq-casa {
    font-size: 12pt;
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
  }
  .print-boleta--etiquetas .etq-remate {
    margin-top: 2px;
    font-size: 9.5pt;
    line-height: 1.25;
    color: #000;
  }
  .print-boleta--etiquetas .etq-lote-label {
    margin-top: 8px;
    font-size: 10pt;
    font-weight: 700;
    letter-spacing: 4px;
    text-transform: uppercase;
  }
  .print-boleta--etiquetas .etq-num {
    font-size: 40pt;
    font-weight: 800;
    line-height: 1.05;
    letter-spacing: 1px;
  }
  .print-boleta--etiquetas .etq-serie {
    font-size: 20pt;
    font-weight: 700;
    vertical-align: super;
  }
  .print-boleta--etiquetas .etq-unidad {
    margin-top: 1px;
    font-size: 12pt;
    font-weight: 700;
    letter-spacing: 1px;
  }
  .print-boleta--etiquetas .etq-titulo {
    margin-top: 6px;
    font-size: 11pt;
    font-weight: 600;
    line-height: 1.3;
    word-break: break-word;
  }
  /* De quién es la pieza, con el CÓDIGO de remitente y nunca con el nombre:
     ese dato es confidencial y la etiqueta queda a la vista en el depósito.
     Va al pie y con una línea arriba: lo que se busca de un vistazo es el
     número de remito; el código se lee después, pero tiene que estar. */
  .print-boleta--etiquetas .etq-remitente {
    margin-top: 8px;
    padding-top: 5px;
    border-top: 1px solid #000;
    display: flex;
    align-items: baseline;
    justify-content: center;
    gap: 6px;
  }
  .print-boleta--etiquetas .etq-remitente-cod {
    font-size: 15pt;
    font-weight: 800;
    letter-spacing: 1px;
  }

  /* ── Etiqueta de ARTÍCULO: un solo renglón ──────────────────────────
     Apilada gastaba media cuartilla de rollo por pieza para decir dos cosas,
     el remito y el remitente, y de una pieza salen tantas etiquetas como
     unidades tenga. En un renglón la tira es corta y se lee igual de lejos.
     La de LOTE sigue apilada con el número grande: ahí el número ES la
     etiqueta, y por eso esto vive bajo `.etq--art` y no toca la otra. */
  .print-boleta--etiquetas .etq--art {
    padding: 3mm 3mm;
    text-align: left;
  }
  .print-boleta--etiquetas .etq--art .etq-linea {
    display: flex;
    align-items: baseline;
    justify-content: center;
    gap: 1.3mm;
    /* Sin wrap: si no entra prefiero achicar la fuente y no partir el
       renglón, que es justo lo que se vino a sacar. */
    flex-wrap: nowrap;
    white-space: nowrap;
  }
  /* La casa es contexto, no el dato: en el depósito todo es de la casa. */
  .print-boleta--etiquetas .etq--art .etq-casa {
    font-size: 7.5pt;
    letter-spacing: 0;
  }
  .print-boleta--etiquetas .etq--art .etq-sep {
    font-size: 9pt;
    color: #000;
  }
  .print-boleta--etiquetas .etq--art .etq-lote-label {
    margin-top: 0;
    font-size: 7pt;
    letter-spacing: 1px;
  }
  /* El número de remito es lo que se busca de un vistazo, así que sigue
     siendo lo más grande del renglón. */
  .print-boleta--etiquetas .etq--art .etq-num {
    font-size: 16pt;
    line-height: 1;
    letter-spacing: 0;
  }
  /* El código de remitente es lo MÁS grande del renglón, por encima del
     remito: «el remito está bien que esté, pero lo importante es el
     remitente, el R5. Que esté más grande eso.» (Nacho, 4-set). No se
     achica el remito para lograrlo porque `.etq--art .etq-num` lo comparte
     con el número de LOTE, que es lo que canta el martillero. */
  .print-boleta--etiquetas .etq--art .etq-remitente-cod {
    font-size: 18pt;
    line-height: 1;
  }
  /* El titulo del lote, dentro del mismo renglon: se acorta si no entra, porque
     un nombre largo no puede empujar al numero fuera del papel. */
  .print-boleta--etiquetas .etq--art .etq-titulo {
    margin-top: 0;
    font-size: 8pt;
    font-weight: 600;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .print-boleta--etiquetas .etq--art .etq-serie {
    font-size: 10pt;
  }

  /* ── Estado de cuenta (impreso) ──────────────────────────────────────────── */
  /* El papel que se le entrega al cliente. Reusa .pb-* entero (encabezado,
     logo a var(--logo-h), campos, tablas, pie): acá solo van las tres cosas
     que no existían. */

  /* La tabla de ventas lleva cuatro columnas de plata (martillo, liquidado,
     cobrado, a cobrar) contra la única de la liquidación. A 11pt no entraban
     sin apretar el texto, así que va a 10pt. Solo esta tabla: las de situación
     y stock tienen pocas columnas y se quedan en el tamaño del resto. */
  .print-boleta .ec-ventas th,
  .print-boleta .ec-ventas td { font-size: 10pt; padding: 6px 7px; }
  /* Anchos FIJOS. Sin esto el navegador reparte por contenido y le daba tanto
     al nombre del remate como a los importes, que son los que no pueden
     achicarse: con las cuatro columnas de plata al ancho automático,
     "US$ 46.000,00" se salía de la celda y pisaba el borde. El 38% del concepto
     es lo que sobra, y alcanza porque el texto va apilado en dos renglones. */
  .print-boleta .ec-ventas { table-layout: fixed; }
  .print-boleta .ec-ventas th:first-child,
  .print-boleta .ec-ventas td:first-child { width: 38%; }
  /* Padding más corto SOLO en las celdas de plata: los milímetros que se le
     sacan al aire son los que necesita el importe para no partirse. */
  .print-boleta .ec-ventas .pb-num { padding-left: 5px; padding-right: 5px; }
  /* Las columnas de plata no se parten nunca: "$ 114.196,66" cortado entre el
     signo y el número deja de ser un importe. */
  .print-boleta .ec-ventas .pb-num,
  .print-boleta .ec-situacion .pb-num { white-space: nowrap; }
  /* El neto lleva palabras ("a su favor") y sí necesita poder envolver. */
  .print-boleta .ec-neto { white-space: normal; }

  /* Concepto de la venta: el remate arriba, el lote y el artículo abajo en
     cuerpo menor. Dos renglones por venta en vez de los cuatro o cinco que
     salían cuando fecha, remate y lote peleaban por tres columnas angostas. */
  .print-boleta .ec-concepto { line-height: 1.35; }
  .print-boleta .ec-remate { font-weight: 600; }
  .print-boleta .ec-fecha { white-space: nowrap; }
  .print-boleta .ec-lote { display: block; font-size: 9pt; color: #333; }
  /* La tabla de lo vendido sin liquidar tiene UNA sola columna de plata, así
     que el concepto se puede quedar con casi toda la hoja. */
  .print-boleta .ec-pendientes th:first-child,
  .print-boleta .ec-pendientes td:first-child { width: 76%; }

  /* Fila de totales: es una <tr> más del <tbody>, NUNCA un <tfoot>. Chrome
     repite el <tfoot> al pie de cada hoja, así que en un estado de cuenta de
     varias páginas el total completo aparecería sobre las primeras filas. Es el
     mismo defecto que ya se arregló en el reporte de piezas y en el municipal
     (ver .rm-totales y el comentario de reporte-municipal-print.js). */
  .print-boleta .ec-totales th,
  .print-boleta .ec-totales td { font-weight: 700; background: #f0f0f0; }

  /* Aviso de período sin movimiento: tiene que LEERSE, no ser una nota al pie.
     Es la diferencia entre un papel que dice "no vendiste nada entre estas dos
     fechas" y una hoja con encabezados vacíos que no explica nada. */
  .print-boleta .pb-vacio {
    margin: 4px 0 24px;
    padding: 10px 12px;
    border: 1px solid #000;
    background: #f7f7f7;
    font-size: 11pt;
  }
}

/* ── Historial del cliente — ficha + KPIs 5 columnas ────────────────────────
   Clases NUEVAS (mockup C). Reutiliza todo el sistema .vt-* de Ventas.
   Usar SOLO tokens semánticos — NUNCA hex directo (rompe dark theme).
   ─────────────────────────────────────────────────────────────────────────── */

/* Variante 5 columnas para la tira de KPIs */
.vt-kpis--5 { grid-template-columns: repeat(5, 1fr); }
@media (max-width: 1100px) { .vt-kpis--5 { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 720px)  { .vt-kpis--5 { grid-template-columns: repeat(2, 1fr); } }

/* Ficha del cliente */
.hist-card {
  display: flex;
  align-items: flex-start;
  gap: 18px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: 20px 24px;
  margin-bottom: 20px;
}

/* Avatar circular con iniciales — verde semántico */
.hist-av {
  flex: none;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--green-light);
  border: 2px solid var(--line-strong);
  display: grid;
  place-items: center;
  font-size: 19px;
  font-weight: 700;
  color: var(--green-700);
  font-family: var(--sans);
}
[data-theme="dark"] .hist-av {
  color: var(--green-400);
}

.hist-identity { min-width: 0; }

/* Acción de la ficha ("Escribirle"): empujada al fondo derecho del card, igual
   que .emp-add en el header de la card de abajo. */
.hist-actions { margin-left: auto; flex: none; align-self: center; }

.hist-name {
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--ink);
  line-height: 1.2;
  margin-bottom: 6px;
}

/* Fila de badges + id mono */
.hist-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}

/* Fila de datos de contacto (documento · teléfono · dirección) */
.hist-contact {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  font-size: 12.5px;
  color: var(--ink-4);
}
.hist-contact i {
  font-size: 11px;
  margin-right: 3px;
  opacity: .75;
}
/* Segunda fila: lo que declaró el comprador desde la web (aparte de la
   dirección/ciudad de arriba, que carga el mostrador). Solo separación: el
   badge de al lado (.hist-tag) ya la distingue, no hace falta otro color. */
.hist-contact--declarado {
  margin-top: 6px;
}

/* Badge de rol derivado */
.hist-tag {
  display: inline-flex;
  align-items: center;
  font-size: 11px;
  font-weight: 600;
  padding: 2px 9px;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--ink-3);
  border: 1px solid var(--line-strong);
}

.hist-tag--green {
  background: var(--green-light);
  color: var(--green-ink);
  border-color: color-mix(in srgb, var(--green-500) 35%, transparent);
}
[data-theme="dark"] .hist-tag--green {
  background: color-mix(in srgb, var(--green-600) 18%, transparent);
  color: var(--green-400);
  border-color: color-mix(in srgb, var(--green-400) 30%, transparent);
}

/* Empresas de facturación del cliente (ficha). Reusa .hist-card pero sin su padding
   ni su flex: el header lleva su divisor a sangre y la lista su padding interno. */
.emp-card { display: block; padding: 0; overflow: hidden; }

.emp-head { display: flex; align-items: center; gap: 12px; padding: 14px 18px; border-bottom: 1px solid var(--line); }
.emp-ic { flex: none; width: 30px; height: 30px; border-radius: 8px; display: grid; place-items: center; background: var(--green-light); color: var(--green-700); font-size: 14px; }
[data-theme="dark"] .emp-ic { color: var(--green-400); }
.emp-htext { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.emp-htext .emp-t { font-size: 14px; font-weight: 700; letter-spacing: -.01em; color: var(--ink); }
.emp-htext .emp-s { font-size: 11.5px; color: var(--ink-4); }
.emp-add { margin-left: auto; flex: none; }

.emp-list { list-style: none; margin: 0; padding: 8px; display: flex; flex-direction: column; gap: 6px; }
.emp-list.emp-scroll { max-height: 232px; overflow-y: auto; }
.emp-item { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border: 1px solid transparent; border-radius: 10px; background: var(--surface-2); transition: border-color .15s, background .15s; }
.emp-item:hover { border-color: color-mix(in srgb, var(--green-ink) 40%, transparent); }
.emp-tile { flex: none; width: 38px; height: 38px; border-radius: 9px; display: grid; place-items: center; background: var(--green-light); color: var(--green-700); border: 1px solid color-mix(in srgb, var(--green-ink) 22%, transparent); font-size: 15px; }
[data-theme="dark"] .emp-tile { color: var(--green-400); }
.emp-info { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.emp-name { font-size: 14px; font-weight: 600; letter-spacing: -.01em; color: var(--ink); }
.emp-detail { color: var(--ink-3); font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.emp-detail .emp-rut { color: var(--ink-2); }
.emp-actions { display: flex; gap: 6px; flex: none; }
.btn-emp-act { width: 32px; height: 32px; display: grid; place-items: center; cursor: pointer; border: 1px solid var(--line-strong); background: var(--surface); color: var(--ink-3); border-radius: 8px; font-size: 12.5px; transition: color .15s, border-color .15s, background .15s; }
.btn-emp-act:hover { color: var(--green-ink); border-color: var(--green-ink); background: var(--green-light); }
.btn-emp-act.emp-del:hover { color: #e8896f; border-color: #c0492f; background: color-mix(in srgb, #c0492f 16%, transparent); }

.emp-empty-wrap { padding: 24px 18px 28px; text-align: center; }
.emp-empty-glyph { width: 46px; height: 46px; border-radius: 12px; margin: 0 auto 12px; display: grid; place-items: center; background: var(--green-light); color: var(--green-700); font-size: 20px; opacity: .9; }
[data-theme="dark"] .emp-empty-glyph { color: var(--green-400); }
.emp-empty-title { margin: 0 0 4px; font-size: 13.5px; font-weight: 600; color: var(--ink); }
.emp-empty-sub { font-size: 12.5px; color: var(--ink-3); }

/* ── Publicación web (modal "Web" de remates/lotes): interruptor con explicación ── */
/* ── Menú desplegable de acciones de fila (components/menu.js) ──────────── */
.row-menu {
  position: fixed; z-index: 240; min-width: 190px;
  background: var(--surface-2); border: 1px solid var(--line-strong);
  border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.3); padding: 5px;
}
.row-menu button {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 9px 11px; border: 0; background: none; color: var(--ink-2);
  font: inherit; font-size: 13px; font-weight: 500; border-radius: 7px;
  cursor: pointer; text-align: left; white-space: nowrap;
}
.row-menu button:hover, .row-menu button:focus-visible { background: var(--ctrl-hover); color: var(--ink); outline: none; }
.row-menu button i { width: 16px; text-align: center; font-size: 12px; color: var(--ink-4); }
.row-menu button:hover i, .row-menu button:focus-visible i { color: inherit; }
.row-menu-sep { height: 1px; background: var(--line); margin: 5px 4px; }
.row-menu button.peligro { color: var(--danger); }
.row-menu button.peligro i { color: inherit; }
.row-menu button.peligro:hover, .row-menu button.peligro:focus-visible { background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger); }
.menu-caret { font-size: 9px !important; margin-left: 2px; }

/* ── Publicación web: checklist "camino a la web" del modal ─────────────── */
/* El modal de publicación es más ancho que el de formulario (480px): checklist
   + pestañas respiran mejor. Mismo patrón :has() que saldo/cierre/lote-edit. */
.modal:has(.pubweb-status) { max-width: 640px; }
/* Cinco pestañas en un modal de 720px: con el padding y el cuerpo de letra de
   .vt-seg, "Fecha y lugar" y "Vista previa" se partian en dos renglones y la
   barra quedaba despareja. Se aprieta el aire lateral y se prohibe el corte, no
   se acortan los nombres: la pestaña tiene que decir lo que tiene adentro. */
.pubweb-tabs { display: flex; margin-bottom: 16px; }

/* ── Clientes: las dos pestañas (de la casa / cuentas web) ─────────────────
   El .vt-seg nació para modales, donde el ancho lo pone el diálogo. En una
   pantalla hay que separarlo del encabezado y del contenido a mano, si no
   queda pegado arriba de la barra de búsqueda. */
.cli-tabs { margin: 0 0 18px; }

/* La nota que explica para qué está esa pestaña. Va ARRIBA de la tabla y no
   como tooltip: la acción que pide (vincular) no es obvia mirando la grilla. */
.cli-web-nota {
  margin: 0 0 14px;
  font-size: 13px;
  line-height: 1.45;
  color: var(--ink-3);
  max-width: 68ch;
}
.cli-web-nota b { color: var(--ink-2); }

/* ── Elegir a qué sala entrar (cuando hay más de un remate abierto) ────────
   Filas grandes y clickeables enteras: se entra desde el menú, muchas veces
   con el remate por empezar y sin tiempo de apuntar a un botón chico. */
/* Angosta a propósito: a lo ancho de la pantalla entera, el título quedaba en
   una punta y el estado en la otra con medio metro de aire muerto en el medio. */
.sala-elegir-lista { display: flex; flex-direction: column; gap: 8px; max-width: 720px; }
.sala-elegir-item {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 16px;
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  background: var(--surface);
  text-decoration: none;
  transition: border-color .15s, background .15s;
}
.sala-elegir-item:hover { border-color: var(--green-600); background: var(--surface-2); }
.sala-elegir-nom { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.sala-elegir-nom b { color: var(--ink-1); font-size: 14px; }
.sala-elegir-nom small { color: var(--ink-4); font-size: 12px; font-family: var(--mono); }
.sala-elegir-item > i { color: var(--ink-4); font-size: 12px; }

/* Aviso al pie del martillo: con la sala cerrada el lote sale SOLO por MC TV.
   Va a la vista y no en un title, porque el sintoma es «apreto y no pasa nada»
   y nadie va a buscar la explicacion con el mouse. */
.cs-solo-tv {
  display: flex; align-items: flex-start; gap: 8px;
  margin: 10px 0 0;
  padding: 10px 12px;
  border: 1px solid var(--line-strong);
  border-left: 3px solid var(--st-prog, var(--line-strong));
  border-radius: 8px;
  background: var(--surface-2);
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--ink-3);
}
.cs-solo-tv b { color: var(--ink-1); }
.cs-solo-tv > i { margin-top: 2px; color: var(--ink-4); }

/* «El público no ve nada»: la lista de TODO lo que falta para que el remate
   se vea afuera. Va arriba de todo y a la vista, porque el sintoma es que uno
   opera la sala y no pasa nada, sin ninguna pista de por que. */
.cs-falta {
  display: flex; align-items: flex-start; gap: 12px;
  margin: 0 0 14px;
  padding: 13px 16px;
  border: 1px solid var(--st-prep, var(--line-strong));
  border-left: 4px solid var(--st-prep, var(--line-strong));
  border-radius: 10px;
  background: var(--surface-2);
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-3);
}
.cs-falta > i { margin-top: 2px; color: var(--st-prep, var(--ink-4)); font-size: 15px; }
.cs-falta b { color: var(--ink-1); }
.cs-falta ul { margin: 6px 0 0; padding-left: 18px; }
.cs-falta li { margin: 2px 0; }

/* El cliente ya vinculado: link al historial, porque el que mira esta columna
   quiere ver QUE compro esa persona, no solo que existe. */
.cli-vinculo { color: var(--ink-2); font-weight: 600; text-decoration: none; }
/* «Crear cliente nuevo» en el modal de vincular: la salida para el que oferta
   por la web y todavía no está en la lista de la casa. */
.uw-crear { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 2px 0 0; font-size: 12.5px; color: var(--ink-3); }
.cli-vinculo:hover { text-decoration: underline; }

/* Encabezado del modal de vinculo: los datos de la cuenta, para decidir sin
   tener que volver a la grilla a mirar la cedula. */
.modal-intro {
  margin: 0 0 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-3);
}
.modal-intro b { color: var(--ink-1); }
.pubweb-tabs button { flex: 1; justify-content: center; white-space: nowrap; gap: 6px; padding: 8px 9px; font-size: 12.5px; }
.pubweb-tabs button i { font-size: 12px; }
/* SEIS pestañas en la barra de Publicación (entró «Condiciones»). Con el aire
   de cinco la barra medía 617 px dentro de 580 y los nombres se cortaban. Se
   aprieta el aire lateral, igual que cuando se pasó de cuatro a cinco, y no se
   acortan los nombres: la pestaña tiene que decir lo que tiene adentro.
   Scopeado con :has(.pubweb-status) —el mismo gancho que le da los 640px— para
   no apretar las barras de tres y cuatro de Lotes y Sitio Web, que van holgadas. */
.modal:has(.pubweb-status) .pubweb-tabs button { gap: 5px; padding: 8px 5px; }
/* ── Pestaña «Condiciones» del panel de publicación ────────────────────────
   Acá se redacta el DOCUMENTO LEGAL del remate, no se completa un campo: es lo
   que la casa está obligada a publicar. La pestaña se compone para que se note
   —etiqueta y contador en una línea, el campo ocupando el resto— en vez de
   parecer un textarea más. */
.cond-cab { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
/* El contador es oficio, no adorno: es el único lugar donde se ve cuánto lleva
   escrito el documento. En mono para que no baile de ancho al teclear. */
.cond-cuenta { font-family: var(--mono); font-size: 11px; font-variant-numeric: tabular-nums; color: var(--ink-3); white-space: nowrap; }
.cond-cuenta--vacia { color: var(--ink-3); opacity: .7; font-style: italic; }
/* Se redacta acá adentro: renglones cómodos y ancho de lectura, no de formulario. */
.cond-campo textarea { line-height: 1.55; }
.cond-ayuda {
  margin-top: 14px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: color-mix(in srgb, var(--green-600) 7%, var(--surface));
  padding: 12px 13px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ink-2);
}
.cond-ayuda p { margin: 0; }
.cond-ayuda p + p { margin-top: 4px; }
/* ARRIBA Y ABAJO: el textarea y la hoja armada, las dos visibles A LA VEZ y
   actualizándose mientras se tipea. Reemplaza el conmutador «Escribir | Vista
   previa» (hoja superpuesta al textarea, PR #513): «para ver cómo queda tiene
   que dejar de ver lo que escribe» (el dueño), que probó las tres opciones y
   eligió esta. Alto FIJO en cada caja y scroll propio adentro — nada de
   crecer con el texto, así ni el modal ni la otra caja se mueven al escribir
   (medido escribiendo 2000 caracteres). resize:none en el textarea por lo
   mismo: agrandarlo a mano correría la hoja de abajo. */
.cond-editor { display: flex; flex-direction: column; gap: 10px; }
.cond-editor textarea { display: block; height: 168px; resize: none; overflow-y: auto; }
/* La hoja se ve como la pantalla del sitio (#condTexto en sitio/index.html):
   papel blanco en los DOS temas, con los colores y tipografías del sitio
   escritos a mano, porque los tokens del admin no son los del sitio. Alto FIJO
   y scroll propio: si el texto es largo scrollea adentro, la caja no crece. */
.cond-hoja {
  display: block; height: 190px; overflow-y: auto; overscroll-behavior: contain;
  padding: 16px 22px 18px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: #fff; color: #5a6673;
  font-family: "Segoe UI", "Avenir Next", system-ui, -apple-system, sans-serif; font-size: 14px; line-height: 1.65;
}
/* Espejo de .cond-h/.cond-p/.cond-li/.cond-sep del <style> del sitio, acotado a
   la hoja para no pisar nada del admin. Si cambian allá, cambian acá. */
.cond-hoja .cond-h { margin: 1.5rem 0 .7rem; font-family: ui-monospace, "Cascadia Mono", Consolas, Menlo, monospace; font-size: 10.5px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: #101e33; }
.cond-hoja .cond-h:first-child { margin-top: 0; }
.cond-hoja .cond-h::after { content: ""; display: block; width: 34px; height: 2px; margin-top: .45rem; background: #c79a3b; }
.cond-hoja .cond-p { margin: 0 0 .55rem; }
.cond-hoja .cond-p:last-child { margin-bottom: 0; }
.cond-hoja .cond-li { display: flex; gap: .6rem; margin: 0 0 .45rem; }
.cond-hoja .cond-li:last-child { margin-bottom: 0; }
.cond-hoja .cond-li::before { content: "·"; flex: none; font-weight: 700; color: #8f6b1f; }
.cond-hoja .cond-sep { height: .6rem; }
.cond-hoja-vacia { margin: 0; font-style: italic; color: #5a6673; }

/* ── Sitio Web → Guía ─────────────────────────────────────────────────────
   Una sección a la vez: arriba las tres solapas (los títulos del sitio), y
   el cuerpo en dos columnas de alto FIJO: los cuadros de texto a la
   izquierda (un renglón por punto) y la sección entera como la ve el
   público a la derecha. Cada
   columna scrollea adentro; la página no se mueve (medido a 1347x672). */
.guia-cabeza { gap: 16px; }
.guia-seg { display: inline-flex; gap: 2px; padding: 3px; border: 1px solid var(--line-strong); border-radius: 10px; background: var(--surface-2); }
.guia-seg button { border: 0; background: transparent; color: var(--ink-3); border-radius: 7px; padding: 7px 14px; font-size: 13.5px; font-weight: 600; cursor: pointer; }
.guia-seg button:hover { color: var(--ink); }
.guia-seg button.on { background: var(--green-600); color: #fff; }
.guia-acciones { display: flex; align-items: center; gap: 10px; margin-left: auto; }
.guia-pendiente { font-size: 12.5px; visibility: hidden; }
.guia-pendiente.is-visible { visibility: visible; }
.guia-cuerpo { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); gap: 18px; height: 346px; padding: 12px 20px 16px; box-sizing: border-box; }
.guia-izq { display: flex; flex-direction: column; min-height: 0; }
.guia-ayuda { flex: none; margin: 0 0 8px; font-size: 13px; line-height: 1.45; color: var(--ink-2); }
.guia-campos { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; display: flex; flex-direction: column; gap: 12px; padding-right: 6px; }
/* Una tarjeta blanca por bloque, con la letra del sitio. Los renglones no
   llevan caja: una línea finita abajo, y un fondo suave en el que se escribe.
   Nada de barras de scroll adentro: cada renglón crece con lo que tiene. */
.guia-tarjeta {
  flex: none; padding: 12px 14px 10px; border-radius: var(--radius-sm); background: #fff; color: #101823;
  font-family: "Segoe UI", "Avenir Next", system-ui, -apple-system, sans-serif;
}
.guia-tarjeta h4 { margin: 0 0 6px; font-size: 12.5px; font-weight: 700; color: #101823; }
.guia-tarjeta h4 span { font-weight: 400; color: #5a6673; }
.guia-filas { counter-reset: guia-punto; }
.guia-fila { counter-increment: guia-punto; display: flex; align-items: flex-start; gap: 8px; padding: 2px 0; border-bottom: 1px solid #eef0f3; }
.guia-fila:last-child { border-bottom: 0; }
/* El número dorado de los pasos (01, 02...) y el punto de las viñetas, como
   en el sitio. Se numeran solos al agregar o borrar. */
.guia-marca { flex: none; width: 22px; padding-top: 5px; font-family: ui-monospace, "Cascadia Mono", Consolas, Menlo, monospace; font-size: 13px; font-weight: 700; line-height: 1.5; color: #8f6b1f; }
.guia-tarjeta[data-tipo="pasos"] .guia-marca::before { content: counter(guia-punto, decimal-leading-zero); }
.guia-tarjeta[data-tipo="lista"] .guia-marca::before { content: "\00b7"; }
.guia-fila textarea, .guia-texto {
  flex: 1; display: block; width: 100%; min-width: 0; box-sizing: border-box; margin: 0;
  padding: 4px 6px; border: 0; border-radius: 6px; background: transparent; color: #101823;
  font: inherit; font-size: 14px; line-height: 1.5; resize: none; overflow: hidden;
}
.guia-fila textarea:focus, .guia-texto:focus { outline: none; border: 0; box-shadow: none; background: #f4f6f8; }
.guia-texto::placeholder { color: #7a8591; font-style: italic; }
.guia-borrar { flex: none; margin-top: 3px; width: 24px; height: 24px; border: 0; border-radius: 6px; background: transparent; color: #7a8591; font-size: 16px; line-height: 1; cursor: pointer; visibility: hidden; }
.guia-fila:hover .guia-borrar, .guia-fila:focus-within .guia-borrar { visibility: visible; }
.guia-borrar:hover { background: #fbe9e7; color: #b3261e; }
.guia-agregar { margin: 6px 0 0 24px; padding: 3px 6px; border: 0; border-radius: 6px; background: transparent; color: #2f6b4f; font-size: 13px; font-weight: 600; cursor: pointer; }
.guia-agregar:hover { background: #eef5f0; }
.guia-der { display: flex; flex-direction: column; min-height: 0; }
.guia-der-rotulo { flex: none; margin: 0 0 6px; font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3); }
/* El papel del sitio: su fondo, sin borde oscuro alrededor. */
.guia-previa { flex: 1; min-height: 0; width: 100%; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: #f7f8fa; }
/* var(--ink) y no var(--ink-1): ese token NO existe en la paleta (lo usan tres
   reglas viejas y no pinta nada, se les queda el color heredado). */
.cond-ayuda b { color: var(--ink); }
/* Modal angosto: primero se van los iconos, que son decoración; el nombre no. */
@media (max-width: 600px) {
  .pubweb-tabs button i { display: none; }
}
.pubweb-status { border: 1px solid var(--line); border-radius: 10px; background: var(--surface-2); padding: 12px 13px; margin-bottom: 14px; }
.pubweb-head { display: inline-flex; align-items: center; gap: 7px; font-size: 13px; font-weight: 700; letter-spacing: .01em; }
.pubweb-head--on  { color: var(--st-activo); }
.pubweb-head--mid { color: var(--st-preparando); }
.pubweb-head--off { color: var(--ink-3); }
.pubweb-list { list-style: none; margin: 9px 0 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.pubweb-item { display: flex; align-items: flex-start; gap: 8px; font-size: 12.5px; color: var(--ink-2); }
.pubweb-item b { color: var(--ink); }
.pubweb-dot { flex: none; width: 17px; height: 17px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 9px; margin-top: 1px; }
.pubweb-item--ok    .pubweb-dot { background: var(--green-glow); color: var(--st-activo); }
.pubweb-item--falta .pubweb-dot { background: var(--amber-bg); color: var(--st-preparando); }
.pubweb-item--info  .pubweb-dot { background: var(--surface); border: 1px solid var(--line-strong); color: var(--ink-4); }
.pubweb-item--info  { color: var(--ink-3); }

/* ── Vista previa de la card de cartelera (modal de publicación) ──────────
   Réplica visual del sitio público, que es SIEMPRE claro: colores fijos de su
   paleta (humo/marino/oro/fuego), independientes del tema del admin. */
.pubweb-pv-stage { display: flex; flex-direction: column; align-items: center; padding: 24px 18px; background: #f7f8fa; border: 1px solid var(--line); border-radius: 10px; }
.pubweb-pv-nota { margin: 10px 2px 0; font-size: 12px; color: var(--ink-3); }
/* Renglón de posición bajo la card: ¿sale primera en la cartelera o no? */
.pubweb-pv-pos { margin: 12px 0 0; font-size: 12px; font-weight: 600; color: #5a6673; }
.pubweb-pv-pos--primera { color: #8f6b1f; }
.pubweb-pv-pos i { font-size: .9em; }
.pv-off { margin: 0 0 12px; font-size: 12.5px; font-weight: 600; color: #8f6b1f; background: #fff8e1; border: 1px solid #e8d9a8; border-radius: 8px; padding: 8px 11px; }
.pv-card { width: 100%; max-width: 300px; background: #fff; border: 1px solid #e2e6eb; border-radius: 12px; overflow: hidden; box-shadow: 0 1px 2px rgba(16,24,35,.07); color: #101823; font-family: 'Segoe UI', 'Avenir Next', system-ui, sans-serif; }
.pv-card--oro { border: 2px solid #c79a3b; }
.pv-card--apagada { filter: grayscale(.55); opacity: .75; }
.pv-foto-wrap { position: relative; }
/* La PORTADA del remate, tambien entera. El sitio pinta esta card con
   .card-media (contain sobre la propia foto desenfocada); la preview seguia con
   cover, asi que recortaba una portada que en la web se ve completa: mostraba
   un encuadre que no existe. */
.pv-foto { width: 100%; aspect-ratio: 3 / 2; object-fit: contain; display: block; background: #eff1f4; }
.pv-cuerpo { display: flex; flex-direction: column; gap: 4px; padding: 15px; }
.pv-meta { font-family: var(--mono); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: #5a6673; }
.pv-meta--fuego { color: #b23a12; }
.pv-tit { margin: 0; font-size: 14.5px; font-weight: 700; line-height: 1.35; color: #101823; }
.pv-sub { margin: 0; font-size: 12.5px; color: #5a6673; }
.pv-chips { display: flex; flex-wrap: wrap; gap: 6px; padding-top: 10px; }
.pv-chip { display: inline-block; font-size: 11.5px; font-weight: 700; padding: 6px 10px; border-radius: 8px; }
.pv-chip--marino { background: #101e33; color: #fff; }
.pv-chip--borde { border: 1px solid #cbd2da; color: #101e33; }
.pv-chip--tenue { color: #5a6673; }
.pv-chip--fuego { background: #e04e1f; color: #fff; }
/* Boleta sin comprador: es una TAREA, no un dato que no aplica. Un «—» gris se
   lee como «no corresponde»; esto tiene que leerse como «falta completarlo». */
.vt-sin-comprador { display: inline-flex; align-items: center; gap: 6px; padding: 3px 9px;
                    border-radius: 999px; font-size: 11.5px; font-weight: 600;
                    background: color-mix(in srgb, var(--pend, #d8b878) 14%, transparent);
                    color: var(--pend, #d8b878); white-space: nowrap; }

.pubweb-quitar { margin-top: 8px; align-self: flex-start; }

/* LA MINIATURA DEL FLYER: la que ya está cargada en el remate (portada_url) o,
   apenas se elige un archivo nuevo, ese. La vista previa de la card ya lo
   mostraba, pero esta en otra pestaña: elegias un archivo y no sabias cual
   habias agarrado hasta guardar, o de guardado no veias nada hasta ahí. Al
   lado del campo, con el nombre y el peso (la cargada no tiene peso: ya
   subida, no hay tope que avisar), porque el tope de 5 MB tambien se
   descubria recien al subir. */
.pubweb-portada-pv[hidden] { display: none; }
.pubweb-portada-pv { display: flex; align-items: center; gap: 12px; margin-top: 10px;
                     padding: 9px; border: 1px solid var(--line-strong); border-radius: 10px;
                     background: var(--surface-2); }
.pubweb-portada-pv img { width: 74px; height: 74px; object-fit: cover; border-radius: 8px;
                         border: 1px solid var(--line); flex: none; background: var(--surface-1); }
.pubweb-portada-pv-txt { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.pubweb-portada-pv-txt b { font-size: 12.5px; word-break: break-all; }
.pubweb-portada-pv-txt span { font-family: var(--mono); font-size: 11px; color: var(--ink-4); }
/* El que no entra se dice ACA, en rojo, y no despues de esperar la subida. */
.pubweb-portada-pv-txt .es-error { color: var(--st-error, #e5484d); font-weight: 600; }
/* «Acá debe mostrar... el catálogo» (el dueño): el link al PDF ya cargado,
   con la MISMA URL que usa el sitio público (catalogo_url, armada en el
   backend con PublicMedia::urlCatalogo). Sale en una línea, debajo del campo
   de archivo, y abre en pestaña nueva para no perder el modal. */
.pubweb-catalogo-link { display: inline-flex; align-items: center; gap: 6px; margin-top: 8px; font-size: 12.5px; font-weight: 600; }
/* Card de CATÁLOGO (lote) en la vista previa: mismos colores del sitio. */
/* Espeja la card del catalogo publico: mismo alto y mismo contain. Si la
   preview recortara y el sitio no, la preview estaria mintiendo. */
.pvl-foto { aspect-ratio: auto; height: 176px; object-fit: contain; background: #eff1f4; }
/* Placeholder de portada (mismo alto que la foto): monograma de la casa. */
.pv-ph { width: 100%; height: 144px; display: flex; align-items: center; justify-content: center; background: #eff1f4; color: #9aa5b1; font-family: 'Palatino Linotype', Palatino, Georgia, serif; font-size: 1.5rem; font-weight: 700; letter-spacing: .04em; }
.pvl-fotos-badge { position: absolute; right: 8px; bottom: 8px; background: rgba(16,24,35,.72); color: #fff; font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 6px; }
.pv-meta--oro { color: #8f6b1f; }
/* Card de FOTO DEL SITIO en la vista previa: mismo alto que su grilla real
   (h-40), para que la proporción no mienta. */
.pvp-foto { aspect-ratio: auto; height: 160px; }
/* Card de PROPIEDAD: misma proporción que .prop-card-foto del sitio
   (aspect-ratio 4/3, ancho completo). Antes tenía alto fijo (128px, el h-32
   viejo de la grilla): con una derivada 4:3 eso dejaba la foto DIMINUTA
   (~170px de ancho contra los ~280px de esta card), con gris de sobra a los
   costados. Acá el ancho manda -igual que en el sitio- y el alto lo pone la
   proporción. */
.pvi-foto { aspect-ratio: 4 / 3; height: auto; }
/* Sin foto la propiedad sale con el cartel oscuro del sitio; una foto del
   sitio sin imagen propia cae a una genérica de la casa. Mismo aspect-ratio
   que .pvi-foto: que no salte de alto al elegir la primera foto. */
.pv-ph--prop { aspect-ratio: 4 / 3; height: auto; background: linear-gradient(135deg, #16283f, #0b1626); color: rgba(255,255,255,.6); font-family: var(--mono); font-size: 10px; font-weight: 700; letter-spacing: .2em; text-transform: uppercase; }
.pv-ph--generica { height: 160px; font-family: var(--mono); font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase; text-align: center; padding: 0 12px; }
.pv-sub--num { font-family: var(--mono); font-size: 11.5px; }
.pv-apagada-nota { margin: 10px 0 0; font-size: 12px; color: var(--ink-3); text-align: center; }
/* Miniatura en el listado de galerías de la portada: sin ver la foto, la fila
   es un título suelto y hay que abrir cada una para saber qué es. */
.web-foto-mini { width: 46px; height: 34px; object-fit: cover; border-radius: 6px; border: 1px solid var(--line); display: block; }
.web-foto-mini--vacia { display: grid; place-items: center; background: var(--surface-2); color: var(--ink-4); font-size: 12px; }

/* ── Sitio Web › Portada: el modal del slide ─────────────────────────────
   Las tres pestañas (Textos, Botón y foto, Vista) miden LO MISMO: el modal no
   salta al pasar de una a otra (regla del dueño: nada de saltos de tamaño). Si
   algo no entra, scrollea adentro. */
/* Editor del slide: campos a la izquierda, vista previa fija a la derecha. */
.slide-editor { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); gap: 20px; align-items: start; }
.slide-editor-campos .form-group { margin-bottom: 10px; }
.slide-editor-fila { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.slide-editor-vista { position: sticky; top: 0; }
.slide-editor-vista .pv-slide { height: 300px; }
/* Con logo, el texto le deja lugar arriba, como en el sitio real. */
.pv-slide--logo .pv-slide-cuerpo { padding-top: 76px; }
/* Alto FIJO del editor: el modal no cambia de tamaño según el tipo de slide. */
.slide-editor { height: 405px; }
.slide-editor-campos { max-height: 405px; overflow-y: auto; overscroll-behavior: contain; padding-right: 4px; }
.slide-editor-nota { margin: 8px 2px 0; font-size: 12px; line-height: 1.45; }
.slide-editor-campos label .muted { font-size: 12px; font-weight: 400; }
.slide-editor-vista .form-check { margin-top: 12px; }
@media (max-width: 760px) { .slide-editor { grid-template-columns: 1fr; height: auto; } .slide-editor-campos { max-height: none; } .slide-editor-vista { position: static; } }
/* Réplica del slide del sitio (#carrusel en sitio/index.html), que es SIEMPRE
   oscuro: colores y tipografías del sitio escritos a mano, porque los tokens
   del admin no son los del sitio. Alto fijo, como el carrusel real. */
.pv-slide { position: relative; width: 100%; height: 300px; overflow: hidden; border-radius: 14px; background: #0b1626; color: #fff;
  font-family: "Segoe UI", "Avenir Next", system-ui, -apple-system, sans-serif; }
.pv-slide::after { content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(0deg, #0b1626 0%, rgba(11,22,38,.5) 45%, transparent 100%), linear-gradient(90deg, rgba(4,10,20,.6) 0%, transparent 80%); }
.pv-slide--apagada { filter: grayscale(.55); opacity: .75; }
.pv-slide-foto { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: .4; }
.pv-slide-logo { position: absolute; top: 14px; right: 14px; z-index: 2; height: 52px; width: auto; padding: 6px 10px; border-radius: 9px; background: rgba(247,247,247,.97); }
.pv-slide-cuerpo { position: relative; z-index: 2; height: 100%; box-sizing: border-box; display: flex; flex-direction: column; align-items: flex-start; gap: 8px; padding: 18px 20px; }
.pv-slide-etiqueta { margin-top: auto; max-width: 100%; border: 1px solid rgba(255,255,255,.3); border-radius: 999px; background: rgba(16,30,51,.7); padding: 3px 10px;
  font-family: ui-monospace, "Cascadia Mono", Consolas, Menlo, monospace; font-size: 9.5px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: rgba(255,255,255,.85); }
.pv-slide-etiqueta--oro { border-color: rgba(217,174,82,.6); color: #d9ae52; }
.pv-slide-titulo { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden; max-width: 30rem;
  font-family: "Palatino Linotype", Palatino, Georgia, serif; font-size: 24px; line-height: 1.15; }
/* Sin etiqueta, el título es el que empuja todo hacia abajo. */
.pv-slide-cuerpo > .pv-slide-titulo:first-child { margin-top: auto; }
.pv-slide-texto { margin: 0; max-width: 28rem; font-size: 12px; line-height: 1.4; color: rgba(255,255,255,.8);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; }
.pv-slide-boton { border-radius: 8px; background: #fff; color: #0b1626; padding: 7px 14px; font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; }
.pv-slide-franja { display: inline-flex; align-items: center; gap: 8px; border: 1px solid rgba(255,255,255,.14); border-radius: 10px; background: rgba(6,13,26,.5);
  padding: 5px 10px; font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; }
.pv-slide-franja img { height: 26px; width: auto; }
.pv-slide-franja i { width: 1px; height: 22px; background: rgba(255,255,255,.28); }
.pvl-est { margin: 0; padding-top: 6px; font-family: var(--mono); font-size: 13px; font-weight: 700; color: #101e33; }
.pvl-ultima { margin: 0; font-family: var(--mono); font-size: 12.5px; font-weight: 700; color: #e04e1f; }
.pvl-ofertar { flex: 1; text-align: center; }

.web-switch { display: flex; align-items: flex-start; gap: 10px; padding: 11px 13px; border: 1px solid var(--line); border-radius: 10px; background: var(--surface-2); cursor: pointer; margin-bottom: 12px; }
/* Sin esto el atributo `hidden` no hace nada acá: `display:flex` de esta misma
   regla es CSS de autor y le gana al `display:none` de la hoja del navegador,
   así que un `.web-switch` con `hidden` quedaba visible igual (afectaba a
   "Recibe pre-ofertas"/"Recibe pujas en vivo" al elegir venta online, y a
   "Puja automática" al lado de la extensión). Mismo patrón que ya usan otras
   clases de este archivo, ej. `.pubweb-portada-pv[hidden]`. */
.web-switch[hidden] { display: none; }
.web-switch input { margin-top: 3px; accent-color: var(--green-600); width: 16px; height: 16px; flex: none; cursor: pointer; }
.web-switch span { display: flex; flex-direction: column; gap: 1px; }
.web-switch b { font-size: 13.5px; font-weight: 600; color: var(--ink); }
.web-switch small { font-size: 12px; color: var(--ink-3); }
.web-intro { margin: -6px 0 14px; font-size: 13px; }
.web-intro b { color: var(--ink-2); }

/* ── Historial: sección Piezas (estado de cada pieza consignada, por unidad) ──
   Reusa la fórmula visual de .badge (color-mix sobre un token --c) para el chip
   de conteo por estado. Cada estado tiene su color semántico. */
.pz-badge {
  --c: var(--st-listo);
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px; border-radius: var(--radius-sm);
  font-size: 12px; font-weight: 600; letter-spacing: -.005em; white-space: nowrap;
  color: color-mix(in srgb, var(--c) 82%, var(--ink));
  background: color-mix(in srgb, var(--c) 13%, var(--surface));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c) 35%, transparent);
}
[data-theme="dark"] .pz-badge { color: var(--c); background: color-mix(in srgb, var(--c) 16%, transparent); }
.pz-badge i { font-size: .82em; opacity: .9; }
.pz-badge--stock { --c: var(--st-listo); }       /* verde: disponible en depósito */
.pz-badge--lote  { --c: var(--st-programado); }   /* azul: comprometida a un lote */
.pz-badge--vend  { --c: var(--st-preparando); }   /* ámbar: vendida, sin liquidar */
.pz-badge--liq   { --c: var(--green-600); }       /* verde fuerte: vendida y liquidada */
.pz-badge--dev   { --c: var(--ink-3); }           /* muted: devuelta (ya vuelta a "en stock") */
.pz-badge--ret   { --c: var(--st-cerrado); }      /* slate: retirada por el cliente */
/* "devuelta" no es un bucket propio (vive dentro de en stock): se aclara en la traza. */
.pz-nota { font-size: 11px; font-style: italic; color: var(--ink-4); }

/* Fila compacta: una línea por pieza, alineada al medio. */
.hist-pz-table td { vertical-align: middle; }
.pz-pieza { min-width: 160px; }
.pz-nom { font-weight: 600; color: var(--ink); }
.pz-qty { color: var(--ink-3); font-size: 12px; margin-left: 2px; }
/* Resumen de estados en UNA línea: texto chico con un punto de color por estado. */
.pz-estado-min { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 16px; }
.pz-st { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 500; color: var(--ink); white-space: nowrap; }
.pz-st::before { content: ''; width: 7px; height: 7px; border-radius: 50%; background: var(--c); flex: none; }
.pz-st--stock { --c: var(--st-listo); }
.pz-st--lote  { --c: var(--st-programado); }
.pz-st--vend  { --c: var(--st-preparando); }
.pz-st--liq   { --c: var(--green-600); }
.pz-st--ret   { --c: var(--st-cerrado); }
/* Imprimir por fila: la celda de acciones es clickeable y muestra el ícono como
   PSEUDO-elemento (::after con un SVG de fondo). Cualquier ELEMENTO real (<button>
   o <i>) dentro de una fila de esta tabla promovía una capa GPU que rompía el
   repintado del hover (dejaba un agujero oscuro sobre la columna "Estado"); un
   pseudo no es un elemento del DOM y lo evita. La celda entera es el target del clic. */
.pz-print-cell { cursor: pointer; text-align: right; }
.pz-print-cell::after {
  content: ""; display: inline-block; width: 15px; height: 15px; vertical-align: middle;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='%23789184' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 6 2 18 2 18 9'/%3E%3Cpath d='M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2'/%3E%3Crect x='6' y='14' width='12' height='8'/%3E%3C/svg%3E") center/contain no-repeat;
  opacity: .5; transition: opacity .15s ease;
}
.hist-pz-table tbody tr:hover .pz-print-cell::after { opacity: 1; }

/* ── Historial: toolbar de filtros (buscador de texto + combobox de remate) ── */
/* Toolbar de ancho completo DEBAJO del título, alineada a la IZQUIERDA — igual que
   el .toolbar del resto de la app (no encajada a la derecha del head). */
.hist-filtros { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 13px 20px; border-bottom: 1px solid var(--line); }
/* Search local del head — replica el look de .toolbar .search (lupa + halo dorado al focus). */
.hist-filtros > .search {
  flex: 1 1 180px; max-width: 240px; height: 36px; padding: 0 12px 0 36px;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  font: inherit; font-size: 13px; background: var(--surface-2); color: var(--ink);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='%23789184' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.2-3.2'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: 12px 50%; background-size: 14px;
  transition: border-color .18s ease, box-shadow .18s ease, background-color .18s ease;
}
.hist-filtros > .search::placeholder { color: var(--ink-4); }
.hist-filtros > .search:focus {
  outline: none;
  border-color: color-mix(in srgb, var(--gold) 55%, transparent);
  box-shadow: 0 0 0 3px var(--gold-glow);
}
/* Combobox buscable de remate — reusa .vt-combo / .vt-combo-list (ya en app.css).
   El input es un combobox (sin lupa); look alineado al search de texto. */
.hist-combo { flex: 1 1 180px; max-width: 240px; }
.hist-combo[hidden] { display: none; }
.hist-combo .search {
  width: 100%; height: 36px; padding: 0 12px; font: inherit; font-size: 13px;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--ink);
  transition: border-color .18s ease, box-shadow .18s ease;
}
.hist-combo .search::placeholder { color: var(--ink-4); }
.hist-combo .search:focus { outline: none; border-color: var(--green-400); box-shadow: var(--ring); }
.hist-combo .vt-combo-list .combo-todos { color: var(--ink-3); font-style: italic; }

/* ── Historial: footer de paginación (reusa .vt-panel-foot) ── */
.hist-pager { flex-wrap: wrap; gap: 10px; }
.hist-pager-info { font-size: 12.5px; color: var(--ink-4); font-variant-numeric: tabular-nums; }
.hist-pager-btns { display: flex; align-items: center; gap: 8px; }
.hist-pager-btns .btn i { font-size: 11px; opacity: .85; }
.hist-pager-btns .btn:disabled { opacity: .45; cursor: default; }

/* ── Historial: banner de 2 saldos (Comprador · Vendedor) ── */
.vt-kpis--2 { grid-template-columns: repeat(2, 1fr); }
.hist-banner { margin-bottom: 16px; }
@media (max-width: 560px) { .vt-kpis--2 { grid-template-columns: 1fr; } }

/* Subhead "Recibos" dentro de un sub-panel (alineado al padding de las tablas). */
.hist-subhead--pad { padding: 0 20px; }

/* Utilidades (clases en vez de style inline — la CSP bloquea estilos inline). */
.vt-money--gold { color: var(--gold); }
.hist-cid { font-size: 11px; color: var(--ink-4); }

/* Botón alineado a la derecha dentro de una barra .hist-filtros (ej. "Ver recibos"). */
.hist-filtros-right { margin-left: auto; }

/* Modal "Ver recibos": contenido a sangre completa (como un panel) — barra de
   filtros arriba, tabla al medio y pie de paginación abajo. La tabla tiene ALTO
   FIJO para 6 filas (thead 38px + 6×61px ≈ 404, +buffer) → el modal no crece ni
   salta entre páginas; las páginas incompletas dejan espacio, no achican. */
.hist-recibos-modal { margin: -24px; }
.hist-recibos-modal .table-wrap { border: none; border-radius: 0; box-shadow: none; height: 408px; overflow-y: auto; }

/* ── Saldo por sección: cabecera de cada panel de rol (Comprador/Vendedor) ──
   El valem es el número protagonista del rol. El de comprador es clickeable
   (toggle de deuda) cuando hay saldo pendiente. */
.hist-saldo-head {
  display: flex; align-items: center; gap: 14px;
  padding: 16px 20px; background: var(--surface-2); border-bottom: 1px solid var(--line);
}
.hist-saldo-ico {
  width: 34px; height: 34px; border-radius: var(--radius-sm); flex: none;
  display: grid; place-items: center;
  background: var(--surface); border: 1px solid var(--line); color: var(--green-ink); font-size: 14px;
}
.hist-saldo-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.hist-saldo-label { font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); font-weight: 600; }
.hist-saldo-meta { font-size: 12px; color: var(--ink-4); }
.hist-saldo-meta i { margin-right: 4px; color: var(--gold); font-size: 10px; }
.hist-saldo-val {
  margin-left: auto; font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 24px; font-weight: 600; letter-spacing: -.02em; color: var(--ink); line-height: 1;
}
.hist-saldo-val small { font-size: 14px; color: var(--ink-4); font-weight: 500; }
.hist-saldo-head--amber .hist-saldo-ico { color: var(--gold); }
.hist-saldo-head--amber .hist-saldo-val { color: var(--gold); }
.hist-saldo-head--clickable { cursor: pointer; transition: background-color .16s ease, box-shadow .16s ease; }
.hist-saldo-head--clickable:hover { background: var(--surface); }
.hist-saldo-head--clickable:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--gold); }
.hist-saldo-head--clickable.is-on { background: var(--gold-glow); box-shadow: inset 0 0 0 2px var(--gold); }
.hist-saldo-head--clickable.is-on .hist-saldo-meta { color: var(--gold); font-weight: 600; }

/* ── Jerarquía de navegación ──
   PRIMARIO: toggle de rol (#hist-seg) = pastilla verde rellena, algo más grande.
   SECUNDARIO: sub-tabs (.vt-subseg) = tabs SUBRAYADAS, más livianas y subordinadas.
   Dos niveles con tratamientos distintos → el ojo distingue rol vs. vista. */
#hist-seg button { padding: 10px 20px; font-size: 14px; }
#hist-seg button i { font-size: 14px; }

.vt-seg.vt-subseg {
  background: transparent; border: none; box-shadow: none;
  border-radius: 0; padding: 0; gap: 2px;
}
/* Glider del sub-seg = subrayado DESLIZANTE (misma animación de change que el tab
   principal). Lo posiciona el mismo wireSubSegmented (offsetLeft-4 alinea igual). */
.vt-seg.vt-subseg .vt-glider {
  display: block; top: auto; bottom: -1px; height: 2px; border-radius: 999px;
  background: var(--rc, var(--green-600)); box-shadow: none;
}
.vt-seg.vt-subseg button {
  border-radius: 0; padding: 13px 16px; font-size: 13px; font-weight: 600;
  color: var(--ink-3); border-bottom: 2px solid transparent; margin-bottom: -1px;
  transition: color .16s ease, border-color .16s ease;
}
.vt-seg.vt-subseg button:hover { color: var(--ink-2); }
.vt-seg.vt-subseg button.on {
  color: var(--green-ink); background: transparent; border-bottom-color: transparent;
}
.vt-seg.vt-subseg button.on .seg-count {
  background: var(--surface-2); color: var(--green-ink); border-color: var(--line);
}

/* ── Historial: "Cierre" agrupado por remate, como TABLA ──
   Cada remate es un <tbody.hist-cierre-remate>: una fila-remate con los totales de
   su liquidación + una fila-detalle desplegable con la tabla de sus lotes. */
.hist-cierre { padding: 16px 20px; }
.hist-cierre-table { width: 100%; }
.hist-cierre-remate.is-hidden { display: none; }
/* Fila-remate: clickeable. HOVER PROLIJO: solo la fila-remate resalta (con un filo de
   acento por rol); la fila-detalle y la sub-tabla NO reaccionan → evita el hover
   repetido/anidado que heredaba de .data-table. Especificidad > la base para ganarle. */
.hist-cierre-row { cursor: pointer; }
.hist-cierre-table tbody tr.hist-cierre-row:hover > td { background: var(--surface-2); color: var(--ink); }
.hist-cierre-table tbody tr.hist-cierre-row:hover > td:first-child { box-shadow: inset 3px 0 0 var(--rc, var(--gold)); }
/* Hover de la fila-detalle: NO cascadear a las celdas anidadas. La sub-tabla de lotes
   son <td> descendientes del <tr> detalle, así que al hoverear el detalle el hover base
   pegaba a TODAS (por eso "a veces siguen apareciendo" los filos dorados). Reset a TODO
   <td> dentro del detalle en hover (no sólo los directos). */
.hist-cierre-table tbody tr.hist-cierre-detrow:hover td { background: transparent; color: inherit; box-shadow: none; }
.hist-cierre-caret-cell { width: 30px; }
.hist-cierre-caret { color: var(--ink-4); display: inline-flex; transition: transform var(--transition); }
.hist-cierre-remate:not(.is-collapsed) .hist-cierre-caret { transform: rotate(90deg); }
.hist-cierre-nom { font-weight: 700; color: var(--ink); }
.hist-cierre-fecha { font-family: var(--mono); font-size: 11.5px; color: var(--ink-4); }
.hist-cierre-num { font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--ink); }
.hist-cierre-com { color: var(--ink-3); }
.hist-cierre-pay { color: var(--green-ink); font-weight: 700; }
.hist-cierre-actions-cell { width: 132px; }
.hist-cierre-pend { color: var(--ink-4); font-style: italic; }
/* Fila-detalle: sub-tabla de lotes con ANIMACIÓN de abrir/cerrar (grid 0fr↔1fr). El td
   queda transparente; el fondo/borde/padding viven en la parte que colapsa (.hcd-inner). */
.hist-cierre-table .hist-cierre-detrow > td { padding: 0; background: transparent; border: 0; }
.hcd-anim { display: grid; grid-template-rows: 1fr; transition: grid-template-rows .28s var(--smooth, ease); }
.hist-cierre-remate.is-collapsed .hcd-anim { grid-template-rows: 0fr; }
.hcd-inner { overflow: hidden; }
.hist-cierre-detwrap { padding: 8px 16px 14px 40px; background: var(--surface-2); border-top: 1px solid var(--line-strong); }
.hist-cierre-detwrap .table-wrap { border: 1px solid var(--line); border-radius: var(--radius-sm); box-shadow: none; }
@media (min-width: 769px) {
  .hist-cierre-detwrap .hist-table th:last-child,
  .hist-cierre-detwrap .hist-table td:last-child { width: 130px; }
}
@media (prefers-reduced-motion: reduce) { .hcd-anim { transition: none; } }

/* ── Configuración (impuestos + permisos del operador) ─────────────────────── */
.cfg-panel { padding: 0 0 4px; }

/* Impuestos: etiqueta + campo + botón en UN renglón. El valor se toca una vez
   por década y la pantalla real del operador es 1347×672: no se le regala alto
   a un solo número. Grid y no flex a propósito: en flex el input se estira o se
   aplasta según el ancho del panel, y esta caja tiene que medir siempre lo mismo. */
.cfg-iva {
  display: grid; grid-template-columns: auto auto auto 1fr; align-items: center;
  gap: 12px; padding: 2px 16px 14px;
}
.cfg-iva-label { font-size: 12.5px; font-weight: 700; color: var(--ink-2); }
/* El sufijo "%" va DENTRO de la caja: sin él, un 22 suelto se lee como pesos. */
.cfg-iva-caja {
  display: inline-flex; align-items: center; gap: 4px; width: 128px;
  padding: 0 11px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface); transition: border-color .15s, box-shadow .15s;
}
.cfg-iva-caja:focus-within { border-color: var(--green-600); box-shadow: 0 0 0 3px rgba(22, 101, 52, .12); }
.cfg-iva-caja input {
  width: 100%; min-width: 0; border: 0; outline: 0; background: transparent;
  padding: 10px 0; font-size: 15px; font-weight: 600; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.cfg-iva-sufijo { color: var(--ink-3); font-size: 14px; font-weight: 600; flex: none; }
@media (max-width: 560px) {
  .cfg-iva { grid-template-columns: auto 1fr; }
  .cfg-iva [data-act="guardar-iva"] { grid-column: 1 / -1; }
}
.cfg-hint { padding: 0 16px; margin: 4px 0 10px; }
/* Dos columnas: checkboxes | preview del sidebar. Colapsa a 1 en pantallas chicas. */
.cfg-grid { display: grid; grid-template-columns: 1fr minmax(220px, 300px); gap: 18px; padding: 4px 16px 16px; align-items: start; }
@media (max-width: 720px) { .cfg-grid { grid-template-columns: 1fr; } }
.cfg-col { min-width: 0; }

.cfg-list { list-style: none; margin: 0 0 8px; padding: 0; display: grid; gap: 6px; }
.cfg-item { margin: 0; }
.cfg-toggle {
  display: flex; align-items: center; gap: 10px; cursor: pointer;
  padding: 11px 13px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface); transition: border-color .15s, background .15s;
}
.cfg-toggle:hover { border-color: var(--green-600); }
.cfg-toggle input { width: 17px; height: 17px; accent-color: var(--green-600); cursor: pointer; flex: none; }
.cfg-item-ico { color: var(--ink-3); width: 18px; text-align: center; }
.cfg-item-label { font-weight: 600; color: var(--ink); }
.cfg-panel .form-actions { padding: 0; margin: 0; }

/* Preview: mini-sidebar que espeja el menú del operador (verde oscuro como el real). */
.cfg-preview { border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden; background: var(--surface); }
.cfg-preview-head { padding: 9px 12px; font-size: 12px; font-weight: 700; color: var(--ink-2); background: var(--surface-2, var(--surface)); border-bottom: 1px solid var(--line); display: flex; align-items: center; gap: 7px; }
.cfg-preview-sidebar { background: var(--green-800); padding: 10px 8px; min-height: 90px; }
.cfg-preview-group { color: var(--gold); font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; padding: 8px 10px 4px; opacity: .85; }
.cfg-preview-item { display: flex; align-items: center; gap: 9px; padding: 8px 10px; border-radius: 8px; color: rgba(255,255,255,.9); font-size: 13px; font-weight: 500; }
.cfg-preview-item i { width: 16px; text-align: center; color: var(--gold); opacity: .9; }
.cfg-preview-empty { color: var(--ink-3); font-size: 12.5px; padding: 14px 10px; margin: 0; display: flex; align-items: center; gap: 8px; }
.cfg-preview-foot { color: var(--ink-3); font-size: 11.5px; padding: 8px 12px 10px; margin: 0; border-top: 1px solid var(--line); }

/* ── Resumen contable por remate (modal) ───────────────────────────────────── */
.rc-table {
  width: 100%;
  border-collapse: collapse;
  margin: 6px 0 4px;
}
.rc-table th,
.rc-table td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--line);
  text-align: left;
}
.rc-table th { font-weight: 500; color: var(--text-soft); }
.rc-table td { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.rc-table tr:last-child th,
.rc-table tr:last-child td { border-bottom: 0; }
.rc-table .rc-fuerte th,
.rc-table .rc-fuerte td { font-weight: 700; color: var(--text); font-size: 1.05em; }
.rc-nota { margin-top: 8px; }

/* ── Reporte municipal (modal) ─────────────────────────────────────────────── */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.rm-table {
  width: 100%;
  border-collapse: collapse;
  margin: 6px 0 4px;
  font-size: .95em;
}
.rm-table th,
.rm-table td { padding: 8px 10px; border-bottom: 1px solid var(--line); text-align: left; white-space: nowrap; }
.rm-table thead th { color: var(--text-soft); font-weight: 600; }
.rm-num { text-align: right; font-variant-numeric: tabular-nums; }
.rm-table td.rm-num { text-align: right; }
.rm-table tfoot th,
.rm-table tfoot td { border-top: 2px solid var(--line-strong, var(--line)); border-bottom: 0; font-weight: 700; padding-top: 10px; }
.rm-table .rm-anulada td { color: var(--muted); text-decoration: line-through; text-decoration-color: color-mix(in srgb, var(--muted) 55%, transparent); }
.rm-table .rm-anulada td .badge { text-decoration: none; }

/* ============================================================================
   CONSOLA DE SALA (views/sala.js) - el remate en vivo.
   Pensada para operar de pie y sin mouse: numeros grandes, contraste alto y
   el boton del martillo imposible de errar.
   ============================================================================ */
/* La consola ocupa la pantalla: un solo scroll por panel, nunca la pagina
   entera. Asi el monto, los pasos y el boton VENDIDO estan SIEMPRE a la vista
   mientras la lista de 183 lotes scrollea sola. */
.sala-page { padding: 0; border: 0; background: transparent; box-shadow: none; }
.consola {
  border: 1px solid var(--line); border-radius: 14px; background: var(--surface);
  overflow: hidden; display: flex; flex-direction: column;
  height: calc(100dvh - 120px);
}

.cs-top { display: flex; align-items: center; gap: 16px; padding: 13px 18px; border-bottom: 1px solid var(--line); background: var(--surface-2); flex-wrap: wrap; }
.cs-vivo { display: inline-flex; align-items: center; gap: 7px; font-size: 12px; font-weight: 700; padding: 4px 11px; border-radius: 99px; background: color-mix(in srgb, var(--st-activo) 18%, transparent); color: var(--st-activo); }
.cs-vivo .dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; animation: cs-latido 1.4s infinite; }
.cs-vivo--off { background: var(--surface); color: var(--ink-4); border: 1px solid var(--line-strong); }
.cs-vivo--off .dot { animation: none; }
@keyframes cs-latido { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
.cs-top h3 { margin: 0; font-size: 14.5px; }
.cs-pos { font-family: var(--mono); font-size: 12.5px; color: var(--ink-3); }
.cs-metricas { margin-left: auto; display: flex; gap: 20px; }
.cs-met b { display: block; font-family: var(--mono); font-size: 15px; font-weight: 600; }
.cs-met span { font-size: 11px; color: var(--ink-4); }
.cs-met--ok b { color: var(--st-activo); }

.cs-cuerpo { display: grid; grid-template-columns: 340px 1fr; flex: 1; min-height: 0; }
.cs-lista { border-right: 1px solid var(--line); display: flex; flex-direction: column; min-height: 0; }
.cs-buscar { padding: 10px; border-bottom: 1px solid var(--line); display: flex; flex-direction: column; gap: 9px; flex: none; }
.cs-buscar-campo { position: relative; }
.cs-buscar-campo i { position: absolute; left: 11px; top: 50%; transform: translateY(-50%); font-size: 12px; color: var(--ink-4); pointer-events: none; }
.cs-buscar-campo input {
  width: 100%; box-sizing: border-box; height: 38px; padding: 0 12px 0 32px;
  border: 1px solid var(--line-strong); border-radius: 10px;
  background: var(--surface-2); color: var(--ink); font: inherit; font-size: 13px;
}
.cs-buscar-campo input::placeholder { color: var(--ink-4); }
.cs-buscar-campo input:focus { outline: none; border-color: var(--green-400); box-shadow: 0 0 0 3px var(--green-glow); }
.cs-filtros { display: flex; flex-wrap: wrap; gap: 5px; }
.cs-chip {
  border: 1px solid var(--line-strong); background: var(--surface-2); color: var(--ink-3);
  border-radius: 99px; padding: 4px 10px; font-size: 11.5px; font-weight: 600;
  cursor: pointer; font-family: var(--sans); display: inline-flex; align-items: center; gap: 5px;
}
.cs-chip b { font-family: var(--mono); font-size: 11px; color: var(--ink-4); }
.cs-chip:hover { border-color: var(--green-400); color: var(--ink-2); }
.cs-chip.on { border-color: var(--green-400); background: var(--green-glow); color: var(--st-activo); }
.cs-chip.on b { color: var(--st-activo); }
.cs-vacio { padding: 20px 14px; font-size: 12.5px; color: var(--ink-4); text-align: center; }
.cs-sinbase { color: var(--st-preparando); }
/* El mínimo interno lleva candado: el operador lo ve, pero no se canta. */
.cs-minimo { color: var(--ink-3); white-space: nowrap; }
.cs-minimo i { font-size: .85em; margin-right: 1px; }
/* "en pantalla" es lo que el público está viendo en ese instante: va con el
   mismo verde del cartel EN VIVO, para que se lea como estado al aire y no
   como un subtítulo más. */
.cs-enpantalla { color: var(--st-activo); font-weight: 700; }
/* padding-right: donde la barra de scroll se dibuja ENCIMA del contenido (mac,
   táctil, Windows con barras finas) tapaba el monto de cada lote, que es
   justo lo que se mira de reojo mientras se canta. */
/* ── Ficha de propiedad (modal) ──────────────────────────────────────────────
   Todo a la vista y sin pestanas: los datos a la izquierda y, a la derecha, las
   fotos y como queda la card en el sitio.

   El ALTO lo fija el modal, no el contenido: `height` en vez del `max-height`
   elastico de .modal, el cuerpo con overflow hidden y el scroll adentro de cada
   columna. Asi nada de lo que se cargue (una descripcion larga, nueve fotos,
   prender "Destacada") lo hace saltar.

   Este bloque tiene que quedar DESPUES de `.modal:has(.pubweb-status)`: misma
   especificidad, gana el ultimo. */
.modal:has(.propm) { max-width: min(96vw, 1040px); height: min(88vh, 700px); max-height: none; }
.modal:has(.propm) .modal-body { padding: 18px 20px; overflow: hidden; }
.propm { height: 100%; display: grid; grid-template-rows: auto 1fr auto; min-height: 0; }
.propm-estado { margin-bottom: 14px; }
.propm-cols { display: grid; gap: 18px; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); min-height: 0; }
/* Cada columna scrollea por su cuenta; la caja del modal nunca. */
.propm-form, .propm-lado { overflow-y: auto; min-height: 0; padding-right: 6px; scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent; }
.propm-form::-webkit-scrollbar, .propm-lado::-webkit-scrollbar { width: 8px; }
.propm-form::-webkit-scrollbar-thumb, .propm-lado::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 99px; }
.propm-bloque { border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface-2); padding: 15px 17px; margin-bottom: 14px; }
.propm-bloque:last-child { margin-bottom: 0; }
.propm-bloque legend, .propm-h { font-family: var(--sans); font-size: 13px; font-weight: 700; letter-spacing: .02em; color: var(--ink); padding: 0 4px; }
.propm-h { margin: 0 0 4px; }
.propm-ayuda { font-size: 12px; color: var(--ink-3); margin-bottom: 12px; }
.propm-nota { margin-top: 10px; font-size: 11.5px; color: var(--ink-3); }
.propm-fila { display: grid; gap: 12px; grid-template-columns: 1fr 1fr; }
.propm-fila--3 { grid-template-columns: repeat(3, 1fr); }
/* El pie del modal es sticky con margenes negativos calibrados contra el
   padding 24px de .modal-body; aca el padding es otro, asi que se recalibra. */
.modal .propm .form-actions { position: static; margin: 14px -20px -18px; padding: 13px 20px; }
/* En pantalla angosta las dos columnas se apilan y scrollea la caja de las dos.
   `display: block` y no un grid de una columna: con el alto ya fijado por
   arriba, las filas `auto` del grid se reparten el espacio en partes iguales y
   recortan el formulario a la mitad. */
@media (max-width: 900px) {
  .propm-cols { display: block; overflow-y: auto; }
  .propm-form, .propm-lado { overflow: visible; padding-right: 0; }
  .propm-lado { margin-top: 14px; }
  .propm-fila, .propm-fila--3 { grid-template-columns: 1fr; }
}
/* Videos de YouTube de la propiedad. Cada fila mide SIEMPRE lo mismo (alto
   fijo) y el renglón del error está reservado aunque esté vacío: agregar,
   marcar vertical o equivocarse de link no mueve nada de lugar. */
.propm-video-alta.form-group { display: flex; flex-direction: row; align-items: stretch; gap: 8px; margin: 0; }
.propm-video-alta input { flex: 1; min-width: 0; width: auto; }
.propm-video-alta .btn { height: auto; flex: none; }
.propm-video-error { height: 32px; margin: 4px 0 6px; font-size: 11.5px; line-height: 16px; color: var(--danger, #b42318); overflow: hidden; }
.propm-videos { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.propm-videos-vacio { height: 40px; display: flex; align-items: center; font-size: 12px; color: var(--ink-3); }
.propm-video { height: 84px; box-sizing: border-box; display: grid; grid-template-columns: 76px minmax(0, 1fr); grid-template-rows: auto auto; column-gap: 10px; row-gap: 6px; align-items: center; padding: 8px 10px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); }
.propm-video-mini { grid-row: 1 / 3; width: 76px; height: 43px; justify-self: center; display: flex; align-items: center; justify-content: center; border-radius: 6px; background: #1d1d1f; color: #fff; font-size: 16px; }
.propm-video-mini--vertical { width: 38px; height: 66px; }
.propm-video-mini { overflow: hidden; }
.propm-video-mini img { width: 100%; height: 100%; object-fit: cover; display: block; }
.propm-video-info { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.propm-video-info b { font-size: 12.5px; }
.propm-video-info small { font-size: 11.5px; color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.propm-video-acc { display: flex; gap: 6px; align-items: center; flex-wrap: nowrap; }
.propm-video-acc .btn-sm { height: 26px; padding: 0 8px; font-size: 11.5px; white-space: nowrap; }
.propm-video-vert { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; margin-right: auto; white-space: nowrap; cursor: pointer; }
/* Arrastre de fotos (mismo grid que el lote). */
.lg-tile[draggable="true"] { cursor: grab; }
.lg-arrastrando { opacity: .45; }
.lg-destino { outline: 2px dashed var(--green-400); outline-offset: 2px; }

/* ── Ordenar una tabla arrastrando las filas ─────────────────────────────────
   Mismo gesto que la galería de fotos. La lista está en el orden real del
   sitio, así que moverla ES cambiar el sitio.

   El feedback tiene que decir DÓNDE va a caer, no solo que algo se mueve: una
   línea gruesa en el hueco, arriba o abajo de la fila según de qué lado del
   medio esté el mouse. Con un borde tenue no se veía nada y parecía roto. */
tr[draggable="true"] { cursor: grab; }
tr[draggable="true"]:active { cursor: grabbing; }
.fila-asa { color: var(--ink-4); font-size: 13px; }
tr[draggable="true"]:hover .fila-asa { color: var(--gold); }
tr[draggable="true"]:hover td { background: var(--ctrl-hover); }
.fila-arrastrando td { opacity: .35; background: var(--gold-glow); }
.fila-destino--arriba td { box-shadow: inset 0 3px 0 var(--gold); }
.fila-destino--abajo td { box-shadow: inset 0 -3px 0 var(--gold); }
/* Dónde quedó lo que acabás de soltar, hasta que la tabla se vuelve a pintar. */
.fila-movida td { animation: fila-aterriza 1.1s ease-out; }
@keyframes fila-aterriza {
  0%   { background: var(--gold-glow); }
  100% { background: transparent; }
}

/* Interruptor de la TRANSMISION en la barra de la consola: apagado es un boton
   neutro; encendido late en rojo, porque significa que hay publico mirando. */
.cs-transmision { border: 1px solid var(--line-strong); background: var(--surface); color: var(--ink-2); }
.cs-transmision:hover { border-color: var(--danger); color: var(--danger); }
.cs-transmision.on { background: var(--danger); border-color: var(--danger); color: #fff; }
.cs-transmision i { font-size: 8px; vertical-align: middle; }
.cs-transmision.on i { animation: latir-tv 1.6s ease-in-out infinite; }
@keyframes latir-tv { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
/* Cerrada, «Abrir sala» es LA acción pendiente de la consola: se planta
   sólido. Y si la hora anunciada ya pasó (público esperando frente a un
   catálogo mudo), pasa a rojo y late. */
.cs-transmision.cs-sala--abrir { background: var(--green-600); border-color: var(--green-600); color: #fff; }
.cs-transmision.cs-sala--abrir:hover { background: color-mix(in srgb, var(--green-600) 82%, #000); border-color: var(--green-600); color: #fff; }
.cs-transmision.cs-sala--tarde { background: var(--danger); border-color: var(--danger); }
.cs-transmision.cs-sala--tarde:hover { background: color-mix(in srgb, var(--danger) 82%, #000); color: #fff; }
.cs-transmision.cs-sala--tarde i { animation: latir-tv 1.6s ease-in-out infinite; }
.cs-rows { overflow: auto; flex: 1; min-height: 0; overscroll-behavior: contain; padding-right: 8px; }
.cs-row { display: grid; grid-template-columns: 40px 36px 1fr auto; gap: 9px; padding: 8px 12px; border-bottom: 1px solid var(--line); align-items: center; cursor: pointer; }
/* La pieza se reconoce por la FOTO, no por el numero: en un remate de muebles
   «Lote 47» no dice nada, y por telefono preguntan por «la cómoda». Chica a
   proposito: es para ubicarse de un vistazo, no para mirarla (para eso esta la
   ficha, que la muestra grande). */
.cs-row-foto { width: 36px; height: 36px; border-radius: 6px; object-fit: cover; display: block;
               background: var(--surface-2); border: 1px solid var(--line); }
.cs-row-foto--no { display: grid; place-items: center; color: var(--ink-4); font-size: 12px; }
.cs-row:hover { background: var(--row-hover); }
.cs-row .n { font-family: var(--mono); font-size: 12px; color: var(--ink-4); }
.cs-row .t b { font-size: 12.5px; font-weight: 600; display: block; line-height: 1.3; }
.cs-row .t small { font-size: 11px; color: var(--ink-4); }
.cs-row .m { font-family: var(--mono); font-size: 12.5px; font-weight: 600; color: var(--st-activo); }
.cs-row .m--sin { color: var(--ink-4); font-weight: 400; }
.cs-row .pre { font-family: var(--mono); font-size: 11px; color: var(--gold); }
.cs-row--vendido .n::before { content: '\2713'; color: var(--st-activo); margin-right: 4px; font-weight: 700; }
.cs-row--sinvender { opacity: .6; }
.cs-row--sinvender .m { color: var(--ink-4); font-weight: 400; }
.cs-row--curso { background: color-mix(in srgb, var(--green-400) 12%, var(--surface)); box-shadow: inset 3px 0 0 var(--green-400); }

/* overflow-y: auto, NO hidden. En pantallas bajas la ficha no entra: el panel
   de pujas se lleva 324px, el historial se achicaba a 11px y el martillo
   quedaba directamente CORTADO, sin ninguna forma de llegar a él. Ahora la
   ficha scrollea entera y no se pierde nada. */
.cs-ficha {
  padding: 16px 18px; display: flex; flex-direction: column; gap: 10px;
  min-width: 0; min-height: 0; overflow-x: hidden; overflow-y: auto;
}
.cs-lote-head { display: flex; align-items: flex-start; gap: 14px; }
.cs-nav { display: flex; flex-direction: column; gap: 6px; flex: none; }
.cs-nav .btn-ico { width: 34px; height: 30px; padding: 0; }
.cs-lote-head img { width: 66px; height: 66px; object-fit: cover; border-radius: 10px; border: 1px solid var(--line-strong); }
.cs-sinfoto { width: 66px; height: 66px; border-radius: 10px; border: 1px dashed var(--line-strong); display: grid; place-items: center; color: var(--ink-4); font-size: 18px; flex: none; }
.cs-lote-head h2 { margin: 0 0 2px; font-size: 17.5px; letter-spacing: -.02em; }
.cs-lote-head .meta { font-size: 12.5px; color: var(--ink-3); margin: 0; }
.cs-lote-head .num { font-family: var(--mono); font-size: 13px; color: var(--gold); font-weight: 600; }

.cs-puja { border: 1px solid var(--line-strong); border-radius: 12px; background: var(--surface-2); padding: 11px 16px; display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.cs-puja .lbl, .cs-pujar .lbl, .cs-hist .lbl { font-family: var(--mono); font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-4); }
.cs-puja .monto { font-family: var(--mono); font-size: 30px; font-weight: 600; letter-spacing: -.03em; color: var(--st-activo); line-height: 1.05; }
.cs-puja .lbl { display: block; margin-bottom: 1px; }
.cs-puja .cs-nada { font-size: 22px; color: var(--ink-4); font-weight: 400; }
.cs-puja--vendido { border-color: color-mix(in srgb, var(--st-activo) 45%, transparent); }
.cs-puja .quien { margin-left: auto; text-align: right; }
.cs-puja .quien { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; justify-content: flex-end; }
.cs-puja .quien b { font-size: 13px; }
.cs-puja .quien small { color: var(--ink-3); font-size: 11.5px; font-family: var(--mono); }
.paleta-chip { display: inline-flex; align-items: center; gap: 6px; font-family: var(--mono); font-size: 12.5px; font-weight: 700; padding: 3px 10px; border-radius: 8px; background: var(--green-glow); color: var(--st-activo); }
.origen { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 700; padding: 3px 9px; border-radius: 99px; text-transform: uppercase; letter-spacing: .04em; }
.origen--web { background: color-mix(in srgb, var(--st-programado) 18%, transparent); color: var(--st-programado); }
.origen--sala { background: color-mix(in srgb, var(--st-activo) 18%, transparent); color: var(--st-activo); }
.origen--telefono { background: color-mix(in srgb, var(--gold) 20%, transparent); color: var(--gold); }

.cs-pujar { border: 1px solid var(--line); border-radius: 12px; padding: 11px 14px; }
.cs-pujar .lbl { display: block; margin-bottom: 8px; }
/* CUANTO SUBE, EN LA MISMA LINEA DEL TITULO. Estaba escondido en «Precio y web»:
   cambiarlo a mitad de remate obligaba a salir de la consola, o sea frenar la
   pista. El campo es chico a proposito: es un numero, no un formulario. */
.cs-pujar-h { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.cs-pujar-h .lbl { margin-bottom: 8px; }
/* UN CHIP, y los tres sistemas adentro. La linea del titulo dice lo unico que se
   lee mientras se canta —con que sube y cuanto— y el resto vive en el panelito,
   que se abre una vez cada tanto. Tres botones siempre visibles convertian un
   rotulo en un formulario. */
/* ── CUÁNTO SUBE CADA OFERTA, al final de la fila de sugerencias ───────────
   El paso YA se ve en esos botones: el «+10» de la primera sugerencia es
   exactamente cuánto sube. Lo que faltaba no era mostrarlo, era poder
   cambiarlo sin salir de la pista.

   Estuvo un rato arriba, en el hueco al lado del título, y no funcionó: ahí
   queda lejos del número con el que se lo compara, y cualquier bloque puesto
   en ese hueco se lee como un widget pegado, con su propio marco y su propia
   tipografía. Acá es el cuarto botón de una fila que ya existe. */
/* En el hueco de la cabecera, arriba a la derecha: el título del lote crece
   hacia abajo y el botón se queda a la altura del número de lote. */
.cs-paso-cfg { margin-left: auto; position: relative; align-self: flex-start; }
.cs-paso-ajuste { display: inline-flex; align-items: baseline; gap: 7px; height: 28px;
                  padding: 0 14px; border: 1px solid var(--line); border-radius: 10px;
                  background: var(--surface-1); color: var(--ink-3);
                  font-family: var(--sans); font-size: 11.5px; white-space: nowrap;
                  cursor: pointer; transition: border-color .12s, color .12s; }
.cs-paso-ajuste:hover { border-color: var(--line-strong); color: var(--ink-2); }
.cs-paso-ajuste[aria-expanded="true"] { border-color: var(--st-activo); color: var(--st-activo); }
/* El número, que es lo que se lee de reojo mientras se canta. */
.cs-paso-ajuste b { font-family: var(--mono); font-size: 13px; font-weight: 600; color: var(--ink); }
.cs-paso-ajuste[aria-expanded="true"] b { color: var(--st-activo); }
.cs-paso-modo { color: var(--ink-4); }
.cs-paso-ajuste i { font-style: normal; color: var(--ink-4); font-size: 10px; }

/* El desplegable cae hacia ABAJO y pegado a la derecha. El botón vive arriba
   de todo, en la cabecera, así que para arriba no hay lugar. */
.cs-paso-pop[hidden] { display: none; }
.cs-paso-pop { position: absolute; right: 0; top: 34px; z-index: 5; width: 264px; padding: 7px;
               border: 1px solid var(--line-strong); border-radius: 11px; background: var(--surface-2);
               box-shadow: 0 12px 32px rgba(0,0,0,.45); }
.cs-paso-op { display: flex; align-items: center; gap: 8px; padding: 7px 8px; border-radius: 7px;
              width: 100%; border: 0; background: none; color: var(--ink-2);
              font-family: var(--sans); font-size: 11.5px; text-align: left; cursor: pointer; }
.cs-paso-op:hover { background: var(--row-hover); }
.cs-paso-op.on { background: color-mix(in srgb, var(--st-activo) 12%, transparent); color: var(--st-activo); }
.cs-paso-op b { margin-left: auto; font-family: var(--mono); font-weight: 600; }
.cs-radio { width: 11px; height: 11px; border-radius: 50%; border: 1.5px solid var(--ink-4); flex: none; }
.cs-paso-op.on .cs-radio { border-color: var(--st-activo); background: var(--st-activo);
                           box-shadow: inset 0 0 0 2px var(--surface-2); }
/* La rampa: lo que va a pasar cuando el precio suba. Cuelga de la escalera. */
.cs-paso-rampa { margin: 1px 0 5px 27px; font-family: var(--mono); font-size: 10.5px; color: var(--ink-4); }
.cs-paso-nota { margin: 5px 8px 2px; font-size: 10.5px; color: var(--ink-4); line-height: 1.35; }
.cs-paso-nota b { color: var(--ink-3); font-weight: 600; }
.cs-paso-valor { margin-left: auto; display: inline-flex; align-items: center; gap: 5px; }
.cs-paso-sim { font-family: var(--mono); color: var(--ink-4); }
.cs-paso-cfg input { width: 68px; height: 26px; padding: 0 8px; border-radius: 6px;
                     border: 1px solid var(--line-strong); background: var(--surface-1); color: var(--ink-1);
                     font-family: var(--mono); font-size: 12px; font-variant-numeric: tabular-nums;
                     text-align: right; }
.cs-paso-cfg input:focus { border-color: var(--st-activo); outline: none; }
/* Sin las flechitas del input number: se comen el ancho del campo y un paso se
   tipea de una, no se sube de a uno con la flecha. */
.cs-paso-cfg input::-webkit-outer-spin-button,
.cs-paso-cfg input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.cs-paso-cfg input { -moz-appearance: textfield; appearance: textfield; }

/* Con la ficha angosta el botón baja abajo del título, a todo el ancho:
   apretado al costado no le queda lugar al nombre de la pieza. */
@media (max-width: 1100px) {
  .cs-paso-cfg { margin-left: 0; flex-basis: 100%; align-self: stretch; }
  .cs-paso-pop { right: auto; left: 0; }
}

/* LA COLUMNA DE LA DERECHA DE LA CABECERA: «sube de a» arriba y la PUJA MINIMA
   abajo. Van juntos porque hablan de lo mismo (cuánto sube cada oferta) y en
   ese hueco sobra lugar: la cabecera ya mide lo que miden el título y su renglón
   de datos, así que la puja mínima no le suma alto a la ficha. */
/* Ancho MINIMO fijo: el titulo del lote se acomoda a lo que le deja esta
   columna, y si la columna cambiara con el texto del chip («escalera de la
   casa», «puja mínima»...) el titulo cambiaria de renglones y la operativa
   entera saltaria al poner o sacar la puja minima. 270px es lo que mide el chip
   con la escalera de la casa y un monto de cuatro cifras. */
.cs-lote-der { margin-left: auto; display: flex; flex-direction: column; align-items: flex-end; gap: 6px; flex: none; min-width: 270px; }
.cs-lote-der .cs-paso-cfg { margin-left: 0; }
@media (max-width: 1100px) { .cs-lote-der { margin-left: 0; align-items: flex-start; min-width: 0; } }
/* Cuando manda la puja mínima sobre el escalado, el chip lo dice en oro. */
.cs-paso-modo--min { color: var(--gold); }
/* La PUJA MINIMA web: un número y Enter. En oro cuando está puesta, porque
   cambia lo que la web puede ofertar y se tiene que ver de reojo. Nada que ver
   con el «mínimo» del candado, que es el interno y secreto. */
.cs-minima { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 5px 0 12px;
             border: 1px solid var(--line); border-radius: 10px; background: var(--surface-1);
             font-family: var(--sans); font-size: 11.5px; color: var(--ink-3); white-space: nowrap; cursor: text; }
.cs-minima small { color: var(--ink-4); font-size: 10.5px; }
.cs-minima input { width: 64px; height: 22px; padding: 0 7px; border-radius: 6px; border: 1px solid var(--line-strong);
                   background: var(--surface-2); color: var(--ink); font-family: var(--mono); font-size: 12.5px;
                   font-variant-numeric: tabular-nums; text-align: right; -moz-appearance: textfield; appearance: textfield; }
.cs-minima input::-webkit-outer-spin-button,
.cs-minima input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.cs-minima input:focus { outline: none; border-color: var(--st-activo); box-shadow: 0 0 0 3px var(--green-glow); }
.cs-minima.on { border-color: color-mix(in srgb, var(--gold) 55%, transparent); color: var(--ink-2); }
.cs-minima.on input { border-color: var(--gold); color: var(--gold); font-weight: 700; }
/* LAS TRES SUGERENCIAS EN UN RENGLON. La columna de «Registrar puja» mide
   310px a 1347 de ancho: con la moneda adentro cada boton pedia 134px y se
   apilaban de a uno, tres renglones de 38px. Sin la moneda (la dice el rotulo
   de arriba) y en una grilla de tres, entran siempre en uno; si un monto muy
   largo no entra, se recorta el «+N», que es lo que menos se lee. */
.cs-pasos { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; margin-bottom: 8px; }
.cs-paso { font-family: var(--mono); font-size: 13.5px; font-weight: 600; height: 38px; padding: 0 8px; min-width: 0; border-radius: 10px; border: 1px solid var(--line-strong); background: var(--surface-2); color: var(--ink); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: 5px; white-space: nowrap; overflow: hidden; }
.cs-paso:hover { border-color: var(--green-400); color: var(--green-ink); background: var(--ctrl-hover); }
.cs-paso small { font-size: 10.5px; color: var(--ink-4); font-family: var(--sans); min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.cs-paso--on { border-color: var(--green-400); background: var(--green-glow); color: var(--st-activo); }
/* MONTO Y REGISTRAR PUJA, EN UN RENGLON. Es todo lo que queda del formulario:
   el origen, «quien llama», su telefono y la paleta se fueron. El campo se
   estira y el boton no. */
.cs-fila { display: flex; gap: 8px; align-items: stretch; }
.cs-monto { flex: 1 1 auto; min-width: 0; width: auto; height: 38px; border-radius: 10px; border: 1px solid var(--line-strong); background: var(--surface-2); color: var(--ink); font-family: var(--mono); font-size: 15px; font-weight: 600; text-align: center; }
.cs-monto:focus { outline: none; border-color: var(--green-400); box-shadow: 0 0 0 3px var(--green-glow); }
.btn-pujar { height: 38px; padding: 0 16px; flex: none; }
.cs-hint { font-size: 11px; color: var(--ink-4); margin: 8px 0 0; }
.cs-hint kbd { font-family: var(--mono); font-size: 11px; background: var(--surface-2); border: 1px solid var(--line-strong); border-bottom-width: 2px; border-radius: 5px; padding: 1px 6px; color: var(--ink-2); }

/* EL MARTILLO, UN RENGLON A TODO EL ANCHO de la ficha, abajo del «Va ganando».
   Vivia al pie de la columna de «Registrar puja» en dos renglones, y en la
   pantalla del operador (1347x672) quedaba abajo del corte: VENDIDO se pasaba
   127px y «Sin vender» 185 (medido el 5-set). Aca entran los tres juntos.
   VENDIDO se lleva el doble, que es la accion grande; en pantallas angostas la
   fila se parte sola, VENDIDO arriba y los otros dos abajo, sin scroll
   horizontal ni botones a medias. */
.cs-martillo { display: flex; flex-wrap: wrap; gap: 10px; flex: none; }
.cs-martillo .cs-solo-tv { flex-basis: 100%; margin: 0; }

.btn-vendido { flex: 2 1 240px; min-width: 0; min-height: 48px; font-size: 15px; font-weight: 700; letter-spacing: .01em; }
.btn-sinvender, .cs-en-pantalla { flex: 1 1 130px; min-width: 0; min-height: 48px; padding: 0 12px; }
.cs-vendido-aviso { margin: 0; font-size: 13px; font-weight: 600; color: var(--st-activo); background: var(--green-glow); border-radius: 10px; padding: 12px 14px; }

/* EL PISO DE LA FICHA, EN DOS COLUMNAS. Las pujas vivian abajo de todo: para
   verlas mientras se canta habia que bajar, y la fila se estiraba a 839px con
   el nombre y la hora separados por medio metro de hueco. Ahora van al costado
   de «Registrar puja», que es el par que se usa junto. El encabezado del lote y
   el «Va ganando» siguen a todo el ancho: el numero grande se mira de lejos.
   Debajo de 1100px vuelve a apilarse, que es lo unico que entra en un portatil
   chico o en la tablet de la pista. */
/* El piso se queda con el alto que sobra y NO crece: la operativa de arriba es
   fija y lo que scrollea, si hay muchas pujas, es la columna de las pujas por
   su cuenta. Antes crecia con el historial y con veinte pujas la ficha entera
   scrolleaba, llevandose «Registrar puja» con ella: «el operador que está
   haciendo eso no tiene que mover la pantalla». */
.cs-piso { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 14px; align-items: start; flex: 1 1 0; min-height: 0; grid-template-rows: minmax(0, 1fr); }
.cs-piso-izq { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
@media (max-width: 1100px) { .cs-piso { grid-template-columns: minmax(0, 1fr); } }
/* Apilado (tablet, celular) vuelve a crecer: ahi la ficha scrollea entera. */
@media (max-width: 1100px) { .cs-piso { flex: 1 0 auto; grid-template-rows: none; } .cs-piso > .cs-hist { overflow: visible; } }
/* Y TAMBIEN SE APILA CUANDO LA FICHA ES ANGOSTA, mida lo que mida la pantalla.
   El corte de 1100 mira el viewport, pero lo que importa es cuanto le queda a la
   ficha despues del menu (248px) y la lista (340px): a 1180 de ancho quedaban
   ~450px y la columna de «Registrar puja» caia a 120px, con los botones
   montados. Con menos de 600px de ficha, una columna. A 1347 hay 650. */
.cs-ficha { container: ficha / inline-size; }
@container ficha (max-width: 599px) {
  .cs-piso { grid-template-columns: minmax(0, 1fr); flex: 1 0 auto; grid-template-rows: none; }
  .cs-piso > .cs-hist { overflow: visible; }
}

.cs-hist { border-top: 1px solid var(--line); padding-top: 10px; flex: 1 0 auto; min-height: 0; overscroll-behavior: contain; }
/* En la columna del costado el borde de arriba sobra: ya la separa el hueco. */
.cs-piso > .cs-hist { border-top: 0; padding-top: 0; align-self: stretch; overflow-y: auto; }

/* Y la fila se acomoda a los 320px de la columna. El renglon de una sola linea
   entraba a lo ancho de la pantalla, pero aca partia el nombre en dos y dejaba
   el «Rechazar» fuera del borde. En dos lineas entra todo sin cortar nada:
   arriba el monto y de donde viene, abajo quien, cuando y la accion.
      US$ 2.000   ANTICIPADA
      Valentina Silva   17:59   [Rechazar]
   Lo que sobra (una pendiente trae «pendiente», la marca de reincidente y el
   boton de aprobar) cae en las filas de abajo solo: son las que conviene que
   ocupen mas lugar, porque son las que hay que mirar. */
.cs-piso > .cs-hist li {
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto;
  grid-template-areas: "monto paleta chip" "quien cuando accion";
  column-gap: 8px; row-gap: 1px; align-items: center;
}
/* Nada se estira a lo ancho de la fila: sin esto el chip de la paleta caia en
   una fila propia, ocupando el ancho entero de la columna, y cada puja pasaba a
   medir tres renglones con una barra verde en el medio. Lo que no tiene lugar
   asignado (una pendiente trae su marca, la de reincidente y el boton de
   aprobar) cae abajo pegado a la izquierda, sin inflar la fila. */
.cs-piso > .cs-hist li > * { justify-self: start; }
.cs-piso > .cs-hist li .m { grid-area: monto; min-width: 0; }
.cs-piso > .cs-hist li .paleta-chip { grid-area: paleta; justify-self: end; }
.cs-piso > .cs-hist li .origen { grid-area: chip; justify-self: end; }
.cs-piso > .cs-hist li .quien { grid-area: quien; min-width: 0; overflow: hidden;
                                text-overflow: ellipsis; white-space: nowrap; }
.cs-piso > .cs-hist li .t { grid-area: cuando; margin-left: 0; }
.cs-piso > .cs-hist li .cs-rechazar { grid-area: accion; justify-self: end; }

/* La columna del costado: ancha para que entre la fila, angosta para no comerle
   la mitad a «Registrar puja». 320px es lo que midio entrar sin cortar nada. */

/* De donde viene la puja, dicho con la palabra que usa la casa. Una ANTICIPADA
   es la que entro antes del cierre de preofertas; despues de eso, lo que llega
   por la web es puja del vivo. Sala y telefono son siempre del vivo. Sin esto
   las tres decian «WEB» y no habia forma de distinguirlas. */
.origen--pre { color: var(--gold); border-color: rgba(216,184,120,.34); background: rgba(216,184,120,.10); }
.cs-hist-h { position: sticky; top: 0; background: var(--surface); padding-bottom: 4px; display: flex; align-items: baseline; gap: 8px; z-index: 1; }
.cs-hist-h .cuenta { font-family: var(--mono); font-size: 11px; color: var(--ink-4); }
.cs-hist ul { list-style: none; margin: 8px 0 0; padding: 0; }
.cs-hist li { display: flex; align-items: center; gap: 9px; font-size: 12px; color: var(--ink-2); padding: 5px 2px; border-bottom: 1px solid var(--line); }
.cs-hist li:last-child { border-bottom: 0; }
/* El verde es «va ganando», y eso lo decide el monto aceptado mas alto, no la
   posicion: una puja pendiente puede encabezar la lista sin contar todavia. */
.cs-hist li.lider { background: color-mix(in srgb, var(--green-400) 8%, transparent); border-radius: 6px; padding: 6px 6px; }
.cs-hist li .m { font-family: var(--mono); font-weight: 600; min-width: 82px; }
.cs-hist li .t { margin-left: auto; font-size: 10.5px; color: var(--ink-4); font-family: var(--mono); white-space: nowrap; }
.cs-hist li .paleta-chip { font-size: 11px; padding: 2px 8px; }
/* Rechazar una puja: se lee la palabra, no una cruz suelta. Queda tenue hasta
   que se pasa por encima, para no gritar en un historial de 50 renglones. */
.cs-rechazar {
  flex: none; height: 22px; padding: 0 8px; border-radius: 6px;
  border: 1px solid var(--line); background: none; color: var(--ink-4); cursor: pointer;
  display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--sans); font-size: 11px; font-weight: 600;
  transition: color .2s, border-color .2s, background .2s;
}
.cs-rechazar i { font-size: 9px; }
.cs-hist li:hover .cs-rechazar { border-color: var(--line-strong); color: var(--ink-3); }
.cs-rechazar:hover, .cs-rechazar:focus-visible {
  color: var(--danger); border-color: color-mix(in srgb, var(--danger) 45%, transparent);
  background: color-mix(in srgb, var(--danger) 10%, transparent); outline: none;
}
/* Aprobar una puja pendiente. Mismo tamano y forma que Rechazar para que no
   compitan: aprobar es el camino normal, no el destacado. Lo que se destaca es
   el chip `pendiente`, que es lo que hay que ver de un vistazo. */
.cs-aprobar {
  flex: none; height: 22px; padding: 0 8px; border-radius: 6px;
  border: 1px solid var(--line); background: none; color: var(--ink-4); cursor: pointer;
  display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--sans); font-size: 11px; font-weight: 600;
  transition: color .2s, border-color .2s, background .2s;
}
.cs-aprobar i { font-size: 9px; }
.cs-hist li:hover .cs-aprobar { border-color: var(--line-strong); color: var(--ink-3); }
.cs-aprobar:hover, .cs-aprobar:focus-visible {
  color: var(--success); border-color: color-mix(in srgb, var(--success) 45%, transparent);
  background: color-mix(in srgb, var(--success) 10%, transparent); outline: none;
}
/* La puja que todavia no entro a la pista: se lee sin buscarla. */
.cs-pend {
  flex: none; padding: 2px 7px; border-radius: 6px;
  background: var(--pend-soft); color: var(--pend);
  font-family: var(--mono, monospace); font-size: 10px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase;
}

/* Cuantos ofertantes no vuelven a aparecer aca. Discreto a proposito: no es una
   metrica del remate, es una puerta de salida por si el bloqueo fue un error. */
.cs-bloq-chip {
  /* Mismo alto y tipografia que «Sala abierta» y «Transmitiendo»: esta en esa
     fila y se lee junto con ellos. Contorneado en vez de relleno porque no es
     un modo del remate — es una puerta de salida por si el bloqueo fue un
     error, y no tiene que competir con los botones que si se usan siempre. */
  flex: none; height: 30px; padding: 0 12px; border-radius: 8px;
  border: 1px solid color-mix(in srgb, var(--danger) 45%, transparent);
  background: color-mix(in srgb, var(--danger) 10%, transparent);
  color: var(--danger); cursor: pointer;
  display: inline-flex; align-items: center; gap: 7px; white-space: nowrap;
  font-family: var(--sans); font-size: 12.5px; font-weight: 600;
  transition: background .2s, border-color .2s;
}
.cs-bloq-chip i { font-size: 11px; }
.cs-bloq-chip:hover, .cs-bloq-chip:focus-visible {
  background: color-mix(in srgb, var(--danger) 16%, transparent);
  border-color: var(--danger); outline: none;
}
.cs-bloq-lista { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.cs-bloq-lista li {
  display: flex; align-items: center; gap: 10px; padding: 8px 2px;
  border-bottom: 1px solid var(--line); font-size: 13px;
}
.cs-bloq-lista li:last-child { border-bottom: 0; }
.cs-bloq-lista .n { font-weight: 600; color: var(--ink-1); }
.cs-bloq-lista .t { color: var(--ink-4); font-family: var(--mono, monospace); font-size: 11.5px; }
.cs-bloq-lista li > :last-child { margin-left: auto; }

/* Ya le dijimos que no antes y volvio a ofertar. Es lo unico que el escritorio
   no puede reconstruir mirando la pantalla, asi que va en la fila: se decide en
   el medio del remate y no hay tiempo de ir a buscarlo a ningun lado. */
.cs-reinc {
  flex: none; display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 7px; border-radius: 6px;
  border: 1px solid color-mix(in srgb, var(--danger) 40%, transparent);
  color: var(--danger);
  font-family: var(--mono, monospace); font-size: 10px; font-weight: 700;
  letter-spacing: .04em;
}
.cs-reinc i { font-size: 9px; }

.cs-hist li.pend {
  background: var(--pend-soft); border-radius: 6px; padding: 6px 6px;
  border-bottom-color: transparent;
}
.cs-hist li.pend .m { color: var(--pend); }

.cs-hist li .origen { font-size: 10px; padding: 2px 7px; }
.cs-hist-vacio { font-size: 12.5px; margin: 8px 0 0; }

@media (max-width: 900px) {
  .consola { height: auto; }
  .cs-cuerpo { grid-template-columns: 1fr; }
  /* En el celular lo primero tiene que ser el lote que está en el martillo, no
     la lista: el operador entra a registrar la puja, no a mirar el catálogo. */
  .cs-ficha { order: -1; }
  .cs-lista { border-right: 0; border-top: 1px solid var(--line); }
  .cs-rows { max-height: 280px; }
  .cs-ficha { overflow: visible; }
  .cs-hist { overflow: visible; }
  .cs-puja .monto { font-size: 32px; }
}
/* Pantallas bajas (notebooks): el monto gigante y los pasos se achican para que
   el boton del martillo no quede nunca abajo del pliegue. */
@media (max-height: 780px) {
  .cs-puja { padding: 9px 14px; }
  .cs-puja .monto { font-size: 29px; }
  .cs-lote-head img, .cs-sinfoto { width: 54px; height: 54px; }
  .cs-lote-head h2 { font-size: 16px; }
  .btn-vendido, .btn-sinvender { height: 44px; }
  .cs-hint { display: none; }
}

/* ============================================================================
   AVISOS de ofertas (components/avisos.js) - la campanita de la barra.
   Prende en rojo cuando entra una oferta nueva; al abrirla se ve quien oferto,
   cuanto y en que lote.
   ============================================================================ */
.topbar-right { margin-left: auto; display: flex; align-items: center; gap: 14px; }
.avisos { position: relative; }
.avisos-btn {
  position: relative; width: 38px; height: 38px; border-radius: 10px;
  border: 1px solid var(--line-strong); background: var(--surface);
  color: var(--ink-3); cursor: pointer; display: grid; place-items: center;
  transition: color .2s, border-color .2s, background .2s;
}
.avisos-btn:hover { color: var(--green-ink); border-color: var(--green-ink); background: var(--ctrl-hover); }
.avisos-btn--hay { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 45%, transparent); }
.avisos-btn--hay i { animation: avisos-toc 1.6s ease-in-out infinite; }
@keyframes avisos-toc {
  0%, 88%, 100% { transform: rotate(0); }
  91% { transform: rotate(12deg); }
  95% { transform: rotate(-10deg); }
}
.avisos-contador[hidden] { display: none; }
/* El de «hay movimiento» es un PUNTO, sin numero: dos cifras pegadas a un boton
   de 32px no se leen. El unico numero es el de la cola, que es una tarea. */
.avisos-contador {
  position: absolute; top: -3px; right: -3px; width: 9px; height: 9px;
  border-radius: 99px; background: var(--danger);
  box-shadow: 0 0 0 2px var(--bg);
}
.avisos-pop[hidden] { display: none; }
.avisos-pop {
  position: absolute; right: 0; top: calc(100% + 8px); width: 380px; max-width: 92vw;
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: 12px;
  box-shadow: 0 16px 40px rgba(0,0,0,.32); z-index: 220; overflow: hidden;
}
.avisos-h { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 11px 13px; border-bottom: 1px solid var(--line); }
.avisos-h b { font-size: 13px; }
.avisos-marcar { border: 0; background: none; color: var(--green-ink); font: inherit; font-size: 11.5px; font-weight: 600; cursor: pointer; }
.avisos-marcar:hover { text-decoration: underline; }
.avisos-vacio { padding: 22px 14px; text-align: center; font-size: 12.5px; color: var(--ink-4); margin: 0; }
.avisos-lista { list-style: none; margin: 0; padding: 0; max-height: 380px; overflow: auto; overscroll-behavior: contain; }
.avisos-item {
  display: grid; grid-template-columns: auto 1fr auto; gap: 10px; align-items: center;
  padding: 10px 13px; border-bottom: 1px solid var(--line); cursor: pointer;
}
.avisos-item:last-child { border-bottom: 0; }
.avisos-item:hover, .avisos-item:focus-visible { background: var(--row-hover); outline: none; }
.avisos-item.es-nueva { background: color-mix(in srgb, var(--green-400) 8%, transparent); }
.avisos-item.es-nueva:hover { background: var(--row-hover); }
.avisos-monto { font-family: var(--mono); font-size: 13.5px; font-weight: 600; color: var(--st-activo); min-width: 78px; }
.avisos-txt { min-width: 0; }
.avisos-txt b { font-size: 12.5px; }
.avisos-txt small { display: block; font-size: 11px; color: var(--ink-4); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.avisos-txt .paleta-chip { font-size: 10.5px; padding: 1px 7px; }
.avisos-meta { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.avisos-cuando { font-size: 10.5px; color: var(--ink-4); font-family: var(--mono); white-space: nowrap; }

/* La cola del visto: contador dorado abajo (no se apaga hasta vaciarla) y
   acciones al pie de cada renglón. Si además hay nuevas, el borde rojo gana. */
.avisos-btn--visto:not(.avisos-btn--hay) { color: var(--gold); border-color: color-mix(in srgb, var(--gold) 55%, transparent); }
.avisos-contador--visto {
  top: auto; bottom: -6px; right: -6px; width: auto; height: 18px; min-width: 18px;
  padding: 0 5px; background: var(--gold); color: var(--bg);
  font-family: var(--mono); font-size: 10.5px; font-weight: 700;
  display: grid; place-items: center;
}
.avisos-contador--visto[hidden] { display: none; }
.avisos-h--cola { background: color-mix(in srgb, var(--gold) 7%, transparent); }
.avisos-h--cola b { color: var(--gold); }
.avisos-cola-n {
  min-width: 20px; padding: 1px 7px; border-radius: 99px; text-align: center;
  background: color-mix(in srgb, var(--gold) 20%, transparent); color: var(--gold);
  font-family: var(--mono); font-size: 11px; font-weight: 700;
}
.avisos-lista--cola { max-height: 250px; border-bottom: 1px solid var(--line); }
/* El aviso FIJO de la sala en el topbar: un toast se pierde si no lo viste;
   esto queda plantado hasta que la sala se abra. Dorado = programada para
   hoy; rojo latiendo = la hora ya paso y el publico espera. */
.topbar-aviso { flex: 1; display: flex; justify-content: center; min-width: 0; padding: 0 14px; }
.topbar-aviso[hidden] { display: none; }
.topbar-sala {
  display: inline-flex; align-items: center; gap: 8px; max-width: 100%;
  padding: 6px 14px; border-radius: 99px; cursor: pointer; font: inherit;
  font-size: 12.5px; font-weight: 600; color: var(--gold);
  border: 1px solid color-mix(in srgb, var(--gold) 45%, transparent);
  background: color-mix(in srgb, var(--gold) 10%, transparent);
}
.topbar-sala-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.topbar-sala-ir { font-weight: 700; white-space: nowrap; }
.topbar-sala:hover { background: color-mix(in srgb, var(--gold) 18%, transparent); }
.topbar-sala--tarde {
  color: var(--danger);
  border-color: color-mix(in srgb, var(--danger) 55%, transparent);
  background: color-mix(in srgb, var(--danger) 12%, transparent);
}
.topbar-sala--tarde:hover { background: color-mix(in srgb, var(--danger) 20%, transparent); }
.topbar-sala--tarde i { animation: avisos-toc 1.6s ease-in-out infinite; }
@media (max-width: 900px) { .topbar-aviso { display: none; } }

/* Los botones van en la columna derecha (donde el feed pone el origen),
   apilados y parejos: en una segunda línea suelta quedaban flotando. */
.avisos-item--cola .avisos-acciones { display: flex; flex-direction: column; gap: 6px; }
.avisos-item--cola .avisos-acciones .btn { justify-content: center; }
.avisos-item--cola .avisos-cuando { margin-left: 4px; }
.avisos-aprobar { color: var(--st-activo); border-color: color-mix(in srgb, var(--st-activo) 45%, transparent); }
.avisos-aprobar:hover:not(:disabled) { background: color-mix(in srgb, var(--st-activo) 12%, transparent); }
.avisos-rechazar:hover:not(:disabled) { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 45%, transparent); }

/* ── Lotes → Mapa: el remate entero de un vistazo ───────────────────────────
   «Tengo 250 lotes: ¿cómo tengo una visión rápida de ver cómo viene, sin
   tener que hacer así?» (el gesto de scrollear). Un casillero por lote, en el
   orden de siempre, pintado por lo que tiene. Medido a 1347×672: los 250
   entran sin scrollear. Vivió en la pantalla de Ofertas (`.of-*` es de esa
   época) hasta que se sacó esa pantalla; el mapa se mudó a Lotes entero, con
   las clases como estaban. */
.of-vista button { padding: 6px 13px; font-size: 13px; }
.of-tablero { display: flex; flex-direction: column; gap: 10px; }
.of-tab-cab { display: flex; align-items: baseline; justify-content: space-between; gap: 6px 14px; flex-wrap: wrap; }
.of-tab-tit, .of-tab-va { margin: 0; font-size: 13.5px; color: var(--ink-3); }
.of-tab-tit b { color: var(--ink); }
.of-tab-va b { font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--ink); }
.of-tab-modo { margin-left: 8px; padding: 2px 9px; border: 1px solid var(--line); border-radius: var(--radius-pill);
               font-size: 11.5px; font-weight: 600; color: var(--ink-3); white-space: nowrap; }
.of-leyenda { display: flex; flex-wrap: wrap; gap: 6px; }
.of-ley { display: inline-flex; align-items: center; gap: 7px; padding: 5px 11px; border: 1px solid var(--line);
          border-radius: var(--radius-pill); background: var(--surface); font-family: var(--sans); font-size: 12.5px;
          color: var(--ink-2); cursor: pointer; transition: border-color .15s, box-shadow .15s; }
.of-ley b { font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--ink); }
.of-ley small { font-size: 11.5px; color: var(--ink-4); }
.of-ley:hover { border-color: var(--line-strong); }
.of-ley.is-on { border-color: var(--ink-3); box-shadow: inset 0 0 0 1px var(--ink-3); }
.of-ley.is-cero { opacity: .6; }
.of-ley-marca { width: 12px; height: 12px; flex: none; border: 1px solid; border-radius: 3px; }

/* Los colores de cada estado: la marca de la leyenda y el casillero son el
   mismo dibujo, así la leyenda se lee sin explicación. */
.of-ley--pendiente .of-ley-marca, .of-celda--pendiente {
  background: color-mix(in srgb, var(--st-preparando) 26%, var(--surface)); border-color: var(--st-preparando); }
.of-ley--con_ofertas .of-ley-marca, .of-celda--con_ofertas {
  background: color-mix(in srgb, var(--st-activo) 18%, var(--surface)); border-color: color-mix(in srgb, var(--st-activo) 60%, transparent); }
.of-ley--rechazadas .of-ley-marca, .of-celda--rechazadas {
  background: color-mix(in srgb, var(--danger) 9%, var(--surface)); border-color: color-mix(in srgb, var(--danger) 55%, transparent); }
.of-ley--sin_ofertas .of-ley-marca, .of-celda--sin_ofertas { background: var(--surface-2); border-color: var(--line); }

.of-mapa { display: grid; grid-template-columns: repeat(auto-fill, minmax(42px, 1fr)); gap: 4px; }
.of-celda { position: relative; height: 28px; min-width: 0; padding: 0 2px; border: 1px solid; border-radius: 6px;
            font-family: var(--mono); font-size: 11.5px; font-weight: 600; font-variant-numeric: tabular-nums;
            line-height: 1; color: var(--ink-2); cursor: pointer; transition: opacity .15s; }
.of-celda--pendiente { font-weight: 800; color: var(--ink); }
.of-celda--sin_ofertas { color: var(--ink-4); }
.of-celda:hover, .of-celda:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; z-index: 1; }
/* Cuántas esperan el visto en ESE lote: un número chico en la esquina. */
.of-celda-n { position: absolute; top: -6px; right: -5px; min-width: 15px; height: 15px; padding: 0 3px;
              border-radius: var(--radius-pill); background: var(--st-preparando); color: var(--surface);
              font-size: 9.5px; font-weight: 800; line-height: 15px; }
/* Vendido: ya cayó el martillo. Tachado y rayado, sin perder su color. */
.of-celda.is-vendido { text-decoration: line-through;
  background-image: repeating-linear-gradient(135deg, transparent 0 4px, color-mix(in srgb, var(--ink) 9%, transparent) 4px 6px); }
/* Lo que no entra en el filtro de la leyenda o en lo buscado: se apaga, no se
   va. Si se fuera, la grilla se reacomodaría y el lote 21 cambiaría de lugar. */
.of-celda.is-apagada { opacity: .16; }

/* ── Las ofertas en la carátula del lote (interno, lo ve solo la casa) ──────
   Un renglón de alto FIJO: cuando entra la primera oferta se repinta en el
   lugar y la card no salta. */
.folio-va { flex: none; align-self: center; font-family: var(--mono); font-size: 12px; font-weight: 700;
            font-variant-numeric: tabular-nums; color: var(--st-activo); white-space: nowrap; }
.folio-ofertas { display: flex; align-items: center; gap: 10px; width: 100%; height: 26px; margin: 8px 0 0; padding: 0 9px;
                 overflow: hidden; white-space: nowrap; border: 1px dashed var(--line-strong); border-radius: 9px;
                 background: transparent; font-family: var(--sans); font-size: 11.5px; color: var(--ink-3);
                 text-align: left; cursor: pointer; transition: background .15s, border-color .15s; }
.folio-ofertas:hover { border-style: solid; background: var(--ctrl-hover); }
.folio-of { display: inline-flex; align-items: center; gap: 4px; font-weight: 600; }
.folio-of i { font-size: 10px; }
.folio-of--pend { color: color-mix(in srgb, var(--st-preparando) 88%, var(--ink)); }
[data-theme="dark"] .folio-of--pend { color: var(--st-preparando); }
.folio-of--acep { color: var(--st-activo); }
.folio-of--rech { color: var(--danger); }
.folio-of.is-cero { color: var(--ink-4); font-weight: 500; }
.folio-of-nada { display: inline-flex; align-items: center; gap: 5px; color: var(--ink-4); }

@media (max-width: 620px) {
  .avisos-pop { position: fixed; left: 10px; right: 10px; width: auto; top: 70px; }
}

/* Filtros de Sitio Web: chips y buscador en la MISMA fila. Apilados en tres
   renglones (resumen, buscador, chips) se comían media pantalla antes de la
   primera fila de la tabla. */
.web-filtros { gap: 12px; }
.web-filtros .search { flex: 0 1 300px; }
@media (max-width: 720px) {
  .web-filtros { flex-direction: column; align-items: stretch; }
  .web-filtros .search { flex: 1 1 auto; max-width: none; }
  .web-filtros .vt-seg { overflow-x: auto; }
}

/* Las opciones de la accion masiva de lotes: eran un desplegable que parecia un
   dato y era una accion. Ahora se ve que hay que elegir UNA cosa para hacer. */
.pubweb-lotes { border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 16px; margin-top: 4px; }
.pubweb-lotes legend { font-family: var(--sans); font-size: 12.5px; font-weight: 700; color: var(--ink); padding: 0 4px; }
.pubweb-op { display: flex; align-items: flex-start; gap: 10px; padding: 8px 10px; border-radius: 9px; cursor: pointer; }
.pubweb-op:hover { background: var(--ctrl-hover); }
.pubweb-op input { margin-top: 3px; flex: none; }
.pubweb-op span { display: flex; flex-direction: column; gap: 1px; }
.pubweb-op b { font-size: 13.5px; font-weight: 600; color: var(--ink); }
.pubweb-op small { font-size: 12px; color: var(--ink-3); }
.pubweb-op:has(input:checked) { background: var(--green-glow); }
.pubweb-op:has(input:checked) b { color: var(--st-activo); }
.pubweb-op-editor { margin: 2px 0 10px 34px; }

/* Editor de la escalera de oferta: los tramos del remate, en el panel Web.
   Va dentro de .pubweb-lotes, asi que hereda su marco y su aire. */
.pubweb-tramos { width: 100%; border-collapse: collapse; margin: 6px 0 0; }
.pubweb-tramos th { font-family: var(--sans); font-size: 11px; font-weight: 700; text-transform: uppercase;
                    letter-spacing: .05em; color: var(--ink-4); text-align: left; padding: 0 6px 4px; }
.pubweb-tramos th:last-child { width: 38px; }
.pubweb-tramos td { padding: 2px 6px; }
.pubweb-tramos input { width: 100%; }
/* Numeros alineados hacia abajo: la escalera se lee como columna, no fila por fila. */
.pubweb-tramos input[type="number"] { font-variant-numeric: tabular-nums; }
.pubweb-tramos-acc { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }

/* Cierre de preofertas: fecha (date picker nativo) + hora (tipeable, ver
   hora-input.js) en la misma fila. Antes era un solo datetime-local: el
   cliente no se quejó de la fecha, así que esa parte sigue como estaba. */
.pubweb-cierre-row { display: flex; gap: 8px; }
.pubweb-cierre-row input[type="date"] { flex: 1.3; min-width: 0; }
.pubweb-cierre-row .hora-field { flex: 1; min-width: 0; }

/* Campo de hora tipeable (ver hora-input.js): un reloj + un cuadro angosto
   ("HH:MM", no una caja de texto suelta) para que se lea como hora de un
   vistazo, sin leer la etiqueta. Pedido del dueño: "haz que sea más obvio
   que es hora, porque ahora es una cosa donde pongas números". */
.hora-field { position: relative; display: inline-flex; align-items: center; width: 100%; }
.hora-field i { position: absolute; left: 11px; font-size: 12px; color: var(--ink-3); pointer-events: none; }
.hora-field input { width: 100%; padding-left: 30px; letter-spacing: .3px; font-variant-numeric: tabular-nums; }
.hora-field:focus-within i { color: var(--green-600); }

/* ── Tablas: el título y la fecha en un solo renglón ────────────────────────
   Con muchas columnas el título caía en tres renglones y la fecha se partía
   al medio ("2026- / 09-12"), dejando filas de alturas distintas. El ancho no
   se lo llevaban los datos: se lo llevaban los ENCABEZADOS, que son nowrap
   por diseño (mono, mayúscula, letter-spacing .15em), más 18px de padding por
   lado en cada columna. Acá el encabezado puede ir en dos renglones (arriba
   no molesta) y el ancho que se libera se lo lleva el título, que es lo único
   que se lee de corrido. Si alguno no entra se corta con puntos suspensivos y
   el texto completo queda en el title, pero la fila no cambia de alto.
   Solo arriba de 768px: abajo la tabla ya se dibuja como tarjetas. */
@media (min-width: 769px) {
  .data-table thead th { white-space: normal; vertical-align: bottom; }
  .data-table thead th, .data-table tbody td { padding-inline: 12px; }
  .data-table tbody td[data-label="Fecha"] { white-space: nowrap; }
  /* El título NO se fuerza a una línea: con el ancho que gana acá entra solo,
     y si la ventana es chica preferimos que envuelva antes que empujar los
     botones de acción fuera de la pantalla. */
  .data-table tbody td[data-label="Título"] { min-width: 22ch; }
}

/* Ritmo vertical propio: Sitio Web es una lista larga y cada margen de más se
   paga en filas que no entran en la pantalla. */
.page-web { padding: 16px 20px; }
.page-web .page-header { margin-bottom: 10px; }
.page-web .page-nav { display: flex; align-items: center; gap: 14px; }
.page-web .web-intro { margin-bottom: 12px; }
.page-web .vt-controls { margin-bottom: 12px; }
.page-web .toolbar { margin-bottom: 12px; }

/* Nota del panel de saldos: por qué no están todos los lotes listados. */
.sl-nota { margin: 14px 2px 2px; font-size: 13px; line-height: 1.5; }
.sl-nota b { color: var(--gold); font-weight: 600; }

/* Alta de pieza desde el stock: la foto y el nombre del objeto elegido. */
.desde-stock-pv { display: flex; align-items: center; gap: 12px; padding: 10px 12px; margin-bottom: 12px; border: 1px solid var(--line); border-radius: 10px; background: var(--surface-2); }
.desde-stock-pv img { width: 56px; height: 56px; flex: none; object-fit: cover; border-radius: 8px; background: var(--surface); }
.desde-stock-pv small { display: block; margin-top: 2px; }

/* ── Banda VENDIDO en la esquina de la card ─────────────────────────────────
   Antes el estado era un chip más del encabezado, del mismo tamaño y color que
   la píldora de publicación web: había que buscarlo para saber si el lote
   estaba vendido. Ahora es una cinta cruzada en la esquina, que se reconoce de
   lejos y sin leer.

   Va en la esquina y no encima del contenido a propósito: el lote vendido se
   sigue consultando (qué tenía, cuántas fotos, en qué moneda), así que la
   marca no puede taparlo. La card ya es overflow:hidden, así que la cinta se
   recorta sola contra el borde; pointer-events:none para no comerse ningún
   click de lo que quede debajo. */
.folio-status:empty { display: none; }

.folio-sello {
  position: absolute; z-index: 3; top: 26px; right: -52px; width: 200px;
  transform: rotate(38deg);
  pointer-events: none; -webkit-user-select: none; user-select: none;
  padding: 7px 0; text-align: center;
  font-family: var(--mono); font-size: 13px; font-weight: 700; line-height: 1.2;
  letter-spacing: .2em; text-transform: uppercase;
  color: #fff; background: var(--green-600);
  box-shadow: 0 6px 16px -6px rgba(0, 0, 0, .6);
}

@media (prefers-reduced-motion: no-preference) {
  .folio-sello { animation: sello-entra .22s ease-out both; }
  @keyframes sello-entra {
    from { opacity: 0; transform: rotate(38deg) translateY(-14px); }
    to   { opacity: 1; transform: rotate(38deg) translateY(0); }
  }
}

/* ── Campo de plata con la moneda a la vista ────────────────────────────────
   Un "25" pelado no dice si son pesos o dólares, y el lote puede ir en una
   moneda distinta a la del remate. El símbolo va pegado al campo, no solo en
   la etiqueta, para que se lea junto con el número. */
.campo-moneda { display: flex; align-items: stretch; }
.campo-moneda-sim {
  display: inline-flex; align-items: center; flex: none;
  padding: 0 12px; min-width: 46px; justify-content: center;
  font-family: var(--mono); font-size: 12px; letter-spacing: .04em;
  color: var(--gold); background: var(--surface-2);
  border: 1px solid var(--line-strong); border-right: 0;
  border-radius: var(--radius-sm) 0 0 var(--radius-sm);
}
.campo-moneda input { flex: 1; min-width: 0; border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
.campo-moneda-lbl { color: var(--gold); font-family: var(--mono); font-size: 12px; }

/* Nota BAJO un campo (el ejemplo en vivo del paso de oferta, p. ej.).
   Los .form-group del modal quedan pegados uno al otro: funciona mientras cada
   uno termina en un input, porque el borde ya separa. Un parrafo suelto al final
   quedaba a 0px del label siguiente y se leia como si fuera de ESE campo. */
.campo-nota { margin-bottom: 14px; line-height: 1.4; }

/* Sitio web > Ajustes: grupos por tema, dos columnas, con aire adentro del panel. */
.ajustes-form { padding: 20px 24px 22px; gap: 22px; }
.ajustes-grupo { min-width: 0; }
.ajustes-grupo + .ajustes-grupo { padding-top: 20px; border-top: 1px solid var(--line); }
.ajustes-grupo h3 { margin: 0 0 4px; font-size: 14px; font-weight: 700; color: var(--ink-1); }
.ajustes-grupo-nota { font-size: 12.5px; margin: 0 0 4px; }
.ajustes-campos { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px 20px; margin-top: 10px; }
.ajustes-campos--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.ajustes-ancho { grid-column: 1 / -1; }
.ajustes-ayuda { font-size: 12px; margin: 0; line-height: 1.35; }
.ajustes-form .form-actions { margin-top: 0; }
@media (max-width: 760px) { .ajustes-campos, .ajustes-campos--3 { grid-template-columns: 1fr; } .ajustes-form { padding: 16px; } }

/* El caret de los menus de accion. FontAwesome del proyecto es un subset de
   78 iconos y NO trae fa-chevron-down: salia un cuadrito vacio en todas las
   tablas. Se usa el chevron que si esta, girado. */
.menu-caret { transform: rotate(90deg); }

/* ── Correo (cola de mails salientes) ─────────────────────────────────────────
   La tira de arriba dice EN QUE MODO esta la cañeria antes que cualquier otra
   cosa: con driver `log` una fila «enviado» NO quiere decir que a la persona le
   llego el mail, y esa confusion hay que cortarla de entrada. */
.co-config { display: flex; flex-wrap: wrap; gap: 14px; align-items: stretch; margin-bottom: 16px; }
.co-config-modo {
  display: flex; gap: 12px; align-items: flex-start; flex: 1 1 340px; min-width: 0;
  padding: 12px 14px; border-radius: var(--radius-sm);
  border: 1px solid var(--line); background: var(--surface-2);
}
.co-config-modo i { font-size: 15px; margin-top: 2px; }
.co-config-modo strong { display: block; font-size: .9rem; color: var(--ink); }
.co-config-modo p { margin: 3px 0 0; font-size: .82rem; line-height: 1.4; color: var(--ink-3); }
/* Tinte translucido y no un color fijo: --gold-soft es un crema CLARO que en el
   tema oscuro deja el titulo ilegible. Un color-mix sobre la superficie de
   abajo funciona igual en los dos temas. */
.co-config-modo--log {
  border-color: color-mix(in srgb, var(--gold) 45%, transparent);
  background: color-mix(in srgb, var(--gold) 9%, transparent);
}
.co-config-modo--log i { color: var(--gold); }
.co-config-modo--smtp i { color: var(--green-400); }

.co-datos {
  flex: 1 1 340px; min-width: 0; display: grid; gap: 4px 18px;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  align-content: center; padding: 12px 14px;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.co-dato { display: flex; gap: 8px; align-items: baseline; min-width: 0; }
.co-dato-rotulo {
  flex: 0 0 auto; font-size: .62rem; letter-spacing: .1em; text-transform: uppercase;
  font-weight: 700; color: var(--ink-4);
}
/* La ruta del log y el host son largos: se recortan en vez de ensanchar la
   tira. El valor entero se ve en el title del navegador. */
.co-dato-valor {
  font-family: var(--mono); font-size: .78rem; color: var(--ink-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
/* Falta APP_URL: los avisos salen SIN el boton que lleva al lote. No es un dato
   mas de la tira (era eso, y se leia como un detalle al lado del usuario del
   SMTP): es lo unico de esta pantalla que hay que ir a arreglar a otro lado, y
   no se nota sin abrir un mail ya enviado. Ocupa el ancho entero de la caja y
   va tintado con el mismo crema del modo prueba, que ya quiere decir «ojo».
   El texto SI se parte en varias lineas: es una explicacion, no un valor. */
.co-falta-url {
  grid-column: 1 / -1; margin: 4px 0 0;
  display: flex; gap: 8px; align-items: flex-start;
  padding: 8px 10px; border-radius: var(--radius-sm);
  border: 1px solid color-mix(in srgb, var(--gold) 45%, transparent);
  background: color-mix(in srgb, var(--gold) 9%, transparent);
  font-size: .8rem; line-height: 1.4; color: var(--ink-2);
}
.co-falta-url i { color: var(--gold); margin-top: 2px; flex: 0 0 auto; }
.co-falta-url code { font-family: var(--mono); font-size: .76rem; }

/* ── La bandeja: la lista a la izquierda, el mail a la derecha ──────────────
   ALTO FIJO, y ese es el punto: la lista scrollea ADENTRO y el visor tambien,
   asi que ni cambiar de fila, ni cambiar de pestaña, ni caer en una pagina con
   tres filas mueve un pixel de lo que hay abajo. La tabla anterior tenia
   min-height medido a mano (833px) y habia que volver a medirla cada vez que
   cambiaba el alto de fila; esto no depende de cuantas filas haya.

   El clamp es para la pantalla del operador (1347x672, medida): con un alto
   fijo de 620 la pagina pedia 370px de scroll, y con esto pide 200. El piso de
   460 existe para que el mail no quede mirandose por una rendija en una
   pantalla mas baja todavia. */
.co-split {
  display: grid;
  grid-template-columns: minmax(0, 360px) minmax(0, 1fr);
  gap: 16px;
  height: clamp(460px, calc(100vh - 290px), 760px);
}
.co-lista, .co-visor {
  display: flex; flex-direction: column;
  min-width: 0; min-height: 0; height: 100%;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface); overflow: hidden;
}

/* Pantalla angosta: uno abajo del otro. La lista se achica (es un indice) y el
   visor se queda con el alto, que es lo que se viene a leer. */
@media (max-width: 1100px) {
  .co-split { grid-template-columns: minmax(0, 1fr); height: auto; }
  .co-lista { height: 320px; }
  .co-visor { height: 520px; }
}

.co-lista-cuerpo { flex: 1; min-height: 0; overflow-y: auto; }
.co-lista-pie {
  flex: none; display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 8px 12px; font-size: .76rem;
  border-top: 1px solid var(--line); background: var(--surface-2);
}
.co-lista-cargando { display: grid; gap: 8px; padding: 12px; }
.co-lista-cargando .skel { height: 46px; }

/* Cada fila: dos renglones y un punto de color. Las dos lineas se recortan con
   puntos suspensivos —el texto entero esta en el title— para que TODAS midan
   lo mismo: una fila que envuelve descoloca la lista entera. */
.co-fila {
  display: flex; align-items: flex-start; gap: 10px;
  width: 100%; padding: 10px 12px; cursor: pointer; text-align: left;
  font: inherit; color: inherit; background: none;
  border: 0; border-bottom: 1px solid var(--line);
  transition: background .14s ease, box-shadow .14s ease;
}
.co-fila:hover { background: var(--row-hover); }
.co-fila.on { background: var(--ctrl-hover); box-shadow: inset 3px 0 0 var(--green-600); }
.co-fila:focus-visible { outline: 2px solid var(--green-600); outline-offset: -2px; }
.co-fila-texto { flex: 1; min-width: 0; display: grid; gap: 2px; }
.co-fila-asunto, .co-fila-meta {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.co-fila-asunto { font-size: .85rem; font-weight: 600; color: var(--ink); }
.co-fila-meta { font-size: .73rem; color: var(--ink-4); }
.co-punto { flex: none; width: 8px; height: 8px; margin-top: 6px; border-radius: 50%; background: var(--ink-4); }
.co-punto--prep   { background: var(--st-preparando); }
.co-punto--prog   { background: var(--st-programado); }
.co-punto--activo { background: var(--green-400); }
.co-punto--anulada{ background: var(--danger); }

/* La cabecera del visor: quien, que, y en que estado quedo. Todo en una linea
   por dato, recortado: lo que no entra esta en el title y en la lista. */
.co-visor-cab { flex: none; padding: 14px 16px 12px; border-bottom: 1px solid var(--line); }
.co-visor-asunto {
  margin: 0 0 4px; font-family: var(--sans); font-size: 1rem; font-weight: 700; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.co-visor-para { margin: 0 0 8px; font-size: .82rem; color: var(--ink-3); }
.co-visor-chips { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.co-chip {
  padding: 2px 8px; border: 1px solid var(--line); border-radius: 999px;
  font-size: .7rem; color: var(--ink-4); white-space: nowrap;
}
.co-chip--motivo { color: var(--gold); border-color: color-mix(in srgb, var(--gold) 45%, transparent); }
.co-visor-error {
  margin: 8px 0 0; font-family: var(--mono); font-size: .74rem; color: var(--danger);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.co-tabs {
  flex: none; display: flex; gap: 2px; padding: 0 16px;
  border-bottom: 1px solid var(--line); background: var(--surface-2);
}
.co-tabs button {
  padding: 9px 12px; margin-bottom: -1px; cursor: pointer;
  font: inherit; font-size: .8rem; font-weight: 600; color: var(--ink-4);
  background: none; border: 0; border-bottom: 2px solid transparent;
}
.co-tabs button:hover { color: var(--ink); }
.co-tabs button[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--green-600); }
.co-tabs button[disabled] { opacity: .45; cursor: not-allowed; }

/* EL MAIL VA ADENTRO DE UN IFRAME CON `sandbox` VACIO, apuntando a un endpoint
   que lo sirve con su propio CSP. Nada de lo que venga en ese cuerpo se
   ejecuta ni puede tocar el escritorio. Ver el encabezado de views/correo.js.
   Fondo blanco fijo: un mail se dibuja sobre blanco tambien cuando el
   escritorio esta en tema oscuro. */
.co-visor-cuerpo { flex: 1; min-height: 0; display: flex; }
/* Sin esto el `hidden` de la pestaña que no se ve no hace nada: el display de
   arriba gana. */
.co-visor-cuerpo > [hidden] { display: none; }
.co-visor-frame { flex: 1; width: 100%; border: 0; background: #fff; }
.co-visor-texto {
  flex: 1; margin: 0; padding: 14px 16px; overflow: auto;
  font-family: var(--mono); font-size: .78rem; line-height: 1.55; color: var(--ink-2);
  white-space: pre-wrap; word-break: break-word;
}
.co-visor-vacio {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 10px; padding: 20px; text-align: center; color: var(--ink-4);
}
.co-visor-vacio i { font-size: 1.7rem; opacity: .5; }
.co-visor-vacio p { margin: 0; font-size: .85rem; }

.co-prueba p.muted { margin-bottom: 14px; line-height: 1.4; }
/* El cartel de «datos de ejemplo». Tinte dorado y no rojo: no es un error, es
   un aviso de que ese mail no es un aviso de verdad. */
.co-aviso-ejemplo {
  display: flex; gap: 8px; align-items: flex-start;
  margin: -4px 0 14px; padding: 10px 12px; border-radius: var(--radius-sm);
  border: 1px solid color-mix(in srgb, var(--gold) 45%, transparent);
  background: color-mix(in srgb, var(--gold) 9%, transparent);
  font-size: .8rem; line-height: 1.45; color: var(--ink-2);
}
.co-aviso-ejemplo[hidden] { display: none; }
.co-aviso-ejemplo i { flex: none; margin-top: 2px; color: var(--gold); }

/* ── Estado de cuenta: disparador en la ficha + modal de período ─────────────
   El botón vive en el encabezado de la ficha (no en una pestaña) porque el
   papel es de toda la ficha: las dos puntas de la deuda, las dos monedas y el
   stock. `.page-header` ya es flex con space-between; este contenedor agrupa
   el botón y el breadcrumb para que queden juntos a la derecha en vez de
   separarse a los dos extremos.
   ─────────────────────────────────────────────────────────────────────────── */
.page-header-actions { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }

/* Fila de rangos del modal. Alto FIJO por fila: los botones de preset y los dos
   campos de fecha no cambian de tamaño al elegir uno u otro, así que el modal no
   salta mientras el operador prueba períodos. */
.ec-rangos { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; min-height: 34px; }
.ec-rangos-lbl { font-size: 13px; font-weight: 600; color: var(--ink-3); }
.ec-rangos label { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--ink-3); }
/* Ancho explícito: un input[type=date] sin ancho propio se estira y se come la
   fila entera dentro de un flex. */
.ec-rangos input[type="date"] { width: 150px; flex: none; }

.ec-h { margin: 16px 0 8px; font-family: var(--sans); font-size: 14px; font-weight: 700; color: var(--ink); }
.ec-pie { margin-top: 10px; font-size: 12px; line-height: 1.45; }
