/* Shared task feedback. Motion follows explicit request state, never elapsed-time progress. */
:root { --motion-ease:cubic-bezier(.22,1,.36,1); --motion-enter:260ms; }

@keyframes ui-reveal {
  from { opacity:0; transform:translateY(6px); }
  to { opacity:1; transform:translateY(0); }
}
@keyframes ui-breathe { 0%,100% { opacity:.4; } 50% { opacity:1; } }
@keyframes ui-travel { from { transform:translateX(-110%); } to { transform:translateX(340%); } }
@keyframes ui-shimmer { from { background-position:150% 0; } to { background-position:-150% 0; } }

/* A stable label and a small moving light make indeterminate waits readable. */
.ui-loading { display:flex; flex-direction:column; align-items:center; justify-content:center; gap:14px;
  padding:36px 20px; min-height:120px; color:var(--text-secondary); font-size:13px; text-align:center;
  animation:ui-reveal var(--motion-enter) var(--motion-ease) backwards; }
.ui-loading::before { content:""; display:block; width:44px; height:4px; flex-shrink:0; border-radius:999px;
  background:linear-gradient(90deg,var(--border),var(--primary),var(--border)); background-size:220% 100%;
  animation:ui-shimmer 1.8s ease-in-out infinite; }
.ui-loading small { display:block; max-width:340px; font-size:12px; line-height:1.7; color:var(--text-secondary); }
.ui-loading[hidden] { display:none; }

/* These classes are set only while requests are active; disabled alone is not a loading state. */
button.ui-busy, button.is-busy, .btn.is-loading { position:relative; overflow:hidden; }
button.ui-busy::after, button.is-busy::after, .btn.is-loading::after {
  content:""; position:absolute; bottom:0; left:0; width:30%; height:2px;
  background:currentColor; opacity:.65; border-radius:999px; pointer-events:none;
  animation:ui-travel 1.6s ease-in-out infinite;
}
.chat-attach-chip.is-uploading, .de-file.is-uploading { position:relative; overflow:hidden; }
.chat-attach-chip.is-uploading::after, .de-file.is-uploading::after {
  content:""; position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(100deg,transparent 20%,color-mix(in srgb,var(--primary) 14%,transparent) 50%,transparent 80%);
  background-size:220% 100%; animation:ui-shimmer 2s ease-in-out infinite;
}
.rec-up:not(.is-fail) .rec-up-fill { position:relative; overflow:hidden; transition:width 360ms var(--motion-ease); }
.rec-up:not(.is-fail) .rec-up-fill::after { content:""; position:absolute; inset:0;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.4),transparent); background-size:220% 100%;
  animation:ui-shimmer 1.8s linear infinite; }

/* Previously all three skeleton stops had the same color, so no shimmer was visible. */
.skeleton { background:linear-gradient(100deg,var(--surface-2) 25%,var(--border) 45%,var(--surface-2) 65%);
  background-size:220% 100%; animation:ui-shimmer 1.8s ease-in-out infinite; }
.chat-progress:not(.is-finished) { position:relative; border-radius:12px;
  background:color-mix(in srgb,var(--primary) 5%,var(--surface)); }
.chat-progress:not(.is-finished)::after { content:""; position:absolute; left:12px; right:12px; bottom:0; height:2px;
  border-radius:999px; background:linear-gradient(90deg,transparent,var(--primary),transparent);
  background-size:220% 100%; animation:ui-shimmer 2.4s ease-in-out infinite; pointer-events:none; }
.chat-progress.is-finished .chat-progress-spinner { border:none; background:var(--tint-green-fg);
  clip-path:polygon(12% 47%,36% 70%,88% 15%,100% 28%,37% 94%,0 59%); }
.chat-progress-step, .de-msg-ver { animation:ui-reveal var(--motion-enter) var(--motion-ease) backwards; }
.de-msg-busy.ui-loading { align-items:flex-start; text-align:left; padding:18px; min-height:100px;
  border:1px solid var(--border); border-radius:14px; background:var(--surface-2); }
.de-wrap.is-revising .de-editor-col { position:relative; }
.de-wrap.is-revising .de-editor-col::after { content:""; position:absolute; top:0; left:0; right:0; height:3px;
  pointer-events:none; background:linear-gradient(90deg,transparent,var(--primary),transparent);
  background-size:220% 100%; animation:ui-shimmer 2.2s ease-in-out infinite; }
.rv-note:has(.rv-spin), .rv-busy { background:color-mix(in srgb,var(--primary) 6%,var(--surface)); }
.rv-note .rv-spin, .rv-busy .rv-spin { box-shadow:0 0 0 5px var(--primary-soft); }

/* Animate bounded panels once when they become visible, without reanimating streamed paragraphs. */
.case-pane.is-active, .adm-pane:not([hidden]), .vt-pane:not([hidden]), .rv-tabbody:not([hidden]),
.full-tab-pane.is-active, .doc-import-dialog[open] {
  animation:ui-reveal var(--motion-enter) var(--motion-ease) backwards;
}
.doc-card, .js-card, .rec-up, .rv-ev, .fb-item {
  animation:ui-reveal var(--motion-enter) var(--motion-ease) backwards;
}
:is(.case-tab,.vt-tab,.rv-tab,.de-tab,#doc-filter-row .chip,#adm-tabs .chip) {
  transition:background 180ms ease,color 180ms ease,border-color 180ms ease,box-shadow 180ms ease;
}
@media (hover:hover) {
  :is(.doc-card,.js-card,.rec-row,.fb-item) { transition:border-color 180ms ease,box-shadow 180ms ease; }
  :is(.doc-card,.js-card,.rec-row,.fb-item):hover { box-shadow:0 3px 14px color-mix(in srgb,var(--text) 5%,transparent); }
}
.doc-import-dialog[aria-busy="true"] .doc-import-drop { background:linear-gradient(110deg,var(--surface-2) 20%,var(--primary-soft) 50%,var(--surface-2) 80%); background-size:220% 100%; animation:ui-shimmer 2s ease-in-out infinite; }
#ai-status:has(.spinner) { padding:22px; border:1px solid var(--border); border-radius:14px;
  background:var(--surface-2); line-height:1.8; }
#ai-status:has(.spinner)::after { content:""; display:block; height:3px; margin-top:14px; border-radius:999px;
  background:linear-gradient(90deg,var(--border),var(--primary),var(--border)); background-size:220% 100%;
  animation:ui-shimmer 2s ease-in-out infinite; }
.briefing-body .ui-loading { min-height:240px; }
.briefing-body .ui-loading::before { width:64px; height:5px; }
.briefing-work-topics { display:flex; gap:8px; flex-wrap:wrap; justify-content:center; margin-top:8px; }
.briefing-work-topics span { border:1px solid var(--border); border-radius:8px; padding:7px 10px; font-size:12px; }
.cal-loading.ui-loading { grid-column:1 / -1; }

/* File pickers share the document import control's shape and interaction. */
.btn.ui-file-pick { display:inline-flex; align-items:center; justify-content:center; gap:7px; min-height:40px;
  padding:9px 18px; border:1px solid var(--border-strong); border-radius:10px;
  background:var(--primary-soft); color:var(--link-color); font-size:13px; font-weight:600; text-decoration:none;
  transition:background-color .18s ease,border-color .18s ease,transform .18s var(--motion-ease); }
.btn.ui-file-pick:not(:disabled):hover { border-color:var(--link-color); transform:translateY(-1px); }
.btn.ui-file-pick:not(:disabled):active { transform:translateY(0); }
.btn.ui-file-pick:focus-visible { outline:2px solid var(--link-color); outline-offset:3px; }
.btn.ui-file-pick.ui-file-pick-compact { min-height:34px; padding:6px 10px; font-size:12px; }
.ui-file-drop { transition:background-color .18s ease,border-color .18s ease; }
.ui-file-drop:is(:hover,:focus-within,.is-over) { border-color:var(--link-color); background:var(--primary-soft); }
.ui-file-drop .ui-file-drop-icon { display:grid; place-items:center; width:44px; height:44px;
  margin:0 auto 12px; border:1px solid var(--border); border-radius:14px;
  background:var(--surface); color:var(--link-color); transition:transform .18s ease; }
.ui-file-drop-icon .ico { width:20px; height:20px; color:inherit; }
.ui-file-drop:is(:hover,:focus-within) .ui-file-drop-icon { transform:translateY(-3px); }
.ui-file-drop.is-over .ui-file-drop-icon { transform:translateY(-5px) rotate(-6deg); }
.fb-drop.ui-file-drop { background:var(--surface-2); border-width:1px; border-radius:14px; }
.fb-drop.ui-file-drop:is(:hover,:focus-within,.is-over) { background:var(--primary-soft); }
.fb-drop .ui-file-drop-icon { margin-bottom:5px; }
.fb-drop-hint .ui-file-pick { margin-top:8px; }
.fb-drop-hint small { color:var(--text-secondary); }
.doc-import-selection:not([hidden]), .fb-thumb { animation:ui-reveal var(--motion-enter) var(--motion-ease) backwards; }

/* Pausing decoration never pauses network work. Reduced motion retains every status label. */
:root[data-motion-paused] *, :root[data-motion-paused] *::before, :root[data-motion-paused] *::after {
  animation-play-state:paused !important;
}
@media (prefers-reduced-motion:reduce) {
  *, *::before, *::after { animation:none !important; transition:none !important; scroll-behavior:auto !important; }
  .anim-in { opacity:1 !important; transform:none !important; }
  .skeleton { background:var(--surface-2); }
}

.de-wrap [hidden] { display:none !important; }
