/* ============================================================
   Awall surface stylesheet: states.css
   Split from styles.css (F1, issue #186) — NO rule changes.
   Owns: empty state + error pages 404/403/500 (shared / F2)
   Concatenating every surfaces/*.css in base.html <link> order
   reproduces the original styles.css byte-for-byte.
   ============================================================ */
.empty-state {
  text-align: center;
  color: var(--color-text-muted);
  padding: var(--space-12) var(--space-6);
  font-size: var(--font-size-sm);
  line-height: 1.65;
}

/* When .empty-state is the card itself (e.g. card empty-state), give it
   a soft dashed boundary so it reads as "intentionally empty", not "loading". */
.card.empty-state {
  border-style: dashed;
  background: transparent;
  box-shadow: none;
}

.empty-state-title {
  display: block;
  font-size: var(--font-size-md);
  font-weight: 600;
  color: var(--color-text-heading);
  margin-bottom: var(--space-2);
}

.empty-state-hint {
  display: block;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

/* ---------------------------------------------------------
   25. Error page
   Same atmosphere vocabulary as auth pages: subtle grid + glow.
   --------------------------------------------------------- */
.error-page {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-surface);
  padding: var(--space-8) var(--space-4);
  text-align: center;
  overflow: hidden;
  isolation: isolate;
}

.error-page::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
  background-image:
    linear-gradient(to right,  var(--color-border) 1px, transparent 1px),
    linear-gradient(to bottom, var(--color-border) 1px, transparent 1px);
  background-size: 64px 64px;
  -webkit-mask-image: radial-gradient(ellipse 60% 50% at 50% 45%, #000 30%, transparent 78%);
          mask-image: radial-gradient(ellipse 60% 50% at 50% 45%, #000 30%, transparent 78%);
  opacity: 0.4;
}

.error-page::after {
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  width: 640px; height: 640px;
  transform: translate(-50%, -50%);
  z-index: -1;
  background: var(--color-primary-glow-faint);
  border-radius: 50%;
  filter: blur(120px);
  pointer-events: none;
}

[data-theme="dark"] .error-page::before { opacity: 0.28; }

.error-page-inner {
  position: relative;
  max-width: 480px;
}

.error-code {
  font-family: var(--font-mono);
  font-size: 96px;
  font-weight: 700;
  color: var(--color-text-heading);
  opacity: 0.18;
  line-height: 1;
  margin-bottom: var(--space-4);
  letter-spacing: -0.04em;
}

.error-title {
  font-size: var(--font-size-2xl);
  font-weight: 700;
  color: var(--color-text-heading);
  letter-spacing: -0.02em;
  margin-bottom: var(--space-3);
}

.error-desc {
  font-size: var(--font-size-base);
  color: var(--color-text-muted);
  line-height: 1.65;
  margin-bottom: var(--space-8);
}

/* ---------------------------------------------------------
   26. Empty-state icon + CTA slots (F2, #187)
   Adds an optional icon slot and consistent CTA spacing to the
   existing .empty-state primitive (used by _state_empty.html).
   --------------------------------------------------------- */
.empty-state-icon {
  display: inline-flex;
  margin-bottom: var(--space-3);
  color: var(--color-text-muted);
}

.empty-state .btn {
  margin-top: var(--space-4);
}

/* ---------------------------------------------------------
   27. Loading skeleton (F2, #187)
   Shimmer placeholder used by _state_loading.html. Reserves
   height so real content swaps in with no layout shift. The
   global prefers-reduced-motion guard (core.css, F4) zeroes the
   shimmer's duration + iteration count, leaving static blocks —
   no per-component guard needed (DESIGN.md §8).
   --------------------------------------------------------- */
.skeleton {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.skeleton-line,
.skeleton-block {
  position: relative;
  overflow: hidden;
  background: var(--color-border);
  border-radius: var(--radius-input);
}

.skeleton-line {
  height: 0.9rem;
}
.skeleton-line--sm {
  width: 40%;
}
.skeleton-line--md {
  width: 70%;
}
.skeleton-block {
  height: 96px;
  border-radius: var(--radius-card);
}

.skeleton-line::after,
.skeleton-block::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, var(--color-surface), transparent);
  animation: awall-skeleton-shimmer 1.4s ease-in-out infinite;
}

@keyframes awall-skeleton-shimmer {
  100% {
    transform: translateX(100%);
  }
}

/* ---------------------------------------------------------
   28. Inline error / retry (F2, #187)
   For failed fetch()/async — message + retry control. Used by
   _state_error.html; role="alert" lives on the markup.
   --------------------------------------------------------- */
.state-error {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-8) var(--space-4);
  text-align: center;
  color: var(--color-danger);
  font-size: var(--font-size-sm);
  line-height: 1.6;
}

.state-error-retry {
  min-height: 44px;
}

