/* Shared loading treatment (operator round 2026-09-05).
   ONE skeleton vocabulary for every surface that waits on data: the Agents
   pane, Files Browse, Files Recent, the file-preview area, Routines, and
   Connectors. Before this file each of those six shipped its own bare
   sentence ("Loading…", "Checking…", "loading…", "Loading agents…",
   "Loading recent files…") or a bespoke skeleton, so the board read as six
   different products mid-load.

   Rules this vocabulary follows:
   - Skeletons stand in for the REAL layout that is about to arrive. A
     surface's skeleton must use that surface's own geometry (row height,
     icon track, card radius), which is why the shapes below are composable
     primitives rather than one fixed "loading card".
   - No spinners. A sweep of light across a placeholder reads as "content is
     coming"; a spinner farm reads as six independent stalls.
   - Colour comes from tokens only, so one markup is correct in dark AND
     light with no per-theme rule.
   - Motion is decorative: prefers-reduced-motion drops to a flat tint. */

:root {
  /* The placeholder body and the light that sweeps across it. Both are
     derived from --ui-text so they track the theme's own contrast rather
     than a hardcoded grey that only looks right in one theme. */
  --cc-skel-base: color-mix(in srgb, var(--ui-text) 9%, transparent);
  --cc-skel-sheen: color-mix(in srgb, var(--ui-text) 17%, transparent);
  --cc-skel-radius: 6px;
}
:root[data-theme="light"] {
  /* Light theme's paper is much closer to the placeholder tint than dark's
     panel is, so the same percentages read as almost-invisible. Lift both
     stops rather than introduce a second set of shapes. */
  --cc-skel-base: color-mix(in srgb, var(--ui-text) 11%, transparent);
  --cc-skel-sheen: color-mix(in srgb, var(--ui-text) 4%, transparent);
}

/* ── the primitive ──────────────────────────────────────────────────────
   One block of "content that hasn't arrived". Everything else in this file
   is a size/shape preset or a layout that arranges these. */
.cc-skel {
  display: block;
  position: relative;
  overflow: hidden;
  height: 10px;
  border-radius: var(--cc-skel-radius);
  background-color: var(--cc-skel-base);
  /* Sweep is a pseudo-element rather than a background-position animation
     so the moving part is composited on its own layer — the whole point of
     "subtle" is that a pane full of these costs nothing to animate. */
}
.cc-skel::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(
    90deg,
    transparent 0%,
    var(--cc-skel-sheen) 50%,
    transparent 100%
  );
  animation: cc-skel-sweep 1.55s cubic-bezier(0.4, 0, 0.25, 1) infinite;
}
@keyframes cc-skel-sweep {
  /* Rests between passes: the sweep occupies the first ~65% of the cycle so
     the eye gets a beat of stillness instead of a continuous strobe. */
  0% { transform: translateX(-100%); }
  65%, 100% { transform: translateX(100%); }
}

/* Staggering: a pane of identical, perfectly in-phase skeletons reads as one
   flashing slab. Four steps is enough to break that up without looking like
   the rows are animating independently. */
.cc-skel[data-cc-delay="1"]::after { animation-delay: 0.10s; }
.cc-skel[data-cc-delay="2"]::after { animation-delay: 0.20s; }
.cc-skel[data-cc-delay="3"]::after { animation-delay: 0.30s; }

@media (prefers-reduced-motion: reduce) {
  .cc-skel::after { animation: none; }
  /* Without motion the placeholder still has to read as "pending", so keep a
     slightly stronger flat tint rather than an animation nobody sees. */
  .cc-skel { background-color: color-mix(in srgb, var(--ui-text) 13%, transparent); }
}

/* ── shape presets ─────────────────────────────────────────────────────── */
.cc-skel--icon { width: 30px; height: 30px; border-radius: 9px; flex: none; }
.cc-skel--avatar { width: 26px; height: 26px; border-radius: 50%; flex: none; }
.cc-skel--title { height: 12px; width: 58%; }
.cc-skel--line { height: 10px; width: 84%; }
.cc-skel--sub { height: 9px; width: 38%; }
.cc-skel--chip { height: 18px; width: 62px; border-radius: 999px; flex: none; }
.cc-skel--pill { height: 22px; width: 86px; border-radius: 7px; flex: none; }
.cc-skel--block { height: 100%; width: 100%; border-radius: 12px; }

/* ── layouts ───────────────────────────────────────────────────────────── */
.cc-skel-list { display: grid; gap: 6px; }
.cc-skel-lines { display: grid; gap: 7px; flex: 1 1 auto; min-width: 0; }

/* A row that mirrors "icon + two lines of text", the shape most of this
   board's lists actually are (Recent cards, rail sessions, connector rows). */
.cc-skel-row {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

/* The same row inside a bordered card, for surfaces whose real content is
   carded (Files Recent, Connectors). Geometry deliberately matches the real
   card so nothing shifts when data lands. */
.cc-skel-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 13px;
  border: 1px solid var(--ui-line);
  border-radius: 11px;
  background: var(--ui-panel);
}

/* ── the honest header ─────────────────────────────────────────────────
   A skeleton alone says "something is coming" but not WHAT or WHY. Every
   surface pairs its skeletons with one live-region line carrying the real
   sentence, so screen readers and sighted users get the same truth. */
.cc-loading-head {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin-bottom: 14px;
}
.cc-loading-dot {
  width: 6px;
  height: 6px;
  margin-top: 6px;
  border-radius: 50%;
  flex: none;
  background: var(--ui-accent);
  animation: cc-loading-pulse 1.1s ease-in-out infinite;
}
@keyframes cc-loading-pulse {
  0%, 100% { opacity: 0.35; transform: scale(0.82); }
  50% { opacity: 1; transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .cc-loading-dot { animation: none; opacity: 0.9; }
}
.cc-loading-copy strong {
  display: block;
  font-family: var(--font-ui);
  font-size: 13.5px;
  font-weight: 650;
  color: var(--ui-text);
}
.cc-loading-copy span {
  display: block;
  margin-top: 1px;
  font-family: var(--font-ui);
  font-size: 12.5px;
  color: var(--ui-muted);
}
