/* Causal, one-shot chat motion. The destination changes shape; decoration never
   fires on its own. Every animated property is transform or opacity except the
   short border-color catch on the already-painted destination row. */

#v2Context[data-chat-motion]::before{
  --motion-ink:var(--purple);
  position:absolute;z-index:45;top:0;right:0;bottom:0;width:3px;
  background:linear-gradient(180deg,transparent 6%,var(--motion-ink) 45%,transparent 94%);
  box-shadow:0 0 18px color-mix(in srgb,var(--motion-ink) 72%,transparent);
  content:"";pointer-events:none;transform:scaleY(.2);transform-origin:center;opacity:0;
  animation:chat-motion-panel-catch .82s cubic-bezier(.2,.8,.2,1) both;
}
#v2Context[data-chat-motion="spawn"]::before{--motion-ink:var(--state-working)}
@keyframes chat-motion-panel-catch{
  0%{opacity:0;transform:scaleY(.18)}
  20%{opacity:.95;transform:scaleY(.34)}
  62%{opacity:.62;transform:scaleY(1)}
  100%{opacity:0;transform:scaleY(.82)}
}

#v2ContextToggle[data-chat-motion="chat-arrival"]{
  position:relative;animation:chat-motion-drawer-catch .82s cubic-bezier(.2,.8,.2,1) both;
}
#v2ContextToggle[data-chat-motion="chat-arrival"]::after{
  position:absolute;top:4px;right:4px;width:7px;height:7px;border:2px solid var(--surface-1);
  border-radius:50%;background:var(--purple);content:"";pointer-events:none;
  animation:chat-motion-drawer-dot .82s ease both;
}
@keyframes chat-motion-drawer-catch{
  0%,100%{transform:none}
  36%{transform:scale(.88)}
  62%{transform:scale(1.08)}
}
@keyframes chat-motion-drawer-dot{
  0%,16%{opacity:0;transform:scale(.4)}
  38%,72%{opacity:1;transform:none}
  100%{opacity:0;transform:scale(1.7)}
}

/* Direct creation: the keyed row is the object that arrives. Its neighbours
   make room via the conversation list controller, and NEW fades before the row
   settles into the ordinary selected treatment. */
.chat-row[data-chat-motion="create"]{
  z-index:4;transform-origin:top center;
  animation:chat-motion-create-row .65s cubic-bezier(.2,.82,.25,1) both;
}
.chat-row[data-chat-motion="create"]::after{
  position:absolute;z-index:5;top:5px;right:6px;padding:2px 5px;border-radius:5px;
  background:var(--purple);color:white;content:"NEW";font-size:.46875rem;font-weight:900;
  letter-spacing:.08em;pointer-events:none;
  animation:chat-motion-new-label .65s ease both;
}
@keyframes chat-motion-create-row{
  0%{opacity:0;transform:translateY(-14px) scale(.975)}
  48%{opacity:1;transform:translateY(0) scale(1.008)}
  100%{opacity:1;transform:none}
}
@keyframes chat-motion-new-label{
  0%,18%{opacity:0;transform:scale(.72)}
  38%,70%{opacity:1;transform:none}
  100%{opacity:0;transform:translateY(-2px)}
}

/* A spawn is a relationship, not another top-level arrival. The parent catches
   first; the child slides along the existing rail while its vertical and elbow
   strokes draw into place. */
.chat-row[data-chat-motion="spawn-parent"] .chat-pill{
  animation:chat-motion-parent-catch .85s cubic-bezier(.2,.82,.25,1) both;
}
.chat-row[data-chat-motion="spawn"]{
  z-index:3;transform-origin:left center;
  animation:chat-motion-child-row .85s cubic-bezier(.2,.82,.25,1) both;
}
.chat-row:is([data-depth="1"],[data-depth="2"])[data-chat-motion="spawn"]::after{
  transform-origin:top;animation:chat-motion-branch-vertical .85s ease both;
}
.chat-row:is([data-depth="1"],[data-depth="2"])[data-chat-motion="spawn"]::before{
  transform-origin:left;animation:chat-motion-branch-elbow .85s ease both;
}
@keyframes chat-motion-parent-catch{
  0%,18%{transform:scale(.88);opacity:.3}
  42%{transform:scale(1.1);opacity:1}
  100%{transform:none;opacity:1}
}
@keyframes chat-motion-child-row{
  0%,24%{opacity:0;transform:translateX(-16px) scale(.97)}
  58%{opacity:1;transform:translateX(1px) scale(1.005)}
  100%{opacity:1;transform:none}
}
@keyframes chat-motion-branch-vertical{0%,20%{transform:scaleY(0)}58%,100%{transform:scaleY(1)}}
@keyframes chat-motion-branch-elbow{0%,42%{transform:scaleX(0)}72%,100%{transform:scaleX(1)}}

/* Tap-send gets one short optimistic-row entrance. Keyboard sends deliberately
   bypass it, and the button's :active state in shell.css provides immediate tap
   feedback without waiting for the optimistic row to mount. */
.timeline-row[data-chat-motion="send"] > .message-bubble,
.timeline-row[data-chat-motion="send"] > .message-stack{
  transform-origin:right bottom;
  animation:chat-motion-message-lift .18s cubic-bezier(.23,1,.32,1) both;
}
@keyframes chat-motion-message-lift{
  0%{opacity:.55;transform:translateY(6px) scale(.985)}
  100%{opacity:1;transform:none}
}

:root[data-v2-attention-motion="still"] [data-chat-motion],
:root[data-v2-attention-motion="still"] [data-chat-motion]::before,
:root[data-v2-attention-motion="still"] [data-chat-motion]::after,
:root[data-v2-attention-motion="still"] [data-chat-motion] .chat-pill,
:root[data-v2-attention-motion="still"] [data-chat-motion] .message-bubble,
:root[data-v2-attention-motion="still"] [data-chat-motion] .message-stack{animation:none}

@media (prefers-reduced-motion:reduce){
  [data-chat-motion],[data-chat-motion]::before,[data-chat-motion]::after,
  [data-chat-motion] .chat-pill,[data-chat-motion] .message-bubble,[data-chat-motion] .message-stack{animation:none}
}

@media (forced-colors:active){
  #v2Context[data-chat-motion]::before{background:Highlight;box-shadow:none}
  .chat-row[data-chat-motion="create"]::after{background:Highlight;color:HighlightText;forced-color-adjust:none}
}
