/* ===========================================================================
   SolutionsDataHub -- chat beat (datahub-chat.js), round 6 2026-10-05.
   Phong: "người hỏi gõ chữ, AI trả lời bên dưới như chat". One clock per
   [data-dh-chat], every step a custom property:
     --t0 (per question)    typing starts; one character every --cd (55ms),
                            the caret rides on the newest character
     --ty (JS)              typing ends: the question is "sent" (a small press)
     --da = --ty + --send   the answer frame appears, 3 dots think inside it
     --ra = --da + --think  the answer's content rises, the dots go
   [data-dh-after] rises 150ms after the answer (the tour's chart).
   Only opacity / transform / box-shadow (the caret) animate. Start states live
   ONLY under html.dh-motion [data-dh-latch]:not(.dh-seen) (datahub-motion.js
   contract): no JS / reduced motion = every text at once, dots never shown.
   The hero film types its question on its own beat (datahub-film-3.css) with
   the keyframes below.
   =========================================================================== */
[data-dh-chat] { --send: 150ms; --think: 900ms; --da: calc(var(--ty, 0ms) + var(--send)); --ra: calc(var(--da) + var(--think)); }
[data-dh-reply] { position: relative; }
.dh-chat-dots { position: absolute; left: var(--dx, 10px); top: var(--dy, 8px); display: flex; gap: 4px; opacity: 0; pointer-events: none; }
.dh-chat-dots i { width: 6px; height: 6px; border-radius: 50%; background: var(--dh-acc); }
.dh-chat-dots i:nth-child(2) { --k: 1; }
.dh-chat-dots i:nth-child(3) { --k: 2; }

/* tour ① 質問する: the picked question, echoed as the user's chat bubble */
.dh-win .dh-tour-ask { width: fit-content; max-width: 88%; margin: 0 0 12px auto; padding: 6px 12px; border-radius: 12px 12px 3px 12px; background: var(--navy); font-size: 13px; font-weight: 700; line-height: 1.6; color: var(--white); }
/* the echo adds ~44px to panel ①; from 1024px the 4 tabs were level (462 / 473px),
   so lift the shared floor to panel ①'s height: switching tabs does not move the page
   (479px since round 7: the 13px floor made panel ① 3px taller) */
@media (min-width: 1024px) { .dh-tour.is-live .dh-tour-panel { min-height: 479px; } }

/* ---- start states: only until the block is seen ------------------------------ */
html.dh-motion [data-dh-latch]:not(.dh-seen) :is(.dh-ch, [data-dh-type], [data-dh-reply], [data-dh-reply] > :not(.dh-chat-dots), [data-dh-after]) { opacity: 0; }

/* ---- the beat ---------------------------------------------------------------- */
html.dh-motion .dh-seen .dh-ch { animation: dh-ch-in 1ms linear calc(var(--t0, 0ms) + var(--i) * var(--cd, 55ms)) both, dh-ch-caret var(--cd, 55ms) steps(1) calc(var(--t0, 0ms) + var(--i) * var(--cd, 55ms)); }
html.dh-motion .dh-seen .dh-ch--last { animation-duration: 1ms, 380ms; }
html.dh-motion .dh-seen [data-dh-type] { animation: dh-chat-in 0.25s var(--ease-out) calc(var(--t0, 0ms) - 120ms) both, dh-chat-send 0.3s var(--ease-out) var(--ty, 0ms) both; }
html.dh-motion .dh-seen [data-dh-reply] { animation: dh-chat-in 0.3s var(--ease-out) var(--da) both; }
html.dh-motion .dh-seen [data-dh-reply] > :not(.dh-chat-dots, .dh-tour-aim) { animation: dh-chat-in 0.45s var(--ease-out) var(--ra) both; }
html.dh-motion .dh-seen .dh-chat-dots { animation: dh-chat-think calc(var(--ra) - var(--da)) linear var(--da) both; }
html.dh-motion .dh-seen .dh-chat-dots i { animation: dh-chat-lift 0.6s var(--ease-soft) calc(var(--da) + 0.15s + var(--k, 0) * 0.12s) 2 both; }
html.dh-motion .dh-seen [data-dh-after] { animation: dh-chat-in 0.45s var(--ease-out) calc(var(--ra) + 150ms) both; }
/* the tour builds a new chart per question (.is-anim): its bars wait for the answer too */
html.dh-motion .dh-seen[data-dh-chat] .dh-tour-cols.is-anim i { animation-delay: calc(var(--ra) + 0.3s + var(--i, 0) * 0.07s); }
html.dh-motion .dh-seen[data-dh-chat] .dh-tour-cols.is-anim b { animation-delay: calc(var(--ra) + 0.6s + var(--i, 0) * 0.07s); }
html.dh-motion .dh-seen[data-dh-chat] .dh-tour-goal.is-anim .dh-tour-track i { animation-delay: calc(var(--ra) + 0.4s + var(--i, 0) * 0.45s); }

@keyframes dh-ch-in { from { opacity: 0; } to { opacity: 1; } }   /* linear, not steps(1): at the end Chrome reports progress 0.9999999999999 for long delays and steps(1) then stays at 0 */
@keyframes dh-ch-caret { from, to { box-shadow: 1.5px 0 0 0 currentColor; } }
@keyframes dh-chat-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes dh-chat-send { 0%, 100% { transform: none; } 45% { transform: scale(0.97); } }
@keyframes dh-chat-think { 0% { opacity: 0; } 12%, 88% { opacity: 1; } 100% { opacity: 0; } }
@keyframes dh-chat-lift { 0%, 100% { transform: none; } 50% { transform: translateY(-3px); } }

@media (prefers-reduced-motion: reduce) {
  .dh-ch, [data-dh-type], [data-dh-reply], [data-dh-reply] > *, [data-dh-after], .dh-chat-dots, .dh-chat-dots i { animation: none !important; }
}
