/* ============================================================
   Loading skeletons (2026-07-15)
   ============================================================
   The portal boot dismisses the auth overlay when AUTH resolves, but the
   first real data render waits on dataReady (daily + history + parse). On a
   real connection that gap is several seconds, during which the static shell
   is visible. This file makes that window look INTENTIONAL: every pane that
   has no data yet shows a shimmer placeholder, never a baked/stale number,
   never an empty white canvas, never a bare gray box.

   Each render function clears its own skeleton the instant real content
   paints (renderKPIs overwrites #kpiRow; renderCharts + _renderHeatLayer call
   _clearPaneSkeleton). A skeleton NEVER transitions to a fake value -- only
   skeleton -> real, or skeleton -> a labeled empty state on failure. */

/* The shimmer sweep. Two palettes: a light translucent one for the navy KPI
   band, a neutral gray one for the light chart/map panes. */
@keyframes skel-sweep {
  0%   { background-position: -200% 0; }
  100% { background-position:  200% 0; }
}

.skel {
  display: inline-block;
  border-radius: 6px;
  /* on-navy default (KPI band): translucent white */
  background-color: rgba(255, 255, 255, 0.10);
  background-image: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0.06) 25%,
    rgba(255, 255, 255, 0.18) 50%,
    rgba(255, 255, 255, 0.06) 75%
  );
  background-size: 200% 100%;
  animation: skel-sweep 1.4s ease-in-out infinite;
}

/* ---- KPI tile skeleton (navy band) ---- */
.kpi-card.kpi-skel .kpi-value { margin-top: 4px; }
.skel-num { width: 72%; height: 24px; }
.skel-sub { width: 48%; height: 11px; margin-top: 8px; border-radius: 5px; }
/* Keep the label crisp (it is real UI, not data) and dim it slightly so the
   card reads as "forming" rather than final. */
.kpi-card.kpi-skel .kpi-label { opacity: 0.85; }

/* ---- Full-pane skeleton overlay (chart + map, light panes) ---- */
.pane-skeleton {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: #f6f7f9;
  border-radius: 8px;
  z-index: 1;
  padding: 18px;
  box-sizing: border-box;
  transition: opacity 0.25s ease;
}
/* On the light panes the shimmer flips to neutral gray. */
.pane-skeleton .skel {
  background-color: rgba(15, 23, 42, 0.06);
  background-image: linear-gradient(
    90deg,
    rgba(15, 23, 42, 0.04) 25%,
    rgba(15, 23, 42, 0.10) 50%,
    rgba(15, 23, 42, 0.04) 75%
  );
}
/* Cleared state: fade out then removed from flow so it can never trap clicks
   on the live chart/map underneath. JS sets .is-cleared, then hidden. */
.pane-skeleton.is-cleared { opacity: 0; pointer-events: none; }
.pane-skeleton[hidden] { display: none; }

/* Chart skeleton: a row of shimmer bars shaped like the bar/line chart. */
.chart-skel-bars {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  width: 100%;
  height: 78%;
}
.chart-skel-bars .skel {
  flex: 1;
  border-radius: 6px 6px 2px 2px;
}
.chart-skel-bars .skel:nth-child(1) { height: 45%; }
.chart-skel-bars .skel:nth-child(2) { height: 68%; }
.chart-skel-bars .skel:nth-child(3) { height: 52%; }
.chart-skel-bars .skel:nth-child(4) { height: 80%; }
.chart-skel-bars .skel:nth-child(5) { height: 60%; }
.chart-skel-bars .skel:nth-child(6) { height: 92%; }
.chart-skel-bars .skel:nth-child(7) { height: 55%; }
.chart-skel-bars .skel:nth-child(8) { height: 72%; }

/* Map skeleton: a soft shimmer silhouette + caption. */
.map-skel { flex-direction: column; align-items: center; justify-content: center; gap: 14px; }
.map-skel-blob {
  width: 62%;
  height: 58%;
  border-radius: 42% 44% 40% 46% / 46% 40% 44% 42%;
  background-color: rgba(15, 23, 42, 0.06);
  background-image: linear-gradient(
    90deg,
    rgba(15, 23, 42, 0.04) 25%,
    rgba(15, 23, 42, 0.10) 50%,
    rgba(15, 23, 42, 0.04) 75%
  );
  background-size: 200% 100%;
  animation: skel-sweep 1.4s ease-in-out infinite;
}
.map-skel-caption {
  font-family: var(--font-stack, system-ui, sans-serif);
  font-size: 12px;
  color: #94a3b8;
  letter-spacing: 0.3px;
}

/* ---- TABLE skeletons (2026-07-17) ----
   Same .skel primitive and the same skel-sweep animation as everything above;
   the ONLY difference is the palette flips to the neutral gray used on light
   surfaces (byte-identical to the .pane-skeleton .skel rule). This is scoped to
   .table-skel and NOT to the generic .is-skeleton marker, because #kpiRow also
   carries .is-skeleton and lives on the navy band where the translucent-white
   palette is correct.

   Used by the three in-shell tables that used to ship baked real-looking data:
     #classicView  (Daily Report scorecard -- a frozen 53-row snapshot)
     #treeBody     (Store Detail tree -- had RETIRED market names, Gulf Coast/Central)
     #rsaTableWrap (RSA Leaderboard -- had 385 REAL associate names + real net sales)
   Each renderer replaces its container's innerHTML wholesale, so the skeleton
   simply disappears the instant real rows paint: skeleton -> real, never
   fake -> real. Column headers and metric row LABELS are kept, because they are
   stable UI chrome, not data (same call the KPI band already makes by keeping
   .kpi-label crisp). Names and every numeric cell are shimmer. */
.table-skel .skel {
  background-color: rgba(15, 23, 42, 0.06);
  background-image: linear-gradient(
    90deg,
    rgba(15, 23, 42, 0.04) 25%,
    rgba(15, 23, 42, 0.10) 50%,
    rgba(15, 23, 42, 0.04) 75%
  );
}
/* A shimmer standing in for one numeric cell. Block so it fills the td box and
   inherits the table's own padding/alignment, keeping the loading table the
   same shape as the real one (no layout jump on handoff). */
.skel-cell {
  display: block;
  height: 11px;
  width: 68%;
  border-radius: 5px;
}
/* Name/label columns read wider than a number. */
.skel-name { width: 58%; }
/* Dim the kept labels so the row reads as "forming" rather than final --
   mirrors .kpi-card.kpi-skel .kpi-label above. */
.table-skel .metric-name { opacity: 0.85; }

/* Respect reduced-motion: hold a static, still-intentional placeholder. */
@media (prefers-reduced-motion: reduce) {
  .skel, .map-skel-blob { animation: none; }
}
