
:root{--bg:#0b1220;--card:#111a2b;--text:#e8eefc;--muted:#a9b5d1;--accent:#5bbcff;--ok:#2dd4bf;--warn:#f59e0b;}
*{box-sizing:border-box}
html, body {
  /* Bloquear completamente el gesto de back-navigation horizontal del SO/browser
     (iOS Safari edge-swipe, Android Chrome edge-swipe-back).
     overscroll-behavior-x:none impide que el scroll horizontal del documento
     active la navegación de historial del sistema.
     overscroll-behavior-y:auto permite que nuestro pull-to-refresh en pwa.js
     detecte el gesto hacia abajo vía touchstart/touchmove (ya no ponemos
     'contain' que lo bloqueaba; el bounce de iOS lo manejamos en pwa.js
     comprobando scrollY === 0 antes de activar el indicador). */
  overscroll-behavior-x: none;
  overscroll-behavior-y: auto;
}
/* Bottom padding so Android nav bar / iOS home indicator doesn't cover content,
   and so the user can scroll a bit past the last element comfortably on phones/tablets. */
body {
  padding-bottom: calc(120px + env(safe-area-inset-bottom, 0px));
}
@media (max-width: 700px) {
  body {
    padding-bottom: calc(160px + env(safe-area-inset-bottom, 0px));
  }
}
/* Prevent Android Chrome edge-swipe-back gesture from firing. The browser interprets
   touch-action: pan-y as "I only handle vertical pan", so horizontal gestures are
   passed to our JavaScript instead of being captured as system back-navigation.
   Horizontal-scrolling tables explicitly set touch-action: pan-x to override this. */
body { touch-action: pan-y; }
.scroll-x, .scroll-x-hint, #vendorSummaryWrap, #historyTableHolder { touch-action: pan-x pan-y; }
body{margin:0;font-family:Inter,system-ui,Arial,sans-serif;background:linear-gradient(180deg,#0b1220,#060912);color:var(--text);min-height:100vh;}
.container{max-width:1100px;margin:0 auto;padding:2px 32px 32px 32px}
/* Panel de Ventas (#tab-main) keeps slightly more top spacing for breathing room */
#tab-main { padding-top: 10px; }
.card{background:linear-gradient(180deg,#111a2b,#0e1726);border:1px solid #1c2a44;border-radius:18px;padding:22px;box-shadow:0 10px 30px rgba(0,0,0,.35)}
/* When the active tab is NOT Panel de Ventas, shrink the card's top padding so the
   page content sits closer to the top (the Panel keeps its airy padding).
   The body[data-active-tab] attribute is set by _showTabNoHistory() on each tab change. */
body[data-active-tab]:not([data-active-tab="main"]) .card {
  padding-top: 6px;
  padding-bottom: 12px;
}
h1,h2,h3{margin:0 0 12px} h1{font-size:28px} h2{font-size:22px;color:var(--accent)}
label{display:block;margin:10px 0 6px;color:var(--muted)}
select,input,button{width:100%;padding:10px 12px;border-radius:12px;border:1px solid #223355;background:#0b1424;color:#e8eefc;}
.row{display:grid;grid-template-columns:1fr 1fr;gap:14px} .row3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:14px}
/* ═══════════════════════════════════════════════════════════════════════════
   BUTTON SHADOWS — Sitio de fondo oscuro (#0b1220 / #060912): se usan sombras
   con componente blanco/claro para dar relieve y separar los botones de las
   tarjetas redondeadas y títulos que comparten el mismo marco rectanguluar.

   Dos capas por botón:
     1. Capa oscura inferior (profundidad / drop-shadow clásico).
     2. Capa blanca/azulada superior (borde de luz que recorta la silueta del
        botón sobre el fondo oscuro — es lo que lo hace "saltar").
   Más un highlight inset sutil en la arista superior (simula luz cenital).
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Botón primario (azul degradado) ── */
button {
  cursor: pointer;
  background: linear-gradient(180deg,#1d9bf0,#1477c9);
  border: none;
  box-shadow:
    0 4px 10px rgba(0,0,0,.55),          /* sombra oscura — profundidad       */
    0 1px 3px  rgba(0,0,0,.40),          /* sombra corta — suelo              */
    0 0  0 1px rgba(255,255,255,.10),    /* borde blanco sutil — silueta      */
    inset 0 1px 0 rgba(255,255,255,.18); /* highlight arista superior         */
  text-shadow: 0 1px 2px rgba(0,0,0,.40);
  transition: box-shadow .15s ease, filter .15s ease, transform .1s ease;
}
button:hover {
  box-shadow:
    0 6px 16px rgba(0,0,0,.60),
    0 2px 5px  rgba(0,0,0,.45),
    0 0  0 1px rgba(255,255,255,.18),
    inset 0 1px 0 rgba(255,255,255,.22);
  filter: brightness(1.08);
}
button:active {
  box-shadow:
    0 2px 5px  rgba(0,0,0,.50),
    0 0  0 1px rgba(255,255,255,.10),
    inset 0 1px 0 rgba(255,255,255,.10);
  transform: translateY(1px);
  filter: brightness(0.96);
}

/* ── Botón secundario (fondo muy oscuro) ── */
button.secondary {
  background: #0b1424;
  border: 1px solid #264169;
  box-shadow:
    0 4px 10px rgba(0,0,0,.55),
    0 1px 3px  rgba(0,0,0,.40),
    0 0  0 1px rgba(100,160,255,.10),
    inset 0 1px 0 rgba(255,255,255,.07);
}
button.secondary:hover {
  box-shadow:
    0 6px 16px rgba(0,0,0,.60),
    0 2px 5px  rgba(0,0,0,.45),
    0 0  0 1px rgba(100,160,255,.18),
    inset 0 1px 0 rgba(255,255,255,.10);
  filter: brightness(1.12);
}

/* ── Botón de limpiar filtros (#clearBtn — amarillo) ── */
#clearBtn {
  background: #ffd400;
  color: #111;
  border-color: #e6be00;
  box-shadow:
    0 4px 10px rgba(0,0,0,.50),
    0 1px 3px  rgba(0,0,0,.35),
    0 0  0 1px rgba(255,255,160,.25),
    inset 0 1px 0 rgba(255,255,255,.35);
  text-shadow: 0 1px 1px rgba(0,0,0,.15);
}
#clearBtn:hover {
  box-shadow:
    0 6px 16px rgba(0,0,0,.55),
    0 2px 5px  rgba(0,0,0,.38),
    0 0  0 1px rgba(255,255,160,.35),
    inset 0 1px 0 rgba(255,255,255,.45);
  filter: brightness(0.97);
}

/* ── Botón toggle de filtros espejo (.fm-toggle — azul suave) ── */
.filters-mirror .fm-toggle {
  display: none;
  width: 100%;
  text-align: left;
  padding: 8px 12px;
  background: rgba(74,144,217,0.10);
  border: 1px solid rgba(74,144,217,0.30);
  border-radius: 6px;
  color: #e8eefc;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  letter-spacing: 0.3px;
  position: relative;
  box-shadow:
    0 3px 8px  rgba(0,0,0,.45),
    0 1px 2px  rgba(0,0,0,.35),
    0 0  0 1px rgba(126,207,244,.12),
    inset 0 1px 0 rgba(255,255,255,.08);
  text-shadow: 0 1px 2px rgba(0,0,0,.35);
}
.filters-mirror .fm-toggle:hover {
  box-shadow:
    0 5px 14px rgba(0,0,0,.50),
    0 2px 4px  rgba(0,0,0,.38),
    0 0  0 1px rgba(126,207,244,.22),
    inset 0 1px 0 rgba(255,255,255,.12);
  filter: brightness(1.1);
}

/* ── Botón .btn-inline (navegación admin — fondo muy oscuro) ── */
.btn-inline {
  display: inline-block;
  padding: 6px 10px;
  border-radius: 10px;
  border: 1px solid #264169;
  background: #0b1424;
  color: #e8eefc;
  text-decoration: none;
  margin-left: 8px;
  font-size: 13px;
  box-shadow:
    0 3px 8px  rgba(0,0,0,.50),
    0 1px 2px  rgba(0,0,0,.38),
    0 0  0 1px rgba(100,160,255,.08),
    inset 0 1px 0 rgba(255,255,255,.07);
  text-shadow: 0 1px 2px rgba(0,0,0,.35);
  transition: box-shadow .15s ease, filter .15s ease;
}
.btn-inline:hover {
  box-shadow:
    0 5px 14px rgba(0,0,0,.55),
    0 2px 4px  rgba(0,0,0,.40),
    0 0  0 1px rgba(100,160,255,.18),
    inset 0 1px 0 rgba(255,255,255,.10);
  filter: brightness(1.2);
}
.kpi{display:grid;grid-template-columns:repeat(5,1fr);gap:14px;margin-top:16px}
.kpi .item{background:#0b1424;border:1px solid #223355;border-radius:14px;padding:14px}
small{color:var(--muted)} .table{width:100%;border-collapse:collapse;margin-top:10px} .table th,.table td{padding:8px;border-bottom:1px solid #223355;text-align:left}
/* CSS sticky headers (desktop only). On mobile the JS float bar takes over, so we
   disable CSS sticky there to avoid two headers showing at once. */
.table thead th {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  z-index: 5;
  background: #0e1726;
  background-clip: padding-box;
  box-shadow: inset 0 -2px 0 0 #4a90d9;
}
body.is-mobile .table thead th {
  position: static;   /* JS float header handles mobile */
}
/* Sortable headers: hover style + cursor */
.table thead th.sortable-h:hover {
  background: #15243d;
  color: #7ecff4;
}
/* Floating cloned header bar built by setupStickyHeaders() in JS */
.sticky-head-float {
  box-shadow: 0 4px 10px rgba(0,0,0,0.45);
}
.sticky-head-float table thead th {
  position: static;            /* clone doesn't need sticky; the bar itself is fixed */
  box-shadow: inset 0 -2px 0 0 #4a90d9;
  background: #0e1726;
}
.badge{display:inline-block;padding:2px 8px;border-radius:999px;background:#122341;border:1px solid #25406a;color:#9cc9ff;font-size:12px}
.footer{margin-top:18px;color:var(--muted);font-size:12px} .link{color:#9cd3ff;text-decoration:none}
.alert{padding:10px 12px;border-radius:12px;background:#21120b;border:1px solid #5a341f;color:#ffd9c0;margin:10px 0}
.success{background:#0e1b18;border-color:#1d4d45;color:#bff3ea}
.logo-top{position:fixed; top:8px; right:12px; z-index:9999; display:block}
.logo-top img{height:64px; width:64px; object-fit:contain; opacity:0.99;image-rendering: -webkit-optimize-contrast;  }
@media (max-width:600px){ .logo-top img{height:40px; width:40px} }
/* (btn-inline consolidated in the BUTTON SHADOWS block above) */
.btn-inline:hover{filter:brightness(1.2)} .header-flex{display:flex;align-items:center;gap:12px;flex-wrap:wrap} .header-flex .spacer{flex:1 1 auto}
.kv{display:inline-block;background:#0b1424;border:1px solid #223355;border-radius:10px;padding:6px 10px;font-size:13px}

/* (clearBtn and btn-inline rules consolidated in the BUTTON SHADOWS block above) */




/* ===== Encabezado con degradado diagonal y relieve ===== */
.header-title {
  background: linear-gradient(135deg, #20b2aa 0%, #0f4c81 100%);
  text-align: center;
  padding: 28px 0 30px;
  border-radius: 10px;
  margin-bottom: 24px;
  color: #fff;
  box-shadow: 0 5px 12px rgba(0,0,0,0.25);
}
.header-title .logo-large {
  height: 90px;
  width: auto;
  display: block;
  margin: 0 auto 12px;
  filter: drop-shadow(0 3px 5px rgba(0,0,0,0.35));
}
.header-title h1 {
  font-size: 28px;
  font-weight: 700;
  margin: 0;
  text-shadow: 1px 1px 4px rgba(0,0,0,0.35);
}

/* Tab headers (no logo inside) use a slimmer style for the web app */
.tab .header-title {
  padding: 8px 16px;
  margin-bottom: 8px;
  border-radius: 8px;
  box-shadow: 0 3px 8px rgba(0,0,0,0.20);
}
.tab .header-title h1 {
  font-size: 18px;
  text-shadow: 0 1px 2px rgba(0,0,0,0.30);
  letter-spacing: 0.3px;
  line-height: 1.2;
}
@media (max-width: 760px) {
  .tab .header-title {
    padding: 6px 12px;
    margin-bottom: 6px;
  }
  .tab .header-title h1 {
    font-size: 15px;
  }
}

/* Fecha inputs visibles */
input[type="date"]{background:#14365f;border:1px solid rgba(31,178,171,.75);color:#ffffff;}
input[type="date"]::-webkit-calendar-picker-indicator{filter:invert(1);opacity:.95;}


/* Calendario visible (amarillo claro) */
input[type="date"]{
  background:#1a2e4f;
  border:2px solid #FFD54F;
  color:#ffffff;
}
input[type="date"]::-webkit-calendar-picker-indicator{
  background-color:#FFD54F;
  color:#000;
  border-radius:6px;
  padding:4px;
  cursor:pointer;
  opacity:1;
  filter:none;
}

/* Resaltado fila TOTAL */
.row-total{
  background: rgba(255, 213, 79, 0.25);
  border-top: 3px solid #FFD54F;
}
.row-total td{
  font-weight:700;
  padding:7px 8px;
}
.row-total td:not(:first-child){
  text-align: right;
}


/* ── Responsive: stack all grids vertically on mobile ──────────────────────── */
@media (max-width: 700px) {
  .container { padding: 2px 10px 12px 10px; }
  .card { padding: 14px 12px; border-radius: 12px; }

  /* Filter rows: 1 column */
  .row  { grid-template-columns: 1fr !important; }
  .row3 { grid-template-columns: 1fr !important; }

  /* KPI items: 2 columns on mobile, 1 when very narrow */
  .kpi  { grid-template-columns: repeat(2,1fr) !important; }

  /* Header flex: stack vertically */
  .header-flex { flex-direction: column; align-items: flex-start; gap: 6px; }
  .header-flex .spacer { display: none; }

  /* Sales cards (Año Actual / Mes Anterior / Mes Actual) */
  #salesCardsRow { flex-direction: column !important; gap: 8px !important; }

  /* KPI analytics row */
  #analyticsKpiRow { flex-direction: column !important; gap: 8px !important; }

  /* Button row */
  .btn-row { flex-direction: column; }
  .btn-row button { width: 100%; }

  /* Tables: allow horizontal scroll instead of overflow */
  .table { font-size: 12px; }
  fieldset { padding: 10px 8px !important; }

  /* Tabs: wrap and smaller text */
  .tabs { flex-wrap: wrap; gap: 4px; }
  .tabs button { font-size: 12px; padding: 7px 8px; flex: 1 1 auto; min-width: 120px;
                 box-shadow: 0 3px 8px rgba(0,0,0,.55), 0 1px 3px rgba(0,0,0,.40); }

  h1 { font-size: 20px; }
  h2 { font-size: 17px; }
  h3 { font-size: 15px; }
}
@media (max-width: 420px) {
  .kpi { grid-template-columns: 1fr !important; }
  #salesCardsRow > div { min-width: unset !important; }
}

/* Tabs navigation bar */
.tabs { display: flex; gap: 6px; padding: 12px 16px; background: rgba(0,0,0,.30);
        flex-wrap: wrap; justify-content: center; }
.tabs button { flex: 0 0 auto; width: auto; padding: 9px 14px; font-size: 13px;
               border-radius: 10px; white-space: nowrap;
               box-shadow: 0 3px 8px rgba(0,0,0,.55), 0 1px 3px rgba(0,0,0,.40);
               text-shadow: 0 1px 2px rgba(0,0,0,.45); }

/* ── Pestaña activa: texto amarillo en menú desktop y hamburguesa ──────────
   body[data-active-tab] se actualiza en _showTabNoHistory() en cada cambio
   de pestaña; los botones/links llevan data-tab="<nombre>" para que el
   selector sea genérico (no hay que tocar el JS si se añaden más pestañas). */
body[data-active-tab] #tabsBar button[data-tab] {
  /* estado inactivo: aspecto normal, nada especial */
}
body[data-active-tab="main"]      #tabsBar button[data-tab="main"],
body[data-active-tab="history"]   #tabsBar button[data-tab="history"],
body[data-active-tab="chart"]     #tabsBar button[data-tab="chart"],
body[data-active-tab="product"]   #tabsBar button[data-tab="product"],
body[data-active-tab="trends"]    #tabsBar button[data-tab="trends"],
body[data-active-tab="analytics"] #tabsBar button[data-tab="analytics"] {
  color: #FFD400;
  text-shadow: 0 0 8px rgba(255,212,0,.55), 0 1px 2px rgba(0,0,0,.50);
  box-shadow:
    0 4px 12px rgba(0,0,0,.60),
    0 1px 3px  rgba(0,0,0,.45),
    0 0  0 1px rgba(255,212,0,.25),
    inset 0 1px 0 rgba(255,255,255,.18);
}
/* Menú hamburguesa: mismo principio, usando .mm-items a[data-tab] */
body[data-active-tab="main"]      .mm-items a[data-tab="main"],
body[data-active-tab="history"]   .mm-items a[data-tab="history"],
body[data-active-tab="chart"]     .mm-items a[data-tab="chart"],
body[data-active-tab="product"]   .mm-items a[data-tab="product"],
body[data-active-tab="trends"]    .mm-items a[data-tab="trends"],
body[data-active-tab="analytics"] .mm-items a[data-tab="analytics"] {
  color: #FFD400;
  border-left-color: #FFD400;
  text-shadow: 0 0 8px rgba(255,212,0,.50);
  background: rgba(255,212,0,.06);
  font-weight: 700;
}

/* Resaltado fila TOTAL */
.row-total{
  background: rgba(255, 213, 79, 0.25);
  border-top: 3px solid #FFD54F;
}
.row-total td{
  font-weight:700;
}

/* Resaltado TOTAL - Informe clientes por compras */
.row-total-clients{
  background: rgba(31,178,171,0.25);
  border-top: 3px solid #1FB2AB;
  border-bottom: 3px solid #1FB2AB;
}
.row-total-clients td{
  font-weight:700;
}

/* Driver/Dependent/Autonomous grid - 3 columns on desktop, stacked on mobile */
@media (min-width: 900px) {
  .dpa-grid { grid-template-columns: 1fr 1fr 1fr !important; }
}

/* ─── Mobile hamburger menu ───────────────────────────────────────────────── */
/* Default (desktop): EVERY mobile-only element is hidden */
#mobileMenuBtn,
#mobileMenuPanel,
#mobileMenuBackdrop { display: none !important; }

/* When body has .is-mobile, show only the hamburger button.
   Panel and backdrop still hidden until .mm-open is toggled. */
body.is-mobile #mobileMenuBtn {
  display: flex !important;
  position: fixed;
  top: 14px;
  right: 14px;
  width: 46px;
  height: 46px;
  background: rgba(74,144,217,0.95);
  border: none;
  border-radius: 12px;
  cursor: pointer;
  z-index: 2147483647;  /* maximum int, always on top */
  padding: 0;
  box-shadow: 0 4px 14px rgba(0,0,0,0.4);
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 5px;
  transition: transform .18s ease, background .18s ease;
  isolation: isolate;
}
body.is-mobile #mobileMenuBtn:active { transform: scale(0.93); }
body.is-mobile #mobileMenuBtn span {
  display: block;
  width: 22px;
  height: 3px;
  background: #fff;
  border-radius: 2px;
  transition: transform .25s ease, opacity .2s ease;
}
/* Hide desktop tabs on mobile */
body.is-mobile .tabs { display: none !important; }
/* Hide desktop logo-top on mobile (hamburger button replaces it) */
body.is-mobile .logo-top { display: none !important; }
/* Reserve space at top for the floating hamburger button */
body.is-mobile { padding-top: 64px; overflow-x: hidden; }
/* Tab content: keep max-width but DON'T set overflow-x:hidden here. Setting it on .tab
   or .container creates additional sticky-positioning contexts that break the sticky
   table headers. The body already has overflow-x:hidden which prevents horizontal page scroll. */
body.is-mobile .tab { max-width: 100%; }
body.is-mobile .container { max-width: 100% !important; }
body.is-mobile canvas { max-width: 100% !important; height: auto !important; }

/* ─── Opt-in horizontal scroll for SPECIFIC wide tables ──────────────────── */
/* Use class .scroll-x on a wrapper div around a wide table. Shows an arrow hint.
   ONLY scrolls horizontally on mobile; on desktop the table fits naturally. */
.scroll-x { position: relative; max-width: 100%; }

body.is-mobile .scroll-x {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
/* Fieldset has special browser behavior that prevents overflow children from working
   correctly. Force display:block within the .scroll-x to fix this. */
body.is-mobile fieldset {
  display: block;
  min-width: 0;
}
body.is-mobile .scroll-x > table {
  min-width: 600px;
  width: auto;
  max-width: none;
}
body.is-mobile .scroll-x > table th,
body.is-mobile .scroll-x > table td {
  white-space: nowrap;
}

/* ─── Scroll hint badges ──────────────────────────────────────────────────
   We use position:FIXED (not sticky) because the outer .container has
   overflow-x:hidden which would clip sticky behavior. JS toggles visibility
   based on whether the corresponding table is in the viewport. */
.scroll-x-outer { position: relative; max-width: 100%; }

/* Badges live in body, position:fixed. The `top` value is set dynamically by JS:
   - When the table header is visible: badge aligns with the table header
   - When the table header has scrolled off-screen: badge sticks at top:70px (below hamburger) */
.scroll-hint-badge {
  position: fixed;
  top: 70px;            /* default; JS may override via inline style */
  background: rgba(255, 252, 220, 0.96);
  color: #5a4400;
  font-size: 11px;
  font-weight: 700;
  padding: 4px 10px;
  border-radius: 12px;
  z-index: 9000;
  pointer-events: none;
  letter-spacing: .3px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.35);
  border: 1px solid rgba(255, 248, 168, 0.85);
  white-space: nowrap;
  opacity: 0;
  visibility: hidden;
  transition: opacity .25s ease, visibility .25s ease, top .15s ease;
  display: none;
}
body.is-mobile .scroll-hint-badge { display: block; }
.scroll-hint-badge.is-visible {
  opacity: 1;
  visibility: visible;
}
.scroll-hint-right {
  right: 14px;
  animation: scrollHintBounce 1.8s ease-in-out infinite;
}
.scroll-hint-left {
  left: 14px;
  animation: scrollHintBounceLeft 1.8s ease-in-out infinite;
}
/* Remove the old pseudo-element styles (kept for backward CSS compatibility but disabled) */
body.is-mobile .scroll-x::before,
body.is-mobile .scroll-x-hint::before,
body.is-mobile .scroll-x::after,
body.is-mobile .scroll-x-hint::after { content: none !important; display: none !important; }
.scroll-x-hint { position: relative; }
@keyframes scrollHintBounce {
  0%, 100% { transform: translateX(0); }
  50%      { transform: translateX(-6px); }
}
@keyframes scrollHintBounceLeft {
  0%, 100% { transform: translateX(0); }
  50%      { transform: translateX(6px); }
}

/* .fit-w → force the table to fit the container without horizontal scroll.
   Used for Probabilidad de Recompra and Clientes en Riesgo (must remain compact). */
.fit-w { max-width: 100%; overflow: hidden; }
.fit-w > table { width: 100%; max-width: 100%; table-layout: auto; }
body.is-mobile .fit-w > table { font-size: 11px; }
body.is-mobile .fit-w > table th,
body.is-mobile .fit-w > table td {
  padding: 5px 6px !important;
  white-space: normal;
  word-break: break-word;
}

/* Vendor summary keeps its own scroll wrap and sticky behavior */
body.is-mobile #vendorSummaryWrap { overflow-x: auto !important; }

/* Hamburger → X when open */
body.is-mobile.mm-open #mobileMenuBtn span:nth-child(1) { transform: translateY(8px) rotate(45deg); }
body.is-mobile.mm-open #mobileMenuBtn span:nth-child(2) { opacity: 0; }
body.is-mobile.mm-open #mobileMenuBtn span:nth-child(3) { transform: translateY(-8px) rotate(-45deg); }

/* Backdrop & panel: ONLY visible when .mm-open is set on body */
body.is-mobile.mm-open #mobileMenuBackdrop {
  display: block !important;
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.55);
  z-index: 2147483645;
  opacity: 1;
  backdrop-filter: blur(2px);
  animation: mmFadeIn .25s ease;
}
@keyframes mmFadeIn {
  from { opacity: 0; } to { opacity: 1; }
}

body.is-mobile.mm-open #mobileMenuPanel {
  display: flex !important;
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: 280px;
  max-width: 84vw;
  background: linear-gradient(180deg, #0f1c33 0%, #0b1424 100%);
  z-index: 2147483646;
  box-shadow: -8px 0 28px rgba(0,0,0,0.55);
  flex-direction: column;
  overflow-y: auto;
  animation: mmPanelSlideIn .32s cubic-bezier(.4,0,.2,1);
}
@keyframes mmPanelSlideIn {
  from { transform: translateX(100%); }
  to   { transform: translateX(0); }
}

.mm-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 22px 18px 18px;
  border-bottom: 1px solid rgba(255,255,255,0.08);
  background: rgba(74,144,217,0.06);
}
.mm-header img {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: #fff;
  padding: 4px;
  object-fit: contain;
}
.mm-header span {
  color: #e8eefc;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: .3px;
}

.mm-items {
  display: flex;
  flex-direction: column;
  padding: 12px 0;
}
.mm-items a {
  display: block;
  padding: 14px 22px;
  color: #d8e4f5;
  text-decoration: none;
  font-size: 14.5px;
  border-left: 3px solid transparent;
  cursor: pointer;
  transition: background .18s ease, border-color .18s ease, color .18s ease, padding-left .18s ease;
}
.mm-items a:hover, .mm-items a:active {
  background: rgba(74,144,217,0.10);
  border-left-color: #4a90d9;
  color: #fff;
  padding-left: 26px;
}

/* Staircase reveal animation when menu opens */
body.is-mobile.mm-open .mm-items a {
  opacity: 0;
  transform: translateX(30px);
  animation: mmItemSlideIn .42s cubic-bezier(.2,.7,.3,1) forwards;
}
body.is-mobile.mm-open .mm-items a:nth-child(1) { animation-delay: .12s; }
body.is-mobile.mm-open .mm-items a:nth-child(2) { animation-delay: .18s; }
body.is-mobile.mm-open .mm-items a:nth-child(3) { animation-delay: .24s; }
body.is-mobile.mm-open .mm-items a:nth-child(4) { animation-delay: .30s; }
body.is-mobile.mm-open .mm-items a:nth-child(5) { animation-delay: .36s; }
body.is-mobile.mm-open .mm-items a:nth-child(6) { animation-delay: .42s; }
body.is-mobile.mm-open .mm-items a:nth-child(7) { animation-delay: .48s; }

@keyframes mmItemSlideIn {
  0%   { opacity: 0; transform: translateX(30px); }
  60%  { opacity: 1; transform: translateX(-3px); }
  100% { opacity: 1; transform: translateX(0); }
}

/* ─── Tree pulse animation on login screen ──────────────────────────────── */
@keyframes treePulse {
  0%, 100% {
    transform: scale(1) rotate(0deg);
    filter: drop-shadow(0 4px 12px rgba(74,144,217,0.25));
  }
  50% {
    transform: scale(1.06) rotate(1deg);
    filter: drop-shadow(0 8px 24px rgba(32,201,184,0.45));
  }
}
#vendorLoadingImg {
  background: #ffffff;
  border-radius: 50%;
  padding: 14px;
  box-shadow: 0 6px 22px rgba(74,144,217,0.25), 0 0 0 4px rgba(74,144,217,0.15);
  border: 3px solid rgba(74,144,217,0.40);
  box-sizing: border-box;
}

/* ─── Floating Loading Overlay (Calculando...) ─────────────────────────────── */
#loadingOverlay {
  position: fixed;
  inset: 0;
  display: none;             /* shown via JS */
  align-items: center;
  justify-content: center;
  background: rgba(11, 20, 36, 0.78);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  z-index: 2147483647;
  animation: loFadeIn .35s ease;
}
@keyframes loFadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
#loadingOverlay.lo-fade-out {
  animation: loFadeOut .45s ease forwards;
}
@keyframes loFadeOut {
  from { opacity: 1; }
  to   { opacity: 0; }
}

.lo-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 20px;
  padding: 32px 40px;
  background: linear-gradient(180deg, rgba(15,28,51,0.95) 0%, rgba(11,20,36,0.95) 100%);
  border: 1px solid rgba(74,144,217,0.30);
  border-radius: 22px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.55), 0 0 0 1px rgba(255,255,255,0.04) inset;
  max-width: 88vw;
}

#loadingOverlayImg {
  width: 160px;
  height: 160px;
  object-fit: contain;
  background: #ffffff;
  border-radius: 50%;
  padding: 14px;
  border: 3px solid rgba(74,144,217,0.45);
  box-shadow: 0 6px 22px rgba(74,144,217,0.30), 0 0 0 6px rgba(74,144,217,0.10);
  box-sizing: border-box;
  animation: treePulse 1.8s ease-in-out infinite;
}

.lo-text {
  font-size: 18px;
  font-weight: 700;
  letter-spacing: 1.5px;
  color: #e8eefc;
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
}
.lo-dots { display: inline-flex; margin-left: 4px; }
.lo-dots span {
  opacity: 0;
  animation: loDot 1.4s infinite;
  font-weight: 700;
}
.lo-dots span:nth-child(1) { animation-delay: 0s; }
.lo-dots span:nth-child(2) { animation-delay: 0.2s; }
.lo-dots span:nth-child(3) { animation-delay: 0.4s; }
@keyframes loDot {
  0%, 100% { opacity: 0; }
  40%      { opacity: 1; }
  80%      { opacity: 0; }
}

/* Smaller overlay image on very small screens */
@media (max-width: 480px) {
  #loadingOverlayImg { width: 130px; height: 130px; padding: 12px; }
  .lo-text { font-size: 16px; letter-spacing: 1.2px; }
  .lo-content { padding: 24px 28px; gap: 16px; }
}

/* ─── Vendor summary table: hover y selección de fila ───────────────────── */
#vendorSummaryTable tbody tr[data-vendor] {
  cursor: pointer;
  transition: background .15s ease, color .15s ease, outline .1s ease;
}
#vendorSummaryTable tbody tr[data-vendor]:hover {
  filter: brightness(1.12);
}

/* ─── Sticky first column for vendor summary table ────────────────────────── */
#vendorSummaryTable .vsticky {
  position: sticky;
  left: 0;
  z-index: 2;
  box-shadow: 4px 0 8px -4px rgba(0,0,0,0.55);
}
/* Header cell: needs its own background since the row's bg won't show under sticky */
#vendorSummaryTable .vsticky-head {
  background: #2a3958;
  z-index: 3;  /* above body sticky cells when scrolling vertically */
}
/* Sticky col on mobile gets a max-width so it doesn't dominate the screen */
@media (max-width: 760px) {
  #vendorSummaryTable .vsticky {
    min-width: 130px;
    max-width: 150px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

/* ─── Vendor summary table: ensure horizontal scroll happens INSIDE the wrap ── */
/* Desktop: table fills 100% of the card with no horizontal scroll.
   Mobile: falls back to the existing horizontal scroll via overflow-x:auto.
   table-layout:fixed + width:100% lets the browser distribute columns
   proportionally; the sticky column gets a fixed width and the 8 numeric
   columns share the rest equally. */
#vendorSummaryWrap {
  overflow-x: auto !important;   /* auto = scroll only when needed */
  overflow-y: visible;
  -webkit-overflow-scrolling: touch;
  position: relative;
  max-width: 100%;
}
#vendorSummaryTable {
  table-layout: fixed;
  width: 100%;
  min-width: 0;   /* override old 720px — desktop no longer needs forced scroll */
}
/* Sticky column: fixed width so numeric columns can share the rest */
#vendorSummaryTable th.vsticky,
#vendorSummaryTable td.vsticky {
  width: 148px;
  min-width: 148px;
  max-width: 148px;
}
/* Numeric columns: equal share of whatever remains after the sticky column.
   Expressed as percentage so the table always fills its container. */
#vendorSummaryTable th:not(.vsticky),
#vendorSummaryTable td:not(.vsticky) {
  width: calc((100% - 148px) / 8);
}
/* Header text: two lines allowed, centered */
#vendorSummaryTable thead th:not(.vsticky) {
  white-space: normal;
  word-break: keep-all;
  line-height: 1.25;
  font-size: 11.5px;
  vertical-align: bottom;
  text-align: right;
}
/* Data cells: always single line, compact font */
#vendorSummaryTable tbody td:not(.vsticky),
#vendorSummaryTable tfoot td:not(.vsticky) {
  white-space: nowrap;
  font-size: 12px;
  font-variant-numeric: tabular-nums;  /* digits all same width for alignment */
}
/* Critical: sticky position */
#vendorSummaryTable th.vsticky,
#vendorSummaryTable td.vsticky {
  position: -webkit-sticky;
  position: sticky;
  left: 0;
  z-index: 5;
}
/* Stronger shadow to make the separation clear */
#vendorSummaryTable th.vsticky::after,
#vendorSummaryTable td.vsticky::after {
  content: "";
  position: absolute;
  top: 0;
  right: -10px;
  width: 10px;
  height: 100%;
  background: linear-gradient(90deg, rgba(0,0,0,0.45) 0%, rgba(0,0,0,0) 100%);
  pointer-events: none;
}

/* On mobile in-app, also constrain the column width */
body.is-mobile #vendorSummaryTable .vsticky {
  min-width: 140px;
  max-width: 160px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Mobile: restore fixed min-width so the table scrolls horizontally
   (desktop uses table-layout:fixed with width:100% — no scroll needed) */
body.is-mobile #vendorSummaryTable {
  min-width: 760px;
  table-layout: auto;   /* let content determine column width on narrow screens */
}
body.is-mobile #vendorSummaryTable th:not(.vsticky),
body.is-mobile #vendorSummaryTable td:not(.vsticky) {
  width: auto;
  min-width: 90px;
}

/* ─── Mobile-only column width adjustments for Tablero Analítico tables ──── */
body.is-mobile .top5-table {
  table-layout: fixed;
}
body.is-mobile .top5-table th:nth-child(1),
body.is-mobile .top5-table td:nth-child(1) {
  width: 38%;
  word-wrap: break-word;
  word-break: break-word;
  white-space: normal;
  font-size: 11px;
  padding: 6px 4px !important;
}
body.is-mobile .top5-table th:nth-child(2),
body.is-mobile .top5-table td:nth-child(2) {
  width: 44%;
  white-space: nowrap;
  font-size: 11.5px;
  padding: 6px 4px !important;
}
body.is-mobile .top5-table th:nth-child(3),
body.is-mobile .top5-table td:nth-child(3) {
  width: 18%;
  white-space: nowrap;
  font-size: 11px;
  padding: 6px 2px !important;
}

/* Cross-sell table: client name 2 lines, recommendations stacked vertically */
body.is-mobile .cross-sell-table {
  table-layout: fixed;
}
body.is-mobile .cross-sell-table th:nth-child(1),
body.is-mobile .cross-sell-table td:nth-child(1) {
  width: 28%;
  word-wrap: break-word;
  word-break: break-word;
  white-space: normal;
  font-size: 11px;
  padding: 6px 4px !important;
  line-height: 1.25;
}
body.is-mobile .cross-sell-table th:nth-child(2),
body.is-mobile .cross-sell-table td:nth-child(2) {
  width: 14%;
  font-size: 11px;
  padding: 6px 2px !important;
}
body.is-mobile .cross-sell-table th:nth-child(3),
body.is-mobile .cross-sell-table td:nth-child(3) {
  width: 58%;
  font-size: 11px;
  padding: 6px 4px !important;
  white-space: normal;
}
/* Make the recommendation pills stack one per line */
body.is-mobile .cross-sell-table td:nth-child(3) span {
  display: block !important;
  white-space: normal !important;
  margin: 3px 0 !important;
  word-break: break-word;
}

/* ─── Collapsible analytics sections ───────────────────────────────────── */
.collapsible-section > legend,
.collapsible-section > h3 {
  position: relative;
  transition: color .2s ease;
}
.collapsible-section > legend:hover,
.collapsible-section > h3:hover {
  color: #7ecff4 !important;
}
/* When collapsed, hide everything except legend AND h3 (one of these is the header) */
.collapsible-section.collapsed > *:not(legend):not(h3) {
  display: none !important;
}
.collapsible-section.collapsed {
  padding-bottom: 14px !important;
}

/* ─── Login layout: centered cards ─────────────────────────────────────── */
.login-container {
  min-height: calc(100vh - 40px);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 16px;
  padding: 24px 16px;
  max-width: 460px !important;
}
.login-card {
  width: 100%;
  max-width: 420px;
  margin: 0 auto;
}
.login-card h1 {
  font-size: 22px;
  background: linear-gradient(90deg, #4a90d9, #20c9b8);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.login-admin-card {
  width: 100%;
  max-width: 420px;
  margin: 0 auto;
  background: rgba(255,255,255,0.025) !important;
  border: 1px dashed rgba(74,144,217,0.25);
  padding: 14px 18px !important;
}
.login-admin-card a.link:hover {
  background: rgba(74,144,217,0.18) !important;
  border-color: rgba(74,144,217,0.7) !important;
}

/* ─── Informe de Ventas por Producto: separación visual entre las dos secciones ─── */
.product-section-2 {
  margin-top: 36px;
  padding: 22px 18px 22px 18px;
  background: linear-gradient(180deg, rgba(32,201,184,0.05) 0%, rgba(74,144,217,0.08) 100%);
  border: 1px solid rgba(74,144,217,0.20);
  border-radius: 14px;
  position: relative;
}
.product-section-divider {
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  margin: 0 0 14px 0;
  padding-top: 6px;
}
.product-section-divider::before,
.product-section-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, transparent 0%, rgba(74,144,217,0.45) 50%, transparent 100%);
}
.product-section-divider span {
  padding: 6px 16px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: #002a3d;
  background: #66ddff;            /* light neon blue (default — Análisis por Ciudad) */
  border-radius: 12px;
  border: 1px solid #2bbef5;
  box-shadow: 0 0 12px rgba(102, 221, 255, 0.55), 0 0 4px rgba(102, 221, 255, 0.85) inset;
  text-shadow: 0 0 4px rgba(255,255,255,0.55);
}

/* Override: "Análisis por los clientes de la ciudad" section uses a deeper purple-blue tint
   to differentiate it from "Análisis por Ciudad" (which uses a teal-blue gradient) */
#productSection2 {
  background: linear-gradient(180deg, rgba(94, 92, 230, 0.16) 0%, rgba(58, 84, 180, 0.22) 100%) !important;
  border: 2px solid rgba(122, 118, 220, 0.45) !important;
  box-shadow: 0 0 18px rgba(94, 92, 230, 0.10) inset;
}
#productSection2 .product-section-divider::before,
#productSection2 .product-section-divider::after {
  background: linear-gradient(90deg, transparent 0%, rgba(122, 118, 220, 0.55) 50%, transparent 100%);
}
#productSection2 .product-section-divider span {
  color: #002a3d;
  background: #66ddff;            /* light neon blue (same badge as Análisis por Ciudad) */
  border-color: #2bbef5;
  box-shadow: 0 0 12px rgba(102, 221, 255, 0.55), 0 0 4px rgba(102, 221, 255, 0.85) inset;
}
/* Keep fieldset legends inside this section in original blue for legibility */
#productSection2 fieldset legend {
  color: #4a90d9;
}

/* ─── Sombra en selectores de filtro (fondo oscuro → sombra con componente claro) ───
   Aplica a todos los <select> que aparecen dentro de filtros/fieldsets/controles
   de la app. Los selects tienen fondo oscuro (#0f1c33 / #1a2e4f / #0b1424) así que
   la sombra usa un borde de luz blanco/azulado para recortar la silueta,
   igual que los botones. Se usa una clase compartida (.sel-shadow) que se
   asigna por JS al cargar (ver initSelectShadows) para no tocar cientos de
   inline-styles dispersos. También se declaran IDs específicos para los
   selects de tendencias y los botones de rol de Leonardo que ya tienen
   estilos inline con border-radius propios. */
.sel-shadow,
#brandFilterClient,
#brandFilterProduct,
#trProd,
#trClient,
#trPeriodSelect {
  box-shadow:
    0 3px 8px  rgba(0,0,0,.55),
    0 1px 2px  rgba(0,0,0,.40),
    0 0  0 1px rgba(126,207,244,.14),
    inset 0 1px 0 rgba(255,255,255,.06);
  transition: box-shadow .15s ease;
}
.sel-shadow:focus,
#brandFilterClient:focus,
#brandFilterProduct:focus,
#trProd:focus,
#trClient:focus,
#trPeriodSelect:focus {
  box-shadow:
    0 4px 12px rgba(0,0,0,.60),
    0 1px 3px  rgba(0,0,0,.45),
    0 0  0 2px rgba(74,144,217,.65),
    inset 0 1px 0 rgba(255,255,255,.08);
  outline: none;
}

/* Botones de rol Vendedor / Jefe de Ventas (Leonardo) — tienen fondo propio
   (#4a90d9 activo, transparente inactivo), ambos sobre fondo oscuro */
#roleBtnVendedor,
#roleBtnJefe {
  box-shadow:
    0 4px 10px rgba(0,0,0,.55),
    0 1px 3px  rgba(0,0,0,.40),
    0 0  0 1px rgba(255,255,255,.12),
    inset 0 1px 0 rgba(255,255,255,.18);
  text-shadow: 0 1px 2px rgba(0,0,0,.40);
  transition: box-shadow .15s ease, filter .15s ease, transform .1s ease, background .2s, color .2s;
}
#roleBtnVendedor:hover,
#roleBtnJefe:hover {
  box-shadow:
    0 6px 16px rgba(0,0,0,.60),
    0 2px 5px  rgba(0,0,0,.45),
    0 0  0 1px rgba(255,255,255,.20),
    inset 0 1px 0 rgba(255,255,255,.22);
  filter: brightness(1.10);
}
#roleBtnVendedor:active,
#roleBtnJefe:active {
  box-shadow:
    0 2px 5px  rgba(0,0,0,.50),
    0 0  0 1px rgba(255,255,255,.10),
    inset 0 1px 0 rgba(255,255,255,.10);
  transform: translateY(1px);
  filter: brightness(0.96);
}

/* Botón toggle de vista (Ver gráfica / Ver como tabla) — class="secondary" ya
   hereda sombra del bloque BUTTON SHADOWS; aquí solo reforzamos el relieve
   porque en pantalla completa compite visualmente con los títulos de fieldset */
#historyChartToggle {
  box-shadow:
    0 4px 12px rgba(0,0,0,.58),
    0 1px 3px  rgba(0,0,0,.42),
    0 0  0 1px rgba(126,207,244,.16),
    inset 0 1px 0 rgba(255,255,255,.09);
}
#historyChartToggle:hover {
  box-shadow:
    0 6px 18px rgba(0,0,0,.62),
    0 2px 5px  rgba(0,0,0,.46),
    0 0  0 1px rgba(126,207,244,.28),
    inset 0 1px 0 rgba(255,255,255,.13);
  filter: brightness(1.12);
}
.filters-mirror {
  margin-bottom: 12px;
  padding: 10px 14px;
  background: rgba(74,144,217,0.06);
  border: 1px solid rgba(74,144,217,0.18);
  border-radius: 8px;
  position: relative;
}
/* (fm-toggle base styles consolidated in the BUTTON SHADOWS block above) */
/* First-time pulse: 3 seconds of breathing glow with the filter palette */
@keyframes fmPulse {
  0%, 100% {
    box-shadow:
      0 0 0   rgba(74,144,217,0.0),
      0 0 0   rgba(122,118,194,0.0);
    background: rgba(74,144,217,0.10);
    border-color: rgba(74,144,217,0.30);
  }
  50% {
    box-shadow:
      0 0 18px rgba(74,144,217,0.85),
      0 0 30px rgba(122,118,194,0.55),
      0 0 6px  rgba(126,207,244,0.65) inset;
    background: rgba(74,144,217,0.28);
    border-color: rgba(126,207,244,0.85);
  }
}
/* Container halo — softer, pulses in sync */
@keyframes fmPulseHost {
  0%, 100% {
    box-shadow: 0 0 0 0 rgba(74, 144, 217, 0.0),
                0 0 0 0 rgba(126, 207, 244, 0.0);
    border-color: rgba(74,144,217,0.18);
  }
  50% {
    box-shadow: 0 0 18px 4px rgba(74, 144, 217, 0.55),
                0 0 32px 8px rgba(126, 207, 244, 0.45),
                0 0 6px 1px rgba(126, 207, 244, 0.75) inset;
    border-color: rgba(126, 207, 244, 0.80);
  }
}
.filters-mirror.fm-pulse {
  animation: fmPulseHost 1s ease-in-out 3;
}
.filters-mirror.fm-pulse .fm-toggle {
  animation: fmPulse 1s ease-in-out 3;
}
.filters-mirror .fm-toggle .fm-chev {
  float: right;
  transition: transform .25s ease;
  color: #7ecff4;
}
.filters-mirror.collapsed .fm-toggle .fm-chev {
  transform: rotate(-90deg);
}
.filters-mirror .fm-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: flex-end;
}
.filters-mirror.collapsed .fm-row {
  display: none;            /* hide filter fields when collapsed */
}
.filters-mirror .fm-field {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.filters-mirror label {
  font-size: 12px;
  color: #aac;
  margin-bottom: 3px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.filters-mirror select,
.filters-mirror input[type="date"] {
  background: #14365f;
  border: 1px solid rgba(31,178,171,.55);
  color: #ffffff;
  width: 100%;
  min-width: 0;
  padding: 6px 8px;
  font-size: 13px;
  border-radius: 6px;
}
@media (max-width: 760px) {
  .filters-mirror .fm-field {
    flex: 1 1 100%;
  }
  /* On mobile, the toggle button is visible — filters can be collapsed */
  .filters-mirror .fm-toggle {
    display: block;
    margin-bottom: 8px;
  }
  /* Spacing between toggle and the fields when expanded */
  .filters-mirror:not(.collapsed) .fm-row {
    margin-top: 4px;
  }
}

/* Tablets (iPad, Android tablet): is-mobile is set by JS based on UA,
   but viewport width may be > 760px so the media query above doesn't fire.
   Show the toggle button and enable collapsed state on ANY is-mobile device,
   regardless of pixel width — this is what the JS collapse logic already uses. */
body.is-mobile .filters-mirror .fm-toggle {
  display: block;
  margin-bottom: 8px;
}
body.is-mobile .filters-mirror .fm-field {
  flex: 1 1 100%;
}
body.is-mobile .filters-mirror:not(.collapsed) .fm-row {
  margin-top: 4px;
}

.tab {
  /* Smooth page-turn transition when switching tabs */
  animation-duration: 300ms;
  animation-timing-function: cubic-bezier(0.22, 0.61, 0.36, 1);
  animation-fill-mode: both;
}
.tab.tab-during-anim {
  /* Prevent overflow during the cross-slide so off-screen content isn't visible */
  overflow: hidden;
}
.tab.tab-slide-in-right  { animation-name: tabSlideInRight; }
.tab.tab-slide-in-left   { animation-name: tabSlideInLeft; }
.tab.tab-slide-out-left  { animation-name: tabSlideOutLeft; }
.tab.tab-slide-out-right { animation-name: tabSlideOutRight; }
@keyframes tabSlideInRight {
  from { opacity: 0.6; transform: translateX(100%); }
  to   { opacity: 1;   transform: translateX(0); }
}
@keyframes tabSlideInLeft {
  from { opacity: 0.6; transform: translateX(-100%); }
  to   { opacity: 1;   transform: translateX(0); }
}
@keyframes tabSlideOutLeft {
  from { opacity: 1;   transform: translateX(0); }
  to   { opacity: 0.6; transform: translateX(-100%); }
}
@keyframes tabSlideOutRight {
  from { opacity: 1;   transform: translateX(0); }
  to   { opacity: 0.6; transform: translateX(100%); }
}
/* The card holds the absolutely-positioned outgoing tab during cross-slide.
   We can't use overflow-x:hidden globally (it breaks sticky table headers),
   so we apply it ONLY during the brief page-turn animation via a class. */
.card {
  position: relative;
  overflow-y: visible;
}
.card.during-tab-anim {
  overflow-x: hidden;
}

/* ─── Swipe-to-change-tab toast (mobile only) ───────────────────────── */
.swipe-toast {
  position: fixed;
  top: 78px;
  left: 50%;
  transform: translateX(-50%) translateY(-8px);
  background: linear-gradient(135deg, rgba(74,144,217,0.95) 0%, rgba(122,118,194,0.95) 100%);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  padding: 8px 18px;
  border-radius: 24px;
  box-shadow: 0 4px 14px rgba(0,0,0,0.4), 0 0 20px rgba(126,207,244,0.40);
  z-index: 9700;
  opacity: 0;
  pointer-events: none;
  white-space: nowrap;
  transition: opacity .25s ease, transform .25s ease;
  letter-spacing: 0.3px;
}
.swipe-toast.show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* ─── Floating "tap here" hint tooltips ─────────────────────────────── */
.hint-tooltip {
  position: fixed;
  background: linear-gradient(135deg, #ff9800 0%, #ff5722 100%);
  color: #fff;
  padding: 8px 14px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 700;
  box-shadow: 0 4px 14px rgba(255, 87, 34, 0.5), 0 0 20px rgba(255, 152, 0, 0.4);
  z-index: 9500;
  pointer-events: none;
  opacity: 0;
  transform: translateY(-6px) scale(1);
  transition: opacity .25s ease, transform .25s ease;
  white-space: nowrap;
  animation: hintBounce 1.1s ease-in-out infinite;
  transform-origin: center center;
}
.hint-tooltip.show {
  opacity: 1;
}
.hint-tooltip::after {
  content: '';
  position: absolute;
  bottom: -7px;
  left: 50%;
  transform: translateX(-50%);
  width: 0;
  height: 0;
  border-left: 8px solid transparent;
  border-right: 8px solid transparent;
  border-top: 8px solid #ff5722;
}
.hint-tooltip.below::after {
  bottom: auto;
  top: -7px;
  border-top: none;
  border-bottom: 8px solid #ff9800;
}
@keyframes hintBounce {
  0%, 100% {
    box-shadow: 0 4px 14px rgba(255, 87, 34, 0.50), 0 0 20px rgba(255, 152, 0, 0.40);
    transform: scale(1);
  }
  50% {
    box-shadow: 0 8px 28px rgba(255, 87, 34, 0.90), 0 0 40px rgba(255, 200, 50, 0.85), 0 0 8px rgba(255,255,255,0.6) inset;
    transform: scale(1.08);
  }
}
/* Filter-palette variant (blue/cyan) — matches the .filters-mirror glow palette */
.hint-tooltip.hint-filter {
  background: linear-gradient(135deg, #4a90d9 0%, #7a76c2 100%);
  color: #fff;
  box-shadow: 0 4px 14px rgba(74,144,217,0.55), 0 0 20px rgba(126,207,244,0.50);
  animation: hintBounceFilter 1.1s ease-in-out infinite;
}
.hint-tooltip.hint-filter::after {
  border-top-color: #4a90d9;
}
.hint-tooltip.hint-filter.below::after {
  border-top-color: transparent;
  border-bottom-color: #7a76c2;
}
@keyframes hintBounceFilter {
  0%, 100% {
    box-shadow: 0 4px 14px rgba(74,144,217,0.55), 0 0 20px rgba(126,207,244,0.50);
    transform: scale(1);
  }
  50% {
    box-shadow:
      0 8px 28px rgba(74,144,217,0.90),
      0 0 40px rgba(126,207,244,0.85),
      0 0 8px rgba(255,255,255,0.55) inset;
    transform: scale(1.08);
  }
}
/* Override scroll-x white-space:nowrap which can cause TOTAL cells to overflow visually */
.row-total td,
.row-total-clients td {
  white-space: nowrap !important;
  overflow: visible !important;
}
/* The first cell (TOTAL label) flush-left in its column */
.row-total td:first-child,
.row-total-clients td:first-child {
  text-align: left !important;
  font-weight: 700 !important;
}
/* All other cells right-aligned — inherit padding from .table td (8px) for column match */
.row-total td:not(:first-child),
.row-total-clients td:not(:first-child) {
  text-align: right !important;
}
/* Avoid TOTAL row cells expanding too much under .scroll-x rule */
.scroll-x > table .row-total td,
.scroll-x > table .row-total-clients td {
  max-width: none;
}
