/* States — Loading / Empty / Error / Skeleton
   依據：output/plan/STYLEGUIDE_REVIEW.md §1.3 P0 補洞
*/

/* Skeleton（載入佔位）— 全部規格移至檔末 P1.1 §1 Skeleton loader 區塊
   (per UCP v1.1 §17.2 + UI_FOUR_STATE spec) — 此處原 .erp-skeleton 舊版定義
   已 deprecated；新版用 var(--erp-surface) token 取代 hex #1f1d1d，
   shimmer keyframe 改名 erp-skeleton-shimmer 避免衝突。
   --text-sm / --avatar 舊 preset 移除（grep 確認無 view/js 使用）；
   --avatar 改用 --circle (per P1.1 新段)。*/

/* Spinner */
.erp-spinner { display: inline-block; width: 20px; height: 20px; border: 2px solid var(--erp-border); border-top-color: var(--erp-gold-primary); border-radius: 50%; animation: erp-spin 800ms linear infinite; }
.erp-spinner--sm { width: 14px; height: 14px; border-width: 1.5px; }
.erp-spinner--lg { width: 32px; height: 32px; border-width: 3px; }
@keyframes erp-spin { to { transform: rotate(360deg); } }

/* Loading wrap（含 spinner + 文字） */
.erp-loading-wrap { display: grid; place-items: center; gap: var(--erp-space-2); padding: var(--erp-space-6); color: var(--erp-text-muted); font-size: 14px; }
.erp-loading-wrap__hint { font-size: 12px; color: var(--erp-text-dim); }

/* Empty state — Wave 3 (P1-E + P3-E) 2026-05-15 重做
   舊：1px dashed border + emoji icon (⚙∅⚐) — 視覺極簡陋（user 截圖 #6）
   新：細緻 solid border + 漸層背景 + 圖示用 FontAwesome SVG（per §4 no-emoji-icons）
   保留：尺寸 / 字級 / 結構（heading + hint + action 三段）
   Wave 11 (A9 推廣) 2026-05-15：加 .empty-state（無 erp- prefix）同樣套用，
   涵蓋 site.css L656 / L1386 的舊 .empty-state（dashed border）— 19 個
   cshtml 用此 class，現在通通拿到 Wave 3 polished 視覺 */
.erp-empty, .erp-empty-state, .empty-state {
  display: grid;
  place-items: center;
  gap: var(--erp-space-3);
  padding: var(--erp-space-8) var(--erp-space-6);
  text-align: center;
  border: 1px solid var(--erp-border) !important;
  border-radius: var(--erp-radius-lg);
  background: linear-gradient(180deg, var(--erp-card) 0%, var(--erp-ds-bg-panel-muted) 100%) !important;
  box-shadow: inset 0 1px 0 rgba(var(--erp-rgb-gold-primary), 0.04);
}
.erp-empty__icon, .erp-empty-state__icon {
  width: 56px; height: 56px;
  display: inline-grid; place-items: center;
  border-radius: 50%;
  background: rgba(var(--erp-rgb-gold-primary), 0.06);
  border: 1px solid rgba(var(--erp-rgb-gold-primary), 0.12);
  color: var(--erp-gold-label);
  font-size: 22px;
}
.erp-empty__title, .erp-empty-state__title { color: var(--erp-text-primary); font-size: 16px; font-weight: 800; margin: 0; }
.erp-empty__hint, .erp-empty-state__hint { color: var(--erp-text-muted); font-size: 14px; max-width: 480px; line-height: 1.5; margin: 0; }
.erp-empty__action, .erp-empty-state__action { margin-top: var(--erp-space-2); display: flex; gap: var(--erp-space-2); flex-wrap: wrap; justify-content: center; }

/* Empty state 情境 modifier — PAGE_TYPE_STANDARD §3 統一規範 */
.erp-empty-state.is-tenant-scope .erp-empty-state__icon { background: rgba(var(--erp-rgb-gold-primary), 0.10); color: var(--erp-gold-primary); }
.erp-empty-state.is-admin-config { border-color: rgba(var(--erp-rgb-gold-primary), 0.32); }
.erp-empty-state.is-admin-config .erp-empty-state__icon { background: rgba(var(--erp-rgb-gold-primary), 0.12); color: var(--erp-gold-light); }
.erp-empty-state.is-permission-denied { border-color: rgba(var(--erp-rgb-danger), 0.32); background: rgba(var(--erp-rgb-danger), 0.03); }
.erp-empty-state.is-permission-denied .erp-empty-state__icon { background: rgba(var(--erp-rgb-danger), 0.12); color: var(--erp-danger); }
.erp-empty-state.is-permission-denied .erp-empty-state__title { color: var(--erp-danger); }
.erp-empty-state.is-search-pending .erp-empty-state__icon { background: rgba(var(--erp-rgb-muted), 0.10); color: var(--erp-text-muted); }
.erp-empty-state.is-empty-result .erp-empty-state__icon { background: rgba(var(--erp-rgb-muted), 0.10); color: var(--erp-text-muted); }

/* erp-error / erp-error-state 雙 alias removed 2026-06-21 (TASK-20260621 S3): error
   state converged onto canonical .erp-state-error (defined below, with retry). */

/* List shell skeleton variant — 套在 erp-list-shell-body 內 */
.erp-list-shell__skeleton { padding: var(--erp-space-4); display: flex; flex-direction: column; gap: var(--erp-space-2); }

/* Confirm input — 危險操作打字確認（PAGE_TYPE_STANDARD §6.3）
   用法：modal body 內含 <input class="erp-confirm-input" data-confirm-target="DELETE-tenant-xxx">
   配 JS：input value 等於 data-confirm-target 才 enable 確認按鈕 */
.erp-confirm-input-wrap { display: grid; gap: var(--erp-space-2); padding: var(--erp-space-3); background: rgba(var(--erp-rgb-danger), 0.06); border: 1px solid rgba(var(--erp-rgb-danger), 0.32); border-radius: var(--erp-radius-md); }
.erp-confirm-input-wrap__hint { color: var(--erp-text-secondary); font-size: 13px; line-height: 1.4; }
.erp-confirm-input-wrap__target { display: inline-block; padding: 2px 8px; background: rgba(var(--erp-rgb-danger), 0.12); border: 1px solid rgba(var(--erp-rgb-danger), 0.4); border-radius: var(--erp-radius-xs); color: var(--erp-danger); font-family: var(--erp-font-mono); font-size: 12px; font-weight: 800; user-select: all; }
.erp-confirm-input { width: 100%; min-height: 40px; padding: 9px 12px; border: 1px solid var(--erp-border); border-radius: var(--erp-radius-sm); background: var(--erp-ds-bg-panel-muted); color: var(--erp-text-secondary); font-family: var(--erp-font-mono); font-size: 14px; }
.erp-confirm-input:focus { border-color: var(--erp-danger); box-shadow: 0 0 0 3px rgba(var(--erp-rgb-danger), 0.18); outline: none; }
.erp-confirm-input.is-matched { border-color: var(--erp-success); }
.erp-confirm-input.is-matched + .erp-confirm-input__feedback { color: var(--erp-success); }
.erp-confirm-input__feedback { color: var(--erp-text-muted); font-size: 12px; min-height: 16px; }

/* Time range pill — 統一時間範圍選擇（PAGE_TYPE_STANDARD §6.2）
   用法：Audits / Traceability / OrderHistory / TenantUsageSnapshot / MarketIntelligence 強制使用 */
.erp-time-range { display: inline-flex; align-items: center; gap: 2px; padding: 2px; background: var(--erp-card); border: 1px solid var(--erp-border); border-radius: var(--erp-radius-sm); }
.erp-time-range__pill { padding: 5px 12px; background: transparent; border: 0; border-radius: var(--erp-radius-xs); color: var(--erp-text-muted); font-size: 12px; font-weight: 700; cursor: pointer; transition: color var(--erp-motion-fast), background-color var(--erp-motion-fast), border-color var(--erp-motion-fast); white-space: nowrap; }
.erp-time-range__pill:hover { color: var(--erp-gold-light); }
.erp-time-range__pill.is-active { background: rgba(var(--erp-rgb-gold-primary), 0.12); color: var(--erp-gold-primary); }
.erp-time-range__pill[aria-pressed="true"] { background: rgba(var(--erp-rgb-gold-primary), 0.12); color: var(--erp-gold-primary); }
.erp-time-range__custom { color: var(--erp-text-secondary); font-style: italic; }
@media (max-width: 767px) {
  .erp-time-range { flex-wrap: wrap; }
  .erp-time-range__pill { font-size: 11px; padding: 4px 10px; }
}

/* Toast sticky variant + action button（PAGE_TYPE_STANDARD §6.4）— 補 erp-toast.js 新支援 */
.erp-toast--sticky { border-left-width: 4px; }
.erp-toast__action { margin-top: var(--erp-space-2); display: inline-flex; gap: var(--erp-space-2); }
.erp-toast__action .erp-button { min-height: 28px; padding-inline: var(--erp-space-3); font-size: 12px; }

/* Toast — 非中斷式訊息，由 erp-toast.js 渲染進 #erp-toast-region 容器 */
.erp-toast-stack { position: fixed; top: var(--erp-space-4); right: var(--erp-space-4); z-index: 1300; display: flex; flex-direction: column; gap: var(--erp-space-2); width: min(420px, calc(100vw - 32px)); pointer-events: none; }
.erp-toast { display: flex; align-items: flex-start; gap: var(--erp-space-3); padding: var(--erp-space-3) var(--erp-space-4); background: var(--erp-card); border: 1px solid var(--erp-border); border-left: 3px solid var(--erp-gold-primary); border-radius: var(--erp-radius-md); box-shadow: 0 10px 30px rgba(var(--erp-rgb-black),.42); color: var(--erp-text-secondary); pointer-events: auto; animation: erp-toast-in 220ms var(--erp-ease); }
.erp-toast.is-leaving { animation: erp-toast-out 180ms var(--erp-ease) forwards; }
.erp-toast--success { border-left-color: var(--erp-success); }
.erp-toast--warning { border-left-color: var(--erp-warning); }
.erp-toast--danger { border-left-color: var(--erp-danger); }
.erp-toast--info { border-left-color: var(--erp-gold-light); }
.erp-toast__icon { flex-shrink: 0; width: 22px; height: 22px; display: inline-grid; place-items: center; font-weight: 900; font-size: 14px; }
.erp-toast--success .erp-toast__icon { color: var(--erp-success); }
.erp-toast--warning .erp-toast__icon { color: var(--erp-warning); }
.erp-toast--danger .erp-toast__icon { color: var(--erp-danger); }
.erp-toast--info .erp-toast__icon { color: var(--erp-gold-light); }
.erp-toast__copy { min-width: 0; flex: 1 1 auto; display: flex; flex-direction: column; gap: 2px; }
.erp-toast__title { color: var(--erp-text-primary); font-size: 14px; font-weight: 800; line-height: 1.3; }
.erp-toast__message { color: var(--erp-text-secondary); font-size: 13px; line-height: 1.45; word-break: break-word; }
.erp-toast__close { flex-shrink: 0; width: 24px; height: 24px; padding: 0; border: 0; background: transparent; color: var(--erp-text-muted); font-size: 18px; line-height: 1; cursor: pointer; border-radius: var(--erp-radius-xs); transition: color var(--erp-motion-fast); }
.erp-toast__close:hover { color: var(--erp-gold-light); }
.erp-toast__close::before { content: "×"; }
@keyframes erp-toast-in { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; transform: translateX(0); } }
@keyframes erp-toast-out { from { opacity: 1; transform: translateX(0); } to { opacity: 0; transform: translateX(20px); } }
@media (max-width: 767px) {
  .erp-toast-stack { top: var(--erp-space-3); right: var(--erp-space-3); left: var(--erp-space-3); width: auto; }
}

/* ═══════════════════════════════════════════════════════════════════════
 * Phase P1.1 (UCP-20260515 v1.1 §17.2 + UI_FOUR_STATE spec)
 * Wave G - 2026-05-16
 *
 * 補 3 個 missing 4-state patterns (existing: empty + loading-wrap + toast)：
 * 1. Skeleton loader (preferred over spinner for > 300ms loads,
 *    per ui-ux-pro-max §3 progressive-loading + UI_FOUR_STATE §2)
 * 2. Error state with retry button
 *    (per ui-ux-pro-max §8 error-recovery + UI_FOUR_STATE §4)
 * 3. State machine helper (.erp-state-host / data-state attr)
 *    (per erp-page-templates archetype state patterns)
 *
 * Tokens: --erp-card, --erp-border, --erp-text-*, --erp-space-*, --erp-radius-*,
 *         --erp-motion-base, --erp-ease, --erp-danger, --erp-gold-*,
 *         --erp-ds-border-danger, --erp-focus-ring, --erp-surface*, --erp-col-min-lg
 * ═════════════════════════════════════════════════════════════════════ */

/* ─── 1. Skeleton loader (shimmer pattern) ──────────────────────────── */

.erp-skeleton {
  display: block;
  background: linear-gradient(
    90deg,
    var(--erp-surface) 0%,
    var(--erp-surface-hover) 50%,
    var(--erp-surface) 100%
  );
  background-size: 200% 100%;
  animation: erp-skeleton-shimmer 1.4s ease-in-out infinite;
  border-radius: var(--erp-radius-xs);
  min-height: 16px;
}

@keyframes erp-skeleton-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* Skeleton presets — sized to match common content shapes */
.erp-skeleton--text       { height: 14px; margin-block-end: var(--erp-space-2); }
.erp-skeleton--text-lg    { height: 20px; margin-block-end: var(--erp-space-2); }
.erp-skeleton--title      { height: 28px; width: 60%; margin-block-end: var(--erp-space-3); }
.erp-skeleton--block      { height: 80px; border-radius: var(--erp-radius-md); }
.erp-skeleton--card       { height: 140px; border-radius: var(--erp-radius-lg); }
.erp-skeleton--circle     { width: 48px; height: 48px; border-radius: var(--erp-radius-pill); }
.erp-skeleton--row        { height: 44px; border-radius: var(--erp-radius-sm); }
.erp-skeleton--row + .erp-skeleton--row { margin-block-start: var(--erp-space-2); }

/* Skeleton container for table loading state */
.erp-skeleton-table {
  display: flex;
  flex-direction: column;
  gap: var(--erp-space-2);
  padding: var(--erp-space-3);
}

/* Skeleton container for card-grid loading state */
.erp-skeleton-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--erp-col-min-lg), 1fr));
  gap: var(--erp-space-3);
}

/* ─── 2. Error state with retry button ──────────────────────────────── */
/* per ui-ux-pro-max §8 error-recovery — error MUST include recovery path */

.erp-state-error {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--erp-space-3);
  padding-block: var(--erp-space-6);
  padding-inline: var(--erp-space-4);
  background: var(--erp-card);
  border: 1px solid var(--erp-ds-border-danger);
  border-radius: var(--erp-radius-lg);
  color: var(--erp-text-secondary);
  text-align: center;
  min-height: 200px;
}

.erp-state-error__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: var(--erp-radius-pill);
  background: rgba(var(--erp-rgb-danger), 0.12);
  color: var(--erp-danger);
  font-size: var(--erp-text-display);
}

.erp-state-error__title {
  color: var(--erp-text-primary);
  font-size: var(--erp-text-h2);
  font-weight: var(--erp-weight-bold);
  margin: 0;
}

.erp-state-error__reason {
  color: var(--erp-text-muted);
  font-size: var(--erp-text-body);
  line-height: 1.5;
  max-width: 56ch;
  margin: 0;
}

.erp-state-error__actions {
  display: flex;
  gap: var(--erp-space-2);
  flex-wrap: wrap;
  justify-content: center;
  margin-block-start: var(--erp-space-2);
}

.erp-state-error__help {
  font-size: var(--erp-text-caption);
  color: var(--erp-text-dim);
  margin-block-start: var(--erp-space-2);
}

.erp-state-error__help a {
  color: var(--erp-gold-light);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.erp-state-error__help a:focus-visible {
  outline: none;
  box-shadow: var(--erp-focus-ring);
  border-radius: var(--erp-radius-xs);
}

/* ─── 3. State machine helper (single host, data-state attr switching) ── */
/* Usage: <div class="erp-state-host" data-state="loading|empty|error|data">
            <div data-state-show="loading">...</div>
            <div data-state-show="empty">...</div>
            <div data-state-show="error">...</div>
            <div data-state-show="data">...</div>
          </div>
   Vue:   :data-state="loading ? 'loading' : error ? 'error' : !rows.length ? 'empty' : 'data'"
*/

.erp-state-host > [data-state-show] {
  /* default: shown when matching state */
}

.erp-state-host[data-state="loading"] > :not([data-state-show="loading"]),
.erp-state-host[data-state="empty"]   > :not([data-state-show="empty"]),
.erp-state-host[data-state="error"]   > :not([data-state-show="error"]),
.erp-state-host[data-state="success"] > :not([data-state-show="success"]),
.erp-state-host[data-state="data"]    > :not([data-state-show="data"]) {
  display: none;
}

/* ─── prefers-reduced-motion ────────────────────────────────────────── */
/* per ui-ux-pro-max §7 reduced-motion — skeleton shimmer disabled */

@media (prefers-reduced-motion: reduce) {
  .erp-skeleton {
    animation: none;
    background: var(--erp-surface);
  }
}

/* ─────────────────────────────────────────────────────────────────────
 * Phase P1.8 (2026-05-16) — Capability Gate UX Foundation
 *
 * 對齊 docs/specs/UI_CAPABILITY_GATE_UX.md §2 三情境 + §6 Disabled vs Deny
 * 嚴格分離 + §9 EP 元件不重寫 base style。
 *
 * 設計原則：用 [data-capability-gate="..."] attribute selector 而非 class，
 * 因為任何 element（button / a / hub-card）都可能是 gate。
 *
 * §6 嚴格分離 — Deny 絕不有 spinner / aria-busy；Disabled 絕不有 lock icon。
 *
 * Authority: docs/specs/UI_CAPABILITY_GATE_UX.md §2-§7
 * Protected zone: permission/access-control/API gate — markup-only edge
 * ──────────────────────────────────────────────────────────────────── */

/* §1 三情境共通 base */
[data-capability-gate] {
  position: relative;
  cursor: not-allowed;
  opacity: 0.62;
}

/* lock icon prefix on button-like elements (spec §6.2) */
.btn[data-capability-gate]::before,
.erp-button[data-capability-gate]::before,
button[data-capability-gate]:not(.no-gate-icon)::before {
  content: '\f023';
  font-family: 'Font Awesome 5 Free';
  font-weight: 900;
  margin-right: var(--erp-space-1);
  opacity: 0.7;
}

/* §2 三情境細分 — visual tone */
[data-capability-gate="hard-deny"] {
  filter: grayscale(0.5);
}

[data-capability-gate="soft-deny"] {
  filter: none;
  opacity: 0.7;
}

[data-capability-gate="conditional"] {
  /* spec §2.3: 保持可點，業務前置不足才彈 wizard */
  opacity: 1;
  cursor: pointer;
}

/* §3 Audit-busy 與 Deny 嚴格分離 */
.btn[disabled][aria-busy="true"][data-capability-gate],
.erp-button[disabled][aria-busy="true"][data-capability-gate] {
  cursor: progress;
}
.btn[disabled][aria-busy="true"][data-capability-gate]::before,
.erp-button[disabled][aria-busy="true"][data-capability-gate]::before {
  content: '';
}

/* §4 Hub card deny variant — spec §2.1 markup */
.hub-card--denied {
  opacity: 0.7;
  cursor: not-allowed;
  pointer-events: auto;
  background: var(--erp-ds-denied-bg);
  border-color: var(--erp-ds-border-strong);
}

.hub-card--denied .hub-card__icon--muted {
  color: var(--erp-ds-denied);
}

.hub-card__deny-reason {
  margin-top: var(--erp-space-1);
  color: var(--erp-text-muted);
  font-size: var(--erp-text-caption);
  line-height: 1.4;
}

.hub-card__call-to-admin {
  margin-top: var(--erp-space-2);
  font-size: var(--erp-text-caption);
}

.hub-card__call-to-admin a {
  color: var(--erp-gold-light);
  text-decoration: underline;
}

.hub-card__call-to-admin a:hover {
  color: var(--erp-gold-primary);
}

/* §5 Chain hint — spec §5.2.1 */
.hub-card__chain-hint {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--erp-space-2);
  margin-top: var(--erp-space-3);
  padding-top: var(--erp-space-2);
  border-top: 1px dashed var(--erp-ds-border-muted);
  color: var(--erp-text-secondary);
  font-size: var(--erp-text-caption);
}

.hub-card__chain-hint > i {
  color: var(--erp-info);
}

.cap-chain-pill {
  display: inline-flex;
  align-items: center;
  padding: 2px var(--erp-space-2);
  background: var(--erp-ds-info-bg);
  color: var(--erp-info);
  border-radius: var(--erp-radius-pill);
  font-size: 11px;
  font-weight: var(--erp-weight-semibold);
}

/* §6 Conditional empty-state variant — spec §2.3 */
.erp-empty-state--conditional {
  border-color: var(--erp-ds-warning-border-soft);
  background: var(--erp-ds-warning-bg-faint);
}

.erp-empty-state--conditional .erp-empty-state__icon {
  color: var(--erp-warning);
}

.erp-empty-state--conditional .erp-empty-state__title {
  color: var(--erp-text-primary);
}

/* §7 Capability audit link (spec §3.4) */
.cap-gate__audit-link {
  display: inline-flex;
  align-items: center;
  gap: var(--erp-space-1);
  margin-top: var(--erp-space-2);
  color: var(--erp-text-muted);
  font-size: var(--erp-text-caption);
  text-decoration: none;
}

.cap-gate__audit-link:hover {
  color: var(--erp-gold-light);
  text-decoration: underline;
}

.cap-gate__audit-link > i {
  font-size: 11px;
}

/* §8 Capability Re-evaluation Notice (spec §4.2)
   support-mode 切租戶後第一次載入顯示，dismissable */
.cap-reeval-notice {
  display: flex;
  align-items: flex-start;
  gap: var(--erp-space-3);
  padding: var(--erp-space-3) var(--erp-space-4);
  background: var(--erp-ds-info-bg);
  border: 1px solid var(--erp-ds-border-strong);
  border-left: var(--erp-border-width-thick) solid var(--erp-info);
  border-radius: var(--erp-radius-md);
  color: var(--erp-text-primary);
  font-size: var(--erp-text-body);
  margin-bottom: var(--erp-space-4);
}

.cap-reeval-notice__icon {
  flex: 0 0 auto;
  font-size: 18px;
  color: var(--erp-info);
}

.cap-reeval-notice__body {
  flex: 1;
  min-width: 0;
}

.cap-reeval-notice__title {
  font-weight: var(--erp-weight-semibold);
  margin-bottom: var(--erp-space-1);
}

.cap-reeval-notice__meta {
  color: var(--erp-text-secondary);
  font-size: var(--erp-text-caption);
}

.cap-reeval-notice__actions {
  display: flex;
  gap: var(--erp-space-2);
  margin-top: var(--erp-space-2);
}

/* Drill-and-return restore flash — erpReturnUrl.restoreScroll() adds this class to
   the scrolled-to anchor so the operator's eye lands on where they were. Token-only. */
.erp-return-flash {
  animation: erp-return-flash-pulse 1.6s ease-out;
  border-radius: var(--erp-radius-md);
}
@keyframes erp-return-flash-pulse {
  0% { box-shadow: 0 0 0 var(--erp-space-1) rgba(var(--erp-rgb-gold-primary), 0.55); }
  100% { box-shadow: 0 0 0 var(--erp-space-1) rgba(var(--erp-rgb-gold-primary), 0); }
}
@media (prefers-reduced-motion: reduce) {
  .erp-return-flash {
    animation: none;
    outline: var(--erp-space-1) solid rgba(var(--erp-rgb-gold-primary), 0.55);
  }
}
