/* loading.css — WS-4 loading / perceived-performance primitives.
 * Skeleton shimmer blocks, the boot splash, and the floor-swap load bar.
 * Depends on the :root tokens defined in css/app.css (--bg-2/-3, --radius-*,
 * --accent, --text, --safe-t) — must be linked AFTER app.css.
 */

/* ── Skeleton primitive ────────────────────────────────────────────────── */
.vnm-skel {
  position: relative;
  display: inline-block;
  overflow: hidden;
  background: var(--bg-3, #DDD8D0);
  border-radius: var(--radius-sm, 6px);
  vertical-align: middle;
}
.vnm-skel::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.65), transparent);
  transform: translateX(-100%);
  animation: vnm-skel-sweep 1.5s ease-in-out infinite;
  will-change: transform;
}
@keyframes vnm-skel-sweep {
  100% { transform: translateX(100%); }
}

/* Size variants — sized to the content they stand in for so nothing shifts
   when the real content swaps in. */
.vnm-skel--text     { display: block; height: 11px; width: 70%; border-radius: 4px; }
.vnm-skel--text-sm  { display: block; height: 9px;  width: 50%; border-radius: 4px; }
.vnm-skel--price     { height: 13px; width: 72px; border-radius: 4px; }
.vnm-skel--price-lg  { display: block; height: 24px; width: 130px; border-radius: var(--radius-sm, 6px); }
.vnm-skel--card      { display: block; height: 100%; width: 100%; }

/* ── Drawer price skeleton block ───────────────────────────────────────── *
 * Sized to match openHotelDrawer's real price+resort-fee markup EXACTLY —
 * measured via a rendered-height probe, not assumed from font-size math
 * (a 28px/700 div actually renders at 37px tall at this stack's line-height,
 * not 28px; the 13px fee line renders at 17px). Matched to the with-resort-fee
 * case since that's the common case on the Strip; a hotel with no resort fee
 * will show a small (~21px) upward shift instead of zero, which is an
 * accepted tradeoff over the alternative of shifting on every hotel. */
.hdb-price-skel { margin-bottom: 12px; }
.hdb-price-skel .vnm-skel--price-lg { height: 37px; width: 130px; margin-bottom: 4px; }
.hdb-price-skel .vnm-skel--text-sm  { height: 17px; width: 210px; margin-top: 0; }

/* Reduced motion: keep the neutral block as a static "reserved space" cue,
   drop the sweep so nothing animates. */
@media (prefers-reduced-motion: reduce) {
  .vnm-skel::after { animation: none; display: none; }
}

/* ── Boot splash ────────────────────────────────────────────────────────
 * Full-viewport layer painted before any JS runs (inline in base.html, right
 * after <body> opens) so it covers the raggedly-popping-in map/chrome. Removed
 * by the inline bootstrap script once the map is genuinely ready, or by a
 * hard failsafe if it never is. z-index set far above every other layer
 * (including the save-map modal's inline z-index:9000) since it must cover
 * the whole app during the very first paint. */
#vnm-boot-splash {
  position: fixed;
  inset: 0;
  z-index: 99999;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg, #F5F0EA);
  opacity: 1;
  transition: opacity .3s ease;
}
#vnm-boot-splash.vnm-boot-splash--out { opacity: 0; pointer-events: none; }
.vnm-boot-wordmark {
  display: flex;
  gap: 0;
  font-weight: 700;
  font-size: 22px;
  letter-spacing: -.01em;
  animation: vnm-boot-pulse 1.6s ease-in-out infinite;
}
.vnm-boot-wordmark .vnm-wordmark-city  { color: var(--accent, #0284C7); }
.vnm-boot-wordmark .vnm-wordmark-brand { color: var(--text, #1C1917); }
@keyframes vnm-boot-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: .55; }
}
@media (prefers-reduced-motion: reduce) {
  .vnm-boot-wordmark { animation: none; }
}

/* ── Floor-swap loading cue ────────────────────────────────────────────── *
 * Thin indeterminate bar just under the header. Created lazily and only
 * made visible after a 150ms delay-before-show (see overlays-vector.js) so
 * fast floor swaps never show it at all. */
#vnm-floor-loadbar {
  position: fixed;
  left: 0; right: 0;
  top: calc(44px + var(--safe-t, 0px));
  height: 2px;
  z-index: var(--z-floor-pill, 350);
  background: var(--bg-3, #DDD8D0);
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
  transition: opacity .15s ease;
}
#vnm-floor-loadbar.is-active { opacity: 1; }
#vnm-floor-loadbar::after {
  content: '';
  position: absolute;
  top: 0; bottom: 0;
  width: 40%;
  background: var(--accent, #0284C7);
  transform: translateX(-100%);
  animation: vnm-floorbar-sweep 1.1s ease-in-out infinite;
}
@keyframes vnm-floorbar-sweep {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(250%); }
}
@media (prefers-reduced-motion: reduce) {
  #vnm-floor-loadbar::after { animation: none; width: 100%; transform: none; opacity: .7; }
}
