3:I[4707,[],""]
6:I[36423,[],""]
8:I[88003,["4304","static/chunks/4304-75b83db16b0d34ab.js","8003","static/chunks/8003-77a01866b8e7e6e5.js","989","static/chunks/989-00a9380fdf607821.js","1326","static/chunks/1326-2bdf304cc7ffd395.js","3482","static/chunks/3482-39727346ba3389e1.js","2067","static/chunks/2067-5ff028a5991d5385.js","9762","static/chunks/9762-bb7f25d1bc47d0e7.js","5616","static/chunks/app/%5Blocale%5D/animation/%5Bid%5D/page-339a742a17becf51.js"],""]
9:I[61103,["8003","static/chunks/8003-77a01866b8e7e6e5.js","3185","static/chunks/app/layout-74b4ccf534333157.js"],"UserProvider"]
a:I[49197,["8003","static/chunks/8003-77a01866b8e7e6e5.js","3185","static/chunks/app/layout-74b4ccf534333157.js"],"Analytics"]
4:["locale","en","d"]
5:["id","b8298c3b-c35e-40b0-a834-c03554a58772","d"]
0:["CAN1vmUv34EyQsNBZt3P6",[[["",{"children":[["locale","en","d"],{"children":["animation",{"children":[["id","b8298c3b-c35e-40b0-a834-c03554a58772","d"],{"children":["__PAGE__",{}]}]}]}]},"$undefined","$undefined",true],["",{"children":[["locale","en","d"],{"children":["animation",{"children":[["id","b8298c3b-c35e-40b0-a834-c03554a58772","d"],{"children":["__PAGE__",{},[["$L1","$L2",null],null],null]},[null,["$","$L3",null,{"parallelRouterKey":"children","segmentPath":["children","$4","children","animation","children","$5","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L6",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","notFoundStyles":"$undefined"}]],null]},[null,["$","$L3",null,{"parallelRouterKey":"children","segmentPath":["children","$4","children","animation","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L6",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","notFoundStyles":"$undefined"}]],null]},[[null,"$L7"],null],null]},[[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/04a2b1dee28c4433.css","precedence":"next","crossOrigin":"$undefined"}],["$","link","1",{"rel":"stylesheet","href":"/_next/static/css/af7c04e52a18620f.css","precedence":"next","crossOrigin":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"className":"bg-gray-950 text-gray-100","children":[["$","$L8",null,{"id":"theme-init","strategy":"beforeInteractive","children":"\n            (() => {\n              try {\n                var path = window.location.pathname;\n                var isHome = path === '/' || path.endsWith('/home') || /\\/(zh|en)\\/home(\\/|$)/.test(path);\n                if (isHome) {\n                  // 首页固定深色主题\n                  document.documentElement.dataset.theme = 'dark';\n                  document.documentElement.style.colorScheme = 'dark';\n                  return;\n                }\n                var stored = localStorage.getItem('site-theme');\n                var theme = stored || 'light';\n                document.documentElement.dataset.theme = theme;\n                document.documentElement.style.colorScheme = theme;\n              } catch (e) {\n                document.documentElement.dataset.theme = 'light';\n                document.documentElement.style.colorScheme = 'light';\n              }\n            })();\n          "}],["$","$L8",null,{"src":"https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-5639745717417263","strategy":"afterInteractive","crossOrigin":"anonymous"}],["$","$L8",null,{"src":"https://www.googletagmanager.com/gtag/js?id=G-C6PN3G0S7V","strategy":"afterInteractive"}],["$","$L8",null,{"id":"google-analytics","strategy":"afterInteractive","children":"\n            window.dataLayer = window.dataLayer || [];\n            function gtag(){dataLayer.push(arguments);}\n            gtag('js', new Date());\n            gtag('config', 'G-C6PN3G0S7V');\n          "}],["$","$L8",null,{"id":"organization-jsonld","type":"application/ld+json","dangerouslySetInnerHTML":{"__html":"{\"@context\":\"https://schema.org\",\"@type\":\"Organization\",\"name\":\"SvgAnimate\",\"url\":\"https://svganimate.ai\",\"logo\":\"https://svganimate.ai/logo.png\"}"}}],["$","$L9",null,{"children":["$","$L3",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L6",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[]}]}],["$","$La",null,{}]]}]}]],null],null],["$Lb",null]]]]
c:I[47279,["1203","static/chunks/app/%5Blocale%5D/layout-da3cb07dac8804ed.js"],"I18nProvider"]
d:I[65373,["1203","static/chunks/app/%5Blocale%5D/layout-da3cb07dac8804ed.js"],"NotificationProvider"]
e:I[78537,["1203","static/chunks/app/%5Blocale%5D/layout-da3cb07dac8804ed.js"],"LocaleAutoRedirect"]
7:["$","$Lc",null,{"locale":"en","dictionary":{"languageName":"English","languageSwitcher":{"tooltip":"Switch language","languages":{"zh":"中文","en":"English"}},"themeSwitcher":{"tooltip":"Switch theme","light":"Light","dark":"Dark"},"actions":{"search":"Search","clear":"Clear"},"brand":{"title":"SvgAnimate Animation Studio","subtitle":"Type a keyword to quickly find the animation you need","searchPlaceholder":"Search animations, e.g. 'sorting algorithm' or 'TCP'...","searchButton":"Search","hotLabel":"🔥 Trending:","hotKeywords":["Algorithm","Network","Astronomy"]},"home":{"featuredTitle":"Featured Picks","searchResultPrefix":"results for","hottest":"Hottest","noResults":"No matching animations","clearSearch":"Clear search","loadMore":"Load more","loadingMore":"Loading...","noMore":"No more data","footerCopy":"© 2025 AI SVG Animation Studio. All rights reserved.","viewAll":"View All Web Animation Examples","privacyPolicy":"Privacy Policy","termsOfService":"Terms of Service","contactMe":"Contact Me","contactEmailLabel":"or email","newHero":{"title":"Create Professional Knowledge Explainers & Animations","subtitle":"AI writes complete HTML video scripts and storyboard previews, professional videos in one click.\nDozens of SVG animation templates to choose from and copy with one click.","ctaHint":"Bring your content to life","primaryCta":"Try It Now","secondaryCta":"Learn More","miniCenterLabel":"Mini creation center preview","titleLine1":"One Prompt","titleLine2":"Professional Knowledge Explainer","titleLine3":"HTML Video & SVG Animation","features":["Auto Script Expansion","Editable Storyboards","Custom Voiceover & Subtitles"]},"scenariosSection":{"title":"Perfect For These Scenarios","subtitle":"","viewMore":"View more scenarios","items":[{"key":"knowledge","title":"Knowledge Explainer","description":"Break abstract concepts into visual scenes and auto-generate visuals and voice so ideas become clear.","cta":"Try It Now"},{"key":"classroom","title":"Classroom Teaching","description":"Generate lively HTML videos for key lesson points and help students grasp core knowledge faster.","cta":"Try It Now"},{"key":"story","title":"Storytelling","description":"Tell brand or educational stories with coherent visual scenes that make content more engaging.","cta":"Try It Now"}]},"midCta":{"title":"No coding, no prompt skills, no professional editing software","subtitle":"Whether it's professional knowledge explainers, process demo videos, fun animations, or web logo animations — create them all in one click.","buttonText":"Get Started Free"}},"sidebar":{"home":"Home","creation":"Create","browse":"Browse Categories","profile":"Profile"},"categories":{"home":"Home","create":"Create","svg-loading-animation":"Loading Animation","svg-logo-animation":"Logo Animation","text-svg-animation":"Text Animation","svg-line-drawing":"Line Drawing","hand-drawn-animation":"Hand-drawn Animation","interactive-svg-animation":"Interactive Animation","flowchart-animation":"Flowchart Animation","svg-map-animation":"Map Animation","svg-mini-game":"Web Mini Game","stem-knowledge-animation":"STEM Education","data-visualization-animation":"Data Visualization","html-video":"HTML Video","stick-figure-animation":"Stick Figure","product-demo-animation":"Product Demo","dynamic-view-webpage":"Dynamic Webpage","3d-animation":"3D Animation","others":"Other"},"categoryPage":{"searchPlaceholder":"Search within this category...","empty":"No animations in this category yet.","countSuffix":"animations"},"statuses":{"loading":"Loading animations...","loadError":"Failed to load animations. Check the database service or refresh."},"login":{"title":"Please sign in","description":"Sign in to create animations and videos, view and edit your work, and export GIF/MP4.","github":"Sign in with GitHub","google":"Sign in with Google","cancel":"Cancel","notLogged":"Not signed in","clickToLogin":"Click to sign in"},"templateCard":{"missing":"Animation component not found","hoverToPlay":"Hover to play","previewHint":"Playback pauses when you leave"},"profile":{"label":"Profile"},"creation":{"label":"Create"},"breadcrumbs":{"back":"Back"},"hotSearchLabel":"Trending","hero":{"version":"Powered by Gemini 3.1 Pro","title1":"SVG Animation Generator –","title2":"Create SVGs & HTML Videos with AI","subtitle":"No coding required, no professional software needed. Describe what you want and AI generates ","subtitle2":"SVG animations","subtitle3":", HTML videos, and export-ready web motion.","svgTooltipTitle":"What are svg animations?","svgTooltipDesc":"svg animations are based on mathematical formulas and never lose quality when scaled. Compared to traditional videos, they're smaller, load faster, and infinitely scalable. Perfect for web displays, educational demos, and brand promotions.","placeholder":"Describe your animation... e.g. 'A rotating DNA double helix structure'","startButton":"Start Generating","advancedButton":"Advanced Mode","navigating":"Redirecting...","creatorPrefix":"Perfect for","creatorBadge":"knowledge educators","example1":"Loading Effect","example2":"Brand Logo","example3":"Data Viz","example4":"Toggle Switch","features":{"infiniteZoom":"Infinite Zoom","ultra4K":"4K Ultra HD","oneClickExport":"One-Click Export","massiveCases":"Massive Gallery"},"freeTrialHint":"Start with free trial","panel":{"tipsTitle":"Prompt Tips","examplesTitle":"Sample Prompts","simpleLabel":"Simple","detailedLabel":"Detailed","detailedBadge":"Detailed · Recommended","useSimple":"Use Simple","useDetailed":"Use Detailed","showcaseTitle":"Best For"},"contentExamples":[{"label":"Physics Motion","title":"Physics Motion Animation","description":"Visualize physical laws with vector motion so abstract concepts become intuitive.","tips":["Describe the motion path and speed clearly","Explain relationships between objects","Add orbits, arrows, and aids if helpful"],"simpleExample":"Earth orbits the sun, the moon orbits the earth","detailedExample":"Build a solar system: a yellow sun in the center, Earth orbits on an elliptical path, the moon circles Earth. Earth is blue, the moon is gray, and the orbits are dotted lines.","showcase":"Great for: science education, physics demos, astronomy explainers"},{"label":"Knowledge Demo","title":"Technical Explainer","description":"Turn complex mechanisms into visuals so viewers grasp technical details fast.","tips":["Describe the workflow step by step","Highlight key parts and their motion","Use precise terminology for accuracy"],"simpleExample":"How a mechanical hard drive reads data","detailedExample":"Show HDD internals: platter spinning at high speed, actuator arm moves to position, head floats above the platter to read data. Color the platter, head, and arm differently and draw the data flow path.","showcase":"Great for: tech talks, product demos, training materials"},{"label":"Video Intro","title":"Logo Intro Animation","description":"Create a polished brand opener to boost impact and recognition.","tips":["Clarify the order and effects of text transforms","Describe rotation/scale/light details","Reference well-known brand intro styles"],"simpleExample":"SvgAnimate text spins into “Animation Studio”","detailedExample":"Make a premium opener: deep blue background, SvgAnimate letters roll in from the right with a gold sheen and light 3D look. After arriving center they rotate 360°, morphing into the Chinese words for “Animation Studio”.","showcase":"Great for: brand promos, video openers, event intros"},{"label":"Character Motion","title":"Character Animation","description":"Use clean shapes to show character movement with rhythm and storytelling.","tips":["Describe character look and colors","State tempo and camera motion","Add beats, cuts, or emotion shifts if needed"],"simpleExample":"A stick figure runs with mountains and clouds scrolling behind","detailedExample":"On a dark gradient background, design a minimalist runner made of geometric shapes. Legs alternate, arms swing; a ground shadow moves. Distant mountains and clouds pan left to imply speed.","showcase":"Great for: product motion, explainers, UI animation demos"}]},"header":{"gallery":"Gallery","learn":"Learn","tools":"Tools","blog":"Blog","membership":"Pricing","profile":"Profile","logout":"Sign Out","startCreating":"Start Creating","login":"Sign In","quotaUsage":"Points","history":"History"},"gallery":{"title":"Web Animation Examples Gallery","subtitle":"Browse featured web animation examples","all":"All","prev":"Prev","next":"Next","searchPlaceholder":"Search by title or description...","searchButton":"Search","adLabel":"Sponsored"},"membership":{"badge":"Simple, transparent pricing","title1":"Choose your","title2":"plan","subtitle":"Start free and scale as you grow. All plans include our core AI features with increasing limits and capabilities.","loading":"Loading...","mostPopular":"Most popular","perMonth":"/month","perYear":"/year","perPurchase":"One-time","freePlanDesc":"Experience basic features","litePlanDesc":"Lightweight entry with flexible top-ups","proPlanDesc":"Best choice for professionals","maxPlanDesc":"Unlimited for advanced users","currentPlan":"Current Plan","purchaseButton":"Purchase Now","subscribeButton":"Subscribe","featuresTitle":"Features:","quotaLabel":"points","quotaPeriod":"per month","quotaPeriodNote":"points do not roll over and reset next month","quotaPeriodOnce":"no expiry","watermarkLabel":"Export","watermarkYes":"with","watermarkNo":"without","watermarkSuffix":"watermark","watermarkFormats":"GIF and video","resolutionLabel":"Supported resolutions","billingCycleLabel":"Billing cycle","monthly":"Monthly","yearly":"Yearly","saveBadge":"Save","paymentTitle":"Scan to Pay","paymentAmount":"Amount:","paymentInstruction":"Please scan the QR code with WeChat to complete payment","paymentTimeLeft":"Time remaining:","paymentCancel":"Cancel Payment","paymentSuccess":"Payment Successful","paymentSuccessDesc":"Membership benefits activated","paymentExpired":"Order Expired","paymentExpiredDesc":"Please create a new order","paymentClose":"Close","subscription":"Subscription Management","subscriptionStatus":"Subscription Status","subscriptionActive":"Active","subscriptionCancelled":"Cancelled","subscriptionPastDue":"Past Due","nextBillingDate":"Next billing date","cancelSubscription":"Cancel Subscription","reactivateSubscription":"Reactivate Subscription","managePaymentMethod":"Manage Payment Method","billingHistory":"Billing History","cancelAtPeriodEnd":"Will cancel at period end","subscriptionRemaining":"Your subscription will remain active until","subscriptionCancelSuccess":"Subscription canceled successfully","subscriptionReactivateSuccess":"Subscription reactivated successfully","alertLogin":"Please sign in first","alertSessionExpired":"Session expired, please sign in again","alertOrderFailed":"Failed to create order","alertPurchaseFailed":"Purchase failed, please try again later","alertPurchaseSuccess":"Purchase successful!","alertSubscribeSuccess":"Subscription activated successfully!","alertSubscribeFailed":"Failed to create subscription","alertActiveSubscription":"You already have an active subscription","alertProcessing":"Processing payment...","redeemTitle":"Redeem membership","redeemSubtitle":"Enter your 8-character code to unlock the plan.","redeemPlaceholder":"Enter redemption code (case-sensitive)","redeemButton":"Redeem","redeemProcessing":"Redeeming...","redeemInvalid":"Invalid redemption code format","redeemFailed":"Redemption failed, please try again later","redeemSuccess":"Redeemed successfully. Membership activated.","redeemExpand":"Expand","redeemCollapse":"Collapse"},"learn":{"title":"AI Web Animation Guide","subtitle":"Learn how to create web animations with AI, from SVG motion to interactive pages and polished product demos.","metaDescription":"A practical guide to creating web animation with AI: SVG motion, interactive pages, prompt writing, and high-quality examples you can ship.","hero":{"badge":"Web Motion Lab","title":"Welcome to the ","titleAccent":"AI Web Animation Guide","description":"This page explains what web animation is, how SVG animation fits into it, how to create interactive motion with AI, and how to turn prompts into production-ready outputs.","featurePills":["Prompt to motion","SVG & HTML outputs","Interactive experiences","Production ready"],"primaryCta":"Start Creating","secondaryCta":"View Examples","previewLabel":"Live Motion Preview","previewTag":"Generated in Seconds","previewStats":[{"title":"Editable Output","description":"SVG or HTML"},{"title":"Smooth Motion","description":"60fps-ready"},{"title":"Interactive Ready","description":"Built for the web"}],"highlights":[{"title":"Prompt to Motion","description":"Describe an idea and get working animation fast."},{"title":"Style Precision","description":"Control color, timing, and easing."},{"title":"Web-Native Output","description":"Use SVG or HTML for real web experiences."},{"title":"Production Ready","description":"Use in sites, demos, UI, or ads."}]},"showcaseSection":{"title":"What You Can Make","subtitle":"From SVG motion to interactive webpages, AI web animation covers far more than a single format.","videoIntro":"Video Intro Animation","videoIntroDesc":"Dynamic text logos, transitions, and slogan effects that make video openings more engaging.","brandShowcase":"Brand Showcase Animation","brandShowcaseDesc":"Dynamic brand identity presentation, breathing light effects, stroke growth to strengthen brand memory.","dataVisualization":"Data Visualization","dataVisualizationDesc":"Dynamically growing bar charts, line graphs, dashboards that make boring data vivid.","knowledgeEducation":"Knowledge Education","knowledgeEducationDesc":"Physics demonstrations, astronomical motion, molecular structures—explain complex concepts through animation.","specialEffects":"Special Effects","specialEffectsDesc":"Explosions, fireworks, magic particles, weather effects (rain/snow) to enhance visual impact.","gameAnimation":"Game Animation","gameAnimationDesc":"Character idle, jump actions, item pickup feedback, UI panel popups—perfect for lightweight game development."},"labSection":{"title":"Web Animation Lab","subtitle":"Preview core motion patterns used in SVG, HTML, and interactive web experiences.","controlsTitle":"Pick an Effect","effects":[{"id":"motion","title":"Motion","description":"Smooth position shift"},{"id":"scale","title":"Scale","description":"Breathing or pulse"},{"id":"rotate","title":"Rotate","description":"Spin or loader"},{"id":"stroke","title":"Stroke","description":"Draw-on path effect"},{"id":"glow","title":"Glow","description":"Neon highlight pulse"},{"id":"morph","title":"Morph","description":"Shape transitions"}]},"whatIsSection":{"title":"What is Web Animation?","content":["Web animation is any motion designed to run natively on the web, including SVG animation, animated HTML interfaces, interactive product demos, and data-driven experiences. It adds clarity, feedback, and visual rhythm to websites and apps.","SVG animation is one important branch of web animation. It is ideal for lightweight vector motion such as icons, loaders, diagrams, and stylized explainers, while HTML, CSS, and JavaScript are often better for full-page interaction and UI behavior.","An AI web animation generator lets you describe the experience you want in natural language, then turns that description into exportable motion for the browser. That can mean SVG output, interactive pages, or a reusable animation concept for your product."],"benefits":["Web-Native Delivery - Motion runs directly in the browser instead of relying only on video","Flexible Output - Use SVG for vector motion or HTML for richer interactive pages","SEO Friendly - Search engines can index real web content better than video-only assets","Highly Editable - Adjust colors, timing, layout, and interactions after generation","Excellent Performance - Lightweight motion can load quickly and feel responsive","Interactive - Support clicks, hover states, filters, tabs, and dynamic content","Cross-Platform Compatible - Works across modern browsers and device sizes","Easy Integration - Embed in landing pages, apps, docs, or product walkthroughs"]},"howToSection":{"title":"How to Generate High-Quality Web Animations","intro":"Creating premium web animation with AI is much easier when your prompt matches the final experience you want. Use the steps below to move from idea to polished motion.","steps":[{"title":"Define the Animation Goal","description":"Decide whether you need an SVG loader, a product demo, a landing-page interaction, or a data story. Clear intent improves output quality."},{"title":"Describe the Subject & Motion","description":"State the main elements and the type of movement: rotate, bounce, morph, reveal, scroll, or respond to user input. Specificity gives the AI stronger direction."},{"title":"Add Timing & Easing","description":"Include duration, easing curves, and loop behavior. Example: 2s duration, ease-in-out, infinite loop."},{"title":"Lock the Visual Style","description":"Mention colors, typography, gradients, spacing, line width, and style references such as minimal, editorial, neon, or dashboard UI."},{"title":"Iterate and Refine","description":"Adjust the prompt based on the result. Small changes in pacing, layout, or interaction rules often improve the final experience."},{"title":"Export and Implement","description":"Preview on multiple devices, then export SVG, video, or HTML depending on the use case and implementation plan."}]},"promptFormula":{"title":"Prompt Formula for Pro Results","description":"A simple structure makes your prompts easier to understand and improves output quality.","tokens":["Subject","Motion","Style","Color","Timing","Easing","Loop"],"exampleLabel":"Example Prompt","example":"Create a glowing circular loader, gradient from orange to cyan, smooth clockwise rotation, 2s duration, ease-in-out, infinite loop."},"tipsSection":{"title":"Professional Prompt Techniques","subtitle":"Use these best practices to improve motion quality, clarity, and real-world usability."},"examplesSection":{"title":"Featured Examples & Prompts","subtitle":"Copy pro prompts, see the output style, and start crafting your own.","filterAll":"All","viewPrompt":"View Prompt","hidePrompt":"Hide Prompt","tryPrompt":"Try This Prompt","previewLabel":"SVG Output"},"ctaSection":{"title":"Ready to Create Your First Web Animation?","subtitle":"Start using AI to create SVG motion, interactive pages, and export-ready web experiences.","buttonText":"Start Creating"},"faqSection":{"title":"Frequently Asked Questions","items":[{"question":"What is an HTML video?","answer":"An HTML video is a video built with web technology. You start from a topic or short description, and the system generates the full script, storyboard, narration, and matching HTML scenes, making it well suited for explainers, product demos, and story-driven content."},{"question":"What is web animation?","answer":"Web animation is motion that runs natively in the browser. It includes SVG animation, animated user interfaces, interactive product demos, data visualization, and motion-driven landing pages."},{"question":"How is SVG animation different from web animation?","answer":"SVG animation is one type of web animation. It is best for vector-based motion such as icons, diagrams, and loaders. Web animation is broader and also includes interactive HTML pages, UI motion, and JavaScript-driven experiences."},{"question":"What does an AI web animation generator do?","answer":"It turns a text prompt into browser-ready motion. Depending on the request, that can mean SVG animation, an interactive HTML page, a product demo flow, or another motion format you can preview and export."},{"question":"Do I need programming knowledge to use this?","answer":"Not at all. You describe the experience you want, and the generator handles the implementation. Design intuition helps, but it is not required."},{"question":"How do I write good prompts?","answer":"Describe the subject, interaction, motion, style, color, timing, easing, and looping. Example: 'Create a product hero section with floating cards, subtle scroll reveal, orange accents, and a clean editorial layout.'"},{"question":"Can I use the generated animations commercially?","answer":"Yes, the animations you create are yours to use in commercial or personal projects."},{"question":"What formats can I export?","answer":"You can export GIF, MP4 video, and HTML, depending on the type of animation or webpage you create."},{"question":"What if the exported file looks wrong or won’t play?","answer":"If the exported video cannot play or differs from what you see on the site, use the “Direct recording” option in the export video menu for a true WYSIWYG capture. We recommend Chrome for best results."},{"question":"Will other people see my animations?","answer":"Your privacy is protected. Unless you choose to publish them, your animations are visible only to you."},{"question":"What if the generated animation doesn't meet my expectations?","answer":"Refine the prompt with clearer motion, timing, layout, or interaction details, and iterate. The more specific the prompt, the closer the output will match your intent."},{"question":"Which types of animations are not suitable for generation?","answer":"SVG animation is code-generated animation, suitable for images composed of geometric elements such as points, lines, surfaces, and volumes. It can abstractly represent things, but it is not suitable for generating realistic images."}]}},"notifications":{"title":"Notifications","empty":"No notifications","loading":"Loading...","markAllRead":"Mark all as read","viewDetail":"View details","gotIt":"Got it"}},"children":["$","$Ld",null,{"children":[["$","$Le",null,{"locale":"en"}],["$","$L3",null,{"parallelRouterKey":"children","segmentPath":["children","$4","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L6",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","notFoundStyles":"$undefined"}]]}]}]
f:T89b,Create a flat 2.5D tech-style SVG animation to demonstrate the interaction flow of network management protocols. The background features a dark circuit board grid texture with a faint breathing light effect.

On the left side of the screen, place an isometric server cluster icon representing the "Upstream NMS/Controller," emitting a calm blue glow. On the right side, place a router or switch icon representing the "Network Device," featuring a fine brushed metal texture. Leave enough space between them to display the data transmission path.

The animation is divided into two looping chapters:

Chapter 1: SNMP Protocol. Establish a lightweight orange dashed path between the two ends. The upstream system emits circular, discrete data packets (representing UDP) at a periodic rhythm, with a tiny floating text label "Get-Request" above. When a packet reaches the device, a hierarchical MIB tree structure projection briefly pops up above the device, followed by the return of a "Response" particle carrying data. Occasionally simulate a "Trap" alarm, where the device actively emits rapid red pulses to the left.

Chapter 2: NETCONF Protocol. The original dashed line disappears, replaced by a clear, semi-transparent cyan solid pipe representing an SSH secure connection. The data flow is no longer discrete particles but neatly arranged rectangular code blocks (implying XML/YANG structures) transmitting at a smooth, linear speed. On the device side, demonstrate the merging of the "Candidate" configuration store into the "Running" configuration store, symbolizing the Commit process of an Atomic Transaction through the closing and opening of a lock icon.

The overall animation rhythm is brisk, with key interaction movements using Elastic Easing effects. Data packets and transmission pipes should have light-trail effects with sharp color contrasts (orange/red for SNMP, cyan/green for NETCONF) to intuitively distinguish between connectionless polling mechanisms and session-based configuration management. A dynamic progress bar or text description is displayed at the bottom center, switching between "SNMP: Polling/Trap" and "NETCONF: RPC/Transaction" according to the animation phase.10:T89b,Create a flat 2.5D tech-style SVG animation to demonstrate the interaction flow of network management protocols. The background features a dark circuit board grid texture with a faint breathing light effect.

On the left side of the screen, place an isometric server cluster icon representing the "Upstream NMS/Controller," emitting a calm blue glow. On the right side, place a router or switch icon representing the "Network Device," featuring a fine brushed metal texture. Leave enough space between them to display the data transmission path.

The animation is divided into two looping chapters:

Chapter 1: SNMP Protocol. Establish a lightweight orange dashed path between the two ends. The upstream system emits circular, discrete data packets (representing UDP) at a periodic rhythm, with a tiny floating text label "Get-Request" above. When a packet reaches the device, a hierarchical MIB tree structure projection briefly pops up above the device, followed by the return of a "Response" particle carrying data. Occasionally simulate a "Trap" alarm, where the device actively emits rapid red pulses to the left.

Chapter 2: NETCONF Protocol. The original dashed line disappears, replaced by a clear, semi-transparent cyan solid pipe representing an SSH secure connection. The data flow is no longer discrete particles but neatly arranged rectangular code blocks (implying XML/YANG structures) transmitting at a smooth, linear speed. On the device side, demonstrate the merging of the "Candidate" configuration store into the "Running" configuration store, symbolizing the Commit process of an Atomic Transaction through the closing and opening of a lock icon.

The overall animation rhythm is brisk, with key interaction movements using Elastic Easing effects. Data packets and transmission pipes should have light-trail effects with sharp color contrasts (orange/red for SNMP, cyan/green for NETCONF) to intuitively distinguish between connectionless polling mechanisms and session-based configuration management. A dynamic progress bar or text description is displayed at the bottom center, switching between "SNMP: Polling/Trap" and "NETCONF: RPC/Transaction" according to the animation phase.11:T9b4,https://svganimate.ai/api/og?title=Create+a+flat+2.5D+tech-style+SVG+animation+for+network+management+demonstration&category=Flowchart+Animation&description=Create+a+flat+2.5D+tech-style+SVG+animation+to+demonstrate+the+interaction+flow+of+network+management+protocols.+The+background+features+a+dark+circuit+board+grid+texture+with+a+faint+breathing+light+effect.%0A%0AOn+the+left+side+of+the+screen%2C+place+an+isometric+server+cluster+icon+representing+the+%22Upstream+NMS%2FController%2C%22+emitting+a+calm+blue+glow.+On+the+right+side%2C+place+a+router+or+switch+icon+representing+the+%22Network+Device%2C%22+featuring+a+fine+brushed+metal+texture.+Leave+enough+space+between+them+to+display+the+data+transmission+path.%0A%0AThe+animation+is+divided+into+two+looping+chapters%3A%0A%0AChapter+1%3A+SNMP+Protocol.+Establish+a+lightweight+orange+dashed+path+between+the+two+ends.+The+upstream+system+emits+circular%2C+discrete+data+packets+%28representing+UDP%29+at+a+periodic+rhythm%2C+with+a+tiny+floating+text+label+%22Get-Request%22+above.+When+a+packet+reaches+the+device%2C+a+hierarchical+MIB+tree+structure+projection+briefly+pops+up+above+the+device%2C+followed+by+the+return+of+a+%22Response%22+particle+carrying+data.+Occasionally+simulate+a+%22Trap%22+alarm%2C+where+the+device+actively+emits+rapid+red+pulses+to+the+left.%0A%0AChapter+2%3A+NETCONF+Protocol.+The+original+dashed+line+disappears%2C+replaced+by+a+clear%2C+semi-transparent+cyan+solid+pipe+representing+an+SSH+secure+connection.+The+data+flow+is+no+longer+discrete+particles+but+neatly+arranged+rectangular+code+blocks+%28implying+XML%2FYANG+structures%29+transmitting+at+a+smooth%2C+linear+speed.+On+the+device+side%2C+demonstrate+the+merging+of+the+%22Candidate%22+configuration+store+into+the+%22Running%22+configuration+store%2C+symbolizing+the+Commit+process+of+an+Atomic+Transaction+through+the+closing+and+opening+of+a+lock+icon.%0A%0AThe+overall+animation+rhythm+is+brisk%2C+with+key+interaction+movements+using+Elastic+Easing+effects.+Data+packets+and+transmission+pipes+should+have+light-trail+effects+with+sharp+color+contrasts+%28orange%2Fred+for+SNMP%2C+cyan%2Fgreen+for+NETCONF%29+to+intuitively+distinguish+between+connectionless+polling+mechanisms+and+session-based+configuration+management.+A+dynamic+progress+bar+or+text+description+is+displayed+at+the+bottom+center%2C+switching+between+%22SNMP%3A+Polling%2FTrap%22+and+%22NETCONF%3A+RPC%2FTransaction%22+according+to+the+animation+phase.12:T89b,Create a flat 2.5D tech-style SVG animation to demonstrate the interaction flow of network management protocols. The background features a dark circuit board grid texture with a faint breathing light effect.

On the left side of the screen, place an isometric server cluster icon representing the "Upstream NMS/Controller," emitting a calm blue glow. On the right side, place a router or switch icon representing the "Network Device," featuring a fine brushed metal texture. Leave enough space between them to display the data transmission path.

The animation is divided into two looping chapters:

Chapter 1: SNMP Protocol. Establish a lightweight orange dashed path between the two ends. The upstream system emits circular, discrete data packets (representing UDP) at a periodic rhythm, with a tiny floating text label "Get-Request" above. When a packet reaches the device, a hierarchical MIB tree structure projection briefly pops up above the device, followed by the return of a "Response" particle carrying data. Occasionally simulate a "Trap" alarm, where the device actively emits rapid red pulses to the left.

Chapter 2: NETCONF Protocol. The original dashed line disappears, replaced by a clear, semi-transparent cyan solid pipe representing an SSH secure connection. The data flow is no longer discrete particles but neatly arranged rectangular code blocks (implying XML/YANG structures) transmitting at a smooth, linear speed. On the device side, demonstrate the merging of the "Candidate" configuration store into the "Running" configuration store, symbolizing the Commit process of an Atomic Transaction through the closing and opening of a lock icon.

The overall animation rhythm is brisk, with key interaction movements using Elastic Easing effects. Data packets and transmission pipes should have light-trail effects with sharp color contrasts (orange/red for SNMP, cyan/green for NETCONF) to intuitively distinguish between connectionless polling mechanisms and session-based configuration management. A dynamic progress bar or text description is displayed at the bottom center, switching between "SNMP: Polling/Trap" and "NETCONF: RPC/Transaction" according to the animation phase.13:T9b4,https://svganimate.ai/api/og?title=Create+a+flat+2.5D+tech-style+SVG+animation+for+network+management+demonstration&category=Flowchart+Animation&description=Create+a+flat+2.5D+tech-style+SVG+animation+to+demonstrate+the+interaction+flow+of+network+management+protocols.+The+background+features+a+dark+circuit+board+grid+texture+with+a+faint+breathing+light+effect.%0A%0AOn+the+left+side+of+the+screen%2C+place+an+isometric+server+cluster+icon+representing+the+%22Upstream+NMS%2FController%2C%22+emitting+a+calm+blue+glow.+On+the+right+side%2C+place+a+router+or+switch+icon+representing+the+%22Network+Device%2C%22+featuring+a+fine+brushed+metal+texture.+Leave+enough+space+between+them+to+display+the+data+transmission+path.%0A%0AThe+animation+is+divided+into+two+looping+chapters%3A%0A%0AChapter+1%3A+SNMP+Protocol.+Establish+a+lightweight+orange+dashed+path+between+the+two+ends.+The+upstream+system+emits+circular%2C+discrete+data+packets+%28representing+UDP%29+at+a+periodic+rhythm%2C+with+a+tiny+floating+text+label+%22Get-Request%22+above.+When+a+packet+reaches+the+device%2C+a+hierarchical+MIB+tree+structure+projection+briefly+pops+up+above+the+device%2C+followed+by+the+return+of+a+%22Response%22+particle+carrying+data.+Occasionally+simulate+a+%22Trap%22+alarm%2C+where+the+device+actively+emits+rapid+red+pulses+to+the+left.%0A%0AChapter+2%3A+NETCONF+Protocol.+The+original+dashed+line+disappears%2C+replaced+by+a+clear%2C+semi-transparent+cyan+solid+pipe+representing+an+SSH+secure+connection.+The+data+flow+is+no+longer+discrete+particles+but+neatly+arranged+rectangular+code+blocks+%28implying+XML%2FYANG+structures%29+transmitting+at+a+smooth%2C+linear+speed.+On+the+device+side%2C+demonstrate+the+merging+of+the+%22Candidate%22+configuration+store+into+the+%22Running%22+configuration+store%2C+symbolizing+the+Commit+process+of+an+Atomic+Transaction+through+the+closing+and+opening+of+a+lock+icon.%0A%0AThe+overall+animation+rhythm+is+brisk%2C+with+key+interaction+movements+using+Elastic+Easing+effects.+Data+packets+and+transmission+pipes+should+have+light-trail+effects+with+sharp+color+contrasts+%28orange%2Fred+for+SNMP%2C+cyan%2Fgreen+for+NETCONF%29+to+intuitively+distinguish+between+connectionless+polling+mechanisms+and+session-based+configuration+management.+A+dynamic+progress+bar+or+text+description+is+displayed+at+the+bottom+center%2C+switching+between+%22SNMP%3A+Polling%2FTrap%22+and+%22NETCONF%3A+RPC%2FTransaction%22+according+to+the+animation+phase.b:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"High-quality SVG animation | Create a flat 2.5D tech-style SVG animation for network management demonstration | Flowchart Animation | SvgAnimate"}],["$","meta","3",{"name":"description","content":"$f"}],["$","meta","4",{"name":"keywords","content":"Create a flat 2.5D tech-style SVG animation for network management demonstration,Flowchart Animation"}],["$","link","5",{"rel":"canonical","href":"https://svganimate.ai/en/animation/b8298c3b-c35e-40b0-a834-c03554a58772"}],["$","link","6",{"rel":"alternate","hrefLang":"zh","href":"https://svganimate.ai/zh/animation/b8298c3b-c35e-40b0-a834-c03554a58772"}],["$","link","7",{"rel":"alternate","hrefLang":"en","href":"https://svganimate.ai/en/animation/b8298c3b-c35e-40b0-a834-c03554a58772"}],["$","link","8",{"rel":"alternate","hrefLang":"x-default","href":"https://svganimate.ai/en/animation/b8298c3b-c35e-40b0-a834-c03554a58772"}],["$","meta","9",{"property":"og:title","content":"High-quality SVG animation | Create a flat 2.5D tech-style SVG animation for network management demonstration | Flowchart Animation | SvgAnimate"}],["$","meta","10",{"property":"og:description","content":"$10"}],["$","meta","11",{"property":"og:url","content":"https://svganimate.ai/en/animation/b8298c3b-c35e-40b0-a834-c03554a58772"}],["$","meta","12",{"property":"og:locale","content":"en_US"}],["$","meta","13",{"property":"og:image","content":"$11"}],["$","meta","14",{"property":"og:image:width","content":"1200"}],["$","meta","15",{"property":"og:image:height","content":"630"}],["$","meta","16",{"property":"og:image:alt","content":"Create a flat 2.5D tech-style SVG animation for network management demonstration"}],["$","meta","17",{"property":"og:locale:alternate","content":"zh_CN"}],["$","meta","18",{"property":"og:type","content":"article"}],["$","meta","19",{"name":"twitter:card","content":"summary_large_image"}],["$","meta","20",{"name":"twitter:title","content":"High-quality SVG animation | Create a flat 2.5D tech-style SVG animation for network management demonstration | Flowchart Animation | SvgAnimate"}],["$","meta","21",{"name":"twitter:description","content":"$12"}],["$","meta","22",{"name":"twitter:image","content":"$13"}],["$","link","23",{"rel":"icon","href":"/icon.ico?fd240352ad5c4cdf","type":"image/x-icon","sizes":"256x256"}]]
1:null
15:"$Sreact.suspense"
16:I[9762,["4304","static/chunks/4304-75b83db16b0d34ab.js","8003","static/chunks/8003-77a01866b8e7e6e5.js","989","static/chunks/989-00a9380fdf607821.js","1326","static/chunks/1326-2bdf304cc7ffd395.js","3482","static/chunks/3482-39727346ba3389e1.js","2067","static/chunks/2067-5ff028a5991d5385.js","9762","static/chunks/9762-bb7f25d1bc47d0e7.js","5616","static/chunks/app/%5Blocale%5D/animation/%5Bid%5D/page-339a742a17becf51.js"],"AnimationDetailClient"]
14:Ta94,{"@context":"https://schema.org","@type":"CreativeWork","name":"Create a flat 2.5D tech-style SVG animation for network management demonstration","description":"Create a flat 2.5D tech-style SVG animation to demonstrate the interaction flow of network management protocols. The background features a dark circuit board grid texture with a faint breathing light effect.\n\nOn the left side of the screen, place an isometric server cluster icon representing the \"Upstream NMS/Controller,\" emitting a calm blue glow. On the right side, place a router or switch icon representing the \"Network Device,\" featuring a fine brushed metal texture. Leave enough space between them to display the data transmission path.\n\nThe animation is divided into two looping chapters:\n\nChapter 1: SNMP Protocol. Establish a lightweight orange dashed path between the two ends. The upstream system emits circular, discrete data packets (representing UDP) at a periodic rhythm, with a tiny floating text label \"Get-Request\" above. When a packet reaches the device, a hierarchical MIB tree structure projection briefly pops up above the device, followed by the return of a \"Response\" particle carrying data. Occasionally simulate a \"Trap\" alarm, where the device actively emits rapid red pulses to the left.\n\nChapter 2: NETCONF Protocol. The original dashed line disappears, replaced by a clear, semi-transparent cyan solid pipe representing an SSH secure connection. The data flow is no longer discrete particles but neatly arranged rectangular code blocks (implying XML/YANG structures) transmitting at a smooth, linear speed. On the device side, demonstrate the merging of the \"Candidate\" configuration store into the \"Running\" configuration store, symbolizing the Commit process of an Atomic Transaction through the closing and opening of a lock icon.\n\nThe overall animation rhythm is brisk, with key interaction movements using Elastic Easing effects. Data packets and transmission pipes should have light-trail effects with sharp color contrasts (orange/red for SNMP, cyan/green for NETCONF) to intuitively distinguish between connectionless polling mechanisms and session-based configuration management. A dynamic progress bar or text description is displayed at the bottom center, switching between \"SNMP: Polling/Trap\" and \"NETCONF: RPC/Transaction\" according to the animation phase.","url":"https://svganimate.ai/en/animation/b8298c3b-c35e-40b0-a834-c03554a58772","inLanguage":"en","genre":"Flowchart Animation","keywords":[],"creator":{"@type":"Organization","name":"SvgAnimate","url":"https://svganimate.ai"},"publisher":{"@type":"Organization","name":"SvgAnimate","url":"https://svganimate.ai"}}17:T89b,Create a flat 2.5D tech-style SVG animation to demonstrate the interaction flow of network management protocols. The background features a dark circuit board grid texture with a faint breathing light effect.

On the left side of the screen, place an isometric server cluster icon representing the "Upstream NMS/Controller," emitting a calm blue glow. On the right side, place a router or switch icon representing the "Network Device," featuring a fine brushed metal texture. Leave enough space between them to display the data transmission path.

The animation is divided into two looping chapters:

Chapter 1: SNMP Protocol. Establish a lightweight orange dashed path between the two ends. The upstream system emits circular, discrete data packets (representing UDP) at a periodic rhythm, with a tiny floating text label "Get-Request" above. When a packet reaches the device, a hierarchical MIB tree structure projection briefly pops up above the device, followed by the return of a "Response" particle carrying data. Occasionally simulate a "Trap" alarm, where the device actively emits rapid red pulses to the left.

Chapter 2: NETCONF Protocol. The original dashed line disappears, replaced by a clear, semi-transparent cyan solid pipe representing an SSH secure connection. The data flow is no longer discrete particles but neatly arranged rectangular code blocks (implying XML/YANG structures) transmitting at a smooth, linear speed. On the device side, demonstrate the merging of the "Candidate" configuration store into the "Running" configuration store, symbolizing the Commit process of an Atomic Transaction through the closing and opening of a lock icon.

The overall animation rhythm is brisk, with key interaction movements using Elastic Easing effects. Data packets and transmission pipes should have light-trail effects with sharp color contrasts (orange/red for SNMP, cyan/green for NETCONF) to intuitively distinguish between connectionless polling mechanisms and session-based configuration management. A dynamic progress bar or text description is displayed at the bottom center, switching between "SNMP: Polling/Trap" and "NETCONF: RPC/Transaction" according to the animation phase.18:T42ba,```javascript
import React, { useState, useEffect, useRef, useMemo } from 'react';

const WIDTH = 1200;
const HEIGHT = 700;
const SERVER_X = 250;
const DEVICE_X = 950;
const GROUND_Y = 400;

// 颜色定义
const COLORS = {
  bg: '#0f172a',
  grid: '#1e293b',
  serverBase: '#1e40af',
  serverHighlight: '#3b82f6',
  serverGlow: 'rgba(59, 130, 246, 0.5)',
  deviceBase: '#334155',
  deviceHighlight: '#94a3b8',
  snmp: '#f97316', // Orange
  snmpTrap: '#ef4444', // Red
  netconf: '#06b6d4', // Cyan
  netconfFlow: '#22d3ee',
  netconfLock: '#10b981', // Emerald
  text: '#e2e8f0',
  textDim: '#64748b'
};

export default function NetworkProtocolAnimation() {
  const [time, setTime] = useState(0);
  const reqRef = useRef(0);
  const startTimeRef = useRef(0);

  // 动画循环
  useEffect(() => {
    const animate = (timestamp) => {
      if (!startTimeRef.current) startTimeRef.current = timestamp;
      const elapsed = timestamp - startTimeRef.current;
      setTime(elapsed);
      reqRef.current = requestAnimationFrame(animate);
    };
    reqRef.current = requestAnimationFrame(animate);

    return () => cancelAnimationFrame(reqRef.current);
  }, []);

  // 周期定义 (16秒为一个完整大循环)
  // 0-8s: SNMP
  // 8-16s: NETCONF
  const CYCLE_DURATION = 16000;
  const normalizedTime = time % CYCLE_DURATION;
  const isSnmpPhase = normalizedTime < 8000;
  const phaseProgress = isSnmpPhase ? normalizedTime : normalizedTime - 8000;

  // --- 2.5D 几何体绘制组件 ---

  const IsometricServer = ({ x, y }) => {
    // 简单的等轴侧服务器堆叠
    const w = 60; // 半宽
    const h = 30; // 每一层的高度
    const offset = 15; // 顶面倾斜高度
    
    return (
      <g transform={`translate(${x}, ${y})`}>
        {/* 底部光晕 */}
        <ellipse cx="0" cy={120} rx="90" ry="30" fill={COLORS.serverGlow} filter="url(#glow)" opacity="0.6">
            <animate attributeName="rx" values="85;95;85" dur="3s" repeatCount="indefinite" />
            <animate attributeName="opacity" values="0.4;0.7;0.4" dur="3s" repeatCount="indefinite" />
        </ellipse>

        {/* 服务器机架主体 */}
        {[0, 1, 2].map(i => {
          const dy = i * -35;
          return (
            <g key={i} transform={`translate(0, ${dy})`}>
              {/* 左侧面 */}
              <path d={`M0,0 L-${w},-${offset} L-${w},${h-offset} L0,${h} Z`} fill="#172554" stroke={COLORS.serverHighlight} strokeWidth="1" />
              {/* 右侧面 */}
              <path d={`M0,0 L${w},-${offset} L${w},${h-offset} L0,${h} Z`} fill="#1e3a8a" stroke={COLORS.serverHighlight} strokeWidth="1" />
              {/* 顶面 */}
              <path d={`M0,0 L-${w},-${offset} L0,-${offset*2} L${w},-${offset} Z`} fill={COLORS.serverBase} stroke={COLORS.serverHighlight} strokeWidth="1" />
              {/* 灯光装饰 */}
              <circle cx={-w + 10} cy={5} r="2" fill="#60a5fa">
                 <animate attributeName="opacity" values="0.2;1;0.2" dur={`${0.5 + i * 0.2}s`} repeatCount="indefinite" />
              </circle>
              <circle cx={-w + 20} cy={10} r="2" fill="#60a5fa">
                 <animate attributeName="opacity" values="1;0.2;1" dur={`${0.7 + i * 0.2}s`} repeatCount="indefinite" />
              </circle>
            </g>
          );
        })}
        {/* 标签 */}
        <text x="0" y="160" textAnchor="middle" fill={COLORS.text} fontSize="14" fontWeight="bold">NMS 控制器</text>
        <text x="0" y="180" textAnchor="middle" fill={COLORS.textDim} fontSize="12">Manager</text>
      </g>
    );
  };

  const IsometricDevice = ({ x, y }) => {
    const w = 80;
    const h = 40;
    const offset = 20;

    return (
      <g transform={`translate(${x}, ${y})`}>
         {/* 底部光晕 */}
         <ellipse cx="0" cy={50} rx="100" ry="25" fill="#64748b" filter="url(#glow)" opacity="0.3" />

        {/* 设备主体 - 类似交换机/路由器 */}
        <g transform="translate(0, 0)">
           {/* 左侧面 */}
           <path d={`M0,0 L-${w},-${offset} L-${w},${h-offset} L0,${h} Z`} fill="#334155" stroke={COLORS.deviceHighlight} strokeWidth="1" />
           {/* 右侧面 */}
           <path d={`M0,0 L${w},-${offset} L${w},${h-offset} L0,${h} Z`} fill="#475569" stroke={COLORS.deviceHighlight} strokeWidth="1" />
           {/* 顶面 */}
           <path d={`M0,0 L-${w},-${offset} L0,-${offset*2} L${w},-${offset} Z`} fill="#1e293b" stroke={COLORS.deviceHighlight} strokeWidth="1" />
           
           {/* 端口纹理 (在右侧面上) */}
           {[0, 1, 2, 3].map(i => (
             <rect key={i} x={10 + i * 15} y={-5} width="8" height="12" transform={`skewY(-26)`} fill="#0f172a" stroke="#94a3b8" strokeWidth="0.5" />
           ))}
        </g>
        <text x="0" y="90" textAnchor="middle" fill={COLORS.text} fontSize="14" fontWeight="bold">网络设备</text>
        <text x="0" y="110" textAnchor="middle" fill={COLORS.textDim} fontSize="12">Agent / Server</text>
      </g>
    );
  };

  // --- 动画逻辑组件 ---

  // SNMP 阶段动画
  const SnmpAnimation = ({ progress }) => {
    // 0-2500ms: Get-Request (Left -> Right)
    // 2500-4000ms: MIB Processing
    // 4000-6000ms: Response (Right -> Left)
    // 6000-8000ms: Trap (Right -> Left Fast)

    const start = { x: SERVER_X + 60, y: GROUND_Y - 40 };
    const end = { x: DEVICE_X - 60, y: GROUND_Y - 40 };
    
    // 计算Get-Request位置
    let packetPos = { x: start.x, y: start.y, opacity: 0 };
    let packetText = "";
    
    if (progress < 2500) {
      const p = Math.min(progress / 2000, 1);
      // Easing out
      const ease = 1 - Math.pow(1 - p, 3);
      packetPos.x = start.x + (end.x - start.x) * ease;
      packetPos.opacity = 1;
      packetText = "Get-Request";
    }

    // MIB Tree 显示
    const showMib = progress > 2000 && progress < 4500;
    const mibOpacity = showMib ? (progress < 2500 ? (progress - 2000)/500 : (progress > 4000 ? (4500-progress)/500 : 1)) : 0;

    // Response 位置
    let responsePos = { x: end.x, y: end.y, opacity: 0 };
    if (progress > 3500 && progress < 5500) {
        const p = Math.min((progress - 3500) / 1500, 1);
        const ease = 1 - Math.pow(1 - p, 3);
        responsePos.x = end.x + (start.x - end.x) * ease; // Backwards
        responsePos.opacity = 1;
    }

    // Trap 位置 (偶尔发生)
    let trapPos = { x: end.x, y: end.y + 30, opacity: 0 };
    if (progress > 6000 && progress < 7500) {
        const p = Math.min((progress - 6000) / 1000, 1);
        trapPos.x = end.x + (start.x - end.x) * p;
        trapPos.opacity = 1 - p; // Fade out as it travels
    }

    return (
      <g>
        {/* 虚线路径 */}
        <path d={`M${start.x},${start.y} L${end.x},${end.y}`} stroke={COLORS.snmp} strokeWidth="2" strokeDasharray="8,8" opacity="0.4" />
        
        {/* Get Request Packet */}
        <g transform={`translate(${packetPos.x}, ${packetPos.y})`} opacity={packetPos.opacity}>
            <circle r="12" fill={COLORS.snmp} filter="url(#glow)">
                <animate attributeName="r" values="10;13;10" dur="1s" repeatCount="indefinite"/>
            </circle>
            <text y="-20" textAnchor="middle" fill={COLORS.snmp} fontSize="12" fontWeight="bold">{packetText}</text>
        </g>

        {/* MIB Tree Projection */}
        <g transform={`translate(${DEVICE_X}, ${GROUND_Y - 120})`} opacity={mibOpacity}>
            <line x1="0" y1="0" x2="-30" y2="-40" stroke={COLORS.snmp} strokeWidth="1" />
            <line x1="0" y1="0" x2="30" y2="-40" stroke={COLORS.snmp} strokeWidth="1" />
            <line x1="-30" y1="-40" x2="-50" y2="-70" stroke={COLORS.snmp} strokeWidth="1" />
            <line x1="-30" y1="-40" x2="-10" y2="-70" stroke={COLORS.snmp} strokeWidth="1" />
            
            <circle cx="0" cy="0" r="5" fill="#fff" />
            <circle cx="-30" cy="-40" r="4" fill={COLORS.snmp} />
            <circle cx="30" cy="-40" r="4" fill={COLORS.snmp} />
            <circle cx="-50" cy="-70" r="3" fill={COLORS.snmp} opacity="0.7" />
            <circle cx="-10" cy="-70" r="3" fill={COLORS.snmp} opacity="0.7" />
            
            <text x="50" y="-30" fill={COLORS.snmp} fontSize="12">MIB OID Query</text>
        </g>

        {/* Response Packet */}
        <g transform={`translate(${responsePos.x}, ${responsePos.y})`} opacity={responsePos.opacity}>
            <rect x="-10" y="-10" width="20" height="20" rx="4" fill={COLORS.snmp} filter="url(#glow)" />
            <text y="-20" textAnchor="middle" fill={COLORS.snmp} fontSize="12">Response</text>
        </g>

        {/* Trap Packet */}
        <g transform={`translate(${trapPos.x}, ${trapPos.y})`} opacity={trapPos.opacity}>
            <circle r="8" fill={COLORS.snmpTrap} filter="url(#glow)" />
            <circle r="14" fill="none" stroke={COLORS.snmpTrap} strokeWidth="1" opacity="0.5">
                 <animate attributeName="r" values="8;20" dur="0.5s" repeatCount="indefinite" />
                 <animate attributeName="opacity" values="0.8;0" dur="0.5s" repeatCount="indefinite" />
            </circle>
            <text y="-20" textAnchor="middle" fill={COLORS.snmpTrap} fontSize="12" fontWeight="bold">TRAP!</text>
        </g>
      </g>
    );
  };

  // NETCONF 阶段动画
  const NetconfAnimation = ({ progress }) => {
    const start = { x: SERVER_X + 60, y: GROUND_Y - 40 };
    const end = { x: DEVICE_X - 60, y: GROUND_Y - 40 };
    const distance = end.x - start.x;

    // 管道
    const pipeOpacity = progress < 1000 ? progress / 1000 : 1;

    // 数据流 (多个代码块)
    // 使用 progress 生成位移
    const flowOffset = (progress * 0.3) % 200; // 速度
    
    // Commit 锁动画 (每4秒触发一次)
    const commitCycle = progress % 4000;
    const isLocking = commitCycle > 2500 && commitCycle < 3500;
    const lockState = isLocking ? 'closed' : 'open';

    return (
      <g>
        {/* SSH 管道 */}
        <g opacity={pipeOpacity}>
             <defs>
                <linearGradient id="pipeGrad" x1="0%" y1="0%" x2="100%" y2="0%">
                    <stop offset="0%" stopColor={COLORS.netconf} stopOpacity="0" />
                    <stop offset="20%" stopColor={COLORS.netconf} stopOpacity="0.2" />
                    <stop offset="80%" stopColor={COLORS.netconf} stopOpacity="0.2" />
                    <stop offset="100%" stopColor={COLORS.netconf} stopOpacity="0" />
                </linearGradient>
             </defs>
             <path d={`M${start.x},${start.y-15} L${end.x},${end.y-15} L${end.x},${end.y+15} L${start.x},${start.y+15} Z`} fill="url(#pipeGrad)" />
             <line x1={start.x} y1={start.y-15} x2={end.x} y2={end.y-15} stroke={COLORS.netconf} strokeWidth="1" strokeOpacity="0.5" />
             <line x1={start.x} y1={start.y+15} x2={end.x} y2={end.y+15} stroke={COLORS.netconf} strokeWidth="1" strokeOpacity="0.5" />
        </g>

        {/* XML/RPC 数据流 */}
        <g clipPath="url(#pipeClip)">
            <clipPath id="pipeClip">
                <rect x={start.x} y={start.y - 30} width={distance} height={60} />
            </clipPath>
            
            {Array.from({ length: 6 }).map((_, i) => {
                const xPos = start.x + ((flowOffset + i * 150) % distance);
                return (
                    <g key={i} transform={`translate(${xPos}, ${start.y})`}>
                        <rect x="-20" y="-8" width="40" height="16" rx="2" fill={COLORS.netconfFlow} opacity="0.8" />
                        <line x1="-15" y1="-3" x2="15" y2="-3" stroke="#fff" strokeWidth="1" opacity="0.5" />
                        <line x1="-15" y1="3" x2="5" y2="3" stroke="#fff" strokeWidth="1" opacity="0.5" />
                        <text x="0" y="-12" textAnchor="middle" fill={COLORS.netconf} fontSize="10">&lt;rpc&gt;</text>
                    </g>
                );
            })}
        </g>

        {/* Transaction / Commit Animation */}
        <g transform={`translate(${DEVICE_X}, ${GROUND_Y - 140})`}>
            {/* Candidate Datastore */}
            <rect x="-60" y="0" width="40" height="50" fill="#1e293b" stroke={COLORS.netconf} strokeWidth="1" rx="4" />
            <text x="-40" y="30" textAnchor="middle" fill={COLORS.netconf} fontSize="10">Candidate</text>
            
            {/* Running Datastore */}
            <rect x="20" y="0" width="40" height="50" fill="#1e293b" stroke={COLORS.netconfLock} strokeWidth="1" rx="4" />
            <text x="40" y="30" textAnchor="middle" fill={COLORS.netconfLock} fontSize="10">Running</text>

            {/* Arrow */}
            <path d="M-15,25 L15,25" stroke="#fff" strokeWidth="2" markerEnd="url(#arrowhead)" />
            
            {/* Lock Icon */}
            <g transform={`translate(0, -20)`}>
                <rect x="-8" y="0" width="16" height="12" rx="2" fill={isLocking ? COLORS.netconfLock : '#64748b'} />
                <path 
                    d={isLocking ? "M-4,0 V-5 A4,4 0 0,1 4,-5 V0" : "M-4,0 V-5 A4,4 0 0,1 4,-5 V-2"} 
                    fill="none" 
                    stroke={isLocking ? COLORS.netconfLock : '#64748b'} 
                    strokeWidth="2" 
                />
            </g>
            <text x="0" y="-35" textAnchor="middle" fill={isLocking ? COLORS.netconfLock : COLORS.textDim} fontSize="12">
                {isLocking ? "Commit (Atomic)" : "Edit Config"}
            </text>
        </g>
      </g>
    );
  };

  return (
    <div style={{ 
      width: '100%', 
      height: '100%', 
      display: 'flex', 
      justifyContent: 'center', 
      alignItems: 'center', 
      backgroundColor: '#000' 
    }}>
      <div style={{ 
          width: WIDTH, 
          height: HEIGHT, 
          position: 'relative', 
          backgroundColor: COLORS.bg,
          overflow: 'hidden',
          boxShadow: '0 0 50px rgba(0,0,0,0.5)'
        }}>
        <svg viewBox={`0 0 ${WIDTH} ${HEIGHT}`} width="100%" height="100%" style={{ display: 'block' }}>
            <defs>
                {/* 滤镜定义 */}
                <filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
                    <feGaussianBlur stdDeviation="4" result="coloredBlur" />
                    <feMerge>
                        <feMergeNode in="coloredBlur" />
                        <feMergeNode in="SourceGraphic" />
                    </feMerge>
                </filter>
                <marker id="arrowhead" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
                    <polygon points="0 0, 10 3.5, 0 7" fill="#fff" />
                </marker>
                
                {/* 背景网格图案 */}
                <pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse">
                    <path d="M 40 0 L 0 0 0 40" fill="none" stroke={COLORS.grid} strokeWidth="1"/>
                </pattern>
            </defs>

            {/* 背景层 */}
            <rect width={WIDTH} height={HEIGHT} fill={COLORS.bg} />
            <rect width={WIDTH} height={HEIGHT} fill="url(#grid)" opacity="0.3" />
            
            {/* 呼吸灯光效背景 */}
            {Array.from({length: 5}).map((_, i) => (
                <circle key={i} cx={200 + i * 200} cy={100 + (i%2)*400} r={100 + i * 20} fill={isSnmpPhase ? COLORS.snmp : COLORS.netconf} opacity="0.03">
                    <animate attributeName="opacity" values="0.03;0.08;0.03" dur={`${3 + i}s`} repeatCount="indefinite" />
                </circle>
            ))}

            {/* 中间连接线 (底层) */}
            <line x1={SERVER_X} y1={GROUND_Y} x2={DEVICE_X} y2={GROUND_Y} stroke="#1e293b" strokeWidth="4" />

            {/* 动态内容 */}
            {isSnmpPhase ? (
                <SnmpAnimation progress={phaseProgress} />
            ) : (
                <NetconfAnimation progress={phaseProgress} />
            )}

            {/* 实体层 */}
            <IsometricServer x={SERVER_X} y={GROUND_Y} />
            <IsometricDevice x={DEVICE_X} y={GROUND_Y} />

            {/* UI 文本层 */}
            <g transform={`translate(${WIDTH/2}, ${HEIGHT - 80})`}>
                <rect x="-200" y="-30" width="400" height="60" rx="30" fill="#1e293b" stroke={isSnmpPhase ? COLORS.snmp : COLORS.netconf} strokeWidth="2" opacity="0.8" />
                <text y="-5" textAnchor="middle" fill={COLORS.text} fontSize="18" fontWeight="bold">
                    {isSnmpPhase ? "SNMP 协议 (简单网络管理协议)" : "NETCONF 协议 (网络配置协议)"}
                </text>
                <text y="15" textAnchor="middle" fill={isSnmpPhase ? COLORS.snmp : COLORS.netconf} fontSize="14">
                    {isSnmpPhase ? "无连接 UDP / 轮询 Polling / 告警 Trap" : "基于 SSH 连接 / XML RPC / 事务性配置"}
                </text>
            </g>

            {/* 进度条 */}
            <rect x="0" y={HEIGHT-4} width={WIDTH * (normalizedTime / CYCLE_DURATION)} height="4" fill={isSnmpPhase ? COLORS.snmp : COLORS.netconf} />

        </svg>
      </div>
    </div>
  );
}
```19:T541,Here is a precise text-to-video prompt structured to exactly match the sequential steps, logic, and tech components defined in your flowchart:

> **Prompt:** A 3D motion-graphics animated workflow diagram depicting a technical attendance system process, following a strict linear flowchart layout. The animation begins on the left as a stylized student character arrives and taps a card onto an "RC522 Reader" module, followed by a small "ESP32-CAM" lens flashing to capture a face image. Animated data pulses flow along a connecting line into a blue block labeled "Node.js Backend Verify Request". The camera pans right as the data splits into a sequence of glowing diamond decision nodes: first a yellow diamond labeled "Verify NFC UID", which outputs a glowing green "Valid" line down to a purple block labeled "Python AI Service Compare Face Embedding". Next, a cyan diamond labeled "Face Matched?" flashes green with a "Yes" pathway leading down to another yellow diamond labeled "NFC Belongs to Same Student?". A final green "Yes" path flows straight into a green box labeled "Store Attendance in Database", which illuminates, instantly lighting up a final box on the far right labeled "Dashboard Updated". The visual style is a clean, isometric infographics diagram with smooth transitions and glowing data pipelines on a dark background.1a:T43af,<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Technical Attendance System Workflow</title>
    <script src="https://cdn.jsdelivr.net/npm/dagre@0.8.5/dist/dagre.min.js"></script>
    <style>
        :root {
            --bg-color: #050a10;
            --panel-color: rgba(15, 23, 42, 0.9);
            --accent-blue: #0ea5e9;
            --accent-green: #22c55e;
            --accent-yellow: #eab308;
            --accent-purple: #a855f7;
            --accent-cyan: #06b6d4;
            --text-main: #f8fafc;
            --text-dim: #94a3b8;
            --line-color: #1e293b;
        }

        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            background-color: var(--bg-color);
            color: var(--text-main);
            font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        #app-container {
            position: relative;
            width: 1200px;
            height: 700px;
            background: radial-gradient(circle at center, #0f172a 0%, #050a10 100%);
            overflow: hidden;
            border: 1px solid #1e293b;
            box-shadow: 0 0 100px rgba(0,0,0,0.8);
        }

        .svg-content {
            width: 100%;
            height: 100%;
        }

        /* Node Styles */
        .node-rect {
            stroke-width: 2;
            rx: 6;
            ry: 6;
            transition: all 0.5s ease;
        }

        .node-diamond {
            stroke-width: 2;
            transition: all 0.5s ease;
        }

        .node-text {
            font-size: 13px;
            font-weight: 600;
            pointer-events: none;
            text-transform: uppercase;
            letter-spacing: 0.5px;
        }

        .node-subtext {
            font-size: 10px;
            fill: var(--text-dim);
        }

        /* Connection Lines */
        .edge-path {
            fill: none;
            stroke: var(--line-color);
            stroke-width: 3;
            stroke-linecap: round;
            stroke-linejoin: round;
        }

        .edge-active {
            stroke: var(--accent-blue);
            stroke-dasharray: 1000;
            stroke-dashoffset: 1000;
            filter: drop-shadow(0 0 5px var(--accent-blue));
        }

        /* Animation Overlay */
        #ui-overlay {
            position: absolute;
            top: 30px;
            left: 40px;
            pointer-events: none;
        }

        #ui-overlay h1 {
            margin: 0;
            font-size: 28px;
            background: linear-gradient(to right, #0ea5e9, #22c55e);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            font-weight: 800;
        }

        #status-bar {
            position: absolute;
            bottom: 30px;
            left: 50%;
            transform: translateX(-50%);
            width: 800px;
            height: 50px;
            background: var(--panel-color);
            border: 1px solid #334155;
            border-radius: 25px;
            display: flex;
            align-items: center;
            padding: 0 25px;
            box-shadow: 0 10px 25px rgba(0,0,0,0.5);
        }

        .status-dot {
            width: 10px;
            height: 10px;
            background: var(--accent-green);
            border-radius: 50%;
            margin-right: 15px;
            box-shadow: 0 0 10px var(--accent-green);
            animation: pulse 1.5s infinite;
        }

        @keyframes pulse {
            0% { opacity: 1; }
            50% { opacity: 0.3; }
            100% { opacity: 1; }
        }

        #status-text {
            font-family: monospace;
            font-size: 14px;
            color: var(--accent-blue);
        }

        .pulse-circle {
            fill: white;
            opacity: 0;
        }

        @keyframes flow {
            to { stroke-dashoffset: 0; }
        }
    </style>
</head>
<body>

<div id="app-container">
    <svg id="main-svg" class="svg-content" viewBox="0 0 1200 700">
        <defs>
            <marker id="arrowhead" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto">
                <path d="M 0 0 L 10 5 L 0 10 z" fill="#334155" />
            </marker>
            <filter id="glow">
                <feGaussianBlur stdDeviation="3.5" result="coloredBlur"/>
                <feMerge>
                    <feMergeNode in="coloredBlur"/>
                    <feMergeNode in="SourceGraphic"/>
                </feMerge>
            </filter>
            <linearGradient id="grad-blue" x1="0%" y1="0%" x2="100%" y2="100%">
                <stop offset="0%" style="stop-color:#0ea5e9;stop-opacity:0.2" />
                <stop offset="100%" style="stop-color:#0ea5e9;stop-opacity:0.05" />
            </linearGradient>
        </defs>

        <!-- Background Grid -->
        <pattern id="grid" width="50" height="50" patternUnits="userSpaceOnUse">
            <path d="M 50 0 L 0 0 0 50" fill="none" stroke="#0f172a" stroke-width="1"/>
        </pattern>
        <rect width="100%" height="100%" fill="url(#grid)" />

        <g id="edges-layer"></g>
        <g id="nodes-layer"></g>
        <g id="animation-layer"></g>
    </svg>

    <div id="ui-overlay">
        <h1>SMART ATTENDANCE FLOW</h1>
        <div style="color: var(--text-dim); font-size: 12px; margin-top: 5px;">AI-POWERED BIOMETRIC VERIFICATION SYSTEM</div>
    </div>

    <div id="status-bar">
        <div class="status-dot"></div>
        <div id="status-text">SYSTEM READY: WAITING FOR INPUT...</div>
    </div>
</div>

<script>
    /**
     * Flowchart Data Structure
     */
    const workflow = {
        nodes: [
            { id: 'start', label: 'User Arrival', type: 'rect', color: 'var(--accent-blue)', sub: 'RFID/NFC Tap' },
            { id: 'reader', label: 'RC522 Reader', type: 'rect', color: 'var(--accent-blue)', sub: 'Capture UID' },
            { id: 'cam', label: 'ESP32-CAM', type: 'rect', color: 'var(--accent-blue)', sub: 'Capture Image' },
            { id: 'backend', label: 'Node.js Backend', type: 'rect', color: 'var(--accent-blue)', sub: 'Verify Request' },
            { id: 'v_nfc', label: 'Verify NFC UID', type: 'diamond', color: 'var(--accent-yellow)', sub: '' },
            { id: 'python_ai', label: 'Python AI Service', type: 'rect', color: 'var(--accent-purple)', sub: 'Compare Face' },
            { id: 'v_face', label: 'Face Matched?', type: 'diamond', color: 'var(--accent-cyan)', sub: '' },
            { id: 'v_same', label: 'Same Student?', type: 'diamond', color: 'var(--accent-yellow)', sub: '' },
            { id: 'db', label: 'Attendance DB', type: 'rect', color: 'var(--accent-green)', sub: 'Commit Log' },
            { id: 'dashboard', label: 'Dashboard', type: 'rect', color: 'var(--accent-green)', sub: 'Live Update' }
        ],
        edges: [
            { from: 'start', to: 'reader' },
            { from: 'reader', to: 'cam' },
            { from: 'cam', to: 'backend' },
            { from: 'backend', to: 'v_nfc' },
            { from: 'v_nfc', to: 'python_ai', label: 'Valid' },
            { from: 'python_ai', to: 'v_face' },
            { from: 'v_face', to: 'v_same', label: 'Yes' },
            { from: 'v_same', to: 'db', label: 'Yes' },
            { from: 'db', to: 'dashboard' }
        ]
    };

    /**
     * Layout Calculation using Dagre
     */
    const g = new dagre.graphlib.Graph();
    g.setGraph({ rankdir: 'LR', nodesep: 60, ranksep: 80, marginx: 100, marginy: 200 });
    g.setDefaultEdgeLabel(() => ({}));

    workflow.nodes.forEach(node => {
        g.setNode(node.id, { 
            width: node.type === 'diamond' ? 120 : 160, 
            height: node.type === 'diamond' ? 80 : 60 
        });
    });
    workflow.edges.forEach(edge => g.setEdge(edge.from, edge.to));

    dagre.layout(g);

    /**
     * Rendering Logic
     */
    const nodesLayer = document.getElementById('nodes-layer');
    const edgesLayer = document.getElementById('edges-layer');
    const animLayer = document.getElementById('animation-layer');
    const statusText = document.getElementById('status-text');

    const nodeElements = {};
    const edgeElements = {};

    function renderWorkflow() {
        // Draw Edges
        workflow.edges.forEach(edge => {
            const edgeData = g.edge(edge.from, edge.to);
            const points = edgeData.points;
            let d = `M ${points[0].x} ${points[0].y}`;
            for (let i = 1; i < points.length; i++) {
                d += ` L ${points[i].x} ${points[i].y}`;
            }

            const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
            path.setAttribute('d', d);
            path.setAttribute('class', 'edge-path');
            path.setAttribute('marker-end', 'url(#arrowhead)');
            edgesLayer.appendChild(path);

            const activePath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
            activePath.setAttribute('d', d);
            activePath.setAttribute('class', 'edge-path edge-active');
            activePath.style.display = 'none';
            edgesLayer.appendChild(activePath);

            edgeElements[`${edge.from}-${edge.to}`] = { base: path, active: activePath };

            if (edge.label) {
                const mid = points[Math.floor(points.length/2)];
                const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
                text.setAttribute('x', mid.x);
                text.setAttribute('y', mid.y - 10);
                text.setAttribute('text-anchor', 'middle');
                text.setAttribute('fill', 'var(--text-dim)');
                text.style.fontSize = '10px';
                text.textContent = edge.label;
                edgesLayer.appendChild(text);
            }
        });

        // Draw Nodes
        workflow.nodes.forEach(node => {
            const layout = g.node(node.id);
            const group = document.createElementNS('http://www.w3.org/2000/svg', 'g');
            group.setAttribute('transform', `translate(${layout.x}, ${layout.y})`);
            
            let shape;
            if (node.type === 'rect') {
                shape = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
                shape.setAttribute('x', -layout.width / 2);
                shape.setAttribute('y', -layout.height / 2);
                shape.setAttribute('width', layout.width);
                shape.setAttribute('height', layout.height);
                shape.setAttribute('class', 'node-rect');
            } else {
                shape = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
                const w = layout.width / 2;
                const h = layout.height / 2;
                shape.setAttribute('points', `0,${-h} ${w},0 0,${h} ${-w},0`);
                shape.setAttribute('class', 'node-diamond');
            }

            shape.setAttribute('fill', 'var(--panel-color)');
            shape.setAttribute('stroke', '#1e293b');
            group.appendChild(shape);

            const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
            text.setAttribute('text-anchor', 'middle');
            text.setAttribute('y', 5);
            text.setAttribute('class', 'node-text');
            text.setAttribute('fill', 'var(--text-dim)');
            text.textContent = node.label;
            group.appendChild(text);

            if (node.sub) {
                const subtext = document.createElementNS('http://www.w3.org/2000/svg', 'text');
                subtext.setAttribute('text-anchor', 'middle');
                subtext.setAttribute('y', 22);
                subtext.setAttribute('class', 'node-subtext');
                subtext.textContent = node.sub;
                group.appendChild(subtext);
            }

            nodesLayer.appendChild(group);
            nodeElements[node.id] = { group, shape, text, config: node };
        });
    }

    /**
     * Animation Sequencer
     */
    async function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }

    async function highlightNode(id, duration = 800) {
        const el = nodeElements[id];
        const color = el.config.color;
        el.shape.setAttribute('stroke', color);
        el.shape.style.filter = 'url(#glow)';
        el.text.setAttribute('fill', 'white');
        
        // Pulse effect
        const pulse = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
        const layout = g.node(id);
        pulse.setAttribute('cx', layout.x);
        pulse.setAttribute('cy', layout.y);
        pulse.setAttribute('r', 10);
        pulse.setAttribute('class', 'pulse-circle');
        pulse.style.fill = color;
        animLayer.appendChild(pulse);

        pulse.animate([
            { r: 10, opacity: 0.8 },
            { r: 100, opacity: 0 }
        ], { duration: 600, easing: 'ease-out' });

        await sleep(duration);
    }

    async function animateEdge(from, to) {
        const edge = edgeElements[`${from}-${to}`];
        edge.active.style.display = 'block';
        const length = edge.active.getTotalLength();
        edge.active.style.strokeDasharray = length;
        edge.active.style.strokeDashoffset = length;
        
        const anim = edge.active.animate([
            { strokeDashoffset: length },
            { strokeDashoffset: 0 }
        ], { duration: 800, easing: 'ease-in-out', fill: 'forwards' });

        // Data Pulse Animation
        const pulse = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
        pulse.setAttribute('r', 4);
        pulse.setAttribute('fill', 'white');
        pulse.style.filter = 'url(#glow)';
        animLayer.appendChild(pulse);

        const startTime = performance.now();
        const duration = 800;

        return new Promise(resolve => {
            function frame(time) {
                const progress = Math.min((time - startTime) / duration, 1);
                const point = edge.active.getPointAtLength(progress * length);
                pulse.setAttribute('cx', point.x);
                pulse.setAttribute('cy', point.y);

                if (progress < 1) {
                    requestAnimationFrame(frame);
                } else {
                    animLayer.removeChild(pulse);
                    resolve();
                }
            }
            requestAnimationFrame(frame);
        });
    }

    async function runSimulation() {
        // Reset
        workflow.nodes.forEach(n => {
            nodeElements[n.id].shape.setAttribute('stroke', '#1e293b');
            nodeElements[n.id].shape.style.filter = 'none';
            nodeElements[n.id].text.setAttribute('fill', 'var(--text-dim)');
        });
        Object.values(edgeElements).forEach(e => {
            e.active.style.display = 'none';
        });

        statusText.textContent = ">>> INITIALIZING: STUDENT DETECTED AT GATE";
        await sleep(1000);

        // Sequence
        statusText.textContent = ">>> STEP 1: RC522 READING NFC CHIP UID...";
        await highlightNode('start');
        await animateEdge('start', 'reader');
        await highlightNode('reader');

        statusText.textContent = ">>> STEP 2: ESP32-CAM TRIGGERING FACE CAPTURE...";
        await animateEdge('reader', 'cam');
        await highlightNode('cam');
        // Flash effect
        const flash = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
        flash.setAttribute('width', 1200);
        flash.setAttribute('height', 700);
        flash.setAttribute('fill', 'white');
        flash.setAttribute('opacity', '0.3');
        animLayer.appendChild(flash);
        setTimeout(() => animLayer.removeChild(flash), 100);

        statusText.textContent = ">>> STEP 3: SENDING PAYLOAD TO NODE.JS BACKEND...";
        await animateEdge('cam', 'backend');
        await highlightNode('backend');

        statusText.textContent = ">>> STEP 4: VERIFYING NFC UID VALIDITY...";
        await animateEdge('backend', 'v_nfc');
        await highlightNode('v_nfc');

        statusText.textContent = ">>> STEP 5: GENERATING FACE EMBEDDINGS (PYTHON AI)...";
        await animateEdge('v_nfc', 'python_ai');
        await highlightNode('python_ai');

        statusText.textContent = ">>> STEP 6: AI COMPARISON IN PROGRESS...";
        await animateEdge('python_ai', 'v_face');
        await highlightNode('v_face');

        statusText.textContent = ">>> STEP 7: CHECKING IDENTITY CONSISTENCY...";
        await animateEdge('v_face', 'v_same');
        await highlightNode('v_same');

        statusText.textContent = ">>> STEP 8: WRITING TO POSTGRESQL DATABASE...";
        await animateEdge('v_same', 'db');
        await highlightNode('db');

        statusText.textContent = ">>> SUCCESS: ATTENDANCE RECORDED. DASHBOARD UPDATED.";
        await animateEdge('db', 'dashboard');
        await highlightNode('dashboard');

        await sleep(3000);
        runSimulation();
    }

    window.onload = () => {
        renderWorkflow();
        runSimulation();
    };
</script>

</body>
</html>1b:T15bf,Call flow
                   LUMEXA IMAGING 
[ TEAMS VOICE ]          [ CONTACT CENTERS ]        [ MOMENTUM DID CALLS ]
    (Microsoft O365 Teams)     (Five9 Inbound Entry)      (Non-Teams/Direct Clinic)
              │                          │                            │
              └──────────────────────────┼────────────────────────────┘
                                         ▼ (All Traffic Ingress)
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                                       MOMENTUM                                          │
└───────┬───────────────────────┬───────────────────────────────┬─────────────────────────┘
        │                       │                               │
        │                       │                               │
        │                       ▼ (Primary / Secondary)         │
        │               ┌───────────────┐                       │
        │               │   SIP TRUNK   │                       │
        │               └───────┬───────┘                       │
        │                       │                               │
        ▼ (Teams Voice Bypass)  ▼ Active Call Setup             ▼ (Direct Route)
┌────────────────────────┐┌───────────────────────────────┐     │
│  MICROSOFT 365 TEAMS   ││      AGENTIC AI ENGINE        │     │
│                        ││                               │     │
│  ┌──────────────────┐  ││ 1. Evaluates Inbound DNIS Code│     │
│  │   TEAMS VOICE    │  ││ 2. Plays Branded Greeting     │     │
│  │ (Teams Softphone)│  ││    (TMI, GDI, AHI, CR, etc.)  │     │
│  └──────────────────┘  ││                               │     │
└────────────────────────┘│   ├── Option A: Route Down    │     │
                          │   └── SIP Trunk (Option B)    │──┐  │
                          └─────────────┬─────────────────┘  │  │
                                        │                    │  │
                                        ▼ (Option A Match)   │  │
                          ┌───────────────────────────────┐  │  │
                          │     FIVE9 CCaaS PLATFORM      │  │  │
                          │   ┌───────────────────────┐   │  │  │
                          │   │   FIVE9 LIVE AGENT    │   │  │  │
                          │   │  Delivered to Queue   │   │  │  │
                          │   └───────────────────────┘   │  │  │
                          └───────────────────────────────┘  │  │
                                                             │  │
                                                             ▼  ▼
                                           [ MOMENTUM CLINIC: [Code]_Clinic ]
                                                    │
                                                    │  (Direct SIP Connection Endpoint)
                                                    ▼
                                            ┌───────────────┐
                                            │   Momentum Phone  │
                                            └───────────────┘

The underlying code footprint maps exactly to your finalized system logic. The MOMENTUM DC-1 and MOMENTUM DC-2 visual sub-elements have been stripped, consolidating the network core purely into a single master horizontal MOMENTUM layer block.
Topology Check
• Consolidated Base Platform: Traffic entering from all channels is unified across a single MOMENTUM edge boundary banner, maintaining standard filtering without extra sub-datacenter layers.
• Preserved Blue/Teal Theme: The visual configuration maintains the clean blue/teal network node presentation style you selected, completely locking the layout architecture coordinates to prevent randomized system re-labeling.
• Component Layer Ordering:
• The Agentic AI Engine operates as an independent middleware section stacked above the single-tier Five9 CCaaS Platform.
• The Momentum Clinic module is securely interconnected directly from the primary MOMENTUM platform block.
• The SIP Trunk (Option B) handoff loops cleanly from the AI block into the clinic boundary layer to reach the desktop Hardphone.1c:T385d,<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>LUMEXA IMAGING - Call Flow Architecture</title>
    <script src="https://cdn.jsdelivr.net/npm/dagre@0.8.5/dist/dagre.min.js"></script>
    <style>
        :root {
            --bg-dark: #06090f;
            --panel-bg: rgba(16, 22, 32, 0.95);
            --accent-teal: #00f2ff;
            --accent-blue: #0072ff;
            --accent-yellow: #ffff00;
            --accent-green: #39ff14;
            --text-primary: #e2e8f0;
            --text-secondary: #94a3b8;
            --border-color: #1e293b;
            --font-main: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
        }

        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            background-color: var(--bg-dark);
            color: var(--text-primary);
            font-family: var(--font-main);
            overflow: hidden;
        }

        #app-container {
            position: relative;
            width: 1200px;
            height: 700px;
            margin: 0 auto;
            overflow: hidden;
            background: radial-gradient(circle at 50% 50%, #0d1625 0%, #06090f 100%);
        }

        .svg-canvas {
            width: 100%;
            height: 100%;
            display: block;
        }

        /* Node Styles */
        .node-rect {
            stroke-width: 2;
            rx: 6;
            ry: 6;
            transition: all 0.3s ease;
        }

        .node-header {
            font-weight: bold;
            font-size: 14px;
            text-transform: uppercase;
            letter-spacing: 1px;
        }

        .node-subtext {
            font-size: 11px;
            fill: var(--text-secondary);
        }

        /* Edge Styles */
        .edge-path {
            fill: none;
            stroke: #2d3e50;
            stroke-width: 2;
            stroke-dasharray: 4 2;
        }

        .edge-active-blue { stroke: var(--accent-blue); stroke-width: 3; filter: drop-shadow(0 0 5px var(--accent-blue)); }
        .edge-active-yellow { stroke: var(--accent-yellow); stroke-width: 3; filter: drop-shadow(0 0 5px var(--accent-yellow)); }
        .edge-active-green { stroke: var(--accent-green); stroke-width: 3; filter: drop-shadow(0 0 5px var(--accent-green)); }

        .arrow-head { fill: #2d3e50; }

        /* Phone Symbols */
        .phone-symbol {
            font-family: Arial, sans-serif;
            font-size: 24px;
            font-weight: bold;
            pointer-events: none;
            filter: drop-shadow(0 0 8px currentColor);
        }

        /* Overlay UI - Centered Title */
        #ui-layer {
            position: absolute;
            top: 20px;
            left: 0;
            width: 100%;
            pointer-events: none;
            display: flex;
            justify-content: center;
            align-items: center;
            text-align: center;
        }

        .title-block h1 {
            margin: 0;
            font-size: 32px;
            color: var(--accent-teal);
            letter-spacing: 6px;
            text-shadow: 0 0 20px rgba(0, 242, 255, 0.5);
        }

        /* Call Description Window - Bottom Left */
        .status-box {
            position: absolute;
            bottom: 30px;
            left: 30px;
            width: 320px;
            background: var(--panel-bg);
            border: 1px solid var(--border-color);
            padding: 15px;
            border-radius: 8px;
            font-size: 13px;
            line-height: 1.6;
            box-shadow: 0 10px 30px rgba(0,0,0,0.5);
            z-index: 10;
        }

        .status-tag {
            color: var(--accent-teal);
            font-weight: bold;
            margin-right: 8px;
        }
    </style>
</head>
<body>

<div id="app-container">
    <svg id="main-svg" class="svg-canvas" viewBox="0 0 1200 700">
        <defs>
            <filter id="glow">
                <feGaussianBlur stdDeviation="2.5" result="coloredBlur"/>
                <feMerge>
                    <feMergeNode in="coloredBlur"/>
                    <feMergeNode in="SourceGraphic"/>
                </feMerge>
            </filter>
            
            <marker id="arrowhead" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
                <polygon points="0 0, 10 3.5, 0 7" class="arrow-head" />
            </marker>

            <linearGradient id="grad-momentum" x1="0%" y1="0%" x2="100%" y2="0%">
                <stop offset="0%" style="stop-color:#004e92;stop-opacity:1" />
                <stop offset="100%" style="stop-color:#000428;stop-opacity:1" />
            </linearGradient>
        </defs>

        <g id="grid-layer"></g>
        <g id="edges-layer"></g>
        <g id="nodes-layer"></g>
        <g id="animation-layer"></g>
    </svg>

    <div id="ui-layer">
        <div class="title-block">
            <h1>LUMEXA IMAGING</h1>
            <div style="color: var(--text-secondary); font-size: 14px; margin-top: 5px; text-transform: uppercase; letter-spacing: 2px;">Unified Communication & Call Routing Architecture</div>
        </div>
    </div>

    <div class="status-box" id="status-display">
        <div><span class="status-tag">[ SYSTEM ]</span> Initializing Network Core...</div>
    </div>
</div>

<script>
const DATA = {
    nodes: [
        // Entry Points
        { id: 'TEAMS_V', label: 'TEAMS VOICE', sub: 'Microsoft O365 Teams', type: 'entry', x: 200, y: 130 },
        { id: 'CC_V', label: 'CONTACT CENTERS', sub: 'Five9 Inbound Entry', type: 'entry', x: 600, y: 130 },
        { id: 'MOM_DID', label: 'MOMENTUM DID', sub: 'Direct Center Calls', type: 'entry', x: 1000, y: 130 },
        
        // Core Platform
        { id: 'MOMENTUM_CORE', label: 'MOMENTUM PLATFORM', sub: 'All Traffic Ingress / Edge Boundary', type: 'core', x: 600, y: 240, w: 1000, h: 60 },
        
        // Center Column (Evenly Aligned)
        { id: 'SIP_TRUNK', label: 'SIP TRUNK', sub: 'Primary / Secondary', type: 'trunk', x: 600, y: 340 },
        { id: 'AI_ENGINE', label: 'AGENTIC AI ENGINE', sub: 'Greeting & DNIS Evaluation', type: 'ai', x: 600, y: 440 },
        { id: 'FIVE9_CC', label: 'FIVE9 CCaaS PLATFORM', sub: 'Queue Management', type: 'app', x: 600, y: 540 },
        { id: 'FIVE9_AGENT', label: 'FIVE9 AGENT', sub: 'Live Agent Desktop', type: 'endpoint', x: 600, y: 640 },
        
        // Side Endpoints
        { id: 'TEAMS_APP', label: 'MICROSOFT 365 TEAMS', sub: 'Teams Voice (Softphone)', type: 'app', x: 200, y: 440 },
        { id: 'CLINIC_END', label: 'Radiology Center', sub: 'Momentum Phone (Hardphone)', type: 'endpoint', x: 1000, y: 640 }
    ],
    edges: [
        { from: 'TEAMS_V', to: 'MOMENTUM_CORE', path: 'C', flow: 'yellow' }, 
        { from: 'CC_V', to: 'MOMENTUM_CORE', path: 'C', flow: 'blue' }, 
        { from: 'MOM_DID', to: 'MOMENTUM_CORE', path: 'C', flow: 'green' }, 
        { from: 'MOMENTUM_CORE', to: 'TEAMS_APP', path: 'L', flow: 'yellow' }, 
        { from: 'MOMENTUM_CORE', to: 'SIP_TRUNK', path: 'C', flow: 'blue' }, 
        { from: 'MOMENTUM_CORE', to: 'CLINIC_END', path: 'R', flow: 'green' }, 
        { from: 'SIP_TRUNK', to: 'AI_ENGINE', path: 'C', flow: 'blue' }, 
        { from: 'AI_ENGINE', to: 'FIVE9_CC', path: 'C', flow: 'blue' }, 
        { from: 'FIVE9_CC', to: 'FIVE9_AGENT', path: 'C', flow: 'blue' }, 
        { from: 'AI_ENGINE', to: 'CLINIC_END', path: 'S', flow: 'blue' } 
    ]
};

const svg = document.getElementById('main-svg');
const nodesLayer = document.getElementById('nodes-layer');
const edgesLayer = document.getElementById('edges-layer');
const animLayer = document.getElementById('animation-layer');
const statusDisplay = document.getElementById('status-display');

function init() {
    drawGrid();
    renderNodes();
    renderEdges();
    startAnimationCycle();
}

function drawGrid() {
    const grid = document.getElementById('grid-layer');
    for(let i=0; i<1200; i+=40) {
        const line = document.createElementNS("http://www.w3.org/2000/svg", "line");
        line.setAttribute("x1", i); line.setAttribute("y1", 0);
        line.setAttribute("x2", i); line.setAttribute("y2", 700);
        line.setAttribute("stroke", "#111827");
        grid.appendChild(line);
    }
    for(let i=0; i<700; i+=40) {
        const line = document.createElementNS("http://www.w3.org/2000/svg", "line");
        line.setAttribute("x1", 0); line.setAttribute("y1", i);
        line.setAttribute("x2", 1200); line.setAttribute("y2", i);
        line.setAttribute("stroke", "#111827");
        grid.appendChild(line);
    }
}

function renderNodes() {
    DATA.nodes.forEach(node => {
        const g = document.createElementNS("http://www.w3.org/2000/svg", "g");
        g.setAttribute("id", `node-${node.id}`);
        g.setAttribute("transform", `translate(${node.x}, ${node.y})`);
        const width = node.w || 240;
        const height = node.h || 60;
        const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
        rect.setAttribute("x", -width/2); rect.setAttribute("y", -height/2);
        rect.setAttribute("width", width); rect.setAttribute("height", height);
        rect.setAttribute("class", "node-rect");
        
        if(node.type === 'core') { 
            rect.setAttribute("fill", "url(#grad-momentum)"); 
            rect.setAttribute("stroke", "#0072ff"); 
        } else if(node.type === 'entry') { 
            rect.setAttribute("fill", "#1e293b"); 
            rect.setAttribute("stroke", "#475569"); 
        } else if(node.type === 'ai') { 
            rect.setAttribute("fill", "#0f172a"); 
            rect.setAttribute("stroke", "#00f2ff"); 
            rect.style.filter = "url(#glow)"; 
        } else { 
            rect.setAttribute("fill", "#111827"); 
            rect.setAttribute("stroke", "#334155"); 
        }
        
        const title = document.createElementNS("http://www.w3.org/2000/svg", "text");
        title.textContent = node.label;
        title.setAttribute("class", "node-header");
        title.setAttribute("text-anchor", "middle");
        title.setAttribute("y", node.sub ? -5 : 5);
        title.setAttribute("fill", node.type === 'ai' ? "#00f2ff" : "white");
        
        g.appendChild(rect);
        g.appendChild(title);
        
        if(node.sub) {
            const sub = document.createElementNS("http://www.w3.org/2000/svg", "text");
            sub.textContent = node.sub;
            sub.setAttribute("class", "node-subtext");
            sub.setAttribute("text-anchor", "middle");
            sub.setAttribute("y", 15);
            g.appendChild(sub);
        }

        nodesLayer.appendChild(g);
    });
}

function renderEdges() {
    DATA.edges.forEach((edge, index) => {
        const fromNode = DATA.nodes.find(n => n.id === edge.from);
        const toNode = DATA.nodes.find(n => n.id === edge.to);
        const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
        const d = calculatePath(fromNode, toNode, edge.path);
        path.setAttribute("d", d);
        path.setAttribute("class", "edge-path");
        path.setAttribute("id", `edge-${index}`);
        path.setAttribute("marker-end", "url(#arrowhead)");
        edgesLayer.appendChild(path);
    });
}

function calculatePath(f, t, type) {
    const startY = f.y + (f.h || 60)/2;
    const endY = t.y - (t.h || 60)/2;
    if(type === 'L') return `M ${f.x-200} ${startY} L ${t.x} ${endY}`;
    if(type === 'R') return `M ${f.x+400} ${startY} L ${t.x} ${endY}`;
    if(type === 'S') return `M ${f.x + 120} ${f.y} Q ${t.x} ${f.y} ${t.x} ${endY}`;
    return `M ${f.x} ${startY} L ${t.x} ${endY}`;
}

async function startAnimationCycle() {
    while(true) {
        // Flow 1: Teams Voice (Neon Yellow)
        updateStatus("TEAMS FLOW", "Routing Teams Voice through Momentum to M365 Teams.");
        await animateCallFlow([0, 3], "yellow", "📞");
        await sleep(1000);

        // Flow 2: Contact Center (Neon Blue)
        updateStatus("CCaaS FLOW", "Routing Contact Center through Momentum, AI Engine, Five9 Platform to Agent.");
        await animateCallFlow([1, 4, 6, 7, 8], "blue", "📞");
        await sleep(1000);

        // Flow 3: Momentum DID (Neon Green)
        updateStatus("RADIOLOGY FLOW", "Routing Momentum DID through Core to Radiology Center.");
        await animateCallFlow([2, 5], "green", "📞");
        await sleep(2000);
        
        resetHighlights();
    }
}

async function animateCallFlow(edgeIndices, color, symbol) {
    const colorMap = {
        blue: '#0072ff',
        yellow: '#ffff00',
        green: '#39ff14'
    };
    const cssClass = `edge-active-${color}`;

    for(let idx of edgeIndices) {
        const path = document.getElementById(`edge-${idx}`);
        if(!path) continue;
        const length = path.getTotalLength();
        path.classList.add(cssClass);
        
        const phone = document.createElementNS("http://www.w3.org/2000/svg", "text");
        phone.textContent = symbol;
        phone.setAttribute("class", "phone-symbol");
        phone.setAttribute("fill", colorMap[color]);
        animLayer.appendChild(phone);

        await new Promise(resolve => {
            let start = null;
            function step(timestamp) {
                if (!start) start = timestamp;
                let progress = (timestamp - start) / 800;
                if (progress > 1) progress = 1;
                const point = path.getPointAtLength(progress * length);
                phone.setAttribute("x", point.x - 12);
                phone.setAttribute("y", point.y + 8);
                if (progress < 1) requestAnimationFrame(step);
                else {
                    setTimeout(() => {
                        if(phone.parentNode) animLayer.removeChild(phone);
                        resolve();
                    }, 50);
                }
            }
            requestAnimationFrame(step);
        });
    }
}

function resetHighlights() {
    document.querySelectorAll('.edge-path').forEach(p => {
        p.className.baseVal = "edge-path";
    });
}

function updateStatus(tag, msg) {
    statusDisplay.innerHTML = `<div><span class="status-tag" style="color:var(--accent-teal)">[ ${tag} ]</span> ${msg}</div>`;
}

function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }

window.onload = init;
</script>
</body>
</html>1d:T735,Create an animated flowchart about leadership in education. The flowchart must center on my personal reflection—what leadership means to me is the core thread connecting all elements.
Include these key ideas:

Leadership does not mean being the best, being bossy, or holding power.
Leadership does mean influencing relationships, mobilizing people to imagine, think, and act, and liberating possibility. A good teacher is inherently a leader.
Central quote: “If you think you are too small to make a difference, try going to bed with a mosquito in the room.”
Context: a VUCA world (volatile, uncertain, complex, ambiguous) that requires leadership.
Emphasize Adaptive Expertise (continuous evaluation of practices) vs. routine expertise (only useful in stable environments; schools are not stable).
Leadership removes barriers to deep listening, especially in education. Include the 4 levels of listening, highlighting Level 3 (empathic) and Level 4 (generative).
Personal anchor: I lead primarily from my role as a mother, shaping my values of sustainability and integrity.
Include brave spaces: they enable openness, but are not always present in my school.
Show that I need others’ stories and perspectives to safely change my mind.
Show when I feel powerful (inspiring students) vs. powerless (workload, invisibility, disconnection).
Role-playing builds awareness of my words, body language, and enthusiasm.
Leadership exists at all levels; include my experience as a moderator.
Show brainstorming structure (safe turn-taking) as a tool for brave spaces.
Persuasion through personal storytelling.
Reflection over time: becoming a mother shaped my worldview and decisions; future goal is to grow into a stronger, more confident leader and seek expert guidance.

Ensure the animation visually loops back to my reflection at each stage.1e:T334a,<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Educational Leadership: A Personal Reflection</title>
    <script src="https://cdn.jsdelivr.net/npm/dagre@0.8.5/dist/dagre.min.js"></script>
    <style>
        :root {
            --bg-dark: #0f172a;
            --panel-bg: rgba(30, 41, 59, 0.7);
            --accent-gold: #fbbf24;
            --accent-blue: #38bdf8;
            --accent-green: #4ade80;
            --accent-red: #f87171;
            --text-primary: #f8fafc;
            --text-secondary: #94a3b8;
            --font-main: 'Inter', system-ui, -apple-system, sans-serif;
        }

        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            background-color: var(--bg-dark);
            color: var(--text-primary);
            font-family: var(--font-main);
            overflow: hidden;
        }

        #app-container {
            position: relative;
            width: 1200px;
            height: 700px;
            margin: auto;
            overflow: hidden;
            display: flex;
            flex-direction: column;
            background: radial-gradient(circle at center, #1e293b 0%, #0f172a 100%);
        }

        svg {
            width: 100%;
            height: 100%;
            user-select: none;
        }

        .node-rect {
            stroke-width: 2;
            rx: 12;
            ry: 12;
            transition: all 0.3s ease;
        }

        .node-text {
            font-size: 13px;
            font-weight: 500;
            fill: var(--text-primary);
            pointer-events: none;
        }

        .node-title {
            font-size: 14px;
            font-weight: 700;
            fill: var(--accent-gold);
            text-transform: uppercase;
        }

        .edge-path {
            fill: none;
            stroke: var(--text-secondary);
            stroke-width: 1.5;
            stroke-dasharray: 5, 5;
            opacity: 0.3;
        }

        .edge-active {
            stroke: var(--accent-blue);
            stroke-width: 3;
            stroke-dasharray: 0;
            opacity: 1;
            filter: drop-shadow(0 0 5px var(--accent-blue));
        }

        #ui-overlay {
            position: absolute;
            top: 20px;
            left: 20px;
            pointer-events: none;
        }

        .title-box h1 {
            margin: 0;
            font-size: 28px;
            background: linear-gradient(to right, var(--accent-gold), var(--accent-blue));
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }

        .quote-box {
            position: absolute;
            bottom: 30px;
            right: 30px;
            width: 350px;
            background: var(--panel-bg);
            border-left: 4px solid var(--accent-gold);
            padding: 15px;
            border-radius: 4px;
            font-style: italic;
            font-size: 14px;
            backdrop-filter: blur(10px);
        }

        .reflection-center {
            fill: rgba(251, 191, 36, 0.1);
            stroke: var(--accent-gold);
            stroke-width: 3;
            stroke-dasharray: 10, 5;
            animation: rotate 60s linear infinite;
        }

        @keyframes rotate {
            from { transform: rotate(0deg); }
            to { transform: rotate(360deg); }
        }

        .pulse {
            animation: pulse-ring 2s infinite;
        }

        @keyframes pulse-ring {
            0% { transform: scale(1); opacity: 0.8; }
            50% { transform: scale(1.05); opacity: 1; }
            100% { transform: scale(1); opacity: 0.8; }
        }

        .vuca-badge {
            font-size: 10px;
            fill: var(--accent-red);
            font-weight: bold;
        }

        #caption-panel {
            position: absolute;
            bottom: 40px;
            left: 50%;
            transform: translateX(-50%);
            width: 600px;
            text-align: center;
            background: rgba(0,0,0,0.6);
            padding: 15px;
            border-radius: 50px;
            border: 1px solid rgba(255,255,255,0.1);
            backdrop-filter: blur(5px);
            color: var(--accent-blue);
            font-weight: 600;
        }
    </style>
</head>
<body>

<div id="app-container">
    <div id="ui-overlay">
        <div class="title-box">
            <h1>The Heart of Educational Leadership</h1>
            <div style="color: var(--text-secondary); margin-top: 5px;">A Personal Journey of Influence & Possibility</div>
        </div>
    </div>

    <svg id="svg-canvas" viewBox="0 0 1200 700">
        <defs>
            <marker id="arrowhead" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto">
                <path d="M 0 0 L 10 5 L 0 10 z" fill="var(--accent-blue)" />
            </marker>
            <filter id="glow">
                <feGaussianBlur stdDeviation="2.5" result="coloredBlur"/>
                <feMerge>
                    <feMergeNode in="coloredBlur"/><feMergeNode in="SourceGraphic"/>
                </feMerge>
            </filter>
        </defs>

        <g id="links-layer"></g>
        <g id="nodes-layer"></g>
        <g id="highlight-layer"></g>
    </svg>

    <div class="quote-box" id="quote-el">
        “If you think you are too small to make a difference, try going to bed with a mosquito in the room.”
    </div>

    <div id="caption-panel">Initializing Reflection...</div>
</div>

<script>
/**
 * DATA STRUCTURE
 */
const nodes = [
    { id: 'core', label: 'MY REFLECTION', type: 'core', desc: 'The anchor: Leadership starts within.' },
    
    // Leadership is NOT
    { id: 'not_bossy', label: 'NOT: Power, Bossy, Being the Best', type: 'negation', desc: 'Shedding traditional ego-driven myths.' },
    
    // Leadership IS
    { id: 'is_influence', label: 'IS: Influencing Relationships', type: 'definition', desc: 'Mobilizing people to imagine, think, and act.' },
    { id: 'liberate', label: 'Liberating Possibility', type: 'definition', desc: 'A good teacher is inherently a leader.' },

    // Context
    { id: 'vuca', label: 'VUCA World Context', type: 'context', desc: 'Volatile, Uncertain, Complex, Ambiguous reality.' },
    { id: 'adaptive', label: 'Adaptive Expertise', type: 'concept', desc: 'Continuous evaluation vs. routine expertise.' },

    // Listening & Barriers
    { id: 'listening', label: '4 Levels of Listening', type: 'process', desc: 'Removing barriers to deep understanding.' },
    { id: 'generative', label: 'Generative Listening (L4)', type: 'highlight', desc: 'The highest form of connection.' },

    // Personal Anchor
    { id: 'motherhood', label: 'Motherhood: My Anchor', type: 'personal', desc: 'Sustainability & Integrity shaped by parenting.' },
    { id: 'brave_spaces', label: 'Brave Spaces & Brainstorming', type: 'personal', desc: 'Safe turn-taking to enable openness.' },

    // Power Dynamics
    { id: 'power_states', label: 'Powerful vs Powerless', type: 'dichotomy', desc: 'Inspiring students vs. Invisibility/Workload.' },
    
    // Growth
    { id: 'persuasion', label: 'Storytelling & Persuasion', type: 'skill', desc: 'Using personal narratives to lead.' },
    { id: 'future', label: 'Future: Stronger Leader', type: 'goal', desc: 'Seeking expert guidance and confidence.' }
];

const edges = [
    { from: 'core', to: 'not_bossy' },
    { from: 'core', to: 'is_influence' },
    { from: 'is_influence', to: 'liberate' },
    { from: 'core', to: 'vuca' },
    { from: 'vuca', to: 'adaptive' },
    { from: 'core', to: 'motherhood' },
    { from: 'motherhood', to: 'future' },
    { from: 'core', to: 'listening' },
    { from: 'listening', to: 'generative' },
    { from: 'generative', to: 'brave_spaces' },
    { from: 'core', to: 'power_states' },
    { from: 'power_states', to: 'persuasion' },
    { from: 'persuasion', to: 'future' }
];

/**
 * LAYOUT ENGINE (DAGRE)
 */
const g = new dagre.graphlib.Graph();
g.setGraph({ rankdir: 'LR', nodesep: 60, ranksep: 100 });
g.setDefaultEdgeLabel(() => ({}));

nodes.forEach(n => {
    g.setNode(n.id, { label: n.label, width: 220, height: 80 });
});

edges.forEach(e => {
    g.setEdge(e.from, e.to);
});

dagre.layout(g);

/**
 * RENDERER
 */
const svg = document.getElementById('svg-canvas');
const nodesLayer = document.getElementById('nodes-layer');
const linksLayer = document.getElementById('links-layer');
const caption = document.getElementById('caption-panel');

const nodeMap = {};

// Draw Edges
edges.forEach((edge, index) => {
    const v = g.node(edge.from);
    const w = g.node(edge.to);
    const pathData = `M${v.x},${v.y} L${w.x},${w.y}`;
    
    const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
    path.setAttribute('d', pathData);
    path.setAttribute('class', 'edge-path');
    path.setAttribute('id', `edge-${edge.from}-${edge.to}`);
    path.setAttribute('marker-end', 'url(#arrowhead)');
    linksLayer.appendChild(path);
});

// Draw Nodes
nodes.forEach(node => {
    const data = g.node(node.id);
    const group = document.createElementNS('http://www.w3.org/2000/svg', 'g');
    group.setAttribute('transform', `translate(${data.x - 110}, ${data.y - 40})`);
    group.setAttribute('id', `node-${node.id}`);
    group.style.opacity = "0";
    group.style.transition = "opacity 0.8s ease, transform 0.8s ease";

    const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
    rect.setAttribute('width', 220);
    rect.setAttribute('height', 80);
    rect.setAttribute('class', 'node-rect');
    
    // Style by type
    let fill = 'rgba(30, 41, 59, 0.8)';
    let stroke = 'var(--accent-blue)';
    if(node.type === 'core') { fill = 'rgba(251, 191, 36, 0.2)'; stroke = 'var(--accent-gold)'; }
    if(node.type === 'negation') { stroke = 'var(--accent-red)'; }
    if(node.type === 'personal') { stroke = 'var(--accent-green)'; }

    rect.setAttribute('fill', fill);
    rect.setAttribute('stroke', stroke);
    
    const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
    text.setAttribute('x', 110);
    text.setAttribute('y', 45);
    text.setAttribute('text-anchor', 'middle');
    text.setAttribute('class', 'node-text');
    text.textContent = node.label;

    group.appendChild(rect);
    group.appendChild(text);
    nodesLayer.appendChild(group);
    
    nodeMap[node.id] = { group, rect, data: node };
});

/**
 * ANIMATION LOGIC
 */
async function runAnimation() {
    const sequence = [
        { id: 'core', time: 2000 },
        { id: 'not_bossy', time: 3000 },
        { id: 'is_influence', time: 3000 },
        { id: 'liberate', time: 2500 },
        { id: 'vuca', time: 3000 },
        { id: 'adaptive', time: 3000 },
        { id: 'listening', time: 3000 },
        { id: 'generative', time: 3000 },
        { id: 'motherhood', time: 3500 },
        { id: 'brave_spaces', time: 3000 },
        { id: 'power_states', time: 3000 },
        { id: 'persuasion', time: 3000 },
        { id: 'future', time: 4000 }
    ];

    while (true) {
        // Reset
        nodes.forEach(n => {
            nodeMap[n.id].group.style.opacity = "0";
            nodeMap[n.id].rect.classList.remove('pulse');
        });
        document.querySelectorAll('.edge-path').forEach(e => e.classList.remove('edge-active'));

        for (let step of sequence) {
            const nodeObj = nodeMap[step.id];
            
            // Show Node
            nodeObj.group.style.opacity = "1";
            nodeObj.rect.classList.add('pulse');
            nodeObj.rect.setAttribute('filter', 'url(#glow)');
            caption.textContent = nodeObj.data.desc;

            // Highlight incoming edges
            edges.forEach(e => {
                if (e.to === step.id) {
                    const edgeEl = document.getElementById(`edge-${e.from}-${e.to}`);
                    if(edgeEl) edgeEl.classList.add('edge-active');
                }
            });

            await new Promise(r => setTimeout(r, step.time));
            
            // Visual Loop back to core brief flash
            if (step.id !== 'core') {
                nodeMap['core'].rect.style.strokeWidth = "5";
                await new Promise(r => setTimeout(r, 200));
                nodeMap['core'].rect.style.strokeWidth = "3";
            }

            nodeObj.rect.classList.remove('pulse');
            nodeObj.rect.removeAttribute('filter');
        }

        caption.textContent = "Reflecting... the cycle begins again.";
        await new Promise(r => setTimeout(r, 3000));
    }
}

// Start
window.onload = () => {
    // Center the graph
    const svgBox = svg.getBoundingClientRect();
    const gWidth = g.graph().width;
    const gHeight = g.graph().height;
    const offsetX = (1200 - gWidth) / 2;
    const offsetY = (700 - gHeight) / 2;
    nodesLayer.setAttribute('transform', `translate(${offsetX}, ${offsetY})`);
    linksLayer.setAttribute('transform', `translate(${offsetX}, ${offsetY})`);
    
    runAnimation();
};
</script>

</body>
</html>1f:T4a47,<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>电机运行状态监控系统 - 高级版</title>
    <script src="https://cdn.jsdelivr.net/npm/dagre@0.8.5/dist/dagre.min.js"></script>
    <style>
        :root {
            --bg-deep: #020617;
            --panel-bg: rgba(15, 23, 42, 0.9);
            --accent-cyan: #22d3ee;
            --accent-blue: #3b82f6;
            --accent-amber: #fbbf24;
            --accent-green: #4ade80;
            --accent-red: #ef4444;
            --text-main: #f1f5f9;
            --text-dim: #64748b;
            --font-main: 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
        }

        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            background-color: var(--bg-deep);
            color: var(--text-main);
            font-family: var(--font-main);
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        #app-container {
            position: relative;
            width: 1200px;
            height: 700px;
            background: radial-gradient(circle at center, #0f172a 0%, #020617 100%);
            display: flex;
            border: 1px solid rgba(255,255,255,0.05);
            box-shadow: 0 0 50px rgba(0,0,0,0.5);
        }

        /* 左侧主显示区 */
        #visual-area {
            flex: 1;
            position: relative;
            overflow: hidden;
        }

        /* 右侧控制面板 */
        #control-panel {
            width: 340px;
            background: var(--panel-bg);
            border-left: 1px solid rgba(34, 211, 238, 0.2);
            padding: 25px;
            display: flex;
            flex-direction: column;
            backdrop-filter: blur(15px);
            z-index: 10;
        }

        .header h1 {
            font-size: 20px;
            margin: 0;
            color: var(--accent-cyan);
            text-transform: uppercase;
            letter-spacing: 2px;
            display: flex;
            align-items: center;
            gap: 10px;
        }

        .header h1::before {
            content: '';
            display: inline-block;
            width: 4px;
            height: 20px;
            background: var(--accent-cyan);
        }

        .status-card {
            margin-top: 25px;
            background: rgba(255,255,255,0.03);
            border: 1px solid rgba(255,255,255,0.05);
            border-radius: 12px;
            padding: 20px;
        }

        .param-row {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;
        }

        .label {
            font-size: 13px;
            color: var(--text-dim);
        }

        .value {
            font-family: 'Consolas', monospace;
            font-size: 24px;
            color: var(--accent-cyan);
            font-weight: 600;
        }

        .unit {
            font-size: 12px;
            color: var(--text-dim);
            margin-left: 4px;
        }

        .status-indicator {
            display: flex;
            align-items: center;
            gap: 8px;
            font-weight: bold;
            padding: 4px 12px;
            border-radius: 20px;
            font-size: 12px;
            background: rgba(34, 211, 238, 0.1);
            border: 1px solid var(--accent-cyan);
        }

        /* 流程图节点样式 */
        .node rect {
            fill: #1e293b;
            stroke: var(--accent-blue);
            stroke-width: 1.5;
        }
        .node text {
            fill: var(--text-main);
            font-size: 11px;
        }
        .edgePath path {
            stroke: var(--text-dim);
            stroke-width: 1.5;
            fill: none;
        }

        /* 动画元素 */
        .airflow {
            stroke: var(--accent-cyan);
            stroke-width: 1.5;
            stroke-linecap: round;
            opacity: 0.4;
        }

        #logic-flow-container {
            position: absolute;
            bottom: 20px;
            left: 20px;
            width: 800px;
            height: 120px;
            background: rgba(0,0,0,0.3);
            border-radius: 8px;
            border: 1px solid rgba(255,255,255,0.05);
        }

        .step-tag {
            position: absolute;
            top: 40px;
            left: 40px;
            padding: 10px 20px;
            background: rgba(34, 211, 238, 0.1);
            border-left: 4px solid var(--accent-cyan);
            backdrop-filter: blur(5px);
            transition: all 0.5s ease;
            opacity: 0;
            transform: translateY(10px);
        }

        .step-tag.active {
            opacity: 1;
            transform: translateY(0);
        }

        .step-tag .title {
            font-weight: bold;
            color: var(--accent-cyan);
            font-size: 14px;
            margin-bottom: 4px;
        }

        .step-tag .desc {
            font-size: 12px;
            color: var(--text-dim);
        }
    </style>
</head>
<body>

<div id="app-container">
    <div id="visual-area">
        <svg id="main-svg" viewBox="0 0 860 700" width="100%" height="100%">
            <defs>
                <filter id="glow">
                    <feGaussianBlur stdDeviation="3" result="coloredBlur"/>
                    <feMerge>
                        <feMergeNode in="coloredBlur"/>
                        <feMergeNode in="SourceGraphic"/>
                    </feMerge>
                </filter>
                <linearGradient id="blade-grad" x1="0%" y1="0%" x2="100%" y2="100%">
                    <stop offset="0%" style="stop-color:#475569;stop-opacity:1" />
                    <stop offset="100%" style="stop-color:#0f172a;stop-opacity:1" />
                </linearGradient>
                <marker id="arrowhead" viewBox="0 0 10 10" refX="9" refY="5" markerUnits="strokeWidth" markerWidth="6" markerHeight="6" orient="auto">
                    <path d="M 0 0 L 10 5 L 0 10 z" fill="var(--text-dim)" />
                </marker>
            </defs>

            <!-- 背景网格 -->
            <g opacity="0.1">
                <pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse">
                    <path d="M 40 0 L 0 0 0 40" fill="none" stroke="white" stroke-width="0.5"/>
                </pattern>
                <rect width="100%" height="100%" fill="url(#grid)" />
            </g>

            <!-- 气流粒子 -->
            <g id="airflow-group"></g>

            <!-- 电机主体 -->
            <g id="motor-assembly" transform="translate(430, 300)">
                <!-- 支撑架 -->
                <path d="M -10 50 L -30 250 M 10 50 L 30 250" stroke="#334155" stroke-width="8" />
                <rect x="-60" y="250" width="120" height="10" rx="5" fill="#1e293b" />
                
                <!-- 后罩 -->
                <circle r="220" fill="none" stroke="#1e293b" stroke-width="1" />
                <g id="cage-lines" opacity="0.2"></g>

                <!-- 旋转部分 -->
                <g id="rotor-group">
                    <!-- 扇叶 -->
                    <g id="blades">
                        <path d="M 0 0 C -30 -80 -20 -180 0 -210 C 20 -180 30 -80 0 0" fill="url(#blade-grad)" stroke="#64748b" stroke-width="0.5" />
                        <path d="M 0 0 C 80 -30 180 -20 210 0 C 180 20 80 30 0 0" fill="url(#blade-grad)" stroke="#64748b" stroke-width="0.5" />
                        <path d="M 0 0 C 30 80 20 180 0 210 C -20 180 -30 80 0 0" fill="url(#blade-grad)" stroke="#64748b" stroke-width="0.5" />
                        <path d="M 0 0 C -80 30 -180 20 -210 0 C -180 -20 -80 -30 0 0" fill="url(#blade-grad)" stroke="#64748b" stroke-width="0.5" />
                    </g>
                    <!-- 轴心 -->
                    <circle r="35" fill="#0f172a" stroke="#334155" stroke-width="4" />
                    <circle id="core-light" r="8" fill="var(--accent-cyan)" filter="url(#glow)">
                        <animate attributeName="opacity" values="0.4;1;0.4" dur="2s" repeatCount="indefinite" />
                    </circle>
                </g>

                <!-- 状态扫描环 -->
                <circle id="scan-ring" r="230" fill="none" stroke="var(--accent-cyan)" stroke-width="1" stroke-dasharray="60 1000" opacity="0.3" />
            </g>

            <!-- 逻辑流程图容器 -->
            <g id="logic-flow-svg" transform="translate(30, 560)"></g>
        </svg>

        <div id="step-tag" class="step-tag">
            <div class="title" id="step-title">系统就绪</div>
            <div class="desc" id="step-desc">等待控制指令输入...</div>
        </div>
    </div>

    <div id="control-panel">
        <div class="header">
            <h1>运行状态监控</h1>
        </div>

        <div class="status-card">
            <div class="param-row">
                <span class="label">当前状态</span>
                <div class="status-indicator" id="status-val">
                    <span style="width:8px; height:8px; border-radius:50%; background:var(--accent-cyan); display:inline-block;"></span>
                    <span>系统待机</span>
                </div>
            </div>
            <div class="param-row">
                <span class="label">实时转速</span>
                <div><span class="value" id="rpm-val">0</span><span class="unit">RPM</span></div>
            </div>
            <div class="param-row">
                <span class="label">核心温度</span>
                <div><span class="value" id="temp-val">24.5</span><span class="unit">°C</span></div>
            </div>
            <div class="param-row">
                <span class="label">负载功率</span>
                <div><span class="value" id="power-val">0</span><span class="unit">W</span></div>
            </div>
            <div class="param-row">
                <span class="label">振动频率</span>
                <div><span class="value" id="vib-val">0.0</span><span class="unit">Hz</span></div>
            </div>
        </div>

        <div class="status-card" style="margin-top: 20px; flex: 1; font-size: 12px; color: var(--text-dim); line-height: 1.8;">
            <div style="color: var(--accent-cyan); margin-bottom: 10px; font-weight: bold;">诊断日志 (Diagnostic Log)</div>
            <div id="log-container">
                [10:00:01] 系统自检完成...<br>
                [10:00:02] 传感器链路正常...<br>
                [10:00:03] 等待启动信号...
            </div>
        </div>

        <div style="font-size: 11px; color: #475569; text-align: center; padding-top: 10px;">
            工业级无刷电机控制系统 v4.0.2
        </div>
    </div>
</div>

<script>
    // 1. 初始化流程图数据 (Dagre)
    const g = new dagre.graphlib.Graph();
    g.setGraph({ rankdir: 'LR', nodesep: 50, ranksep: 60 });
    g.setDefaultEdgeLabel(() => ({}));

    const nodes = [
        { id: 'start', label: '控制指令' },
        { id: 'pwm', label: 'PWM 调制' },
        { id: 'driver', label: '功率驱动' },
        { id: 'motor', label: '电机执行' },
        { id: 'sensor', label: '霍尔反馈' },
        { id: 'calc', label: '闭环计算' }
    ];

    nodes.forEach(n => g.setNode(n.id, { label: n.label, width: 90, height: 34 }));
    g.setEdge('start', 'pwm');
    g.setEdge('pwm', 'driver');
    g.setEdge('driver', 'motor');
    g.setEdge('motor', 'sensor');
    g.setEdge('sensor', 'calc');
    g.setEdge('calc', 'pwm');

    dagre.layout(g);

    // 渲染流程图
    const flowSvg = document.getElementById('logic-flow-svg');
    g.edges().forEach(e => {
        const edge = g.edge(e);
        const points = edge.points.map(p => `${p.x},${p.y}`).join(' ');
        const polyline = document.createElementNS('http://www.w3.org/2000/svg', 'polyline');
        polyline.setAttribute('points', points);
        polyline.setAttribute('fill', 'none');
        polyline.setAttribute('stroke', 'rgba(100, 116, 139, 0.5)');
        polyline.setAttribute('stroke-width', '1.5');
        polyline.setAttribute('marker-end', 'url(#arrowhead)');
        flowSvg.appendChild(polyline);
    });

    g.nodes().forEach(v => {
        const node = g.node(v);
        const group = document.createElementNS('http://www.w3.org/2000/svg', 'g');
        group.setAttribute('transform', `translate(${node.x - node.width/2}, ${node.y - node.height/2})`);
        
        const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
        rect.setAttribute('width', node.width);
        rect.setAttribute('height', node.height);
        rect.setAttribute('rx', '4');
        rect.setAttribute('fill', '#0f172a');
        rect.setAttribute('stroke', '#334155');
        rect.id = `node-${v}`;
        
        const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
        text.setAttribute('x', node.width/2);
        text.setAttribute('y', node.height/2 + 4);
        text.setAttribute('text-anchor', 'middle');
        text.setAttribute('fill', '#94a3b8');
        text.style.fontSize = '11px';
        text.textContent = node.label;
        
        group.appendChild(rect);
        group.appendChild(text);
        flowSvg.appendChild(group);
    });

    // 2. 动画逻辑
    const state = {
        rpm: 0,
        targetRpm: 1800,
        temp: 24.5,
        power: 0,
        vib: 0,
        angle: 0,
        phase: 0, // 0: standby, 1: starting, 2: running
        startTime: Date.now()
    };

    const elements = {
        rotor: document.getElementById('rotor-group'),
        rpm: document.getElementById('rpm-val'),
        temp: document.getElementById('temp-val'),
        power: document.getElementById('power-val'),
        vib: document.getElementById('vib-val'),
        status: document.getElementById('status-val'),
        scan: document.getElementById('scan-ring'),
        tag: document.getElementById('step-tag'),
        tagTitle: document.getElementById('step-title'),
        tagDesc: document.getElementById('step-desc'),
        log: document.getElementById('log-container'),
        airflow: document.getElementById('airflow-group')
    };

    // 初始化后罩线条
    const cage = document.getElementById('cage-lines');
    for(let i=0; i<360; i+=15) {
        const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
        const r = 220;
        line.setAttribute('x1', 0);
        line.setAttribute('y1', 0);
        line.setAttribute('x2', r * Math.cos(i * Math.PI / 180));
        line.setAttribute('y2', r * Math.sin(i * Math.PI / 180));
        line.setAttribute('stroke', '#475569');
        cage.appendChild(line);
    }

    // 粒子系统
    const particles = [];
    for(let i=0; i<40; i++) {
        const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
        line.setAttribute('class', 'airflow');
        elements.airflow.appendChild(line);
        particles.push({
            el: line,
            x: Math.random() * 400 + 450,
            y: Math.random() * 400 + 100,
            len: Math.random() * 30 + 10,
            speed: Math.random() * 5 + 2
        });
    }

    function addLog(msg) {
        const time = new Date().toLocaleTimeString().split(' ')[0];
        elements.log.innerHTML = `[${time}] ${msg}<br>` + elements.log.innerHTML;
        if (elements.log.innerHTML.length > 500) elements.log.innerHTML = elements.log.innerHTML.substring(0, 500);
    }

    function update(time) {
        const dt = 0.016; // 约 60fps
        const elapsed = (Date.now() - state.startTime) / 1000;

        // 状态机
        if (state.phase === 0 && elapsed > 2) {
            state.phase = 1;
            elements.tag.classList.add('active');
            elements.tagTitle.textContent = "启动序列激活";
            elements.tagDesc.textContent = "正在注入启动电流，克服静摩擦...";
            elements.status.innerHTML = `<span style="width:8px; height:8px; border-radius:50%; background:var(--accent-amber); display:inline-block;"></span><span>启动中</span>`;
            elements.status.style.borderColor = "var(--accent-amber)";
            elements.status.style.color = "var(--accent-amber)";
            addLog("接收到启动指令...");
            document.getElementById('node-start').setAttribute('stroke', 'var(--accent-amber)');
        } else if (state.phase === 1) {
            state.rpm += 15;
            state.temp += 0.05;
            state.power = state.rpm * 0.15 + Math.random() * 5;
            state.vib = (state.rpm / 1000) + Math.random() * 0.2;
            
            if (state.rpm >= state.targetRpm) {
                state.phase = 2;
                state.rpm = state.targetRpm;
                elements.tagTitle.textContent = "稳定运行状态";
                elements.tagDesc.textContent = "闭环控制已锁定，各项参数正常。";
                elements.status.innerHTML = `<span style="width:8px; height:8px; border-radius:50%; background:var(--accent-green); display:inline-block;"></span><span>运行正常</span>`;
                elements.status.style.borderColor = "var(--accent-green)";
                elements.status.style.color = "var(--accent-green)";
                addLog("转速锁定：1800 RPM");
                document.querySelectorAll('.node rect').forEach(r => r.setAttribute('stroke', 'var(--accent-green)'));
            }
        } else if (state.phase === 2) {
            state.rpm = state.targetRpm + Math.sin(time / 500) * 5;
            state.temp = 42.0 + Math.sin(time / 2000) * 0.3;
            state.power = 270 + Math.random() * 4;
            state.vib = 1.8 + Math.random() * 0.1;
        }

        // 更新UI
        elements.rpm.textContent = Math.floor(state.rpm);
        elements.temp.textContent = state.temp.toFixed(1);
        elements.power.textContent = Math.floor(state.power);
        elements.vib.textContent = state.vib.toFixed(1);

        // 旋转
        state.angle += (state.rpm / 60) * 360 * dt;
        elements.rotor.setAttribute('transform', `rotate(${state.angle % 360})`);
        elements.scan.setAttribute('transform', `rotate(${time / 20})`);

        // 粒子更新
        const flowFactor = state.rpm / state.targetRpm;
        particles.forEach(p => {
            p.x += p.speed * (1 + flowFactor * 4);
            if (p.x > 860) {
                p.x = 430;
                p.y = Math.random() * 440 + 80;
            }
            p.el.setAttribute('x1', p.x);
            p.el.setAttribute('y1', p.y);
            p.el.setAttribute('x2', p.x + p.len);
            p.el.setAttribute('y2', p.y);
            p.el.setAttribute('opacity', 0.1 + flowFactor * 0.4);
        });

        requestAnimationFrame(update);
    }

    requestAnimationFrame(update);
</script>

</body>
</html>20:T8e8,Modern tech-style web SVG flowchart animation featuring a dark background with cyan-blue, purple, and bright orange neon tech lighting. The lines are smooth and clean with a slight fluorescent glow, presenting a high-tech feel and professional, rigorous data flow texture.

The visual adopts a horizontal layout extending from left to right. On the left, the data source area features scattered micro-skeuomorphic glowing data cards representing Order Table, Inventory Table, SD Report, IDC Report, Biz Index, Model Matrix, and keydates. Glowing data particles of different colors flow out from these nodes at a constant speed in pulses, converging toward the center along streamlined tracks with a breathing light effect.

Data particles enter a cleaning and standardization processing module with dynamic rotating gears and funnel animations. The originally cluttered and multi-colored particles are filtered here, turning into orderly, uniformly colored pure bright blue data blocks. Subsequently, these standardized data slide smoothly into a data warehouse server array with a 3D feel and frosted glass luster. The stacked indicator lights of the servers flash rhythmically, symbolizing secure data storage.

Next, a highlighted light strip leads from the data warehouse into the analysis and modeling area. This area simulates the efficient operation of complex algorithms and model calculations through dynamically interconnected neural network nodes and rapidly flashing matrix connections.

The processed data stream turns into brilliant flowing light, injected into the terminal display area on the right. Gradient bar charts growing upwards, smoothly unfolding line charts, and rotating 3D pie charts are dynamically generated in sequence. Finally, a golden glowing upward arrow or target bullseye representing auxiliary business decision-making emerges above all charts, with the arrow featuring a delicate particle trail effect.

The overall animation rhythm follows a cadence of multi-source convergence, steady processing, and progressive explosion of results. The movement of the light flow has a smooth easing effect, and each node accompanies a slight elastic scaling feedback as data passes through, forming an endless, smooth, and complete data link ecosystem.21:T559d,<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>现代科技数据流转全链路可视化</title>
    <style>
        :root {
            --bg-deep: #020406;
            --neon-cyan: #00f2ff;
            --neon-purple: #bc00ff;
            --neon-orange: #ff8c00;
            --neon-blue: #0066ff;
            --neon-gold: #ffd700;
            --glass: rgba(255, 255, 255, 0.03);
            --glass-border: rgba(255, 255, 255, 0.12);
            --text-main: #e0f7fa;
            --font-main: 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
        }

        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            background-color: var(--bg-deep);
            color: var(--text-main);
            font-family: var(--font-main);
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        #app-container {
            position: relative;
            width: 1200px;
            height: 700px;
            background: radial-gradient(circle at center, #0a141d 0%, #020406 100%);
            border: 1px solid rgba(0, 242, 255, 0.1);
            overflow: hidden;
            box-shadow: 0 0 100px rgba(0, 0, 0, 0.9);
        }

        .svg-canvas {
            width: 100%;
            height: 100%;
        }

        /* 节点基础样式 - 微拟物化 */
        .node-card {
            fill: url(#grad-node);
            stroke: var(--glass-border);
            stroke-width: 1.5;
            transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
        }

        .node-group:hover .node-card {
            stroke: var(--neon-cyan);
            filter: brightness(1.5);
            transform: translate(-2px, -2px);
        }

        /* 霓虹发光滤镜 */
        .glow-cyan { filter: url(#glow-cyan); }
        .glow-purple { filter: url(#glow-purple); }
        .glow-orange { filter: url(#glow-orange); }
        .glow-gold { filter: url(#glow-gold); }

        /* 动画定义 */
        @keyframes rotate-gear {
            from { transform: rotate(0deg); }
            to { transform: rotate(360deg); }
        }
        .rotating { transform-origin: center; animation: rotate-gear 8s linear infinite; }
        .rotating-reverse { transform-origin: center; animation: rotate-gear 10s linear infinite reverse; }

        @keyframes breathe {
            0%, 100% { opacity: 0.2; stroke-width: 1; }
            50% { opacity: 0.6; stroke-width: 2; }
        }
        .path-breathe { animation: breathe 4s ease-in-out infinite; }

        @keyframes matrix-flicker {
            0%, 100% { opacity: 0.1; }
            50% { opacity: 0.7; stroke-width: 1.5; }
        }
        .matrix-line { animation: matrix-flicker 2s infinite; }

        @keyframes chart-grow {
            from { transform: scaleY(0); }
            to { transform: scaleY(1); }
        }
        .chart-bar { transform-origin: bottom; animation: chart-grow 1.5s cubic-bezier(0.4, 0, 0.2, 1) forwards; }

        @keyframes float-arrow {
            0%, 100% { transform: translateY(0) scale(1); }
            50% { transform: translateY(-15px) scale(1.05); }
        }
        .floating-arrow { animation: float-arrow 3s ease-in-out infinite; }

        @keyframes server-blink {
            0%, 100% { fill: #00ff00; filter: blur(1px); }
            50% { fill: #004400; filter: none; }
        }
        .led-blink { animation: server-blink 1s infinite; }
    </style>
</head>
<body>

<div id="app-container">
    <svg class="svg-canvas" viewBox="0 0 1200 700" xmlns="http://www.w3.org/2000/svg">
        <defs>
            <!-- 霓虹滤镜 -->
            <filter id="glow-cyan" x="-50%" y="-50%" width="200%" height="200%">
                <feGaussianBlur stdDeviation="3" result="blur" />
                <feComposite in="SourceGraphic" in2="blur" operator="over" />
            </filter>
            <filter id="glow-purple" x="-50%" y="-50%" width="200%" height="200%">
                <feGaussianBlur stdDeviation="4" result="blur" />
                <feComposite in="SourceGraphic" in2="blur" operator="over" />
            </filter>
            <filter id="glow-gold" x="-50%" y="-50%" width="200%" height="200%">
                <feGaussianBlur stdDeviation="6" result="blur" />
                <feComposite in="SourceGraphic" in2="blur" operator="over" />
            </filter>
            
            <!-- 渐变定义 -->
            <linearGradient id="grad-node" x1="0%" y1="0%" x2="100%" y2="100%">
                <stop offset="0%" style="stop-color:rgba(255,255,255,0.08);stop-opacity:1" />
                <stop offset="100%" style="stop-color:rgba(255,255,255,0.02);stop-opacity:1" />
            </linearGradient>
            <linearGradient id="grad-server" x1="0%" y1="0%" x2="0%" y2="100%">
                <stop offset="0%" style="stop-color:#1a2a3a;stop-opacity:1" />
                <stop offset="100%" style="stop-color:#05080a;stop-opacity:1" />
            </linearGradient>
            <linearGradient id="grad-gold" x1="0%" y1="0%" x2="0%" y2="100%">
                <stop offset="0%" style="stop-color:#fff3a0;stop-opacity:1" />
                <stop offset="100%" style="stop-color:#ffd700;stop-opacity:1" />
            </linearGradient>

            <!-- 背景网格 -->
            <pattern id="grid" width="60" height="60" patternUnits="userSpaceOnUse">
                <path d="M 60 0 L 0 0 0 60" fill="none" stroke="rgba(0, 242, 255, 0.03)" stroke-width="1"/>
            </pattern>
        </defs>

        <!-- 背景层 -->
        <rect width="1200" height="700" fill="url(#grid)" />
        
        <!-- 标题 -->
        <g transform="translate(60, 50)">
            <text x="0" y="0" font-size="26" font-weight="bold" fill="var(--neon-cyan)" class="glow-cyan" style="letter-spacing: 2px;">智能数据全链路生态系统</text>
            <text x="0" y="25" font-size="12" fill="rgba(255,255,255,0.3)" style="letter-spacing: 1px;">INTELLIGENT DATA PIPELINE ECOSYSTEM</text>
        </g>

        <!-- 连线轨道 -->
        <g id="tracks" fill="none" stroke-width="1.5">
            <g class="path-breathe" stroke="rgba(0, 242, 255, 0.15)">
                <path id="p1" d="M 210 120 C 330 120, 360 350, 430 350" />
                <path id="p2" d="M 210 190 C 330 190, 360 350, 430 350" />
                <path id="p3" d="M 210 260 C 330 260, 360 350, 430 350" />
                <path id="p4" d="M 210 350 L 430 350" />
                <path id="p5" d="M 210 440 C 330 440, 360 350, 430 350" />
                <path id="p6" d="M 210 510 C 330 510, 360 350, 430 350" />
                <path id="p7" d="M 210 580 C 330 580, 360 350, 430 350" />
            </g>
            <path id="p-etl-wh" d="M 540 350 L 630 350" stroke="rgba(0, 242, 255, 0.3)" />
            <path id="p-wh-ana" d="M 790 350 L 860 350" stroke="rgba(188, 0, 255, 0.3)" />
            <path id="p-ana-dis" d="M 1010 350 L 1060 350" stroke="rgba(0, 242, 255, 0.3)" />
        </g>

        <!-- 1. 数据源区 -->
        <g id="source-nodes">
            <g transform="translate(60, 100)" class="node-group">
                <rect width="150" height="40" rx="6" class="node-card" />
                <text x="75" y="25" text-anchor="middle" font-size="12" fill="var(--text-main)">订单表 (Orders)</text>
                <circle cx="150" cy="20" r="3" fill="var(--neon-purple)" class="glow-purple" />
            </g>
            <g transform="translate(60, 170)" class="node-group">
                <rect width="150" height="40" rx="6" class="node-card" />
                <text x="75" y="25" text-anchor="middle" font-size="12" fill="var(--text-main)">库存表 (Stock)</text>
                <circle cx="150" cy="20" r="3" fill="var(--neon-cyan)" class="glow-cyan" />
            </g>
            <g transform="translate(60, 240)" class="node-group">
                <rect width="150" height="40" rx="6" class="node-card" />
                <text x="75" y="25" text-anchor="middle" font-size="12" fill="var(--text-main)">SD Report</text>
                <circle cx="150" cy="20" r="3" fill="var(--neon-orange)" class="glow-orange" />
            </g>
            <g transform="translate(60, 330)" class="node-group">
                <rect width="150" height="40" rx="6" class="node-card" />
                <text x="75" y="25" text-anchor="middle" font-size="12" fill="var(--text-main)">IDC Report</text>
                <circle cx="150" cy="20" r="3" fill="var(--neon-cyan)" class="glow-cyan" />
            </g>
            <g transform="translate(60, 420)" class="node-group">
                <rect width="150" height="40" rx="6" class="node-card" />
                <text x="75" y="25" text-anchor="middle" font-size="12" fill="var(--text-main)">业务指标 (Biz Index)</text>
                <circle cx="150" cy="20" r="3" fill="var(--neon-purple)" class="glow-purple" />
            </g>
            <g transform="translate(60, 490)" class="node-group">
                <rect width="150" height="40" rx="6" class="node-card" />
                <text x="75" y="25" text-anchor="middle" font-size="12" fill="var(--text-main)">模型矩阵 (Matrix)</text>
                <circle cx="150" cy="20" r="3" fill="var(--neon-orange)" class="glow-orange" />
            </g>
            <g transform="translate(60, 560)" class="node-group">
                <rect width="150" height="40" rx="6" class="node-card" />
                <text x="75" y="25" text-anchor="middle" font-size="12" fill="var(--text-main)">关键日期 (Keydates)</text>
                <circle cx="150" cy="20" r="3" fill="var(--neon-cyan)" class="glow-cyan" />
            </g>
        </g>

        <!-- 2. 清洗处理区 (ETL) -->
        <g id="etl-zone" transform="translate(430, 280)">
            <rect width="110" height="140" rx="12" class="node-card" />
            <!-- 漏斗动画 -->
            <path d="M 30 35 L 80 35 L 65 75 L 45 75 Z" fill="none" stroke="var(--neon-cyan)" stroke-width="2" class="glow-cyan">
                <animate attributeName="stroke-dasharray" values="0,200;200,0" dur="3s" repeatCount="indefinite" />
            </path>
            <!-- 齿轮 -->
            <g transform="translate(40, 100)">
                <path class="rotating" d="M-12,-4 L-12,4 L-15,6 L-12,10 L-8,8 L-6,12 L-2,12 L0,15 L2,12 L6,12 L8,8 L12,10 L15,6 L12,4 L12,-4 L15,-6 L12,-10 L8,-8 L6,-12 L2,-12 L0,-15 L-2,-12 L-6,-12 L-8,-8 L-12,-10 L-15,-6 Z" fill="none" stroke="var(--neon-cyan)" stroke-width="1" />
            </g>
            <g transform="translate(75, 105)">
                <path class="rotating-reverse" d="M-10,-3 L-10,3 L-12,5 L-10,8 L-7,7 L-5,10 L-2,10 L0,12 L2,10 L5,10 L7,7 L10,8 L12,5 L10,3 L10,-3 L12,-5 L10,-8 L7,-7 L5,-10 L2,-10 L0,-12 L-2,-10 L-5,-10 L-7,-7 L-10,-8 L-12,-5 Z" fill="none" stroke="var(--neon-cyan)" stroke-width="1" />
            </g>
            <text x="55" y="132" text-anchor="middle" font-size="11" fill="var(--neon-cyan)" class="glow-cyan">清洗与标准化</text>
        </g>

        <!-- 3. 数据仓库 (Warehouse) -->
        <g id="warehouse-zone" transform="translate(630, 280)">
            <rect width="160" height="140" rx="10" fill="url(#grad-server)" stroke="var(--glass-border)" style="filter: drop-shadow(0 0 10px rgba(0,0,0,0.5));" />
            <!-- 服务器阵列 -->
            <g transform="translate(15, 20)">
                <rect width="130" height="28" rx="3" fill="rgba(255,255,255,0.05)" stroke="rgba(255,255,255,0.1)" />
                <circle cx="12" cy="14" r="2.5" class="led-blink" />
                <rect x="25" y="12" width="90" height="4" rx="2" fill="rgba(255,255,255,0.1)" />
            </g>
            <g transform="translate(15, 55)">
                <rect width="130" height="28" rx="3" fill="rgba(255,255,255,0.05)" stroke="rgba(255,255,255,0.1)" />
                <circle cx="12" cy="14" r="2.5" class="led-blink" style="animation-delay: 0.3s" />
                <rect x="25" y="12" width="90" height="4" rx="2" fill="rgba(255,255,255,0.1)" />
            </g>
            <g transform="translate(15, 90)">
                <rect width="130" height="28" rx="3" fill="rgba(255,255,255,0.05)" stroke="rgba(255,255,255,0.1)" />
                <circle cx="12" cy="14" r="2.5" class="led-blink" style="animation-delay: 0.6s" />
                <rect x="25" y="12" width="90" height="4" rx="2" fill="rgba(255,255,255,0.1)" />
            </g>
            <text x="80" y="132" text-anchor="middle" font-size="11" fill="var(--text-main)">核心数据仓库</text>
        </g>

        <!-- 4. 分析建模 (Analysis) -->
        <g id="analysis-zone" transform="translate(860, 280)">
            <rect width="150" height="140" rx="12" class="node-card" style="stroke:var(--neon-purple)" />
            <g id="nn-net">
                <circle cx="35" cy="40" r="4" fill="var(--neon-purple)" class="glow-purple" />
                <circle cx="35" cy="70" r="4" fill="var(--neon-purple)" class="glow-purple" />
                <circle cx="35" cy="100" r="4" fill="var(--neon-purple)" class="glow-purple" />
                <circle cx="80" cy="55" r="4" fill="var(--neon-cyan)" class="glow-cyan" />
                <circle cx="80" cy="85" r="4" fill="var(--neon-cyan)" class="glow-cyan" />
                <circle cx="125" cy="70" r="5" fill="var(--neon-purple)" class="glow-purple" />
                
                <g stroke="rgba(188, 0, 255, 0.4)" stroke-width="1">
                    <line x1="35" y1="40" x2="80" y2="55" class="matrix-line" />
                    <line x1="35" y1="70" x2="80" y2="55" class="matrix-line" style="animation-delay:0.2s" />
                    <line x1="35" y1="70" x2="80" y2="85" class="matrix-line" style="animation-delay:0.4s" />
                    <line x1="35" y1="100" x2="80" y2="85" class="matrix-line" style="animation-delay:0.6s" />
                    <line x1="80" y1="55" x2="125" y2="70" class="matrix-line" style="animation-delay:0.8s" />
                    <line x1="80" y1="85" x2="125" y2="70" class="matrix-line" style="animation-delay:1s" />
                </g>
            </g>
            <text x="75" y="132" text-anchor="middle" font-size="11" fill="var(--neon-purple)">智能分析建模</text>
        </g>

        <!-- 5. 终端展示区 (Display) -->
        <g id="display-zone" transform="translate(1060, 250)">
            <!-- 柱状图 -->
            <g transform="translate(0, 110)">
                <rect x="0" y="-35" width="10" height="35" fill="var(--neon-cyan)" class="chart-bar" />
                <rect x="15" y="-55" width="10" height="55" fill="var(--neon-cyan)" class="chart-bar" style="animation-delay:0.2s" />
                <rect x="30" y="-45" width="10" height="45" fill="var(--neon-cyan)" class="chart-bar" style="animation-delay:0.4s" />
            </g>
            <!-- 折线图 -->
            <path d="M 55 90 L 70 65 L 85 75 L 105 45" fill="none" stroke="var(--neon-purple)" stroke-width="2.5" stroke-linecap="round" stroke-dasharray="150">
                <animate attributeName="stroke-dashoffset" from="150" to="0" dur="3s" repeatCount="indefinite" />
            </path>
            <!-- 饼图 -->
            <circle cx="85" cy="115" r="18" fill="none" stroke="var(--neon-cyan)" stroke-width="12" stroke-dasharray="70 30" class="rotating" />
            
            <!-- 决策箭头 -->
            <g id="decision-target" transform="translate(35, -60)" class="floating-arrow">
                <path d="M 20 0 L 40 30 L 30 30 L 30 65 L 10 65 L 10 30 L 0 30 Z" fill="url(#grad-gold)" class="glow-gold" />
                <text x="20" y="85" text-anchor="middle" font-size="13" font-weight="bold" fill="var(--neon-gold)" class="glow-gold">业务决策辅助</text>
            </g>
        </g>

        <!-- 动态粒子层 -->
        <g id="particle-layer"></g>
    </svg>
</div>

<script>
    const particleLayer = document.getElementById('particle-layer');
    const paths = {
        sources: [
            document.getElementById('p1'), document.getElementById('p2'),
            document.getElementById('p3'), document.getElementById('p4'),
            document.getElementById('p5'), document.getElementById('p6'),
            document.getElementById('p7')
        ],
        etlWh: document.getElementById('p-etl-wh'),
        whAna: document.getElementById('p-wh-ana'),
        anaDis: document.getElementById('p-ana-dis')
    };

    const sourceColors = ['#bc00ff', '#00f2ff', '#ff8c00', '#00f2ff', '#bc00ff', '#ff8c00', '#00f2ff'];
    const particles = [];

    class Particle {
        constructor(path, type, colorIdx = 0) {
            this.path = path;
            this.type = type; // 'raw', 'clean', 'pulse', 'result'
            this.el = document.createElementNS('http://www.w3.org/2000/svg', this.type === 'clean' ? 'rect' : 'circle');
            this.len = path.getTotalLength();
            this.speed = (0.0015 + Math.random() * 0.002) * (type === 'result' ? 1.5 : 1);
            this.pos = Math.random();
            this.colorIdx = colorIdx;
            
            this.initStyle();
            particleLayer.appendChild(this.el);
        }

        initStyle() {
            if (this.type === 'raw') {
                this.el.setAttribute('r', '3');
                this.el.setAttribute('fill', sourceColors[this.colorIdx]);
                this.el.setAttribute('filter', 'url(#glow-cyan)');
            } else if (this.type === 'clean') {
                this.el.setAttribute('width', '6');
                this.el.setAttribute('height', '6');
                this.el.setAttribute('rx', '1');
                this.el.setAttribute('fill', '#00f2ff');
                this.el.setAttribute('filter', 'url(#glow-cyan)');
            } else if (this.type === 'pulse') {
                this.el.setAttribute('r', '4');
                this.el.setAttribute('fill', '#bc00ff');
                this.el.setAttribute('filter', 'url(#glow-purple)');
            } else {
                this.el.setAttribute('r', '2.5');
                this.el.setAttribute('fill', '#ffd700');
                this.el.setAttribute('filter', 'url(#glow-gold)');
            }
        }

        update() {
            this.pos += this.speed;
            if (this.pos > 1) {
                this.pos = 0;
                // 触发节点弹性反馈 (模拟)
                this.triggerFeedback();
            }

            const point = this.path.getPointAtLength(this.pos * this.len);
            
            if (this.type === 'clean') {
                this.el.setAttribute('x', point.x - 3);
                this.el.setAttribute('y', point.y - 3);
            } else {
                this.el.setAttribute('cx', point.x);
                this.el.setAttribute('cy', point.y);
            }

            let opacity = 1;
            if (this.pos < 0.1) opacity = this.pos * 10;
            if (this.pos > 0.9) opacity = (1 - this.pos) * 10;
            this.el.setAttribute('opacity', opacity);
        }

        triggerFeedback() {
            // 简单的节点缩放反馈逻辑可以在这里通过修改对应DOM实现
        }
    }

    function init() {
        // 1. 原始数据粒子 (多色汇聚)
        paths.sources.forEach((p, idx) => {
            for(let i=0; i<5; i++) {
                setTimeout(() => {
                    particles.push(new Particle(p, 'raw', idx));
                }, i * 800);
            }
        });

        // 2. 标准化数据块 (纯净蓝)
        for(let i=0; i<8; i++) {
            setTimeout(() => {
                particles.push(new Particle(paths.etlWh, 'clean'));
            }, i * 600);
        }

        // 3. 分析脉冲 (紫色)
        for(let i=0; i<5; i++) {
            setTimeout(() => {
                particles.push(new Particle(paths.whAna, 'pulse'));
            }, i * 1000);
        }

        // 4. 结果流光 (金色)
        for(let i=0; i<12; i++) {
            setTimeout(() => {
                particles.push(new Particle(paths.anaDis, 'result'));
            }, i * 400);
        }

        animate();
    }

    function animate() {
        particles.forEach(p => p.update());
        requestAnimationFrame(animate);
    }

    init();

    // 交互：点击产生科技涟漪
    document.querySelector('svg').addEventListener('mousedown', (e) => {
        const ripple = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
        const rect = e.currentTarget.getBoundingClientRect();
        const x = (e.clientX - rect.left) * (1200 / rect.width);
        const y = (e.clientY - rect.top) * (700 / rect.height);
        
        ripple.setAttribute('cx', x);
        ripple.setAttribute('cy', y);
        ripple.setAttribute('r', '0');
        ripple.setAttribute('fill', 'none');
        ripple.setAttribute('stroke', 'var(--neon-cyan)');
        ripple.setAttribute('stroke-width', '2');
        ripple.style.opacity = '0.8';
        
        const anim = document.createElementNS('http://www.w3.org/2000/svg', 'animate');
        anim.setAttribute('attributeName', 'r');
        anim.setAttribute('from', '0');
        anim.setAttribute('to', '120');
        anim.setAttribute('dur', '0.8s');
        anim.setAttribute('fill', 'freeze');
        
        const animOp = document.createElementNS('http://www.w3.org/2000/svg', 'animate');
        animOp.setAttribute('attributeName', 'opacity');
        animOp.setAttribute('from', '0.8');
        animOp.setAttribute('to', '0');
        animOp.setAttribute('dur', '0.8s');
        animOp.setAttribute('fill', 'freeze');
        
        ripple.appendChild(anim);
        ripple.appendChild(animOp);
        particleLayer.appendChild(ripple);
        
        setTimeout(() => ripple.remove(), 900);
    });
</script>
</body>
</html>22:T3f88,<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>SOC 网络安全告警处置流程自动化</title>
    <style>
        :root {
            --bg-color: #04080f;
            --primary-glow: #00f2ff;
            --danger-glow: #ff3e3e;
            --success-glow: #00ff9d;
            --warning-glow: #ffbb00;
            --text-color: #e0f7fa;
            --line-color: rgba(0, 242, 255, 0.2);
            --font-family: 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
        }

        * { box-sizing: border-box; }
        body, html {
            margin: 0; padding: 0;
            width: 100%; height: 100%;
            background-color: var(--bg-color);
            color: var(--text-color);
            font-family: var(--font-family);
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        #app-container {
            position: relative;
            width: 1200px;
            height: 700px;
            background: radial-gradient(circle at center, #0a192f 0%, #04080f 100%);
            border: 1px solid #1a3a5a;
            box-shadow: 0 0 100px rgba(0, 242, 255, 0.1);
        }

        .canvas-svg {
            width: 100%;
            height: 100%;
        }

        /* 节点样式 */
        .node-rect {
            fill: rgba(10, 25, 47, 0.8);
            stroke: var(--line-color);
            stroke-width: 2;
            transition: all 0.5s ease;
        }

        .node-active {
            stroke: var(--primary-glow);
            filter: url(#glow);
        }

        .node-label {
            font-size: 14px;
            fill: #88a0b0;
            text-anchor: middle;
            pointer-events: none;
            font-weight: 300;
        }

        .node-title {
            font-size: 18px;
            fill: var(--text-color);
            text-anchor: middle;
            pointer-events: none;
            font-weight: 600;
        }

        /* 连线样式 */
        .flow-path {
            fill: none;
            stroke: var(--line-color);
            stroke-width: 2;
            stroke-dasharray: 5, 5;
        }

        .flow-path-active {
            stroke: var(--primary-glow);
            stroke-dasharray: 1000;
            stroke-dashoffset: 1000;
            animation: dash 2s linear forwards;
            filter: url(#glow);
        }

        @keyframes dash {
            to { stroke-dashoffset: 0; }
        }

        /* 粒子流 */
        .particle {
            fill: var(--primary-glow);
            filter: url(#glow);
        }

        /* 告警闪烁 */
        .alarm-flash {
            animation: alarm-pulse 1s infinite;
        }

        @keyframes alarm-pulse {
            0% { fill: rgba(255, 62, 62, 0.2); stroke: #ff3e3e; }
            50% { fill: rgba(255, 62, 62, 0.5); stroke: #ff9999; }
            100% { fill: rgba(255, 62, 62, 0.2); stroke: #ff3e3e; }
        }

        /* 控制台样式 */
        #console {
            position: absolute;
            bottom: 20px;
            right: 20px;
            width: 350px;
            height: 180px;
            background: rgba(0, 10, 20, 0.8);
            border-left: 3px solid var(--primary-glow);
            padding: 15px;
            font-family: 'Consolas', monospace;
            font-size: 12px;
            color: #00ff9d;
            overflow-y: hidden;
            box-shadow: 0 5px 15px rgba(0,0,0,0.5);
        }

        .log-entry {
            margin-bottom: 5px;
            opacity: 0;
            transform: translateX(10px);
            animation: log-in 0.3s forwards;
        }

        @keyframes log-in {
            to { opacity: 1; transform: translateX(0); }
        }

        /* 顶部标题 */
        #header {
            position: absolute;
            top: 30px;
            left: 40px;
        }

        #header h1 {
            margin: 0;
            font-size: 28px;
            letter-spacing: 3px;
            background: linear-gradient(90deg, #00f2ff, #00ff9d);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            text-transform: uppercase;
        }

        #header p {
            margin: 5px 0 0 0;
            color: #4a6a8a;
            font-size: 14px;
            letter-spacing: 1px;
        }

        .status-badge {
            display: inline-block;
            padding: 2px 8px;
            border-radius: 4px;
            font-size: 10px;
            margin-left: 10px;
            vertical-align: middle;
            border: 1px solid currentColor;
        }
    </style>
</head>
<body>

<div id="app-container">
    <div id="header">
        <h1>SOC 威胁告警智能化处置流</h1>
        <p>INTELLIGENT THREAT DETECTION & RESPONSE SYSTEM <span id="system-status" class="status-badge" style="color:#00ff9d">系统运行正常</span></p>
    </div>

    <svg class="canvas-svg" viewBox="0 0 1200 700">
        <defs>
            <filter id="glow">
                <feGaussianBlur stdDeviation="2.5" result="coloredBlur"/>
                <feMerge>
                    <feMergeNode in="coloredBlur"/>
                    <feMergeNode in="SourceGraphic"/>
                </feMerge>
            </filter>
            
            <marker id="arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto">
                <path d="M 0 0 L 10 5 L 0 10 z" fill="var(--line-color)" />
            </marker>

            <!-- 渐变定义 -->
            <linearGradient id="grad-blue" x1="0%" y1="0%" x2="100%" y2="100%">
                <stop offset="0%" style="stop-color:#00c6ff;stop-opacity:0.2" />
                <stop offset="100%" style="stop-color:#0072ff;stop-opacity:0.1" />
            </linearGradient>
        </defs>

        <!-- 背景装饰网格 -->
        <g opacity="0.1">
            <path d="M 0 100 L 1200 100 M 0 200 L 1200 200 M 0 300 L 1200 300 M 0 400 L 1200 400 M 0 500 L 1200 500 M 0 600 L 1200 600" stroke="#00f2ff" stroke-width="1" fill="none"/>
            <path d="M 100 0 L 100 700 M 200 0 L 200 700 M 300 0 L 300 700 M 400 0 L 400 700 M 500 0 L 500 700 M 600 0 L 600 700 M 700 0 L 700 700 M 800 0 L 800 700 M 900 0 L 900 700 M 1000 0 L 1000 700 M 1100 0 L 1100 700" stroke="#00f2ff" stroke-width="1" fill="none"/>
        </g>

        <!-- 流程连线层 -->
        <g id="links-layer">
            <!-- Ingress to Monitor -->
            <path id="path1" d="M 150 350 L 250 350" class="flow-path" marker-end="url(#arrow)"/>
            <!-- Monitor to Engine -->
            <path id="path2" d="M 410 350 L 490 350" class="flow-path" marker-end="url(#arrow)"/>
            <!-- Engine to Decision -->
            <path id="path3" d="M 650 350 L 730 350" class="flow-path" marker-end="url(#arrow)"/>
            
            <!-- Decision to Auto (Up) -->
            <path id="path-auto" d="M 810 310 L 810 210 L 890 210" class="flow-path" marker-end="url(#arrow)"/>
            <!-- Decision to Manual (Down) -->
            <path id="path-manual" d="M 810 390 L 810 490 L 890 490" class="flow-path" marker-end="url(#arrow)"/>

            <!-- Auto to Report -->
            <path id="path-report1" d="M 1050 210 L 1090 210 L 1090 310" class="flow-path" marker-end="url(#arrow)"/>
            <!-- Manual to Report -->
            <path id="path-report2" d="M 1050 490 L 1090 490 L 1090 390" class="flow-path" marker-end="url(#arrow)"/>
        </g>

        <!-- 节点层 -->
        <g id="nodes-layer">
            <!-- 1. 流量入口 -->
            <g transform="translate(40, 310)">
                <rect width="110" height="80" rx="5" class="node-rect" />
                <text x="55" y="40" class="node-title">流量输入</text>
                <text x="55" y="62" class="node-label">Ingress Traffic</text>
            </g>

            <!-- 2. 实时监测 -->
            <g id="node-monitor" transform="translate(250, 310)">
                <rect width="160" height="80" rx="5" class="node-rect" />
                <text x="80" y="40" class="node-title">实时行为监测</text>
                <text x="80" y="62" class="node-label">Monitoring</text>
            </g>

            <!-- 3. 分析引擎 -->
            <g id="node-engine" transform="translate(490, 310)">
                <rect width="160" height="80" rx="5" class="node-rect" />
                <text x="80" y="40" class="node-title">AI 安全研判</text>
                <text x="80" y="62" class="node-label">Security Engine</text>
            </g>

            <!-- 4. 决策中心 -->
            <g id="node-decision" transform="translate(730, 310)">
                <rect width="160" height="80" rx="5" class="node-rect" />
                <text x="80" y="40" class="node-title">威胁等级决策</text>
                <text x="80" y="62" class="node-label">Decision</text>
            </g>

            <!-- 5. 自动拦截 -->
            <g id="node-auto" transform="translate(890, 170)">
                <rect width="160" height="80" rx="5" class="node-rect" />
                <text x="80" y="40" class="node-title">自动化拦截</text>
                <text x="80" y="62" class="node-label">Auto Blocking</text>
            </g>

            <!-- 6. 人工处理 -->
            <g id="node-manual" transform="translate(890, 450)">
                <rect width="160" height="80" rx="5" class="node-rect" />
                <text x="80" y="40" class="node-title">人工介入处理</text>
                <text x="80" y="62" class="node-label">Manual Handling</text>
            </g>

            <!-- 7. 事件报告 -->
            <g id="node-report" transform="translate(1010, 310)">
                <rect width="160" height="80" rx="5" class="node-rect" />
                <text x="80" y="40" class="node-title">报告与存档</text>
                <text x="80" y="62" class="node-label">Reporting</text>
            </g>
        </g>

        <!-- 动态粒子层 -->
        <g id="particles-layer"></g>
    </svg>

    <div id="console"></div>
</div>

<script>
    const svg = document.querySelector('.canvas-svg');
    const consoleEl = document.getElementById('console');
    const particlesLayer = document.getElementById('particles-layer');
    const sysStatus = document.getElementById('system-status');

    const nodes = {
        monitor: document.getElementById('node-monitor'),
        engine: document.getElementById('node-engine'),
        decision: document.getElementById('node-decision'),
        auto: document.getElementById('node-auto'),
        manual: document.getElementById('node-manual'),
        report: document.getElementById('node-report')
    };

    const paths = {
        p1: document.getElementById('path1'),
        p2: document.getElementById('path2'),
        p3: document.getElementById('path3'),
        pAuto: document.getElementById('path-auto'),
        pManual: document.getElementById('path-manual'),
        pReport1: document.getElementById('path-report1'),
        pReport2: document.getElementById('path-report2')
    };

    function addLog(msg, type = 'info') {
        const entry = document.createElement('div');
        entry.className = 'log-entry';
        const time = new Date().toLocaleTimeString().split(' ')[0];
        let color = '#00ff9d';
        if (type === 'warn') color = '#ffbb00';
        if (type === 'error') color = '#ff3e3e';
        
        entry.innerHTML = `<span style="color:#4a6a8a">[${time}]</span> <span style="color:${color}">${msg}</span>`;
        consoleEl.prepend(entry);
        if (consoleEl.children.length > 8) consoleEl.lastElementChild.remove();
    }

    function resetAll() {
        Object.values(nodes).forEach(n => n.querySelector('rect').classList.remove('node-active', 'alarm-flash'));
        Object.values(paths).forEach(p => p.classList.remove('flow-path-active'));
        sysStatus.textContent = '系统运行正常';
        sysStatus.style.color = '#00ff9d';
    }

    async function wait(ms) { return new Promise(r => setTimeout(r, ms)); }

    function createParticle(pathEl, color = 'var(--primary-glow)') {
        const particle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
        particle.setAttribute('r', '4');
        particle.setAttribute('fill', color);
        particle.setAttribute('filter', 'url(#glow)');
        particlesLayer.appendChild(particle);

        const length = pathEl.getTotalLength();
        let start = null;
        const duration = 1500;

        function step(timestamp) {
            if (!start) start = timestamp;
            const progress = (timestamp - start) / duration;
            if (progress < 1) {
                const point = pathEl.getPointAtLength(progress * length);
                particle.setAttribute('cx', point.x);
                particle.setAttribute('cy', point.y);
                requestAnimationFrame(step);
            } else {
                particle.remove();
            }
        }
        requestAnimationFrame(step);
    }

    async function runFlow(isHighRisk = true) {
        resetAll();
        
        // 1. 流量监测
        addLog("正在扫描实时网络流量...", "info");
        paths.p1.classList.add('flow-path-active');
        createParticle(paths.p1);
        await wait(1000);
        nodes.monitor.querySelector('rect').classList.add('node-active');
        
        // 2. 发现异常
        await wait(800);
        addLog("检测到异常流量行为模式!", "warn");
        nodes.monitor.querySelector('rect').classList.add('alarm-flash');
        sysStatus.textContent = '发现威胁告警';
        sysStatus.style.color = '#ff3e3e';
        
        // 3. 传导至引擎
        paths.p2.classList.add('flow-path-active');
        createParticle(paths.p2, '#ff3e3e');
        await wait(1200);
        nodes.engine.querySelector('rect').classList.add('node-active');
        addLog("AI 安全引擎正在深度研判...", "info");
        
        // 4. 决策
        await wait(1500);
        paths.p3.classList.add('flow-path-active');
        createParticle(paths.p3);
        await wait(1000);
        nodes.decision.querySelector('rect').classList.add('node-active');

        if (isHighRisk) {
            // 自动化路径
            addLog("研判结果：高危攻击。触发自动拦截机制。", "error");
            paths.pAuto.classList.add('flow-path-active');
            createParticle(paths.pAuto, '#ff3e3e');
            await wait(1500);
            nodes.auto.querySelector('rect').classList.add('node-active');
            addLog("防火墙已封禁来源 IP，连接已阻断。", "info");
            
            await wait(1000);
            paths.pReport1.classList.add('flow-path-active');
            createParticle(paths.pReport1);
            await wait(1500);
        } else {
            // 人工路径
            addLog("研判结果：可疑行为。下发安全专家人工审计。", "warn");
            paths.pManual.classList.add('flow-path-active');
            createParticle(paths.pManual, '#ffbb00');
            await wait(1500);
            nodes.manual.querySelector('rect').classList.add('node-active');
            addLog("安全专家已介入，正在核实事件详情...", "info");
            await wait(2000);
            addLog("专家处理完毕：确认为误报，已添加白名单。", "info");
            
            paths.pReport2.classList.add('flow-path-active');
            createParticle(paths.pReport2);
            await wait(1500);
        }

        // 5. 归档
        nodes.report.querySelector('rect').classList.add('node-active');
        addLog("事件处置报告已生成，数据已存入 SOC 数据库。", "success");
        await wait(3000);
        
        // 循环
        runFlow(!isHighRisk);
    }

    // 初始化背景流量
    function spawnBackgroundParticles() {
        setInterval(() => {
            if (!sysStatus.textContent.includes('威胁')) {
                createParticle(paths.p1);
            }
        }, 2000);
    }

    window.onload = () => {
        spawnBackgroundParticles();
        runFlow(true);
    };
</script>

</body>
</html>23:T3ea7,<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>数据分析平台全链路流程可视化</title>
    <style>
        :root {
            --bg-color: #05080a;
            --primary-blue: #00d2ff;
            --process-teal: #00f2ff;
            --storage-purple: #a855f7;
            --ai-gold: #fbbf24;
            --success-green: #22c55e;
            --text-main: #f8fafc;
            --text-dim: #94a3b8;
            --node-bg: rgba(15, 23, 42, 0.8);
            --font-family: 'PingFang SC', 'Microsoft YaHei', -apple-system, sans-serif;
        }

        * { box-sizing: border-box; }
        body, html {
            margin: 0; padding: 0;
            width: 100%; height: 100%;
            background-color: var(--bg-color);
            color: var(--text-main);
            font-family: var(--font-family);
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        #app-container {
            position: relative;
            width: 1200px;
            height: 700px;
            background: radial-gradient(circle at center, #0f172a 0%, #05080a 100%);
            border: 1px solid #1e293b;
            box-shadow: 0 0 100px rgba(0,0,0,0.8);
            overflow: hidden;
        }

        .svg-canvas {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: 1;
        }

        /* 顶部装饰 */
        .header {
            position: absolute;
            top: 30px;
            left: 40px;
            z-index: 10;
        }
        .header h1 {
            margin: 0;
            font-size: 28px;
            font-weight: 300;
            letter-spacing: 4px;
            background: linear-gradient(90deg, var(--primary-blue), #fff);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            text-transform: uppercase;
        }
        .header .sub-title {
            color: var(--text-dim);
            font-size: 14px;
            margin-top: 8px;
            letter-spacing: 1px;
        }

        /* 状态指示器 */
        #status-panel {
            position: absolute;
            bottom: 30px;
            right: 40px;
            width: 350px;
            background: rgba(15, 23, 42, 0.9);
            border-left: 4px solid var(--primary-blue);
            padding: 20px;
            border-radius: 4px;
            font-size: 14px;
            backdrop-filter: blur(10px);
            z-index: 10;
            box-shadow: 0 10px 25px rgba(0,0,0,0.5);
        }
        #status-title {
            color: var(--primary-blue);
            font-weight: bold;
            margin-bottom: 8px;
            display: flex;
            align-items: center;
        }
        #status-desc {
            color: var(--text-main);
            line-height: 1.6;
        }

        /* 节点样式 */
        .node-rect {
            fill: var(--node-bg);
            stroke: #334155;
            stroke-width: 1.5;
            transition: all 0.5s ease;
        }
        .node-active {
            stroke: var(--primary-blue);
            filter: drop-shadow(0 0 8px var(--primary-blue));
        }
        .node-label {
            font-size: 14px;
            fill: var(--text-main);
            pointer-events: none;
        }
        .node-sub-label {
            font-size: 11px;
            fill: var(--text-dim);
            pointer-events: none;
        }

        /* 连线样式 */
        .flow-path {
            fill: none;
            stroke: #1e293b;
            stroke-width: 2;
            stroke-dasharray: 5,5;
        }
        .flow-path-active {
            stroke: var(--primary-blue);
            stroke-dasharray: 1000;
            stroke-dashoffset: 1000;
            animation: dashDraw 2s forwards ease-in-out;
        }
        @keyframes dashDraw {
            to { stroke-dashoffset: 0; }
        }

        /* 粒子流 */
        .particle {
            fill: var(--primary-blue);
            filter: blur(1px);
        }

        /* 图标样式 */
        .icon-box {
            fill: var(--text-dim);
            transition: fill 0.5s;
        }
        .node-active .icon-box {
            fill: var(--primary-blue);
        }
    </style>
</head>
<body>

<div id="app-container">
    <div class="header">
        <h1>智能数据分析平台工作流</h1>
        <div class="sub-title">DATA ANALYSIS PLATFORM WORKFLOW ARCHITECTURE</div>
    </div>

    <svg class="svg-canvas" id="main-svg" viewBox="0 0 1200 700">
        <defs>
            <filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
                <feGaussianBlur stdDeviation="4" result="blur" />
                <feComposite in="SourceGraphic" in2="blur" operator="over" />
            </filter>
            
            <linearGradient id="grad-blue" x1="0%" y1="0%" x2="100%" y2="0%">
                <stop offset="0%" style="stop-color:#00d2ff;stop-opacity:0.1" />
                <stop offset="100%" style="stop-color:#00d2ff;stop-opacity:0.5" />
            </linearGradient>

            <!-- 常用图标 -->
            <symbol id="icon-web" viewBox="0 0 24 24">
                <path d="M12,2L4.5,20.29L5.21,21L12,18L18.79,21L19.5,20.29L12,2Z" />
            </symbol>
            <symbol id="icon-app" viewBox="0 0 24 24">
                <path d="M17,1H7A2,2 0 0,0 5,3V21A2,2 0 0,0 7,23H17A2,2 0 0,0 19,21V3A2,2 0 0,0 17,1M17,19H7V5H17V19Z" />
            </symbol>
            <symbol id="icon-db" viewBox="0 0 24 24">
                <path d="M12,3C7.58,3 4,4.79 4,7C4,9.21 7.58,11 12,11C16.42,11 20,9.21 20,7C20,4.79 16.42,3 12,3M4,9V12C4,14.21 7.58,16 12,16C16.42,16 20,14.21 20,12V9C20,11.21 16.42,13 12,13C7.58,13 4,11.21 4,9M4,14V17C4,19.21 7.58,21 12,21C16.42,21 20,19.21 20,17V14C20,16.21 16.42,18 12,18C7.58,18 4,16.21 4,14Z" />
            </symbol>
            <symbol id="icon-etl" viewBox="0 0 24 24">
                <path d="M12,6V9L16,5L12,1V4A8,8 0 0,0 4,12C4,13.57 4.46,15.03 5.24,16.26L6.7,14.8C6.25,13.97 6,13.03 6,12A6,6 0 0,1 12,6M18.76,7.74L17.3,9.2C17.74,10.04 18,10.97 18,12A6,6 0 0,1 12,18V15L8,19L12,23V20A8,8 0 0,0 20,12C20,10.43 19.54,8.97 18.76,7.74Z" />
            </symbol>
            <symbol id="icon-ai" viewBox="0 0 24 24">
                <path d="M13,3V9H21V3H13M15,5H19V7H15V5M3,13V19H11V13H3M5,15H9V17H5V15M13,13V21H21V13H13M15,15H19V19H15V15M3,3V11H11V3H3M5,5H9V9H5V5Z" />
            </symbol>
            <symbol id="icon-chart" viewBox="0 0 24 24">
                <path d="M16,11.78L20.24,4.45L21.97,5.45L16.74,14.5L10.23,10.75L5.46,19H22V21H2V3H4V17.54L9.5,8L16,11.78Z" />
            </symbol>
            <symbol id="icon-decision" viewBox="0 0 24 24">
                <path d="M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M11,16.5L6.5,12L7.91,10.59L11,13.67L16.59,8.09L18,9.5L11,16.5Z" />
            </symbol>
        </defs>

        <!-- 背景网格 -->
        <g opacity="0.1">
            <path d="M 0 350 L 1200 350 M 600 0 L 600 700" stroke="var(--primary-blue)" stroke-width="1"/>
            <circle cx="600" cy="350" r="300" fill="none" stroke="var(--primary-blue)" stroke-width="0.5"/>
        </g>

        <!-- 连线组 -->
        <g id="paths-group"></g>

        <!-- 节点组 -->
        <g id="nodes-group"></g>

        <!-- 动画粒子组 -->
        <g id="particles-group"></g>
    </svg>

    <div id="status-panel">
        <div id="status-title">系统就绪</div>
        <div id="status-desc">等待启动数据分析流程...</div>
    </div>
</div>

<script>
    const svg = document.getElementById('main-svg');
    const nodesGroup = document.getElementById('nodes-group');
    const pathsGroup = document.getElementById('paths-group');
    const particlesGroup = document.getElementById('particles-group');
    const statusTitle = document.getElementById('status-title');
    const statusDesc = document.getElementById('status-desc');

    const NODES = [
        // 数据源
        { id: 'src_web', x: 100, y: 150, title: '网站日志', sub: 'WEB Traffic', icon: '#icon-web', group: 'source' },
        { id: 'src_app', x: 100, y: 350, title: '移动终端', sub: 'Mobile App', icon: '#icon-app', group: 'source' },
        { id: 'src_db', x: 100, y: 550, title: '业务数据库', sub: 'OLTP DB', icon: '#icon-db', group: 'source' },
        // 处理层
        { id: 'etl', x: 380, y: 350, title: '接入与清洗', sub: 'ETL / Cleaning', icon: '#icon-etl' },
        // 存储层
        { id: 'dw', x: 650, y: 350, title: '数据仓库', sub: 'Data Warehouse', icon: '#icon-db' },
        // 分析层
        { id: 'ai', x: 920, y: 350, title: '建模与分析', sub: 'ML & Analytics', icon: '#icon-ai' },
        // 结果层
        { id: 'viz', x: 1100, y: 250, title: '可视化', sub: 'BI Dashboard', icon: '#icon-chart' },
        { id: 'decision', x: 1100, y: 450, title: '业务决策', sub: 'Decision Support', icon: '#icon-decision' }
    ];

    const LINKS = [
        { from: 'src_web', to: 'etl' },
        { from: 'src_app', to: 'etl' },
        { from: 'src_db', to: 'etl' },
        { from: 'etl', to: 'dw' },
        { from: 'dw', to: 'ai' },
        { from: 'ai', to: 'viz' },
        { from: 'ai', to: 'decision' }
    ];

    const nodeMap = {};

    function init() {
        // 绘制节点
        NODES.forEach(node => {
            const g = document.createElementNS("http://www.w3.org/2000/svg", "g");
            g.setAttribute("transform", `translate(${node.x},${node.y})`);
            g.setAttribute("id", `node-${node.id}`);
            
            const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
            rect.setAttribute("x", "-70");
            rect.setAttribute("y", "-40");
            rect.setAttribute("width", "140");
            rect.setAttribute("height", "80");
            rect.setAttribute("rx", "8");
            rect.setAttribute("class", "node-rect");
            
            const icon = document.createElementNS("http://www.w3.org/2000/svg", "use");
            icon.setAttribute("href", node.icon);
            icon.setAttribute("x", "-15");
            icon.setAttribute("y", "-30");
            icon.setAttribute("width", "30");
            icon.setAttribute("height", "30");
            icon.setAttribute("class", "icon-box");

            const text = document.createElementNS("http://www.w3.org/2000/svg", "text");
            text.setAttribute("class", "node-label");
            text.setAttribute("y", "15");
            text.setAttribute("text-anchor", "middle");
            text.textContent = node.title;

            const subText = document.createElementNS("http://www.w3.org/2000/svg", "text");
            subText.setAttribute("class", "node-sub-label");
            subText.setAttribute("y", "32");
            subText.setAttribute("text-anchor", "middle");
            subText.textContent = node.sub;

            g.appendChild(rect);
            g.appendChild(icon);
            g.appendChild(text);
            g.appendChild(subText);
            nodesGroup.appendChild(g);
            nodeMap[node.id] = node;
        });

        // 绘制连线
        LINKS.forEach((link, idx) => {
            const from = nodeMap[link.from];
            const to = nodeMap[link.to];
            const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
            
            // 贝塞尔曲线
            const dx = to.x - from.x;
            const dy = to.y - from.y;
            const d = `M ${from.x + 70} ${from.y} C ${from.x + 150} ${from.y}, ${to.x - 150} ${to.y}, ${to.x - 70} ${to.y}`;
            
            path.setAttribute("d", d);
            path.setAttribute("class", "flow-path");
            path.setAttribute("id", `link-${idx}`);
            pathsGroup.appendChild(path);
            link.pathEl = path;
        });

        startAnimationCycle();
    }

    async function startAnimationCycle() {
        while(true) {
            resetAll();
            await wait(1000);

            // Step 1: Data Ingestion
            updateStatus("数据采集阶段", "正在从网站、App和数据库获取原始数据流...");
            highlightNodes(['src_web', 'src_app', 'src_db']);
            await animateParticles([0, 1, 2]);
            await wait(500);

            // Step 2: ETL
            updateStatus("接入与清洗", "ETL引擎正在对数据进行去重、缺失值填充和格式标准化。");
            highlightNodes(['etl']);
            await wait(1000);
            await animateParticles([3]);

            // Step 3: Warehouse
            updateStatus("数据入库", "清洗后的数据已存入分布式数据仓库，支持高并发查询。");
            highlightNodes(['dw']);
            await wait(1000);
            await animateParticles([4]);

            // Step 4: Modeling
            updateStatus("建模与分析", "机器学习模型正在运行，执行特征工程与预测分析。");
            highlightNodes(['ai']);
            await wait(1500);
            await animateParticles([5, 6]);

            // Step 5: Output
            updateStatus("决策支持", "分析结果已转化为可视化报表，为业务部门提供决策依据。");
            highlightNodes(['viz', 'decision']);
            await wait(3000);
        }
    }

    function highlightNodes(ids) {
        ids.forEach(id => {
            const el = document.querySelector(`#node-${id} .node-rect`);
            el.classList.add('node-active');
        });
    }

    function resetAll() {
        document.querySelectorAll('.node-rect').forEach(el => el.classList.remove('node-active'));
        document.querySelectorAll('.flow-path').forEach(el => el.classList.remove('flow-path-active'));
        particlesGroup.innerHTML = '';
    }

    function updateStatus(title, desc) {
        statusTitle.textContent = title;
        statusDesc.textContent = desc;
    }

    function animateParticles(linkIndices) {
        return new Promise(resolve => {
            let completed = 0;
            linkIndices.forEach(idx => {
                const link = LINKS[idx];
                link.pathEl.classList.add('flow-path-active');
                
                // 生成多个粒子
                for(let i=0; i<5; i++) {
                    setTimeout(() => {
                        createParticle(link.pathEl, () => {
                            if(i === 4) {
                                completed++;
                                if(completed === linkIndices.length) resolve();
                            }
                        });
                    }, i * 200);
                }
            });
        });
    }

    function createParticle(pathEl, onComplete) {
        const particle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
        particle.setAttribute("r", "3");
        particle.setAttribute("class", "particle");
        particle.setAttribute("filter", "url(#glow)");
        particlesGroup.appendChild(particle);

        const length = pathEl.getTotalLength();
        let start = null;
        const duration = 1500;

        function step(timestamp) {
            if (!start) start = timestamp;
            const progress = (timestamp - start) / duration;
            const currentLen = progress * length;

            if (progress < 1) {
                const point = pathEl.getPointAtLength(currentLen);
                particle.setAttribute("cx", point.x);
                particle.setAttribute("cy", point.y);
                requestAnimationFrame(step);
            } else {
                particle.remove();
                if(onComplete) onComplete();
            }
        }
        requestAnimationFrame(step);
    }

    function wait(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    window.onload = init;
</script>
</body>
</html>24:T3a94,<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>AI 问答系统工作流动画</title>
    <style>
        :root {
            --bg-color: #030712;
            --card-bg: rgba(17, 24, 39, 0.8);
            --accent-primary: #3b82f6; /* 科技蓝 */
            --accent-secondary: #10b981; /* 成功绿 */
            --accent-glow: #6366f1; /* 紫蓝 */
            --text-main: #f3f4f6;
            --text-dim: #9ca3af;
            --border-color: #1f2937;
        }

        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            background-color: var(--bg-color);
            color: var(--text-main);
            font-family: 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        #app-container {
            position: relative;
            width: 1200px;
            height: 700px;
            background: radial-gradient(circle at 50% 50%, #0f172a 0%, #030712 100%);
            overflow: hidden;
            border: 1px solid var(--border-color);
            box-shadow: 0 0 60px rgba(0,0,0,0.8);
        }

        .canvas-svg {
            width: 100%;
            height: 100%;
        }

        /* 节点样式 */
        .node-rect {
            fill: var(--card-bg);
            stroke: var(--border-color);
            stroke-width: 2;
            rx: 12;
        }

        .node-active {
            stroke: var(--accent-primary);
            filter: url(#glow);
            transition: all 0.5s ease;
        }

        .label-title {
            font-size: 16px;
            font-weight: 600;
            fill: var(--text-main);
            pointer-events: none;
        }

        .label-desc {
            font-size: 12px;
            fill: var(--text-dim);
            pointer-events: none;
        }

        /* 连线样式 */
        .flow-line {
            fill: none;
            stroke: var(--border-color);
            stroke-width: 2;
            stroke-dasharray: 6 4;
        }

        .flow-active {
            stroke: var(--accent-primary);
            stroke-dashoffset: 100;
            animation: flowMove 2s linear infinite;
        }

        @keyframes flowMove {
            to { stroke-dashoffset: 0; }
        }

        /* 数据粒子 */
        .particle {
            fill: var(--accent-primary);
            filter: url(#glow);
        }

        /* 顶部装饰 */
        #header {
            position: absolute;
            top: 30px;
            left: 50%;
            transform: translateX(-50%);
            text-align: center;
            z-index: 10;
        }

        #header h1 {
            margin: 0;
            font-size: 28px;
            letter-spacing: 4px;
            background: linear-gradient(90deg, #3b82f6, #10b981);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            text-transform: uppercase;
        }

        #header p {
            margin: 8px 0 0 0;
            color: var(--text-dim);
            font-size: 14px;
        }

        /* 实时状态面板 */
        #status-panel {
            position: absolute;
            bottom: 40px;
            left: 50%;
            transform: translateX(-50%);
            width: 800px;
            background: rgba(15, 23, 42, 0.9);
            border-top: 2px solid var(--accent-primary);
            padding: 20px;
            border-radius: 4px;
            font-family: monospace;
            box-shadow: 0 -10px 30px rgba(0,0,0,0.5);
        }

        .status-line {
            height: 24px;
            line-height: 24px;
            font-size: 14px;
            color: var(--accent-secondary);
        }

        .cursor {
            display: inline-block;
            width: 8px;
            height: 16px;
            background: var(--accent-secondary);
            margin-left: 5px;
            animation: blink 0.8s infinite;
        }

        @keyframes blink { 50% { opacity: 0; } }

        /* 图标样式 */
        .icon-svg {
            fill: var(--accent-primary);
        }
    </style>
</head>
<body>

<div id="app-container">
    <div id="header">
        <h1>AI 问答系统工作流</h1>
        <p>从输入到生成的全链路闭环演示</p>
    </div>

    <svg class="canvas-svg" viewBox="0 0 1200 700">
        <defs>
            <filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
                <feGaussianBlur stdDeviation="4" result="blur" />
                <feComposite in="SourceGraphic" in2="blur" operator="over" />
            </filter>
            
            <marker id="arrowhead" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto">
                <path d="M 0 0 L 10 5 L 0 10 z" fill="var(--accent-primary)" />
            </marker>

            <!-- 图标定义 -->
            <symbol id="icon-user" viewBox="0 0 24 24">
                <path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/>
            </symbol>
            <symbol id="icon-brain" viewBox="0 0 24 24">
                <path d="M9.5 3A6.5 6.5 0 0 0 3 9.5c0 2.82 1.83 5.21 4.3 6.05L7 17a1 1 0 0 0 1 1h1a1 1 0 0 0 1-1v-1h1a1 1 0 0 0 1-1v-1h2v2h-1v1h1v1h-1v1h1v1h1a1 1 0 0 0 1-1v-2h1a1 1 0 0 0 1-1v-1.05c2.47-.84 4.3-3.23 4.3-6.05A6.5 6.5 0 0 0 14.5 3h-5z"/>
            </symbol>
            <symbol id="icon-db" viewBox="0 0 24 24">
                <path d="M12 2C9.24 2 7 3.34 7 5s2.24 3 5 3 5-1.34 5-3-2.24-3-5-3zm0 14c-2.76 0-5-1.34-5-3v2c0 1.66 2.24 3 5 3s5-1.34 5-3v-2c0 1.66-2.24 3-5 3zM7 10c0 1.66 2.24 3 5 3s5-1.34 5-3V8c0 1.66-2.24 3-5 3s-5-1.34-5-3v2z"/>
            </symbol>
            <symbol id="icon-api" viewBox="0 0 24 24">
                <path d="M12 2L4 5v11c0 5.25 3.42 10.16 8 11.5 4.58-1.34 8-6.25 8-11.5V5l-8-3zm-1 14.5h2v2h-2v-2zm0-8.5h2v6h-2V8z"/>
            </symbol>
        </defs>

        <!-- 连线层 -->
        <g id="links-group"></g>

        <!-- 节点层 -->
        <g id="nodes-group">
            <!-- 1. 用户输入 -->
            <g id="node-0" transform="translate(100, 280)">
                <rect class="node-rect" width="180" height="100" />
                <use href="#icon-user" x="70" y="10" width="40" height="40" class="icon-svg" />
                <text x="90" y="70" text-anchor="middle" class="label-title">用户输入</text>
                <text x="90" y="88" text-anchor="middle" class="label-desc">提交问题或指令</text>
            </g>

            <!-- 2. 请求解析 -->
            <g id="node-1" transform="translate(360, 280)">
                <rect class="node-rect" width="180" height="100" />
                <use href="#icon-api" x="75" y="10" width="30" height="30" class="icon-svg" />
                <text x="90" y="70" text-anchor="middle" class="label-title">请求解析器</text>
                <text x="90" y="88" text-anchor="middle" class="label-desc">意图识别与预处理</text>
            </g>

            <!-- 3. LLM 语义理解 -->
            <g id="node-2" transform="translate(620, 280)">
                <rect class="node-rect" width="180" height="100" />
                <use href="#icon-brain" x="75" y="10" width="30" height="30" class="icon-svg" />
                <text x="90" y="70" text-anchor="middle" class="label-title">LLM 模型</text>
                <text x="90" y="88" text-anchor="middle" class="label-desc">语义分析与理解</text>
            </g>

            <!-- 4. 知识库检索 -->
            <g id="node-3" transform="translate(620, 480)">
                <rect class="node-rect" width="180" height="100" />
                <use href="#icon-db" x="75" y="10" width="30" height="30" class="icon-svg" />
                <text x="90" y="70" text-anchor="middle" class="label-title">向量知识库</text>
                <text x="90" y="88" text-anchor="middle" class="label-desc">检索 RAG 关联内容</text>
            </g>

            <!-- 5. 答案生成 -->
            <g id="node-4" transform="translate(880, 280)">
                <rect class="node-rect" width="180" height="100" />
                <circle cx="90" cy="30" r="15" fill="var(--accent-secondary)" opacity="0.3" />
                <text x="90" y="35" text-anchor="middle" fill="var(--accent-secondary)" font-size="20">AI</text>
                <text x="90" y="70" text-anchor="middle" class="label-title">生成引擎</text>
                <text x="90" y="88" text-anchor="middle" class="label-desc">合成最终回答</text>
            </g>
        </g>

        <!-- 动态粒子层 -->
        <g id="particles-group"></g>
    </svg>

    <div id="status-panel">
        <div id="status-text" class="status-line">系统就绪，等待用户输入...</div>
    </div>
</div>

<script>
    const NODE_CONFIG = [
        { id: 0, x: 100, y: 280, w: 180, h: 100, title: "用户输入" },
        { id: 1, x: 360, y: 280, w: 180, h: 100, title: "请求解析器" },
        { id: 2, x: 620, y: 280, w: 180, h: 100, title: "LLM 模型" },
        { id: 3, x: 620, y: 480, w: 180, h: 100, title: "向量知识库" },
        { id: 4, x: 880, y: 280, w: 180, h: 100, title: "生成引擎" }
    ];

    const FLOW_PATH = [
        { from: 0, to: 1, type: 'forward' },
        { from: 1, to: 2, type: 'forward' },
        { from: 2, to: 3, type: 'request' },
        { from: 3, to: 4, type: 'retrieve' },
        { from: 2, to: 4, type: 'forward' },
        { from: 4, to: 0, type: 'return' }
    ];

    const statusText = document.getElementById('status-text');
    const linksGroup = document.getElementById('links-group');
    const particlesGroup = document.getElementById('particles-group');

    function initLines() {
        FLOW_PATH.forEach((path, index) => {
            const from = NODE_CONFIG[path.from];
            const to = NODE_CONFIG[path.to];
            const line = document.createElementNS('http://www.w3.org/2000/svg', 'path');
            
            let d = "";
            const startX = from.x + from.w;
            const startY = from.y + from.h/2;
            const endX = to.x;
            const endY = to.y + to.h/2;

            if (path.type === 'return') {
                // 特殊处理返回路径：从底部绕回
                d = `M ${from.x + from.w/2} ${from.y + from.h} L ${from.x + from.w/2} 620 L ${to.x + to.w/2} 620 L ${to.x + to.w/2} ${to.y + to.h}`;
            } else if (path.type === 'request') {
                d = `M ${from.x + from.w/2} ${from.y + from.h} L ${to.x + to.w/2} ${to.y}`;
            } else if (path.type === 'retrieve') {
                d = `M ${from.x + from.w} ${from.y + from.h/2} C ${from.x + from.w + 50} ${from.y + from.h/2}, ${to.x - 50} ${to.y + to.h/2}, ${to.x} ${to.y + to.h/2}`;
            } else {
                d = `M ${startX} ${startY} L ${endX} ${endY}`;
            }

            line.setAttribute('d', d);
            line.setAttribute('id', `path-${index}`);
            line.setAttribute('class', 'flow-line');
            linksGroup.appendChild(line);
        });
    }

    async function updateStatus(text) {
        statusText.innerHTML = `> ${text}<span class="cursor"></span>`;
    }

    function highlightNode(id, active) {
        const node = document.querySelector(`#node-${id} rect`);
        if (active) {
            node.classList.add('node-active');
        } else {
            node.classList.remove('node-active');
        }
    }

    function highlightPath(index, active) {
        const path = document.getElementById(`path-${index}`);
        if (active) {
            path.classList.add('flow-active');
        } else {
            path.classList.remove('flow-active');
        }
    }

    async function createParticle(pathIdx, duration = 1000) {
        const path = document.getElementById(`path-${pathIdx}`);
        const particle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
        particle.setAttribute('r', '4');
        particle.setAttribute('class', 'particle');
        particlesGroup.appendChild(particle);

        const length = path.getTotalLength();
        const startTime = performance.now();

        return new Promise(resolve => {
            function anim(time) {
                const progress = (time - startTime) / duration;
                if (progress < 1) {
                    const point = path.getPointAtLength(progress * length);
                    particle.setAttribute('cx', point.x);
                    particle.setAttribute('cy', point.y);
                    requestAnimationFrame(anim);
                } else {
                    particlesGroup.removeChild(particle);
                    resolve();
                }
            }
            requestAnimationFrame(anim);
        });
    }

    async function runWorkflow() {
        // Reset
        NODE_CONFIG.forEach(n => highlightNode(n.id, false));
        for(let i=0; i<FLOW_PATH.length; i++) highlightPath(i, false);

        // Step 1: User Input
        await updateStatus("接收到用户提问: '如何解释量子纠缠？'");
        highlightNode(0, true);
        await new Promise(r => setTimeout(r, 800));
        
        // Step 2: Parser
        highlightPath(0, true);
        await createParticle(0);
        highlightNode(1, true);
        await updateStatus("请求解析中... 识别意图为: [知识查询], 关键词: [量子纠缠]");
        await new Promise(r => setTimeout(r, 1000));

        // Step 3: LLM Understanding
        highlightPath(1, true);
        await createParticle(1);
        highlightNode(2, true);
        await updateStatus("LLM 正在分析语义... 需要补充专业物理背景知识。");
        await new Promise(r => setTimeout(r, 1000));

        // Step 4: RAG Retrieval
        highlightPath(2, true);
        await createParticle(2);
        highlightNode(3, true);
        await updateStatus("正在检索知识库... 匹配到 3 条高相关度专业文献。");
        await new Promise(r => setTimeout(r, 1200));

        // Step 5: Inference
        highlightPath(3, true);
        await createParticle(3);
        highlightPath(4, true);
        await createParticle(4);
        highlightNode(4, true);
        await updateStatus("生成引擎正在结合检索结果与模型能力，推理生成答案...");
        await new Promise(r => setTimeout(r, 1500));

        // Step 6: Return
        highlightPath(5, true);
        await createParticle(5, 1500);
        await updateStatus("回答生成完毕，正在返回客户端。内容：'量子纠缠是一种物理现象...'");
        
        await new Promise(r => setTimeout(r, 3000));
        runWorkflow(); // Loop
    }

    window.onload = () => {
        initLines();
        runWorkflow();
    };
</script>

</body>
</html>2:[["$","$L8",null,{"id":"animation-breadcrumb-jsonld-b8298c3b-c35e-40b0-a834-c03554a58772","type":"application/ld+json","dangerouslySetInnerHTML":{"__html":"{\"@context\":\"https://schema.org\",\"@type\":\"BreadcrumbList\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https://svganimate.ai/en/home\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Gallery\",\"item\":\"https://svganimate.ai/en/gallery\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Create a flat 2.5D tech-style SVG animation for network management demonstration\",\"item\":\"https://svganimate.ai/en/animation/b8298c3b-c35e-40b0-a834-c03554a58772\"}]}"}}],["$","$L8",null,{"id":"animation-creativework-jsonld-b8298c3b-c35e-40b0-a834-c03554a58772","type":"application/ld+json","dangerouslySetInnerHTML":{"__html":"$14"}}],["$","$15",null,{"fallback":null,"children":["$","$L16",null,{"locale":"en","template":{"id":"b8298c3b-c35e-40b0-a834-c03554a58772","exportName":"$undefined","title":"Create a flat 2.5D tech-style SVG animation for network management demonstration","description":"$17","category":"flowchart-animation","tags":[],"likes":0,"favorites":0,"views":2229,"sourceType":"SvgAnimation","componentSource":"$18","isLiked":false,"isFavorited":false},"relatedTemplates":[{"id":"6e715cae-f293-4e63-be72-89156264cd74","exportName":"$undefined","title":"Here is a precise text-to-vide","description":"$19","category":"flowchart-animation","tags":[],"likes":0,"favorites":0,"views":0,"sourceType":"SvgAnimation","componentSource":"$1a","isLiked":false,"isFavorited":false},{"id":"5cb71ba8-136d-4db4-85d7-3f01a025fe3f","exportName":"$undefined","title":"Call flow\n                   L","description":"$1b","category":"flowchart-animation","tags":[],"likes":0,"favorites":0,"views":6,"sourceType":"SvgAnimation","componentSource":"$1c","isLiked":false,"isFavorited":false},{"id":"c4079e46-4678-47f2-badb-a552c8b93ea0","exportName":"$undefined","title":"Create an animated flowchart a","description":"$1d","category":"flowchart-animation","tags":[],"likes":0,"favorites":0,"views":38,"sourceType":"SvgAnimation","componentSource":"$1e","isLiked":false,"isFavorited":false},{"id":"99ad20bb-8e14-4d9d-a697-b509fe011d14","exportName":"$undefined","title":"Rotating Fan","description":"Rotating Fan","category":"flowchart-animation","tags":[],"likes":0,"favorites":0,"views":41,"sourceType":"SvgAnimation","componentSource":"$1f","isLiked":false,"isFavorited":false},{"id":"639e921e-4751-4a45-882e-28e5d7cea2e9","exportName":"$undefined","title":"Modern tech-style web SVG flowchart animation, dark background with cyan-blue and purple","description":"$20","category":"flowchart-animation","tags":[],"likes":0,"favorites":0,"views":381,"sourceType":"SvgAnimation","componentSource":"$21","isLiked":false,"isFavorited":false},{"id":"f45b768c-940f-41cb-9697-0d79cf29bb0d","exportName":"$undefined","title":"Web SVG flowchart animation, specifically demonstrating the network security alarm disposal process: system real-time","description":"Web SVG flowchart animation, specifically demonstrating the network security alarm disposal process: the system monitors network traffic and behavior in real-time, triggers an alarm immediately upon detecting anomalies, the security analysis engine evaluates the event, chooses automatic interception or manual handling by security personnel after judging the threat level, and finally generates an event report and processing record. The flowchart is suitable for network security product official websites or SOC platform introduction pages.","category":"flowchart-animation","tags":[],"likes":0,"favorites":0,"views":350,"sourceType":"SvgAnimation","componentSource":"$22","isLiked":false,"isFavorited":false},{"id":"32966b67-cb9b-49e7-a160-acd74706ec70","exportName":"$undefined","title":"Web SVG flowchart animation, specifically demonstrating the workflow of a data analysis platform: from the web","description":"Web SVG flowchart animation, specifically demonstrating the workflow of a data analysis platform: data from multiple sources such as websites, apps, and databases are integrated into the system, cleaned and standardized, stored in a data warehouse, then processed through analysis and modeling, and finally presented via charts and reports to support business decisions. The flowchart illustrates the complete lifecycle from data collection to decision support.","category":"flowchart-animation","tags":[],"likes":0,"favorites":0,"views":360,"sourceType":"SvgAnimation","componentSource":"$23","isLiked":false,"isFavorited":false},{"id":"7fd0a98b-259a-45ce-9a14-3f2ce80acdaa","exportName":"$undefined","title":"Web SVG flowchart animation, specifically demonstrating the complete workflow of an AI Q&A system: User","description":"Web SVG flowchart animation, specifically demonstrating the complete workflow of an AI Q&A system: the user inputs a question, the system receives and parses it, the large model understands the semantics and retrieves knowledge base content, then generates an answer based on the retrieval results, and finally returns the answer to the user. Each step is represented by clear modules, with lines showing the flow of information, suitable for AI product official websites to demonstrate 'how questions are processed'.","category":"flowchart-animation","tags":[],"likes":0,"favorites":0,"views":320,"sourceType":"SvgAnimation","componentSource":"$24","isLiked":false,"isFavorited":false}],"playbackSourceScope":"public"}]}]]
