/* =============================================================================
   Skeleton loading kit — shared by the storefront and the admin panel.
   -----------------------------------------------------------------------------
   Grey placeholder shapes shown only while something is actually loading. Built
   and placed by af-skeleton.js; nothing here changes a loaded page.

   Performance: the placeholder bars themselves never animate. Each skeleton has a
   single shimmer band (::after) that slides across it with transform — composited,
   so a table of 80 bars costs the same as one bar. Rows inside a real <tbody>,
   which cannot carry an overlay, use a gentle opacity pulse instead.

   Everything is prefixed afsk- so it cannot collide with page-level styles (the
   order page already has its own .sk-bar / .sk-row).
   ============================================================================= */

:root {
  --afsk-base: #E9ECF1;               /* placeholder fill */
  --afsk-shine: rgba(255, 255, 255, .55);
  --afsk-radius: 6px;
  --afsk-gap: 12px;
}
/* Admin dark mode and the Liquid Glass skin: tint from the surface, not a fixed grey. */
body.admin-dark-mode {
  --afsk-base: rgba(255, 255, 255, .08);
  --afsk-shine: rgba(255, 255, 255, .07);
}
body.af-glass:not(.admin-dark-mode) {
  --afsk-base: rgba(30, 45, 75, .08);
  --afsk-shine: rgba(255, 255, 255, .6);
}

/* ── Root + shimmer ─────────────────────────────────────────────────────────── */
.afsk {
  position: relative;
  overflow: hidden;
  width: 100%;
  pointer-events: none;
  user-select: none;
}
.afsk::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 20%, var(--afsk-shine) 50%, transparent 80%);
  transform: translateX(-100%);
  animation: afsk-sweep 1.5s ease-in-out infinite;
}
@keyframes afsk-sweep { to { transform: translateX(100%); } }

/* Screen readers hear one "Loading…" per skeleton, never the shapes. */
.afsk-sr {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ── Primitives ─────────────────────────────────────────────────────────────── */
.afsk-b {                              /* a bar / block */
  display: block;
  height: 12px;
  border-radius: var(--afsk-radius);
  background: var(--afsk-base);
}
.afsk-b.is-sm    { height: 9px; }
.afsk-b.is-lg    { height: 18px; }
.afsk-b.is-xl    { height: 26px; }
.afsk-b.is-btn   { height: 34px; border-radius: 9px; }
.afsk-b.is-input { height: 38px; border-radius: 8px; }
.afsk-b.is-round { border-radius: 50%; }

.afsk-col  { display: flex; flex-direction: column; gap: 9px; }
.afsk-row  { display: flex; align-items: center; gap: var(--afsk-gap); }
.afsk-grow { flex: 1 1 auto; min-width: 0; }

/* Lines: a paragraph or a small panel. */
.afsk-lines { display: flex; flex-direction: column; gap: 10px; padding: 14px 4px; }

/* Table: one grid row per line, column template set inline by JS so the
   placeholders sit under the real column headers. */
.afsk-table { display: flex; flex-direction: column; }
.afsk-tr {
  display: grid;
  align-items: center;
  gap: 0;
  padding: 0;
  border-bottom: 1px solid var(--afsk-base);
  min-height: 44px;
}
.afsk-tr > span { padding: 0 8px; }
.afsk-tr .afsk-b { max-width: 100%; }

/* Cards: dashboard stat tiles and similar. */
.afsk-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: var(--afsk-gap);
}
.afsk-card {
  display: flex; align-items: center; gap: 12px;
  padding: 16px;
  border-radius: 14px;
  border: 1px solid var(--afsk-base);
}

/* Chart: bars rising from a baseline, inside the chart's own box. */
.afsk-chart {
  display: flex; align-items: flex-end; gap: 4%;
  height: 100%; min-height: 160px;
  padding: 18px 14px 14px;
  box-sizing: border-box;
}
.afsk-chart .afsk-b { flex: 1 1 0; border-radius: 6px 6px 2px 2px; }

/* Form: label + field pairs. */
.afsk-form { display: flex; flex-direction: column; gap: 16px; padding: 6px 0; }

/* Product grid (storefront). Column count follows the viewport like the real grid. */
.afsk-products {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}
@media (min-width: 576px)  { .afsk-products { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 992px)  { .afsk-products { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
.afsk-pcard { display: flex; flex-direction: column; gap: 8px; }
.afsk-pcard .afsk-img { aspect-ratio: 1 / 1; height: auto; border-radius: 10px; }

/* Product detail (storefront). */
.afsk-detail { display: grid; grid-template-columns: 1fr; gap: 20px; }
@media (min-width: 768px) { .afsk-detail { grid-template-columns: 1fr 1fr; gap: 32px; } }
.afsk-detail .afsk-img { aspect-ratio: 1 / 1; height: auto; border-radius: 12px; }

/* ── Host: an element whose loader has been swapped for a skeleton ───────────────
   Only the original loader content is hidden; .afsk is the visible child. */
.afsk-host > :not(.afsk) { display: none !important; }
.afsk-host { text-align: left !important; }
/* A table cell host keeps the cell, loses the padding that centred the spinner. */
td.afsk-host { padding: 6px 0 !important; }

/* Page navigation: the outgoing page is hidden in place (layout kept, so the
   footer and sidebar do not jump) and the incoming page's shape shown on top. */
.afsk-nav-scope { position: relative; }
/* opacity, not visibility: a descendant can switch visibility back on for itself
   (the order page does, for its chips and row actions), but it cannot undo a
   parent's opacity. */
.afsk-nav-scope.afsk-navigating > :not(.afsk-nav) { opacity: 0 !important; pointer-events: none !important; }
.afsk-nav {
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: 5;
  padding: 16px 12px;
  box-sizing: border-box;
}
.afsk-nav-front { max-width: 1240px; margin: 0 auto; padding: 16px; }

/* Images (storefront product cards): a shimmer on the image box until the picture
   arrives or fails. Background only — no positioning change on the box. */
.afsk-img-wait {
  background-color: var(--afsk-base) !important;
  background-image: linear-gradient(100deg, transparent 20%, var(--afsk-shine) 50%, transparent 80%) !important;
  background-size: 200% 100% !important;
  background-repeat: no-repeat !important;
  animation: afsk-img 1.5s ease-in-out infinite;
}
@keyframes afsk-img { from { background-position: 150% 0; } to { background-position: -50% 0; } }

/* Rows placed into a real <tbody> (order list): a pulse, since a row cannot carry
   the sweeping overlay. */
.afsk-pulse { animation: afsk-pulse 1.4s ease-in-out infinite; }
@keyframes afsk-pulse { 50% { opacity: .55; } }

/* ── Reduced motion: static placeholders ────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .afsk::after { display: none; }
  .afsk-img-wait, .afsk-pulse { animation: none !important; }
}
