diff --git a/frontend/src/pages/LandingPage.tsx b/frontend/src/pages/LandingPage.tsx
index b8073a93..ae7a37ef 100644
--- a/frontend/src/pages/LandingPage.tsx
+++ b/frontend/src/pages/LandingPage.tsx
@@ -225,6 +225,7 @@ export default function LandingPage() {
+ FlowPilot is thinking...
diff --git a/frontend/src/styles/landing.css b/frontend/src/styles/landing.css
index 4e2f1dd9..9567ec51 100644
--- a/frontend/src/styles/landing.css
+++ b/frontend/src/styles/landing.css
@@ -1510,58 +1510,70 @@
============================================ */
/* ── A) ANIMATED CHAT MESSAGES ── */
-/* Each chat line fades in and slides up with staggered timing.
- The typing indicator appears between user message and AI response,
- then hides when the AI lines appear. */
+/* Deliberate, watchable conversation sequence.
+ User types → thinking → AI responds line by line → doc confirmation */
.landing-chat-animated {
opacity: 0;
- transform: translateY(8px);
- animation: landingChatReveal 0.4s ease-out both;
- /* Base delay: 1.5s (after hero entrance) + stagger per line */
- animation-delay: calc(1.5s + var(--chat-index, 0) * 0.6s);
+ transform: translateX(-20px);
+ animation: landingChatSlideIn 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
+ /* Slower stagger: 1.2s per message so each line is clearly individual.
+ Base delay 2s (after hero + preview entrance). */
+ animation-delay: calc(2s + var(--chat-index, 0) * 1.2s);
}
-/* The typing indicator (index 1) appears, then fades out when index 2 appears */
+/* The typing indicator (index 1) has its own lifecycle: appear → hold → collapse */
.landing-chat-animated:nth-child(2) {
- animation: landingTypingLifecycle 1.8s ease both;
- animation-delay: calc(1.5s + 0.6s);
+ animation: landingTypingLifecycle 3s ease both;
+ animation-delay: 3.2s; /* appears after user message */
}
-@keyframes landingChatReveal {
+/* AI responses start after typing indicator finishes (3.2s + 3s = 6.2s) */
+.landing-chat-animated:nth-child(3) { animation-delay: 6.2s; }
+.landing-chat-animated:nth-child(4) { animation-delay: 7.2s; }
+.landing-chat-animated:nth-child(5) { animation-delay: 8.2s; }
+/* Doc confirmation comes last with extra pause */
+.landing-chat-animated:nth-child(6) { animation-delay: 9.6s; }
+
+@keyframes landingChatSlideIn {
from {
opacity: 0;
- transform: translateY(8px);
+ transform: translateX(-20px);
}
to {
opacity: 1;
- transform: translateY(0);
+ transform: translateX(0);
}
}
@keyframes landingTypingLifecycle {
- 0% { opacity: 0; transform: translateY(8px); }
- 15% { opacity: 1; transform: translateY(0); }
- 70% { opacity: 1; transform: translateY(0); }
- 100% { opacity: 0; transform: translateY(0); height: 0; padding: 0; margin: 0; overflow: hidden; }
+ 0% { opacity: 0; transform: translateX(-20px); }
+ 10% { opacity: 1; transform: translateX(0); }
+ 75% { opacity: 1; transform: translateX(0); }
+ 90% { opacity: 0; transform: translateX(0); }
+ 100% { opacity: 0; height: 0; padding: 0; margin: 0; overflow: hidden; }
}
-/* ── Typing indicator dots ── */
+/* ── Typing indicator dots — bigger, with label ── */
.landing-typing-indicator {
display: flex;
align-items: center;
- gap: 4px;
- padding: 4px 8px;
+ gap: 6px;
+ padding: 6px 10px;
+ border-radius: 8px;
+ background: rgba(96, 165, 250, 0.06);
+ border: 1px solid rgba(96, 165, 250, 0.1);
+ width: fit-content;
}
.landing-typing-indicator span {
display: block;
- width: 5px;
- height: 5px;
+ width: 6px;
+ height: 6px;
border-radius: 50%;
background: #60a5fa;
- opacity: 0.4;
- animation: landingTypingBounce 1.2s ease-in-out infinite;
+ opacity: 0.5;
+ animation: landingTypingBounce 1s ease-in-out infinite;
}
.landing-typing-indicator span:nth-child(2) {
@@ -1572,28 +1584,54 @@
animation-delay: 0.3s;
}
+/* The label text span — no bounce animation */
+.landing-typing-indicator span:nth-child(4) {
+ width: auto;
+ height: auto;
+ border-radius: 0;
+ background: transparent;
+ opacity: 1;
+ animation: none;
+}
+
@keyframes landingTypingBounce {
0%, 60%, 100% {
transform: translateY(0);
opacity: 0.4;
}
30% {
- transform: translateY(-4px);
+ transform: translateY(-5px);
opacity: 1;
}
}
-/* ── Sidebar items stagger in ── */
-.landing-preview-sidebar-item {
- opacity: 0;
- animation: landingChatReveal 0.3s ease-out both;
+/* ── App preview cinematic entrance ── */
+.landing-app-preview {
+ animation: landingPreviewEntrance 1s cubic-bezier(0.22, 1, 0.36, 1) 0.75s both;
}
-.landing-preview-sidebar-item:nth-child(1) { animation-delay: 0.8s; }
-.landing-preview-sidebar-item:nth-child(2) { animation-delay: 0.9s; }
-.landing-preview-sidebar-item:nth-child(3) { animation-delay: 1.0s; }
-.landing-preview-sidebar-item:nth-child(4) { animation-delay: 1.1s; }
-.landing-preview-sidebar-item:nth-child(5) { animation-delay: 1.2s; }
+@keyframes landingPreviewEntrance {
+ from {
+ opacity: 0;
+ transform: translateY(40px) scale(0.95);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0) scale(1);
+ }
+}
+
+/* ── Sidebar items stagger in with slide ── */
+.landing-preview-sidebar-item {
+ opacity: 0;
+ animation: landingChatSlideIn 0.35s cubic-bezier(0.22, 1, 0.36, 1) both;
+}
+
+.landing-preview-sidebar-item:nth-child(1) { animation-delay: 1.2s; }
+.landing-preview-sidebar-item:nth-child(2) { animation-delay: 1.35s; }
+.landing-preview-sidebar-item:nth-child(3) { animation-delay: 1.5s; }
+.landing-preview-sidebar-item:nth-child(4) { animation-delay: 1.65s; }
+.landing-preview-sidebar-item:nth-child(5) { animation-delay: 1.8s; }
/* ── B) SCROLL-DRIVEN ENHANCEMENTS ── */
/* Upgrade the basic reveal to use scroll-driven parallax where supported */
@@ -1698,7 +1736,8 @@
/* ── REDUCED MOTION ── */
@media (prefers-reduced-motion: reduce) {
.landing-chat-animated,
- .landing-preview-sidebar-item {
+ .landing-preview-sidebar-item,
+ .landing-app-preview {
opacity: 1;
transform: none;
animation: none;