yanghao 5 dienas atpakaļ
revīzija
b2b99869ae
64 mainītis faili ar 7037 papildinājumiem un 0 dzēšanām
  1. 39 0
      .gitignore
  2. 3 0
      .vscode/extensions.json
  3. 38 0
      README.md
  4. 14 0
      index.html
  5. 8 0
      jsconfig.json
  6. 25 0
      new-portal/src/App.vue
  7. 52 0
      new-portal/src/components/layout/SideButtons.vue
  8. 24 0
      package.json
  9. 1870 0
      pnpm-lock.yaml
  10. BIN
      public/favicon.ico
  11. 50 0
      src/App.vue
  12. 81 0
      src/assets/base.css
  13. 63 0
      src/assets/illustrations/hero-industrial.svg
  14. 9 0
      src/assets/illustrations/logo-placeholder.svg
  15. 38 0
      src/assets/illustrations/section-data.svg
  16. BIN
      src/assets/images/afterSales.jpg
  17. BIN
      src/assets/images/banner.jpg
  18. BIN
      src/assets/images/banner2.jpg
  19. BIN
      src/assets/images/banner3.jpg
  20. BIN
      src/assets/images/bg-index-3.jpg
  21. BIN
      src/assets/images/bg.jpg
  22. BIN
      src/assets/images/bg2.jpg
  23. BIN
      src/assets/images/bg2.png
  24. BIN
      src/assets/images/foot-bj.jpg
  25. BIN
      src/assets/images/form_back.png
  26. BIN
      src/assets/images/form_img6.png
  27. BIN
      src/assets/images/form_img7.png
  28. BIN
      src/assets/images/indexP8.jpg
  29. BIN
      src/assets/images/index_back2.png
  30. BIN
      src/assets/images/index_img4_backs.png
  31. BIN
      src/assets/images/jiaohu.png
  32. BIN
      src/assets/images/logo.png
  33. BIN
      src/assets/images/title1.png
  34. BIN
      src/assets/images/title2.png
  35. BIN
      src/assets/images/方案.png
  36. BIN
      src/assets/images/案例.png
  37. 222 0
      src/assets/main.css
  38. 44 0
      src/components/HelloWorld.vue
  39. 64 0
      src/components/PageHero.vue
  40. 95 0
      src/components/TheWelcome.vue
  41. 86 0
      src/components/WelcomeItem.vue
  42. 7 0
      src/components/icons/IconCommunity.vue
  43. 7 0
      src/components/icons/IconDocumentation.vue
  44. 7 0
      src/components/icons/IconEcosystem.vue
  45. 7 0
      src/components/icons/IconSupport.vue
  46. 19 0
      src/components/icons/IconTooling.vue
  47. 195 0
      src/components/layout/AppFooter.vue
  48. 237 0
      src/components/layout/AppHeader.vue
  49. 220 0
      src/components/layout/FormBanner.vue
  50. 106 0
      src/components/layout/SideButtons.vue
  51. 64 0
      src/components/motion/BackToTop.vue
  52. 85 0
      src/components/motion/CountUp.vue
  53. 56 0
      src/components/motion/Reveal.vue
  54. 11 0
      src/main.js
  55. 68 0
      src/router/index.js
  56. 210 0
      src/views/AboutView.vue
  57. 202 0
      src/views/CasesView.vue
  58. 211 0
      src/views/ContactView.vue
  59. 2009 0
      src/views/HomeView.vue
  60. 102 0
      src/views/NewsView.vue
  61. 28 0
      src/views/NotFoundView.vue
  62. 147 0
      src/views/ProductsView.vue
  63. 192 0
      src/views/SolutionsView.vue
  64. 22 0
      vite.config.js

+ 39 - 0
.gitignore

@@ -0,0 +1,39 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+.DS_Store
+dist
+dist-ssr
+coverage
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
+
+*.tsbuildinfo
+
+.eslintcache
+
+# Cypress
+/cypress/videos/
+/cypress/screenshots/
+
+# Vitest
+__screenshots__/
+
+# Vite
+*.timestamp-*-*.mjs

+ 3 - 0
.vscode/extensions.json

@@ -0,0 +1,3 @@
+{
+  "recommendations": ["Vue.volar"]
+}

+ 38 - 0
README.md

@@ -0,0 +1,38 @@
+# new-portal
+
+This template should help get you started developing with Vue 3 in Vite.
+
+## Recommended IDE Setup
+
+[VS Code](https://code.visualstudio.com/) + [Vue (Official)](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
+
+## Recommended Browser Setup
+
+- Chromium-based browsers (Chrome, Edge, Brave, etc.):
+  - [Vue.js devtools](https://chromewebstore.google.com/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd)
+  - [Turn on Custom Object Formatter in Chrome DevTools](http://bit.ly/object-formatters)
+- Firefox:
+  - [Vue.js devtools](https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/)
+  - [Turn on Custom Object Formatter in Firefox DevTools](https://fxdx.dev/firefox-devtools-custom-object-formatters/)
+
+## Customize configuration
+
+See [Vite Configuration Reference](https://vite.dev/config/).
+
+## Project Setup
+
+```sh
+pnpm install
+```
+
+### Compile and Hot-Reload for Development
+
+```sh
+pnpm dev
+```
+
+### Compile and Minify for Production
+
+```sh
+pnpm build
+```

+ 14 - 0
index.html

@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+  <head>
+    <meta charset="UTF-8">
+    <link rel="icon" href="/favicon.ico">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="工业互联网门户:面向制造、能源、园区等行业,提供设备接入、数据治理、工业应用与智能分析等能力。">
+    <title>工业互联网门户</title>
+  </head>
+  <body>
+    <div id="app"></div>
+    <script type="module" src="/src/main.js"></script>
+  </body>
+</html>

+ 8 - 0
jsconfig.json

@@ -0,0 +1,8 @@
+{
+  "compilerOptions": {
+    "paths": {
+      "@/*": ["./src/*"]
+    }
+  },
+  "exclude": ["node_modules", "dist"]
+}

+ 25 - 0
new-portal/src/App.vue

@@ -0,0 +1,25 @@
+<script setup>
+import { RouterView } from 'vue-router'
+import AppHeader from './components/layout/AppHeader.vue'
+import AppFooter from './components/layout/AppFooter.vue'
+import BackToTop from './components/motion/BackToTop.vue'
+import FormBanner from './components/layout/FormBanner.vue'
+import SideButtons from './components/layout/SideButtons.vue' // 引入新的侧边按钮组件
+</script>
+
+<template>
+  <div class="app-shell">
+    <AppHeader />
+    <main class="app-main">
+      <RouterView v-slot="{ Component }">
+        <Transition name="page" mode="out-in">
+          <component :is="Component" />
+        </Transition>
+      </RouterView>
+    </main>
+    <FormBanner />
+    <AppFooter />
+    <BackToTop />
+    <SideButtons /> <!-- 使用新的侧边按钮组件 -->
+  </div>
+</template>

+ 52 - 0
new-portal/src/components/layout/SideButtons.vue

@@ -0,0 +1,52 @@
+<template>
+  <div class="side-buttons">
+    <div class="button-item" @click="handleFreeExperience">
+      <img src="https://placehold.co/64x64?text=免费体验" alt="免费体验图标" />
+      <span>免费体验</span>
+    </div>
+    <div class="button-item" @click="handleOnlineConsultation">
+      <img src="https://placehold.co/64x64?text=在线咨询" alt="在线咨询图标" />
+      <span>在线咨询</span>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useRouter } from 'vue-router';
+
+const router = useRouter();
+
+const handleFreeExperience = () => {
+  // 处理免费体验逻辑,例如跳转页面
+  router.push('/free-experience');
+};
+
+const handleOnlineConsultation = () => {
+  // 处理在线咨询逻辑,例如打开聊天窗口或跳转页面
+  router.push('/online-consultation');
+};
+</script>
+
+<style scoped>
+.side-buttons {
+  position: fixed;
+  right: 20px;
+  top: 50%;
+  transform: translateY(-50%);
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+}
+
+.button-item {
+  display: flex;
+  align-items: center;
+  cursor: pointer;
+}
+
+.button-item img {
+  width: 32px;
+  height: 32px;
+  margin-right: 8px;
+}
+</style>

+ 24 - 0
package.json

@@ -0,0 +1,24 @@
+{
+  "name": "new-portal",
+  "version": "0.0.0",
+  "private": true,
+  "type": "module",
+  "scripts": {
+    "dev": "vite",
+    "build": "vite build",
+    "preview": "vite preview"
+  },
+  "dependencies": {
+    "vue": "^3.5.27",
+    "vue-router": "^5.0.1"
+  },
+  "devDependencies": {
+    "@iconify/vue": "^5.0.0",
+    "@vitejs/plugin-vue": "^6.0.3",
+    "vite": "^7.3.1",
+    "vite-plugin-vue-devtools": "^8.0.5"
+  },
+  "engines": {
+    "node": "^20.19.0 || >=22.12.0"
+  }
+}

+ 1870 - 0
pnpm-lock.yaml

@@ -0,0 +1,1870 @@
+lockfileVersion: '9.0'
+
+settings:
+  autoInstallPeers: true
+  excludeLinksFromLockfile: false
+
+importers:
+
+  .:
+    dependencies:
+      vue:
+        specifier: ^3.5.27
+        version: 3.5.28
+      vue-router:
+        specifier: ^5.0.1
+        version: 5.0.2(@vue/compiler-sfc@3.5.28)(vue@3.5.28)
+    devDependencies:
+      '@iconify/vue':
+        specifier: ^5.0.0
+        version: 5.0.0(vue@3.5.28)
+      '@vitejs/plugin-vue':
+        specifier: ^6.0.3
+        version: 6.0.4(vite@7.3.1(yaml@2.8.2))(vue@3.5.28)
+      vite:
+        specifier: ^7.3.1
+        version: 7.3.1(yaml@2.8.2)
+      vite-plugin-vue-devtools:
+        specifier: ^8.0.5
+        version: 8.0.6(vite@7.3.1(yaml@2.8.2))(vue@3.5.28)
+
+packages:
+
+  '@babel/code-frame@7.29.0':
+    resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/compat-data@7.29.0':
+    resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/core@7.29.0':
+    resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/generator@7.29.1':
+    resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-annotate-as-pure@7.27.3':
+    resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-compilation-targets@7.28.6':
+    resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-create-class-features-plugin@7.28.6':
+    resolution: {integrity: sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0
+
+  '@babel/helper-globals@7.28.0':
+    resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-member-expression-to-functions@7.28.5':
+    resolution: {integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-module-imports@7.28.6':
+    resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-module-transforms@7.28.6':
+    resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0
+
+  '@babel/helper-optimise-call-expression@7.27.1':
+    resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-plugin-utils@7.28.6':
+    resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-replace-supers@7.28.6':
+    resolution: {integrity: sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0
+
+  '@babel/helper-skip-transparent-expression-wrappers@7.27.1':
+    resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-string-parser@7.27.1':
+    resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-validator-identifier@7.28.5':
+    resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-validator-option@7.27.1':
+    resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helpers@7.28.6':
+    resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/parser@7.29.0':
+    resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==}
+    engines: {node: '>=6.0.0'}
+    hasBin: true
+
+  '@babel/plugin-proposal-decorators@7.29.0':
+    resolution: {integrity: sha512-CVBVv3VY/XRMxRYq5dwr2DS7/MvqPm23cOCjbwNnVrfOqcWlnefua1uUs0sjdKOGjvPUG633o07uWzJq4oI6dA==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@babel/plugin-syntax-decorators@7.28.6':
+    resolution: {integrity: sha512-71EYI0ONURHJBL4rSFXnITXqXrrY8q4P0q006DPfN+Rk+ASM+++IBXem/ruokgBZR8YNEWZ8R6B+rCb8VcUTqA==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@babel/plugin-syntax-import-attributes@7.28.6':
+    resolution: {integrity: sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@babel/plugin-syntax-import-meta@7.10.4':
+    resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@babel/plugin-syntax-jsx@7.28.6':
+    resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@babel/plugin-syntax-typescript@7.28.6':
+    resolution: {integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@babel/plugin-transform-typescript@7.28.6':
+    resolution: {integrity: sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@babel/template@7.28.6':
+    resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/traverse@7.29.0':
+    resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/types@7.29.0':
+    resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==}
+    engines: {node: '>=6.9.0'}
+
+  '@esbuild/aix-ppc64@0.27.3':
+    resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==}
+    engines: {node: '>=18'}
+    cpu: [ppc64]
+    os: [aix]
+
+  '@esbuild/android-arm64@0.27.3':
+    resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==}
+    engines: {node: '>=18'}
+    cpu: [arm64]
+    os: [android]
+
+  '@esbuild/android-arm@0.27.3':
+    resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==}
+    engines: {node: '>=18'}
+    cpu: [arm]
+    os: [android]
+
+  '@esbuild/android-x64@0.27.3':
+    resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [android]
+
+  '@esbuild/darwin-arm64@0.27.3':
+    resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==}
+    engines: {node: '>=18'}
+    cpu: [arm64]
+    os: [darwin]
+
+  '@esbuild/darwin-x64@0.27.3':
+    resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [darwin]
+
+  '@esbuild/freebsd-arm64@0.27.3':
+    resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==}
+    engines: {node: '>=18'}
+    cpu: [arm64]
+    os: [freebsd]
+
+  '@esbuild/freebsd-x64@0.27.3':
+    resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [freebsd]
+
+  '@esbuild/linux-arm64@0.27.3':
+    resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==}
+    engines: {node: '>=18'}
+    cpu: [arm64]
+    os: [linux]
+
+  '@esbuild/linux-arm@0.27.3':
+    resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==}
+    engines: {node: '>=18'}
+    cpu: [arm]
+    os: [linux]
+
+  '@esbuild/linux-ia32@0.27.3':
+    resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==}
+    engines: {node: '>=18'}
+    cpu: [ia32]
+    os: [linux]
+
+  '@esbuild/linux-loong64@0.27.3':
+    resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==}
+    engines: {node: '>=18'}
+    cpu: [loong64]
+    os: [linux]
+
+  '@esbuild/linux-mips64el@0.27.3':
+    resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==}
+    engines: {node: '>=18'}
+    cpu: [mips64el]
+    os: [linux]
+
+  '@esbuild/linux-ppc64@0.27.3':
+    resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==}
+    engines: {node: '>=18'}
+    cpu: [ppc64]
+    os: [linux]
+
+  '@esbuild/linux-riscv64@0.27.3':
+    resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==}
+    engines: {node: '>=18'}
+    cpu: [riscv64]
+    os: [linux]
+
+  '@esbuild/linux-s390x@0.27.3':
+    resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==}
+    engines: {node: '>=18'}
+    cpu: [s390x]
+    os: [linux]
+
+  '@esbuild/linux-x64@0.27.3':
+    resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [linux]
+
+  '@esbuild/netbsd-arm64@0.27.3':
+    resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==}
+    engines: {node: '>=18'}
+    cpu: [arm64]
+    os: [netbsd]
+
+  '@esbuild/netbsd-x64@0.27.3':
+    resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [netbsd]
+
+  '@esbuild/openbsd-arm64@0.27.3':
+    resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==}
+    engines: {node: '>=18'}
+    cpu: [arm64]
+    os: [openbsd]
+
+  '@esbuild/openbsd-x64@0.27.3':
+    resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [openbsd]
+
+  '@esbuild/openharmony-arm64@0.27.3':
+    resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==}
+    engines: {node: '>=18'}
+    cpu: [arm64]
+    os: [openharmony]
+
+  '@esbuild/sunos-x64@0.27.3':
+    resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [sunos]
+
+  '@esbuild/win32-arm64@0.27.3':
+    resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==}
+    engines: {node: '>=18'}
+    cpu: [arm64]
+    os: [win32]
+
+  '@esbuild/win32-ia32@0.27.3':
+    resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==}
+    engines: {node: '>=18'}
+    cpu: [ia32]
+    os: [win32]
+
+  '@esbuild/win32-x64@0.27.3':
+    resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [win32]
+
+  '@iconify/types@2.0.0':
+    resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
+
+  '@iconify/vue@5.0.0':
+    resolution: {integrity: sha512-C+KuEWIF5nSBrobFJhT//JS87OZ++QDORB6f2q2Wm6fl2mueSTpFBeBsveK0KW9hWiZ4mNiPjsh6Zs4jjdROSg==}
+    peerDependencies:
+      vue: '>=3'
+
+  '@jridgewell/gen-mapping@0.3.13':
+    resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
+
+  '@jridgewell/remapping@2.3.5':
+    resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
+
+  '@jridgewell/resolve-uri@3.1.2':
+    resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
+    engines: {node: '>=6.0.0'}
+
+  '@jridgewell/sourcemap-codec@1.5.5':
+    resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
+
+  '@jridgewell/trace-mapping@0.3.31':
+    resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+
+  '@polka/url@1.0.0-next.29':
+    resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
+
+  '@rolldown/pluginutils@1.0.0-rc.2':
+    resolution: {integrity: sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw==}
+
+  '@rollup/rollup-android-arm-eabi@4.57.1':
+    resolution: {integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==}
+    cpu: [arm]
+    os: [android]
+
+  '@rollup/rollup-android-arm64@4.57.1':
+    resolution: {integrity: sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==}
+    cpu: [arm64]
+    os: [android]
+
+  '@rollup/rollup-darwin-arm64@4.57.1':
+    resolution: {integrity: sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==}
+    cpu: [arm64]
+    os: [darwin]
+
+  '@rollup/rollup-darwin-x64@4.57.1':
+    resolution: {integrity: sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==}
+    cpu: [x64]
+    os: [darwin]
+
+  '@rollup/rollup-freebsd-arm64@4.57.1':
+    resolution: {integrity: sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==}
+    cpu: [arm64]
+    os: [freebsd]
+
+  '@rollup/rollup-freebsd-x64@4.57.1':
+    resolution: {integrity: sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==}
+    cpu: [x64]
+    os: [freebsd]
+
+  '@rollup/rollup-linux-arm-gnueabihf@4.57.1':
+    resolution: {integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==}
+    cpu: [arm]
+    os: [linux]
+
+  '@rollup/rollup-linux-arm-musleabihf@4.57.1':
+    resolution: {integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==}
+    cpu: [arm]
+    os: [linux]
+
+  '@rollup/rollup-linux-arm64-gnu@4.57.1':
+    resolution: {integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==}
+    cpu: [arm64]
+    os: [linux]
+
+  '@rollup/rollup-linux-arm64-musl@4.57.1':
+    resolution: {integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==}
+    cpu: [arm64]
+    os: [linux]
+
+  '@rollup/rollup-linux-loong64-gnu@4.57.1':
+    resolution: {integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==}
+    cpu: [loong64]
+    os: [linux]
+
+  '@rollup/rollup-linux-loong64-musl@4.57.1':
+    resolution: {integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==}
+    cpu: [loong64]
+    os: [linux]
+
+  '@rollup/rollup-linux-ppc64-gnu@4.57.1':
+    resolution: {integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==}
+    cpu: [ppc64]
+    os: [linux]
+
+  '@rollup/rollup-linux-ppc64-musl@4.57.1':
+    resolution: {integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==}
+    cpu: [ppc64]
+    os: [linux]
+
+  '@rollup/rollup-linux-riscv64-gnu@4.57.1':
+    resolution: {integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==}
+    cpu: [riscv64]
+    os: [linux]
+
+  '@rollup/rollup-linux-riscv64-musl@4.57.1':
+    resolution: {integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==}
+    cpu: [riscv64]
+    os: [linux]
+
+  '@rollup/rollup-linux-s390x-gnu@4.57.1':
+    resolution: {integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==}
+    cpu: [s390x]
+    os: [linux]
+
+  '@rollup/rollup-linux-x64-gnu@4.57.1':
+    resolution: {integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==}
+    cpu: [x64]
+    os: [linux]
+
+  '@rollup/rollup-linux-x64-musl@4.57.1':
+    resolution: {integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==}
+    cpu: [x64]
+    os: [linux]
+
+  '@rollup/rollup-openbsd-x64@4.57.1':
+    resolution: {integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==}
+    cpu: [x64]
+    os: [openbsd]
+
+  '@rollup/rollup-openharmony-arm64@4.57.1':
+    resolution: {integrity: sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==}
+    cpu: [arm64]
+    os: [openharmony]
+
+  '@rollup/rollup-win32-arm64-msvc@4.57.1':
+    resolution: {integrity: sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==}
+    cpu: [arm64]
+    os: [win32]
+
+  '@rollup/rollup-win32-ia32-msvc@4.57.1':
+    resolution: {integrity: sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==}
+    cpu: [ia32]
+    os: [win32]
+
+  '@rollup/rollup-win32-x64-gnu@4.57.1':
+    resolution: {integrity: sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==}
+    cpu: [x64]
+    os: [win32]
+
+  '@rollup/rollup-win32-x64-msvc@4.57.1':
+    resolution: {integrity: sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==}
+    cpu: [x64]
+    os: [win32]
+
+  '@types/estree@1.0.8':
+    resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
+
+  '@vitejs/plugin-vue@6.0.4':
+    resolution: {integrity: sha512-uM5iXipgYIn13UUQCZNdWkYk+sysBeA97d5mHsAoAt1u/wpN3+zxOmsVJWosuzX+IMGRzeYUNytztrYznboIkQ==}
+    engines: {node: ^20.19.0 || >=22.12.0}
+    peerDependencies:
+      vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0
+      vue: ^3.2.25
+
+  '@vue-macros/common@3.1.2':
+    resolution: {integrity: sha512-h9t4ArDdniO9ekYHAD95t9AZcAbb19lEGK+26iAjUODOIJKmObDNBSe4+6ELQAA3vtYiFPPBtHh7+cQCKi3Dng==}
+    engines: {node: '>=20.19.0'}
+    peerDependencies:
+      vue: ^2.7.0 || ^3.2.25
+    peerDependenciesMeta:
+      vue:
+        optional: true
+
+  '@vue/babel-helper-vue-transform-on@1.5.0':
+    resolution: {integrity: sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA==}
+
+  '@vue/babel-plugin-jsx@1.5.0':
+    resolution: {integrity: sha512-mneBhw1oOqCd2247O0Yw/mRwC9jIGACAJUlawkmMBiNmL4dGA2eMzuNZVNqOUfYTa6vqmND4CtOPzmEEEqLKFw==}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+    peerDependenciesMeta:
+      '@babel/core':
+        optional: true
+
+  '@vue/babel-plugin-resolve-type@1.5.0':
+    resolution: {integrity: sha512-Wm/60o+53JwJODm4Knz47dxJnLDJ9FnKnGZJbUUf8nQRAtt6P+undLUAVU3Ha33LxOJe6IPoifRQ6F/0RrU31w==}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@vue/compiler-core@3.5.28':
+    resolution: {integrity: sha512-kviccYxTgoE8n6OCw96BNdYlBg2GOWfBuOW4Vqwrt7mSKWKwFVvI8egdTltqRgITGPsTFYtKYfxIG8ptX2PJHQ==}
+
+  '@vue/compiler-dom@3.5.28':
+    resolution: {integrity: sha512-/1ZepxAb159jKR1btkefDP+J2xuWL5V3WtleRmxaT+K2Aqiek/Ab/+Ebrw2pPj0sdHO8ViAyyJWfhXXOP/+LQA==}
+
+  '@vue/compiler-sfc@3.5.28':
+    resolution: {integrity: sha512-6TnKMiNkd6u6VeVDhZn/07KhEZuBSn43Wd2No5zaP5s3xm8IqFTHBj84HJah4UepSUJTro5SoqqlOY22FKY96g==}
+
+  '@vue/compiler-ssr@3.5.28':
+    resolution: {integrity: sha512-JCq//9w1qmC6UGLWJX7RXzrGpKkroubey/ZFqTpvEIDJEKGgntuDMqkuWiZvzTzTA5h2qZvFBFHY7fAAa9475g==}
+
+  '@vue/devtools-api@8.0.6':
+    resolution: {integrity: sha512-+lGBI+WTvJmnU2FZqHhEB8J1DXcvNlDeEalz77iYgOdY1jTj1ipSBaKj3sRhYcy+kqA8v/BSuvOz1XJucfQmUA==}
+
+  '@vue/devtools-core@8.0.6':
+    resolution: {integrity: sha512-fN7iVtpSQQdtMORWwVZ1JiIAKriinhD+lCHqPw9Rr252ae2TczILEmW0zcAZifPW8HfYcbFkn+h7Wv6kQQCayw==}
+    peerDependencies:
+      vue: ^3.0.0
+
+  '@vue/devtools-kit@8.0.6':
+    resolution: {integrity: sha512-9zXZPTJW72OteDXeSa5RVML3zWDCRcO5t77aJqSs228mdopYj5AiTpihozbsfFJ0IodfNs7pSgOGO3qfCuxDtw==}
+
+  '@vue/devtools-shared@8.0.6':
+    resolution: {integrity: sha512-Pp1JylTqlgMJvxW6MGyfTF8vGvlBSCAvMFaDCYa82Mgw7TT5eE5kkHgDvmOGHWeJE4zIDfCpCxHapsK2LtIAJg==}
+
+  '@vue/reactivity@3.5.28':
+    resolution: {integrity: sha512-gr5hEsxvn+RNyu9/9o1WtdYdwDjg5FgjUSBEkZWqgTKlo/fvwZ2+8W6AfKsc9YN2k/+iHYdS9vZYAhpi10kNaw==}
+
+  '@vue/runtime-core@3.5.28':
+    resolution: {integrity: sha512-POVHTdbgnrBBIpnbYU4y7pOMNlPn2QVxVzkvEA2pEgvzbelQq4ZOUxbp2oiyo+BOtiYlm8Q44wShHJoBvDPAjQ==}
+
+  '@vue/runtime-dom@3.5.28':
+    resolution: {integrity: sha512-4SXxSF8SXYMuhAIkT+eBRqOkWEfPu6nhccrzrkioA6l0boiq7sp18HCOov9qWJA5HML61kW8p/cB4MmBiG9dSA==}
+
+  '@vue/server-renderer@3.5.28':
+    resolution: {integrity: sha512-pf+5ECKGj8fX95bNincbzJ6yp6nyzuLDhYZCeFxUNp8EBrQpPpQaLX3nNCp49+UbgbPun3CeVE+5CXVV1Xydfg==}
+    peerDependencies:
+      vue: 3.5.28
+
+  '@vue/shared@3.5.28':
+    resolution: {integrity: sha512-cfWa1fCGBxrvaHRhvV3Is0MgmrbSCxYTXCSCau2I0a1Xw1N1pHAvkWCiXPRAqjvToILvguNyEwjevUqAuBQWvQ==}
+
+  acorn@8.15.0:
+    resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
+    engines: {node: '>=0.4.0'}
+    hasBin: true
+
+  ansis@4.2.0:
+    resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==}
+    engines: {node: '>=14'}
+
+  ast-kit@2.2.0:
+    resolution: {integrity: sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==}
+    engines: {node: '>=20.19.0'}
+
+  ast-walker-scope@0.8.3:
+    resolution: {integrity: sha512-cbdCP0PGOBq0ASG+sjnKIoYkWMKhhz+F/h9pRexUdX2Hd38+WOlBkRKlqkGOSm0YQpcFMQBJeK4WspUAkwsEdg==}
+    engines: {node: '>=20.19.0'}
+
+  baseline-browser-mapping@2.9.19:
+    resolution: {integrity: sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==}
+    hasBin: true
+
+  birpc@2.9.0:
+    resolution: {integrity: sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==}
+
+  browserslist@4.28.1:
+    resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==}
+    engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+    hasBin: true
+
+  bundle-name@4.1.0:
+    resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==}
+    engines: {node: '>=18'}
+
+  caniuse-lite@1.0.30001769:
+    resolution: {integrity: sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==}
+
+  chokidar@5.0.0:
+    resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==}
+    engines: {node: '>= 20.19.0'}
+
+  confbox@0.1.8:
+    resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==}
+
+  confbox@0.2.4:
+    resolution: {integrity: sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==}
+
+  convert-source-map@2.0.0:
+    resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+
+  copy-anything@4.0.5:
+    resolution: {integrity: sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==}
+    engines: {node: '>=18'}
+
+  csstype@3.2.3:
+    resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+
+  debug@4.4.3:
+    resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
+    engines: {node: '>=6.0'}
+    peerDependencies:
+      supports-color: '*'
+    peerDependenciesMeta:
+      supports-color:
+        optional: true
+
+  default-browser-id@5.0.1:
+    resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==}
+    engines: {node: '>=18'}
+
+  default-browser@5.5.0:
+    resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==}
+    engines: {node: '>=18'}
+
+  define-lazy-prop@3.0.0:
+    resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==}
+    engines: {node: '>=12'}
+
+  electron-to-chromium@1.5.286:
+    resolution: {integrity: sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==}
+
+  entities@7.0.1:
+    resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==}
+    engines: {node: '>=0.12'}
+
+  error-stack-parser-es@1.0.5:
+    resolution: {integrity: sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==}
+
+  esbuild@0.27.3:
+    resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==}
+    engines: {node: '>=18'}
+    hasBin: true
+
+  escalade@3.2.0:
+    resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
+    engines: {node: '>=6'}
+
+  estree-walker@2.0.2:
+    resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
+
+  exsolve@1.0.8:
+    resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==}
+
+  fdir@6.5.0:
+    resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
+    engines: {node: '>=12.0.0'}
+    peerDependencies:
+      picomatch: ^3 || ^4
+    peerDependenciesMeta:
+      picomatch:
+        optional: true
+
+  fsevents@2.3.3:
+    resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+    engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+    os: [darwin]
+
+  gensync@1.0.0-beta.2:
+    resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
+    engines: {node: '>=6.9.0'}
+
+  hookable@5.5.3:
+    resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
+
+  is-docker@3.0.0:
+    resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==}
+    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+    hasBin: true
+
+  is-inside-container@1.0.0:
+    resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==}
+    engines: {node: '>=14.16'}
+    hasBin: true
+
+  is-what@5.5.0:
+    resolution: {integrity: sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==}
+    engines: {node: '>=18'}
+
+  is-wsl@3.1.0:
+    resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==}
+    engines: {node: '>=16'}
+
+  js-tokens@4.0.0:
+    resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+  jsesc@3.1.0:
+    resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
+    engines: {node: '>=6'}
+    hasBin: true
+
+  json5@2.2.3:
+    resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+    engines: {node: '>=6'}
+    hasBin: true
+
+  kolorist@1.8.0:
+    resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==}
+
+  local-pkg@1.1.2:
+    resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==}
+    engines: {node: '>=14'}
+
+  lru-cache@5.1.1:
+    resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+
+  magic-string-ast@1.0.3:
+    resolution: {integrity: sha512-CvkkH1i81zl7mmb94DsRiFeG9V2fR2JeuK8yDgS8oiZSFa++wWLEgZ5ufEOyLHbvSbD1gTRKv9NdX69Rnvr9JA==}
+    engines: {node: '>=20.19.0'}
+
+  magic-string@0.30.21:
+    resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
+
+  mitt@3.0.1:
+    resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
+
+  mlly@1.8.0:
+    resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==}
+
+  mrmime@2.0.1:
+    resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
+    engines: {node: '>=10'}
+
+  ms@2.1.3:
+    resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+  muggle-string@0.4.1:
+    resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==}
+
+  nanoid@3.3.11:
+    resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
+    engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+    hasBin: true
+
+  nanoid@5.1.6:
+    resolution: {integrity: sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==}
+    engines: {node: ^18 || >=20}
+    hasBin: true
+
+  node-releases@2.0.27:
+    resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==}
+
+  ohash@2.0.11:
+    resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==}
+
+  open@10.2.0:
+    resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==}
+    engines: {node: '>=18'}
+
+  pathe@2.0.3:
+    resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
+
+  perfect-debounce@2.1.0:
+    resolution: {integrity: sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==}
+
+  picocolors@1.1.1:
+    resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+  picomatch@4.0.3:
+    resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
+    engines: {node: '>=12'}
+
+  pkg-types@1.3.1:
+    resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==}
+
+  pkg-types@2.3.0:
+    resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==}
+
+  postcss@8.5.6:
+    resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
+    engines: {node: ^10 || ^12 || >=14}
+
+  quansync@0.2.11:
+    resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==}
+
+  readdirp@5.0.0:
+    resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==}
+    engines: {node: '>= 20.19.0'}
+
+  rfdc@1.4.1:
+    resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
+
+  rollup@4.57.1:
+    resolution: {integrity: sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==}
+    engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+    hasBin: true
+
+  run-applescript@7.1.0:
+    resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==}
+    engines: {node: '>=18'}
+
+  scule@1.3.0:
+    resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==}
+
+  semver@6.3.1:
+    resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+    hasBin: true
+
+  sirv@3.0.2:
+    resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==}
+    engines: {node: '>=18'}
+
+  source-map-js@1.2.1:
+    resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+    engines: {node: '>=0.10.0'}
+
+  speakingurl@14.0.1:
+    resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==}
+    engines: {node: '>=0.10.0'}
+
+  superjson@2.2.6:
+    resolution: {integrity: sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==}
+    engines: {node: '>=16'}
+
+  tinyglobby@0.2.15:
+    resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
+    engines: {node: '>=12.0.0'}
+
+  totalist@3.0.1:
+    resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
+    engines: {node: '>=6'}
+
+  ufo@1.6.3:
+    resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==}
+
+  unplugin-utils@0.3.1:
+    resolution: {integrity: sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==}
+    engines: {node: '>=20.19.0'}
+
+  unplugin@3.0.0:
+    resolution: {integrity: sha512-0Mqk3AT2TZCXWKdcoaufeXNukv2mTrEZExeXlHIOZXdqYoHHr4n51pymnwV8x2BOVxwXbK2HLlI7usrqMpycdg==}
+    engines: {node: ^20.19.0 || >=22.12.0}
+
+  update-browserslist-db@1.2.3:
+    resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==}
+    hasBin: true
+    peerDependencies:
+      browserslist: '>= 4.21.0'
+
+  vite-dev-rpc@1.1.0:
+    resolution: {integrity: sha512-pKXZlgoXGoE8sEKiKJSng4hI1sQ4wi5YT24FCrwrLt6opmkjlqPPVmiPWWJn8M8byMxRGzp1CrFuqQs4M/Z39A==}
+    peerDependencies:
+      vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.1 || ^7.0.0-0
+
+  vite-hot-client@2.1.0:
+    resolution: {integrity: sha512-7SpgZmU7R+dDnSmvXE1mfDtnHLHQSisdySVR7lO8ceAXvM0otZeuQQ6C8LrS5d/aYyP/QZ0hI0L+dIPrm4YlFQ==}
+    peerDependencies:
+      vite: ^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0
+
+  vite-plugin-inspect@11.3.3:
+    resolution: {integrity: sha512-u2eV5La99oHoYPHE6UvbwgEqKKOQGz86wMg40CCosP6q8BkB6e5xPneZfYagK4ojPJSj5anHCrnvC20DpwVdRA==}
+    engines: {node: '>=14'}
+    peerDependencies:
+      '@nuxt/kit': '*'
+      vite: ^6.0.0 || ^7.0.0-0
+    peerDependenciesMeta:
+      '@nuxt/kit':
+        optional: true
+
+  vite-plugin-vue-devtools@8.0.6:
+    resolution: {integrity: sha512-IiTCIJDb1ZliOT8fPbYXllyfgARzz1+R1r8RN9ScGIDzAB6o8bDME1a9JjrfdSJibL7i8DIPQH+pGv0U7haBeA==}
+    engines: {node: '>=v14.21.3'}
+    peerDependencies:
+      vite: ^6.0.0 || ^7.0.0-0
+
+  vite-plugin-vue-inspector@5.3.2:
+    resolution: {integrity: sha512-YvEKooQcSiBTAs0DoYLfefNja9bLgkFM7NI2b07bE2SruuvX0MEa9cMaxjKVMkeCp5Nz9FRIdcN1rOdFVBeL6Q==}
+    peerDependencies:
+      vite: ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0
+
+  vite@7.3.1:
+    resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==}
+    engines: {node: ^20.19.0 || >=22.12.0}
+    hasBin: true
+    peerDependencies:
+      '@types/node': ^20.19.0 || >=22.12.0
+      jiti: '>=1.21.0'
+      less: ^4.0.0
+      lightningcss: ^1.21.0
+      sass: ^1.70.0
+      sass-embedded: ^1.70.0
+      stylus: '>=0.54.8'
+      sugarss: ^5.0.0
+      terser: ^5.16.0
+      tsx: ^4.8.1
+      yaml: ^2.4.2
+    peerDependenciesMeta:
+      '@types/node':
+        optional: true
+      jiti:
+        optional: true
+      less:
+        optional: true
+      lightningcss:
+        optional: true
+      sass:
+        optional: true
+      sass-embedded:
+        optional: true
+      stylus:
+        optional: true
+      sugarss:
+        optional: true
+      terser:
+        optional: true
+      tsx:
+        optional: true
+      yaml:
+        optional: true
+
+  vue-router@5.0.2:
+    resolution: {integrity: sha512-YFhwaE5c5JcJpNB1arpkl4/GnO32wiUWRB+OEj1T0DlDxEZoOfbltl2xEwktNU/9o1sGcGburIXSpbLpPFe/6w==}
+    peerDependencies:
+      '@pinia/colada': '>=0.21.2'
+      '@vue/compiler-sfc': ^3.5.17
+      pinia: ^3.0.4
+      vue: ^3.5.0
+    peerDependenciesMeta:
+      '@pinia/colada':
+        optional: true
+      '@vue/compiler-sfc':
+        optional: true
+      pinia:
+        optional: true
+
+  vue@3.5.28:
+    resolution: {integrity: sha512-BRdrNfeoccSoIZeIhyPBfvWSLFP4q8J3u8Ju8Ug5vu3LdD+yTM13Sg4sKtljxozbnuMu1NB1X5HBHRYUzFocKg==}
+    peerDependencies:
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+
+  webpack-virtual-modules@0.6.2:
+    resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==}
+
+  wsl-utils@0.1.0:
+    resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==}
+    engines: {node: '>=18'}
+
+  yallist@3.1.1:
+    resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+
+  yaml@2.8.2:
+    resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==}
+    engines: {node: '>= 14.6'}
+    hasBin: true
+
+snapshots:
+
+  '@babel/code-frame@7.29.0':
+    dependencies:
+      '@babel/helper-validator-identifier': 7.28.5
+      js-tokens: 4.0.0
+      picocolors: 1.1.1
+
+  '@babel/compat-data@7.29.0': {}
+
+  '@babel/core@7.29.0':
+    dependencies:
+      '@babel/code-frame': 7.29.0
+      '@babel/generator': 7.29.1
+      '@babel/helper-compilation-targets': 7.28.6
+      '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0)
+      '@babel/helpers': 7.28.6
+      '@babel/parser': 7.29.0
+      '@babel/template': 7.28.6
+      '@babel/traverse': 7.29.0
+      '@babel/types': 7.29.0
+      '@jridgewell/remapping': 2.3.5
+      convert-source-map: 2.0.0
+      debug: 4.4.3
+      gensync: 1.0.0-beta.2
+      json5: 2.2.3
+      semver: 6.3.1
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/generator@7.29.1':
+    dependencies:
+      '@babel/parser': 7.29.0
+      '@babel/types': 7.29.0
+      '@jridgewell/gen-mapping': 0.3.13
+      '@jridgewell/trace-mapping': 0.3.31
+      jsesc: 3.1.0
+
+  '@babel/helper-annotate-as-pure@7.27.3':
+    dependencies:
+      '@babel/types': 7.29.0
+
+  '@babel/helper-compilation-targets@7.28.6':
+    dependencies:
+      '@babel/compat-data': 7.29.0
+      '@babel/helper-validator-option': 7.27.1
+      browserslist: 4.28.1
+      lru-cache: 5.1.1
+      semver: 6.3.1
+
+  '@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.29.0)':
+    dependencies:
+      '@babel/core': 7.29.0
+      '@babel/helper-annotate-as-pure': 7.27.3
+      '@babel/helper-member-expression-to-functions': 7.28.5
+      '@babel/helper-optimise-call-expression': 7.27.1
+      '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0)
+      '@babel/helper-skip-transparent-expression-wrappers': 7.27.1
+      '@babel/traverse': 7.29.0
+      semver: 6.3.1
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/helper-globals@7.28.0': {}
+
+  '@babel/helper-member-expression-to-functions@7.28.5':
+    dependencies:
+      '@babel/traverse': 7.29.0
+      '@babel/types': 7.29.0
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/helper-module-imports@7.28.6':
+    dependencies:
+      '@babel/traverse': 7.29.0
+      '@babel/types': 7.29.0
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)':
+    dependencies:
+      '@babel/core': 7.29.0
+      '@babel/helper-module-imports': 7.28.6
+      '@babel/helper-validator-identifier': 7.28.5
+      '@babel/traverse': 7.29.0
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/helper-optimise-call-expression@7.27.1':
+    dependencies:
+      '@babel/types': 7.29.0
+
+  '@babel/helper-plugin-utils@7.28.6': {}
+
+  '@babel/helper-replace-supers@7.28.6(@babel/core@7.29.0)':
+    dependencies:
+      '@babel/core': 7.29.0
+      '@babel/helper-member-expression-to-functions': 7.28.5
+      '@babel/helper-optimise-call-expression': 7.27.1
+      '@babel/traverse': 7.29.0
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/helper-skip-transparent-expression-wrappers@7.27.1':
+    dependencies:
+      '@babel/traverse': 7.29.0
+      '@babel/types': 7.29.0
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/helper-string-parser@7.27.1': {}
+
+  '@babel/helper-validator-identifier@7.28.5': {}
+
+  '@babel/helper-validator-option@7.27.1': {}
+
+  '@babel/helpers@7.28.6':
+    dependencies:
+      '@babel/template': 7.28.6
+      '@babel/types': 7.29.0
+
+  '@babel/parser@7.29.0':
+    dependencies:
+      '@babel/types': 7.29.0
+
+  '@babel/plugin-proposal-decorators@7.29.0(@babel/core@7.29.0)':
+    dependencies:
+      '@babel/core': 7.29.0
+      '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0)
+      '@babel/helper-plugin-utils': 7.28.6
+      '@babel/plugin-syntax-decorators': 7.28.6(@babel/core@7.29.0)
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/plugin-syntax-decorators@7.28.6(@babel/core@7.29.0)':
+    dependencies:
+      '@babel/core': 7.29.0
+      '@babel/helper-plugin-utils': 7.28.6
+
+  '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.0)':
+    dependencies:
+      '@babel/core': 7.29.0
+      '@babel/helper-plugin-utils': 7.28.6
+
+  '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.29.0)':
+    dependencies:
+      '@babel/core': 7.29.0
+      '@babel/helper-plugin-utils': 7.28.6
+
+  '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)':
+    dependencies:
+      '@babel/core': 7.29.0
+      '@babel/helper-plugin-utils': 7.28.6
+
+  '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)':
+    dependencies:
+      '@babel/core': 7.29.0
+      '@babel/helper-plugin-utils': 7.28.6
+
+  '@babel/plugin-transform-typescript@7.28.6(@babel/core@7.29.0)':
+    dependencies:
+      '@babel/core': 7.29.0
+      '@babel/helper-annotate-as-pure': 7.27.3
+      '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0)
+      '@babel/helper-plugin-utils': 7.28.6
+      '@babel/helper-skip-transparent-expression-wrappers': 7.27.1
+      '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0)
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/template@7.28.6':
+    dependencies:
+      '@babel/code-frame': 7.29.0
+      '@babel/parser': 7.29.0
+      '@babel/types': 7.29.0
+
+  '@babel/traverse@7.29.0':
+    dependencies:
+      '@babel/code-frame': 7.29.0
+      '@babel/generator': 7.29.1
+      '@babel/helper-globals': 7.28.0
+      '@babel/parser': 7.29.0
+      '@babel/template': 7.28.6
+      '@babel/types': 7.29.0
+      debug: 4.4.3
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/types@7.29.0':
+    dependencies:
+      '@babel/helper-string-parser': 7.27.1
+      '@babel/helper-validator-identifier': 7.28.5
+
+  '@esbuild/aix-ppc64@0.27.3':
+    optional: true
+
+  '@esbuild/android-arm64@0.27.3':
+    optional: true
+
+  '@esbuild/android-arm@0.27.3':
+    optional: true
+
+  '@esbuild/android-x64@0.27.3':
+    optional: true
+
+  '@esbuild/darwin-arm64@0.27.3':
+    optional: true
+
+  '@esbuild/darwin-x64@0.27.3':
+    optional: true
+
+  '@esbuild/freebsd-arm64@0.27.3':
+    optional: true
+
+  '@esbuild/freebsd-x64@0.27.3':
+    optional: true
+
+  '@esbuild/linux-arm64@0.27.3':
+    optional: true
+
+  '@esbuild/linux-arm@0.27.3':
+    optional: true
+
+  '@esbuild/linux-ia32@0.27.3':
+    optional: true
+
+  '@esbuild/linux-loong64@0.27.3':
+    optional: true
+
+  '@esbuild/linux-mips64el@0.27.3':
+    optional: true
+
+  '@esbuild/linux-ppc64@0.27.3':
+    optional: true
+
+  '@esbuild/linux-riscv64@0.27.3':
+    optional: true
+
+  '@esbuild/linux-s390x@0.27.3':
+    optional: true
+
+  '@esbuild/linux-x64@0.27.3':
+    optional: true
+
+  '@esbuild/netbsd-arm64@0.27.3':
+    optional: true
+
+  '@esbuild/netbsd-x64@0.27.3':
+    optional: true
+
+  '@esbuild/openbsd-arm64@0.27.3':
+    optional: true
+
+  '@esbuild/openbsd-x64@0.27.3':
+    optional: true
+
+  '@esbuild/openharmony-arm64@0.27.3':
+    optional: true
+
+  '@esbuild/sunos-x64@0.27.3':
+    optional: true
+
+  '@esbuild/win32-arm64@0.27.3':
+    optional: true
+
+  '@esbuild/win32-ia32@0.27.3':
+    optional: true
+
+  '@esbuild/win32-x64@0.27.3':
+    optional: true
+
+  '@iconify/types@2.0.0': {}
+
+  '@iconify/vue@5.0.0(vue@3.5.28)':
+    dependencies:
+      '@iconify/types': 2.0.0
+      vue: 3.5.28
+
+  '@jridgewell/gen-mapping@0.3.13':
+    dependencies:
+      '@jridgewell/sourcemap-codec': 1.5.5
+      '@jridgewell/trace-mapping': 0.3.31
+
+  '@jridgewell/remapping@2.3.5':
+    dependencies:
+      '@jridgewell/gen-mapping': 0.3.13
+      '@jridgewell/trace-mapping': 0.3.31
+
+  '@jridgewell/resolve-uri@3.1.2': {}
+
+  '@jridgewell/sourcemap-codec@1.5.5': {}
+
+  '@jridgewell/trace-mapping@0.3.31':
+    dependencies:
+      '@jridgewell/resolve-uri': 3.1.2
+      '@jridgewell/sourcemap-codec': 1.5.5
+
+  '@polka/url@1.0.0-next.29': {}
+
+  '@rolldown/pluginutils@1.0.0-rc.2': {}
+
+  '@rollup/rollup-android-arm-eabi@4.57.1':
+    optional: true
+
+  '@rollup/rollup-android-arm64@4.57.1':
+    optional: true
+
+  '@rollup/rollup-darwin-arm64@4.57.1':
+    optional: true
+
+  '@rollup/rollup-darwin-x64@4.57.1':
+    optional: true
+
+  '@rollup/rollup-freebsd-arm64@4.57.1':
+    optional: true
+
+  '@rollup/rollup-freebsd-x64@4.57.1':
+    optional: true
+
+  '@rollup/rollup-linux-arm-gnueabihf@4.57.1':
+    optional: true
+
+  '@rollup/rollup-linux-arm-musleabihf@4.57.1':
+    optional: true
+
+  '@rollup/rollup-linux-arm64-gnu@4.57.1':
+    optional: true
+
+  '@rollup/rollup-linux-arm64-musl@4.57.1':
+    optional: true
+
+  '@rollup/rollup-linux-loong64-gnu@4.57.1':
+    optional: true
+
+  '@rollup/rollup-linux-loong64-musl@4.57.1':
+    optional: true
+
+  '@rollup/rollup-linux-ppc64-gnu@4.57.1':
+    optional: true
+
+  '@rollup/rollup-linux-ppc64-musl@4.57.1':
+    optional: true
+
+  '@rollup/rollup-linux-riscv64-gnu@4.57.1':
+    optional: true
+
+  '@rollup/rollup-linux-riscv64-musl@4.57.1':
+    optional: true
+
+  '@rollup/rollup-linux-s390x-gnu@4.57.1':
+    optional: true
+
+  '@rollup/rollup-linux-x64-gnu@4.57.1':
+    optional: true
+
+  '@rollup/rollup-linux-x64-musl@4.57.1':
+    optional: true
+
+  '@rollup/rollup-openbsd-x64@4.57.1':
+    optional: true
+
+  '@rollup/rollup-openharmony-arm64@4.57.1':
+    optional: true
+
+  '@rollup/rollup-win32-arm64-msvc@4.57.1':
+    optional: true
+
+  '@rollup/rollup-win32-ia32-msvc@4.57.1':
+    optional: true
+
+  '@rollup/rollup-win32-x64-gnu@4.57.1':
+    optional: true
+
+  '@rollup/rollup-win32-x64-msvc@4.57.1':
+    optional: true
+
+  '@types/estree@1.0.8': {}
+
+  '@vitejs/plugin-vue@6.0.4(vite@7.3.1(yaml@2.8.2))(vue@3.5.28)':
+    dependencies:
+      '@rolldown/pluginutils': 1.0.0-rc.2
+      vite: 7.3.1(yaml@2.8.2)
+      vue: 3.5.28
+
+  '@vue-macros/common@3.1.2(vue@3.5.28)':
+    dependencies:
+      '@vue/compiler-sfc': 3.5.28
+      ast-kit: 2.2.0
+      local-pkg: 1.1.2
+      magic-string-ast: 1.0.3
+      unplugin-utils: 0.3.1
+    optionalDependencies:
+      vue: 3.5.28
+
+  '@vue/babel-helper-vue-transform-on@1.5.0': {}
+
+  '@vue/babel-plugin-jsx@1.5.0(@babel/core@7.29.0)':
+    dependencies:
+      '@babel/helper-module-imports': 7.28.6
+      '@babel/helper-plugin-utils': 7.28.6
+      '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0)
+      '@babel/template': 7.28.6
+      '@babel/traverse': 7.29.0
+      '@babel/types': 7.29.0
+      '@vue/babel-helper-vue-transform-on': 1.5.0
+      '@vue/babel-plugin-resolve-type': 1.5.0(@babel/core@7.29.0)
+      '@vue/shared': 3.5.28
+    optionalDependencies:
+      '@babel/core': 7.29.0
+    transitivePeerDependencies:
+      - supports-color
+
+  '@vue/babel-plugin-resolve-type@1.5.0(@babel/core@7.29.0)':
+    dependencies:
+      '@babel/code-frame': 7.29.0
+      '@babel/core': 7.29.0
+      '@babel/helper-module-imports': 7.28.6
+      '@babel/helper-plugin-utils': 7.28.6
+      '@babel/parser': 7.29.0
+      '@vue/compiler-sfc': 3.5.28
+    transitivePeerDependencies:
+      - supports-color
+
+  '@vue/compiler-core@3.5.28':
+    dependencies:
+      '@babel/parser': 7.29.0
+      '@vue/shared': 3.5.28
+      entities: 7.0.1
+      estree-walker: 2.0.2
+      source-map-js: 1.2.1
+
+  '@vue/compiler-dom@3.5.28':
+    dependencies:
+      '@vue/compiler-core': 3.5.28
+      '@vue/shared': 3.5.28
+
+  '@vue/compiler-sfc@3.5.28':
+    dependencies:
+      '@babel/parser': 7.29.0
+      '@vue/compiler-core': 3.5.28
+      '@vue/compiler-dom': 3.5.28
+      '@vue/compiler-ssr': 3.5.28
+      '@vue/shared': 3.5.28
+      estree-walker: 2.0.2
+      magic-string: 0.30.21
+      postcss: 8.5.6
+      source-map-js: 1.2.1
+
+  '@vue/compiler-ssr@3.5.28':
+    dependencies:
+      '@vue/compiler-dom': 3.5.28
+      '@vue/shared': 3.5.28
+
+  '@vue/devtools-api@8.0.6':
+    dependencies:
+      '@vue/devtools-kit': 8.0.6
+
+  '@vue/devtools-core@8.0.6(vite@7.3.1(yaml@2.8.2))(vue@3.5.28)':
+    dependencies:
+      '@vue/devtools-kit': 8.0.6
+      '@vue/devtools-shared': 8.0.6
+      mitt: 3.0.1
+      nanoid: 5.1.6
+      pathe: 2.0.3
+      vite-hot-client: 2.1.0(vite@7.3.1(yaml@2.8.2))
+      vue: 3.5.28
+    transitivePeerDependencies:
+      - vite
+
+  '@vue/devtools-kit@8.0.6':
+    dependencies:
+      '@vue/devtools-shared': 8.0.6
+      birpc: 2.9.0
+      hookable: 5.5.3
+      mitt: 3.0.1
+      perfect-debounce: 2.1.0
+      speakingurl: 14.0.1
+      superjson: 2.2.6
+
+  '@vue/devtools-shared@8.0.6':
+    dependencies:
+      rfdc: 1.4.1
+
+  '@vue/reactivity@3.5.28':
+    dependencies:
+      '@vue/shared': 3.5.28
+
+  '@vue/runtime-core@3.5.28':
+    dependencies:
+      '@vue/reactivity': 3.5.28
+      '@vue/shared': 3.5.28
+
+  '@vue/runtime-dom@3.5.28':
+    dependencies:
+      '@vue/reactivity': 3.5.28
+      '@vue/runtime-core': 3.5.28
+      '@vue/shared': 3.5.28
+      csstype: 3.2.3
+
+  '@vue/server-renderer@3.5.28(vue@3.5.28)':
+    dependencies:
+      '@vue/compiler-ssr': 3.5.28
+      '@vue/shared': 3.5.28
+      vue: 3.5.28
+
+  '@vue/shared@3.5.28': {}
+
+  acorn@8.15.0: {}
+
+  ansis@4.2.0: {}
+
+  ast-kit@2.2.0:
+    dependencies:
+      '@babel/parser': 7.29.0
+      pathe: 2.0.3
+
+  ast-walker-scope@0.8.3:
+    dependencies:
+      '@babel/parser': 7.29.0
+      ast-kit: 2.2.0
+
+  baseline-browser-mapping@2.9.19: {}
+
+  birpc@2.9.0: {}
+
+  browserslist@4.28.1:
+    dependencies:
+      baseline-browser-mapping: 2.9.19
+      caniuse-lite: 1.0.30001769
+      electron-to-chromium: 1.5.286
+      node-releases: 2.0.27
+      update-browserslist-db: 1.2.3(browserslist@4.28.1)
+
+  bundle-name@4.1.0:
+    dependencies:
+      run-applescript: 7.1.0
+
+  caniuse-lite@1.0.30001769: {}
+
+  chokidar@5.0.0:
+    dependencies:
+      readdirp: 5.0.0
+
+  confbox@0.1.8: {}
+
+  confbox@0.2.4: {}
+
+  convert-source-map@2.0.0: {}
+
+  copy-anything@4.0.5:
+    dependencies:
+      is-what: 5.5.0
+
+  csstype@3.2.3: {}
+
+  debug@4.4.3:
+    dependencies:
+      ms: 2.1.3
+
+  default-browser-id@5.0.1: {}
+
+  default-browser@5.5.0:
+    dependencies:
+      bundle-name: 4.1.0
+      default-browser-id: 5.0.1
+
+  define-lazy-prop@3.0.0: {}
+
+  electron-to-chromium@1.5.286: {}
+
+  entities@7.0.1: {}
+
+  error-stack-parser-es@1.0.5: {}
+
+  esbuild@0.27.3:
+    optionalDependencies:
+      '@esbuild/aix-ppc64': 0.27.3
+      '@esbuild/android-arm': 0.27.3
+      '@esbuild/android-arm64': 0.27.3
+      '@esbuild/android-x64': 0.27.3
+      '@esbuild/darwin-arm64': 0.27.3
+      '@esbuild/darwin-x64': 0.27.3
+      '@esbuild/freebsd-arm64': 0.27.3
+      '@esbuild/freebsd-x64': 0.27.3
+      '@esbuild/linux-arm': 0.27.3
+      '@esbuild/linux-arm64': 0.27.3
+      '@esbuild/linux-ia32': 0.27.3
+      '@esbuild/linux-loong64': 0.27.3
+      '@esbuild/linux-mips64el': 0.27.3
+      '@esbuild/linux-ppc64': 0.27.3
+      '@esbuild/linux-riscv64': 0.27.3
+      '@esbuild/linux-s390x': 0.27.3
+      '@esbuild/linux-x64': 0.27.3
+      '@esbuild/netbsd-arm64': 0.27.3
+      '@esbuild/netbsd-x64': 0.27.3
+      '@esbuild/openbsd-arm64': 0.27.3
+      '@esbuild/openbsd-x64': 0.27.3
+      '@esbuild/openharmony-arm64': 0.27.3
+      '@esbuild/sunos-x64': 0.27.3
+      '@esbuild/win32-arm64': 0.27.3
+      '@esbuild/win32-ia32': 0.27.3
+      '@esbuild/win32-x64': 0.27.3
+
+  escalade@3.2.0: {}
+
+  estree-walker@2.0.2: {}
+
+  exsolve@1.0.8: {}
+
+  fdir@6.5.0(picomatch@4.0.3):
+    optionalDependencies:
+      picomatch: 4.0.3
+
+  fsevents@2.3.3:
+    optional: true
+
+  gensync@1.0.0-beta.2: {}
+
+  hookable@5.5.3: {}
+
+  is-docker@3.0.0: {}
+
+  is-inside-container@1.0.0:
+    dependencies:
+      is-docker: 3.0.0
+
+  is-what@5.5.0: {}
+
+  is-wsl@3.1.0:
+    dependencies:
+      is-inside-container: 1.0.0
+
+  js-tokens@4.0.0: {}
+
+  jsesc@3.1.0: {}
+
+  json5@2.2.3: {}
+
+  kolorist@1.8.0: {}
+
+  local-pkg@1.1.2:
+    dependencies:
+      mlly: 1.8.0
+      pkg-types: 2.3.0
+      quansync: 0.2.11
+
+  lru-cache@5.1.1:
+    dependencies:
+      yallist: 3.1.1
+
+  magic-string-ast@1.0.3:
+    dependencies:
+      magic-string: 0.30.21
+
+  magic-string@0.30.21:
+    dependencies:
+      '@jridgewell/sourcemap-codec': 1.5.5
+
+  mitt@3.0.1: {}
+
+  mlly@1.8.0:
+    dependencies:
+      acorn: 8.15.0
+      pathe: 2.0.3
+      pkg-types: 1.3.1
+      ufo: 1.6.3
+
+  mrmime@2.0.1: {}
+
+  ms@2.1.3: {}
+
+  muggle-string@0.4.1: {}
+
+  nanoid@3.3.11: {}
+
+  nanoid@5.1.6: {}
+
+  node-releases@2.0.27: {}
+
+  ohash@2.0.11: {}
+
+  open@10.2.0:
+    dependencies:
+      default-browser: 5.5.0
+      define-lazy-prop: 3.0.0
+      is-inside-container: 1.0.0
+      wsl-utils: 0.1.0
+
+  pathe@2.0.3: {}
+
+  perfect-debounce@2.1.0: {}
+
+  picocolors@1.1.1: {}
+
+  picomatch@4.0.3: {}
+
+  pkg-types@1.3.1:
+    dependencies:
+      confbox: 0.1.8
+      mlly: 1.8.0
+      pathe: 2.0.3
+
+  pkg-types@2.3.0:
+    dependencies:
+      confbox: 0.2.4
+      exsolve: 1.0.8
+      pathe: 2.0.3
+
+  postcss@8.5.6:
+    dependencies:
+      nanoid: 3.3.11
+      picocolors: 1.1.1
+      source-map-js: 1.2.1
+
+  quansync@0.2.11: {}
+
+  readdirp@5.0.0: {}
+
+  rfdc@1.4.1: {}
+
+  rollup@4.57.1:
+    dependencies:
+      '@types/estree': 1.0.8
+    optionalDependencies:
+      '@rollup/rollup-android-arm-eabi': 4.57.1
+      '@rollup/rollup-android-arm64': 4.57.1
+      '@rollup/rollup-darwin-arm64': 4.57.1
+      '@rollup/rollup-darwin-x64': 4.57.1
+      '@rollup/rollup-freebsd-arm64': 4.57.1
+      '@rollup/rollup-freebsd-x64': 4.57.1
+      '@rollup/rollup-linux-arm-gnueabihf': 4.57.1
+      '@rollup/rollup-linux-arm-musleabihf': 4.57.1
+      '@rollup/rollup-linux-arm64-gnu': 4.57.1
+      '@rollup/rollup-linux-arm64-musl': 4.57.1
+      '@rollup/rollup-linux-loong64-gnu': 4.57.1
+      '@rollup/rollup-linux-loong64-musl': 4.57.1
+      '@rollup/rollup-linux-ppc64-gnu': 4.57.1
+      '@rollup/rollup-linux-ppc64-musl': 4.57.1
+      '@rollup/rollup-linux-riscv64-gnu': 4.57.1
+      '@rollup/rollup-linux-riscv64-musl': 4.57.1
+      '@rollup/rollup-linux-s390x-gnu': 4.57.1
+      '@rollup/rollup-linux-x64-gnu': 4.57.1
+      '@rollup/rollup-linux-x64-musl': 4.57.1
+      '@rollup/rollup-openbsd-x64': 4.57.1
+      '@rollup/rollup-openharmony-arm64': 4.57.1
+      '@rollup/rollup-win32-arm64-msvc': 4.57.1
+      '@rollup/rollup-win32-ia32-msvc': 4.57.1
+      '@rollup/rollup-win32-x64-gnu': 4.57.1
+      '@rollup/rollup-win32-x64-msvc': 4.57.1
+      fsevents: 2.3.3
+
+  run-applescript@7.1.0: {}
+
+  scule@1.3.0: {}
+
+  semver@6.3.1: {}
+
+  sirv@3.0.2:
+    dependencies:
+      '@polka/url': 1.0.0-next.29
+      mrmime: 2.0.1
+      totalist: 3.0.1
+
+  source-map-js@1.2.1: {}
+
+  speakingurl@14.0.1: {}
+
+  superjson@2.2.6:
+    dependencies:
+      copy-anything: 4.0.5
+
+  tinyglobby@0.2.15:
+    dependencies:
+      fdir: 6.5.0(picomatch@4.0.3)
+      picomatch: 4.0.3
+
+  totalist@3.0.1: {}
+
+  ufo@1.6.3: {}
+
+  unplugin-utils@0.3.1:
+    dependencies:
+      pathe: 2.0.3
+      picomatch: 4.0.3
+
+  unplugin@3.0.0:
+    dependencies:
+      '@jridgewell/remapping': 2.3.5
+      picomatch: 4.0.3
+      webpack-virtual-modules: 0.6.2
+
+  update-browserslist-db@1.2.3(browserslist@4.28.1):
+    dependencies:
+      browserslist: 4.28.1
+      escalade: 3.2.0
+      picocolors: 1.1.1
+
+  vite-dev-rpc@1.1.0(vite@7.3.1(yaml@2.8.2)):
+    dependencies:
+      birpc: 2.9.0
+      vite: 7.3.1(yaml@2.8.2)
+      vite-hot-client: 2.1.0(vite@7.3.1(yaml@2.8.2))
+
+  vite-hot-client@2.1.0(vite@7.3.1(yaml@2.8.2)):
+    dependencies:
+      vite: 7.3.1(yaml@2.8.2)
+
+  vite-plugin-inspect@11.3.3(vite@7.3.1(yaml@2.8.2)):
+    dependencies:
+      ansis: 4.2.0
+      debug: 4.4.3
+      error-stack-parser-es: 1.0.5
+      ohash: 2.0.11
+      open: 10.2.0
+      perfect-debounce: 2.1.0
+      sirv: 3.0.2
+      unplugin-utils: 0.3.1
+      vite: 7.3.1(yaml@2.8.2)
+      vite-dev-rpc: 1.1.0(vite@7.3.1(yaml@2.8.2))
+    transitivePeerDependencies:
+      - supports-color
+
+  vite-plugin-vue-devtools@8.0.6(vite@7.3.1(yaml@2.8.2))(vue@3.5.28):
+    dependencies:
+      '@vue/devtools-core': 8.0.6(vite@7.3.1(yaml@2.8.2))(vue@3.5.28)
+      '@vue/devtools-kit': 8.0.6
+      '@vue/devtools-shared': 8.0.6
+      sirv: 3.0.2
+      vite: 7.3.1(yaml@2.8.2)
+      vite-plugin-inspect: 11.3.3(vite@7.3.1(yaml@2.8.2))
+      vite-plugin-vue-inspector: 5.3.2(vite@7.3.1(yaml@2.8.2))
+    transitivePeerDependencies:
+      - '@nuxt/kit'
+      - supports-color
+      - vue
+
+  vite-plugin-vue-inspector@5.3.2(vite@7.3.1(yaml@2.8.2)):
+    dependencies:
+      '@babel/core': 7.29.0
+      '@babel/plugin-proposal-decorators': 7.29.0(@babel/core@7.29.0)
+      '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.0)
+      '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.29.0)
+      '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0)
+      '@vue/babel-plugin-jsx': 1.5.0(@babel/core@7.29.0)
+      '@vue/compiler-dom': 3.5.28
+      kolorist: 1.8.0
+      magic-string: 0.30.21
+      vite: 7.3.1(yaml@2.8.2)
+    transitivePeerDependencies:
+      - supports-color
+
+  vite@7.3.1(yaml@2.8.2):
+    dependencies:
+      esbuild: 0.27.3
+      fdir: 6.5.0(picomatch@4.0.3)
+      picomatch: 4.0.3
+      postcss: 8.5.6
+      rollup: 4.57.1
+      tinyglobby: 0.2.15
+    optionalDependencies:
+      fsevents: 2.3.3
+      yaml: 2.8.2
+
+  vue-router@5.0.2(@vue/compiler-sfc@3.5.28)(vue@3.5.28):
+    dependencies:
+      '@babel/generator': 7.29.1
+      '@vue-macros/common': 3.1.2(vue@3.5.28)
+      '@vue/devtools-api': 8.0.6
+      ast-walker-scope: 0.8.3
+      chokidar: 5.0.0
+      json5: 2.2.3
+      local-pkg: 1.1.2
+      magic-string: 0.30.21
+      mlly: 1.8.0
+      muggle-string: 0.4.1
+      pathe: 2.0.3
+      picomatch: 4.0.3
+      scule: 1.3.0
+      tinyglobby: 0.2.15
+      unplugin: 3.0.0
+      unplugin-utils: 0.3.1
+      vue: 3.5.28
+      yaml: 2.8.2
+    optionalDependencies:
+      '@vue/compiler-sfc': 3.5.28
+
+  vue@3.5.28:
+    dependencies:
+      '@vue/compiler-dom': 3.5.28
+      '@vue/compiler-sfc': 3.5.28
+      '@vue/runtime-dom': 3.5.28
+      '@vue/server-renderer': 3.5.28(vue@3.5.28)
+      '@vue/shared': 3.5.28
+
+  webpack-virtual-modules@0.6.2: {}
+
+  wsl-utils@0.1.0:
+    dependencies:
+      is-wsl: 3.1.0
+
+  yallist@3.1.1: {}
+
+  yaml@2.8.2: {}

BIN
public/favicon.ico


+ 50 - 0
src/App.vue

@@ -0,0 +1,50 @@
+<script setup>
+import { RouterView } from 'vue-router'
+import AppHeader from './components/layout/AppHeader.vue'
+import AppFooter from './components/layout/AppFooter.vue'
+import BackToTop from './components/motion/BackToTop.vue'
+import FormBanner from './components/layout/FormBanner.vue'
+import SideButtons from './components/layout/SideButtons.vue'
+</script>
+
+<template>
+  <div class="app-shell">
+    <AppHeader />
+    <main class="app-main">
+      <RouterView v-slot="{ Component }">
+        <Transition name="page" mode="out-in">
+          <component :is="Component" />
+        </Transition>
+      </RouterView>
+    </main>
+    <FormBanner />
+    <AppFooter />
+    <BackToTop />
+    <SideButtons />
+  </div>
+</template>
+
+<style>
+.page-enter-active,
+.page-leave-active {
+  transition: opacity 240ms ease, transform 240ms ease;
+}
+
+.page-enter-from,
+.page-leave-to {
+  opacity: 0;
+  transform: translate3d(0, 8px, 0);
+}
+
+@media (prefers-reduced-motion: reduce) {
+  .page-enter-active,
+  .page-leave-active {
+    transition: none;
+  }
+  .page-enter-from,
+  .page-leave-to {
+    opacity: 1;
+    transform: none;
+  }
+}
+</style>

+ 81 - 0
src/assets/base.css

@@ -0,0 +1,81 @@
+:root {
+  /* Brand */
+  --brand-50: #eff6ff;
+  --brand-100: #dbeafe;
+  --brand-200: #bfdbfe;
+  --brand-500: #2563eb;
+  --brand-600: #1d4ed8;
+  --brand-700: #1e40af;
+
+  /* Neutrals */
+  --slate-50: #f8fafc;
+  --slate-100: #f1f5f9;
+  --slate-200: #e2e8f0;
+  --slate-300: #cbd5e1;
+  --slate-500: #64748b;
+  --slate-700: rgb(51, 51, 51);
+  --slate-800: #1f2937;
+  --slate-900: #0f172a;
+
+  /* Semantic */
+  --bg: #ffffff;
+  --bg-soft: var(--slate-50);
+  --text: var(--slate-900);
+  --text-muted: var(--slate-500);
+  --border: rgba(15, 23, 42, 0.12);
+  --shadow: 0 10px 30px rgba(2, 6, 23, 0.10);
+  --back-top: rgba(0, 0, 0, 0.1) 0px 6px 12px 1px;
+
+  /* Layout */
+  --container-max: 1200px;
+  --radius-lg: 16px;
+  --radius-md: 12px;
+  --radius-sm: 10px;
+  --section-pad: 72px;
+  --header-h: 72px;
+}
+
+*,
+*::before,
+*::after {
+  box-sizing: border-box;
+  margin: 0;
+}
+
+body {
+  min-height: 100vh;
+  color: var(--text);
+  background: var(--bg);
+  line-height: 1.6;
+  font-family:
+    Inter,
+    -apple-system,
+    BlinkMacSystemFont,
+    'Segoe UI',
+    Roboto,
+    Oxygen,
+    Ubuntu,
+    Cantarell,
+    'Fira Sans',
+    'Droid Sans',
+    'Helvetica Neue',
+    sans-serif;
+  font-size: 15px;
+  text-rendering: optimizeLegibility;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+img {
+  max-width: 100%;
+  height: auto;
+}
+
+a {
+  color: inherit;
+  text-decoration: none;
+}
+
+button {
+  font: inherit;
+}

+ 63 - 0
src/assets/illustrations/hero-industrial.svg

@@ -0,0 +1,63 @@
+<svg width="1200" height="840" viewBox="0 0 1200 840" fill="none" xmlns="http://www.w3.org/2000/svg">
+  <defs>
+    <linearGradient id="g1" x1="140" y1="120" x2="980" y2="760" gradientUnits="userSpaceOnUse">
+      <stop stop-color="#DBEAFE"/>
+      <stop offset="0.45" stop-color="#93C5FD"/>
+      <stop offset="1" stop-color="#1D4ED8"/>
+    </linearGradient>
+    <linearGradient id="g2" x1="80" y1="100" x2="1060" y2="780" gradientUnits="userSpaceOnUse">
+      <stop stop-color="#FFFFFF" stop-opacity="0.9"/>
+      <stop offset="1" stop-color="#FFFFFF" stop-opacity="0.2"/>
+    </linearGradient>
+    <filter id="s" x="-40" y="-40" width="1280" height="920" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+      <feDropShadow dx="0" dy="18" stdDeviation="22" flood-color="#0B1220" flood-opacity="0.18"/>
+    </filter>
+  </defs>
+
+  <rect x="0" y="0" width="1200" height="840" rx="44" fill="url(#g2)"/>
+  <g filter="url(#s)">
+    <rect x="110" y="130" width="980" height="580" rx="32" fill="#FFFFFF"/>
+    <rect x="110" y="130" width="980" height="84" rx="32" fill="#F8FAFC"/>
+    <circle cx="160" cy="172" r="10" fill="#CBD5E1"/>
+    <circle cx="195" cy="172" r="10" fill="#CBD5E1"/>
+    <circle cx="230" cy="172" r="10" fill="#CBD5E1"/>
+
+    <rect x="150" y="250" width="360" height="200" rx="22" fill="url(#g1)" opacity="0.22"/>
+    <rect x="150" y="470" width="360" height="200" rx="22" fill="#F8FAFC"/>
+    <rect x="540" y="250" width="510" height="420" rx="22" fill="#F8FAFC"/>
+
+    <rect x="180" y="285" width="220" height="16" rx="8" fill="#1D4ED8" opacity="0.75"/>
+    <rect x="180" y="315" width="290" height="14" rx="7" fill="#1D4ED8" opacity="0.35"/>
+    <rect x="180" y="342" width="260" height="14" rx="7" fill="#1D4ED8" opacity="0.28"/>
+
+    <g opacity="0.85">
+      <path d="M612 600 C680 540, 730 520, 804 480 C860 450, 914 430, 990 390" stroke="#1D4ED8" stroke-width="10" stroke-linecap="round" stroke-linejoin="round" opacity="0.55"/>
+      <path d="M612 600 C676 560, 724 544, 792 520 C846 500, 914 470, 990 430" stroke="#38BDF8" stroke-width="10" stroke-linecap="round" stroke-linejoin="round" opacity="0.35"/>
+      <circle cx="612" cy="600" r="14" fill="#1D4ED8"/>
+      <circle cx="804" cy="480" r="14" fill="#2563EB"/>
+      <circle cx="990" cy="390" r="14" fill="#1D4ED8"/>
+      <circle cx="990" cy="430" r="14" fill="#38BDF8"/>
+    </g>
+
+    <g opacity="0.95">
+      <rect x="180" y="505" width="220" height="18" rx="9" fill="#0F172A" opacity="0.82"/>
+      <rect x="180" y="538" width="290" height="14" rx="7" fill="#64748B" opacity="0.55"/>
+      <rect x="180" y="565" width="260" height="14" rx="7" fill="#64748B" opacity="0.40"/>
+      <rect x="180" y="592" width="210" height="14" rx="7" fill="#64748B" opacity="0.32"/>
+    </g>
+
+    <g>
+      <rect x="580" y="290" width="430" height="92" rx="18" fill="#FFFFFF" stroke="#E2E8F0"/>
+      <rect x="600" y="316" width="220" height="14" rx="7" fill="#0F172A" opacity="0.82"/>
+      <rect x="600" y="342" width="340" height="12" rx="6" fill="#94A3B8" opacity="0.70"/>
+      <rect x="580" y="402" width="430" height="92" rx="18" fill="#FFFFFF" stroke="#E2E8F0"/>
+      <rect x="600" y="428" width="250" height="14" rx="7" fill="#0F172A" opacity="0.80"/>
+      <rect x="600" y="454" width="360" height="12" rx="6" fill="#94A3B8" opacity="0.68"/>
+      <rect x="580" y="514" width="430" height="132" rx="18" fill="#FFFFFF" stroke="#E2E8F0"/>
+      <rect x="600" y="540" width="240" height="14" rx="7" fill="#0F172A" opacity="0.80"/>
+      <rect x="600" y="566" width="360" height="12" rx="6" fill="#94A3B8" opacity="0.68"/>
+      <rect x="600" y="590" width="320" height="12" rx="6" fill="#94A3B8" opacity="0.56"/>
+    </g>
+  </g>
+</svg>
+

+ 9 - 0
src/assets/illustrations/logo-placeholder.svg

@@ -0,0 +1,9 @@
+<svg width="360" height="120" viewBox="0 0 360 120" fill="none" xmlns="http://www.w3.org/2000/svg">
+  <rect x="10" y="10" width="340" height="100" rx="22" fill="#FFFFFF"/>
+  <rect x="10" y="10" width="340" height="100" rx="22" stroke="#E2E8F0"/>
+  <circle cx="70" cy="60" r="18" fill="#DBEAFE"/>
+  <path d="M62 60c10-18 26-18 36 0c-10 18-26 18-36 0Z" fill="#1D4ED8" opacity="0.8"/>
+  <rect x="105" y="48" width="170" height="12" rx="6" fill="#0F172A" opacity="0.75"/>
+  <rect x="105" y="68" width="140" height="10" rx="5" fill="#94A3B8" opacity="0.7"/>
+</svg>
+

+ 38 - 0
src/assets/illustrations/section-data.svg

@@ -0,0 +1,38 @@
+<svg width="1200" height="640" viewBox="0 0 1200 640" fill="none" xmlns="http://www.w3.org/2000/svg">
+  <defs>
+    <linearGradient id="bg" x1="100" y1="60" x2="1100" y2="580" gradientUnits="userSpaceOnUse">
+      <stop stop-color="#EFF6FF"/>
+      <stop offset="1" stop-color="#FFFFFF"/>
+    </linearGradient>
+    <linearGradient id="line" x1="250" y1="420" x2="950" y2="220" gradientUnits="userSpaceOnUse">
+      <stop stop-color="#1D4ED8" stop-opacity="0.20"/>
+      <stop offset="0.5" stop-color="#38BDF8" stop-opacity="0.35"/>
+      <stop offset="1" stop-color="#1D4ED8" stop-opacity="0.20"/>
+    </linearGradient>
+  </defs>
+  <rect x="0" y="0" width="1200" height="640" rx="40" fill="url(#bg)"/>
+  <g opacity="0.9">
+    <rect x="120" y="120" width="360" height="400" rx="26" fill="#FFFFFF" stroke="#E2E8F0"/>
+    <rect x="160" y="160" width="220" height="16" rx="8" fill="#0F172A" opacity="0.82"/>
+    <rect x="160" y="192" width="280" height="12" rx="6" fill="#94A3B8" opacity="0.70"/>
+    <rect x="160" y="222" width="250" height="12" rx="6" fill="#94A3B8" opacity="0.55"/>
+    <rect x="160" y="282" width="280" height="12" rx="6" fill="#94A3B8" opacity="0.52"/>
+    <rect x="160" y="312" width="240" height="12" rx="6" fill="#94A3B8" opacity="0.45"/>
+    <rect x="160" y="342" width="260" height="12" rx="6" fill="#94A3B8" opacity="0.40"/>
+    <rect x="160" y="402" width="190" height="42" rx="14" fill="#DBEAFE"/>
+    <rect x="360" y="402" width="80" height="42" rx="14" fill="#1D4ED8" opacity="0.18"/>
+  </g>
+  <g>
+    <rect x="540" y="140" width="540" height="140" rx="26" fill="#FFFFFF" stroke="#E2E8F0"/>
+    <rect x="580" y="178" width="240" height="16" rx="8" fill="#0F172A" opacity="0.82"/>
+    <rect x="580" y="210" width="420" height="12" rx="6" fill="#94A3B8" opacity="0.65"/>
+
+    <rect x="540" y="310" width="540" height="210" rx="26" fill="#FFFFFF" stroke="#E2E8F0"/>
+    <rect x="580" y="350" width="260" height="16" rx="8" fill="#0F172A" opacity="0.82"/>
+    <path d="M590 470 C680 420, 740 410, 820 370 C890 336, 950 320, 1030 290" stroke="url(#line)" stroke-width="12" stroke-linecap="round" opacity="1"/>
+    <circle cx="590" cy="470" r="12" fill="#1D4ED8"/>
+    <circle cx="820" cy="370" r="12" fill="#38BDF8"/>
+    <circle cx="1030" cy="290" r="12" fill="#1D4ED8"/>
+  </g>
+</svg>
+

BIN
src/assets/images/afterSales.jpg


BIN
src/assets/images/banner.jpg


BIN
src/assets/images/banner2.jpg


BIN
src/assets/images/banner3.jpg


BIN
src/assets/images/bg-index-3.jpg


BIN
src/assets/images/bg.jpg


BIN
src/assets/images/bg2.jpg


BIN
src/assets/images/bg2.png


BIN
src/assets/images/foot-bj.jpg


BIN
src/assets/images/form_back.png


BIN
src/assets/images/form_img6.png


BIN
src/assets/images/form_img7.png


BIN
src/assets/images/indexP8.jpg


BIN
src/assets/images/index_back2.png


BIN
src/assets/images/index_img4_backs.png


BIN
src/assets/images/jiaohu.png


BIN
src/assets/images/logo.png


BIN
src/assets/images/title1.png


BIN
src/assets/images/title2.png


BIN
src/assets/images/方案.png


BIN
src/assets/images/案例.png


+ 222 - 0
src/assets/main.css

@@ -0,0 +1,222 @@
+@import './base.css';
+
+#app {
+  min-height: 100vh;
+}
+
+.reveal {
+  opacity: 0;
+  transform: translate3d(0, var(--reveal-y, 14px), 0);
+  transition:
+    opacity 520ms ease,
+    transform 520ms ease;
+  transition-delay: var(--reveal-delay, 0ms);
+  will-change: transform, opacity;
+}
+
+.reveal.is-visible {
+  opacity: 1;
+  transform: translate3d(0, 0, 0);
+}
+
+.hover-lift {
+  transition: transform 160ms ease, box-shadow 160ms ease;
+}
+
+.hover-lift:hover {
+  transform: translateY(-2px);
+  box-shadow: var(--shadow);
+}
+
+.float {
+  animation: floatY 6s ease-in-out infinite;
+}
+
+@keyframes floatY {
+  0%,
+  100% {
+    transform: translateY(0);
+  }
+  50% {
+    transform: translateY(-8px);
+  }
+}
+
+.container {
+  width: 100%;
+  max-width: var(--container-max);
+  margin: 0 auto;
+  padding: 0 20px;
+}
+
+.app-shell {
+  min-height: 100vh;
+  display: flex;
+  flex-direction: column;
+}
+
+.app-main {
+  flex: 1;
+  padding-top: var(--header-h);
+}
+
+.section {
+  padding: var(--section-pad) 0;
+}
+
+.section--soft {
+  background: var(--bg-soft);
+}
+
+.section-kicker {
+  display: inline-flex;
+  gap: 8px;
+  align-items: center;
+  padding: 6px 10px;
+  border-radius: 999px;
+  background: rgba(37, 99, 235, 0.08);
+  color: var(--brand-700);
+  font-weight: 600;
+  font-size: 12px;
+}
+
+.h2 {
+  font-size: 28px;
+  line-height: 1.25;
+  letter-spacing: -0.02em;
+}
+
+.muted {
+  color: var(--text-muted);
+}
+
+.grid {
+  display: grid;
+  gap: 18px;
+}
+
+.grid-3 {
+  grid-template-columns: repeat(3, minmax(0, 1fr));
+}
+
+.grid-4 {
+  grid-template-columns: repeat(4, minmax(0, 1fr));
+}
+
+.card {
+  background: #fff;
+  border: 1px solid var(--border);
+  /* border-radius: var(--radius-lg); */
+  box-shadow: 0 1px 0 rgba(2, 6, 23, 0.02);
+}
+
+.card-pad {
+  padding: 18px;
+}
+
+.btn {
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  gap: 8px;
+  height: 36px;
+  padding: 0 14px;
+  border-radius: 5px;
+  border: 1px solid transparent;
+  cursor: pointer;
+  user-select: none;
+  transition: 160ms ease;
+
+}
+
+.btn-primary {
+  background: var(--brand-600);
+  color: #fff;
+}
+
+.btn-primary:hover {
+  background: var(--brand-700);
+}
+
+.btn:active {
+  transform: translateY(1px);
+}
+
+.btn:focus-visible {
+  outline: none;
+  box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.14);
+}
+
+.btn-ghost {
+  background: rgba(15, 23, 42, 0.02);
+  border-color: var(--border);
+  color: var(--text);
+}
+
+.btn-ghost:hover {
+  background: rgba(15, 23, 42, 0.04);
+}
+
+.btn-link {
+  height: auto;
+  padding: 0;
+  border: 0;
+  background: transparent;
+  color: var(--brand-700);
+}
+
+.pill {
+  display: inline-flex;
+  align-items: center;
+  gap: 6px;
+  padding: 6px 10px;
+  border-radius: 999px;
+  border: 1px solid var(--border);
+  background: #fff;
+  color: var(--slate-700);
+  font-size: 12px;
+  font-weight: 600;
+}
+
+.divider {
+  height: 1px;
+  background: var(--border);
+}
+
+@media (max-width: 960px) {
+  :root {
+    --section-pad: 56px;
+    --header-h: 64px;
+  }
+
+  .grid-4 {
+    grid-template-columns: repeat(2, minmax(0, 1fr));
+  }
+
+  .grid-3 {
+    grid-template-columns: repeat(1, minmax(0, 1fr));
+  }
+}
+
+@media (max-width: 520px) {
+  .grid-4 {
+    grid-template-columns: repeat(1, minmax(0, 1fr));
+  }
+}
+
+@media (prefers-reduced-motion: reduce) {
+  .reveal {
+    transition: none;
+    opacity: 1;
+    transform: none;
+  }
+  .float {
+    animation: none;
+  }
+  .hover-lift,
+  .hover-lift:hover {
+    transition: none;
+    transform: none;
+    box-shadow: none;
+  }
+}

+ 44 - 0
src/components/HelloWorld.vue

@@ -0,0 +1,44 @@
+<script setup>
+defineProps({
+  msg: {
+    type: String,
+    required: true,
+  },
+})
+</script>
+
+<template>
+  <div class="greetings">
+    <h1 class="green">{{ msg }}</h1>
+    <h3>
+      You’ve successfully created a project with
+      <a href="https://vite.dev/" target="_blank" rel="noopener">Vite</a> +
+      <a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>.
+    </h3>
+  </div>
+</template>
+
+<style scoped>
+h1 {
+  font-weight: 500;
+  font-size: 2.6rem;
+  position: relative;
+  top: -10px;
+}
+
+h3 {
+  font-size: 1.2rem;
+}
+
+.greetings h1,
+.greetings h3 {
+  text-align: center;
+}
+
+@media (min-width: 1024px) {
+  .greetings h1,
+  .greetings h3 {
+    text-align: left;
+  }
+}
+</style>

+ 64 - 0
src/components/PageHero.vue

@@ -0,0 +1,64 @@
+<script setup>
+defineProps({
+  title: { type: String, required: true },
+  subtitle: { type: String, default: '' },
+  kicker: { type: String, default: '' },
+})
+</script>
+
+<template>
+  <section class="pageHero">
+    <div class="container pageHero__inner">
+      <div class="pageHero__content">
+        <div v-if="kicker" class="section-kicker">{{ kicker }}</div>
+        <h1 class="pageHero__title">{{ title }}</h1>
+        <p v-if="subtitle" class="muted pageHero__subtitle">{{ subtitle }}</p>
+        <div class="pageHero__actions">
+          <slot name="actions"></slot>
+        </div>
+      </div>
+    </div>
+  </section>
+</template>
+
+<style scoped>
+.pageHero {
+  padding: 52px 0 24px;
+  background:
+    radial-gradient(900px 420px at 20% 10%, rgba(37, 99, 235, 0.18), transparent 60%),
+    radial-gradient(900px 420px at 80% 30%, rgba(56, 189, 248, 0.14), transparent 60%),
+    linear-gradient(180deg, #ffffff, var(--bg-soft));
+  border-bottom: 1px solid var(--border);
+}
+
+.pageHero__title {
+  margin-top: 12px;
+  font-size: 34px;
+  line-height: 1.18;
+  letter-spacing: -0.03em;
+}
+
+.pageHero__subtitle {
+  margin-top: 10px;
+  max-width: 70ch;
+}
+
+.pageHero__actions {
+  margin-top: 16px;
+  display: flex;
+  gap: 12px;
+  flex-wrap: wrap;
+  align-items: center;
+}
+
+@media (max-width: 520px) {
+  .pageHero {
+    padding: 44px 0 18px;
+  }
+
+  .pageHero__title {
+    font-size: 28px;
+  }
+}
+</style>
+

+ 95 - 0
src/components/TheWelcome.vue

@@ -0,0 +1,95 @@
+<script setup>
+import WelcomeItem from './WelcomeItem.vue'
+import DocumentationIcon from './icons/IconDocumentation.vue'
+import ToolingIcon from './icons/IconTooling.vue'
+import EcosystemIcon from './icons/IconEcosystem.vue'
+import CommunityIcon from './icons/IconCommunity.vue'
+import SupportIcon from './icons/IconSupport.vue'
+
+const openReadmeInEditor = () => fetch('/__open-in-editor?file=README.md')
+</script>
+
+<template>
+  <WelcomeItem>
+    <template #icon>
+      <DocumentationIcon />
+    </template>
+    <template #heading>Documentation</template>
+
+    Vue’s
+    <a href="https://vuejs.org/" target="_blank" rel="noopener">official documentation</a>
+    provides you with all information you need to get started.
+  </WelcomeItem>
+
+  <WelcomeItem>
+    <template #icon>
+      <ToolingIcon />
+    </template>
+    <template #heading>Tooling</template>
+
+    This project is served and bundled with
+    <a href="https://vite.dev/guide/features.html" target="_blank" rel="noopener">Vite</a>. The
+    recommended IDE setup is
+    <a href="https://code.visualstudio.com/" target="_blank" rel="noopener">VSCode</a>
+    +
+    <a href="https://github.com/vuejs/language-tools" target="_blank" rel="noopener"
+      >Vue - Official</a
+    >. If you need to test your components and web pages, check out
+    <a href="https://vitest.dev/" target="_blank" rel="noopener">Vitest</a>
+    and
+    <a href="https://www.cypress.io/" target="_blank" rel="noopener">Cypress</a>
+    /
+    <a href="https://playwright.dev/" target="_blank" rel="noopener">Playwright</a>.
+
+    <br />
+
+    More instructions are available in
+    <a href="javascript:void(0)" @click="openReadmeInEditor"><code>README.md</code></a
+    >.
+  </WelcomeItem>
+
+  <WelcomeItem>
+    <template #icon>
+      <EcosystemIcon />
+    </template>
+    <template #heading>Ecosystem</template>
+
+    Get official tools and libraries for your project:
+    <a href="https://pinia.vuejs.org/" target="_blank" rel="noopener">Pinia</a>,
+    <a href="https://router.vuejs.org/" target="_blank" rel="noopener">Vue Router</a>,
+    <a href="https://test-utils.vuejs.org/" target="_blank" rel="noopener">Vue Test Utils</a>, and
+    <a href="https://github.com/vuejs/devtools" target="_blank" rel="noopener">Vue Dev Tools</a>. If
+    you need more resources, we suggest paying
+    <a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">Awesome Vue</a>
+    a visit.
+  </WelcomeItem>
+
+  <WelcomeItem>
+    <template #icon>
+      <CommunityIcon />
+    </template>
+    <template #heading>Community</template>
+
+    Got stuck? Ask your question on
+    <a href="https://chat.vuejs.org" target="_blank" rel="noopener">Vue Land</a>
+    (our official Discord server), or
+    <a href="https://stackoverflow.com/questions/tagged/vue.js" target="_blank" rel="noopener"
+      >StackOverflow</a
+    >. You should also follow the official
+    <a href="https://bsky.app/profile/vuejs.org" target="_blank" rel="noopener">@vuejs.org</a>
+    Bluesky account or the
+    <a href="https://x.com/vuejs" target="_blank" rel="noopener">@vuejs</a>
+    X account for latest news in the Vue world.
+  </WelcomeItem>
+
+  <WelcomeItem>
+    <template #icon>
+      <SupportIcon />
+    </template>
+    <template #heading>Support Vue</template>
+
+    As an independent project, Vue relies on community backing for its sustainability. You can help
+    us by
+    <a href="https://vuejs.org/sponsor/" target="_blank" rel="noopener">becoming a sponsor</a>.
+  </WelcomeItem>
+</template>

+ 86 - 0
src/components/WelcomeItem.vue

@@ -0,0 +1,86 @@
+<template>
+  <div class="item">
+    <i>
+      <slot name="icon"></slot>
+    </i>
+    <div class="details">
+      <h3>
+        <slot name="heading"></slot>
+      </h3>
+      <slot></slot>
+    </div>
+  </div>
+</template>
+
+<style scoped>
+.item {
+  margin-top: 2rem;
+  display: flex;
+  position: relative;
+}
+
+.details {
+  flex: 1;
+  margin-left: 1rem;
+}
+
+i {
+  display: flex;
+  place-items: center;
+  place-content: center;
+  width: 32px;
+  height: 32px;
+  color: var(--color-text);
+}
+
+h3 {
+  font-size: 1.2rem;
+  font-weight: 500;
+  margin-bottom: 0.4rem;
+  color: var(--color-heading);
+}
+
+@media (min-width: 1024px) {
+  .item {
+    margin-top: 0;
+    padding: 0.4rem 0 1rem calc(var(--section-gap) / 2);
+  }
+
+  i {
+    top: calc(50% - 25px);
+    left: -26px;
+    position: absolute;
+    border: 1px solid var(--color-border);
+    background: var(--color-background);
+    /* border-radius: 8px; */
+    width: 50px;
+    height: 50px;
+  }
+
+  .item:before {
+    content: " ";
+    border-left: 1px solid var(--color-border);
+    position: absolute;
+    left: 0;
+    bottom: calc(50% + 25px);
+    height: calc(50% - 25px);
+  }
+
+  .item:after {
+    content: " ";
+    border-left: 1px solid var(--color-border);
+    position: absolute;
+    left: 0;
+    top: calc(50% + 25px);
+    height: calc(50% - 25px);
+  }
+
+  .item:first-of-type:before {
+    display: none;
+  }
+
+  .item:last-of-type:after {
+    display: none;
+  }
+}
+</style>

+ 7 - 0
src/components/icons/IconCommunity.vue

@@ -0,0 +1,7 @@
+<template>
+  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
+    <path
+      d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
+    />
+  </svg>
+</template>

+ 7 - 0
src/components/icons/IconDocumentation.vue

@@ -0,0 +1,7 @@
+<template>
+  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
+    <path
+      d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
+    />
+  </svg>
+</template>

+ 7 - 0
src/components/icons/IconEcosystem.vue

@@ -0,0 +1,7 @@
+<template>
+  <svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor">
+    <path
+      d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
+    />
+  </svg>
+</template>

+ 7 - 0
src/components/icons/IconSupport.vue

@@ -0,0 +1,7 @@
+<template>
+  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
+    <path
+      d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
+    />
+  </svg>
+</template>

+ 19 - 0
src/components/icons/IconTooling.vue

@@ -0,0 +1,19 @@
+<!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
+<template>
+  <svg
+    xmlns="http://www.w3.org/2000/svg"
+    xmlns:xlink="http://www.w3.org/1999/xlink"
+    aria-hidden="true"
+    role="img"
+    class="iconify iconify--mdi"
+    width="24"
+    height="24"
+    preserveAspectRatio="xMidYMid meet"
+    viewBox="0 0 24 24"
+  >
+    <path
+      d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
+      fill="currentColor"
+    ></path>
+  </svg>
+</template>

+ 195 - 0
src/components/layout/AppFooter.vue

@@ -0,0 +1,195 @@
+<script setup>
+import { Icon } from "@iconify/vue";
+const links = {
+  产品: [
+    { label: "工业PaaS", hint: "平台能力与组件化", to: "/products" },
+    { label: "设备接入", hint: "边缘与协议适配", to: "/products" },
+    { label: "数据治理", hint: "资产、主数据与指标", to: "/products" },
+  ],
+  解决方案: [
+    { label: "离散制造", hint: "质量与效率提升", to: "/solutions" },
+    { label: "流程工业", hint: "预测与能效优化", to: "/solutions" },
+    { label: "园区与能源", hint: "可视化与运行管理", to: "/solutions" },
+  ],
+  资源: [
+    { label: "新闻动态", hint: "平台更新与活动", to: "/news" },
+    { label: "客户案例", hint: "行业实践与价值", to: "/cases" },
+    { label: "联系我们", hint: "咨询与演示申请", to: "/contact" },
+  ],
+};
+</script>
+
+<template>
+  <footer class="footer">
+    <div class="container footer__top">
+      <div class="footer__brand">
+        <img
+          src="../../assets//images/logo.png"
+          alt=""
+          style="width: auto; height: 36px"
+        />
+        <div class="footer__brandText">
+          <div class="footer__brandName">工业互联网门户</div>
+          <div class="muted">
+            连接设备、数据与业务,打造可持续的工业数字化底座。
+          </div>
+          <!-- <div class="footer__badges">
+            <span class="pill">安全合规</span>
+            <span class="pill">开放生态</span>
+            <span class="pill">工业级稳定</span>
+          </div> -->
+        </div>
+      </div>
+
+      <div class="footer__cols">
+        <div
+          v-for="(group, title) in links"
+          :key="title"
+          class="footer__col"
+          style="
+            display: flex;
+            flex-direction: column;
+
+            justify-content: center;
+          "
+        >
+          <div class="footer__colTitle">{{ title }}</div>
+          <RouterLink
+            v-for="item in group"
+            :key="item.label"
+            class="footer__link"
+            :to="item.to"
+          >
+            <span class="footer__linkLabel">{{ item.label }}</span>
+            <span class="footer__linkHint muted">{{ item.hint }}</span>
+          </RouterLink>
+        </div>
+      </div>
+    </div>
+
+    <div class="container footer__bottom">
+      <div class="muted">
+        © {{ new Date().getFullYear() }} Industrial Internet Portal.
+        保留所有权利。
+      </div>
+      <div class="muted" style="display: flex; gap: 15px">
+        <div style="display: flex; align-items: center; gap: 6px">
+          <Icon icon="ri:phone-fill" width="20" height="20" />
+          <span>400-000-0000</span>
+        </div>
+
+        <div style="display: flex; align-items: center; gap: 6px">
+          <Icon icon="ri:mail-fill" width="20" height="20" />
+          <span>kerui@deepOil.com</span>
+        </div>
+      </div>
+    </div>
+  </footer>
+</template>
+
+<style scoped>
+.footer {
+  background: #3b4660;
+  border-top: 1px solid rgba(255, 255, 255, 0.1);
+  color: #ffffff;
+}
+
+.footer__top {
+  padding: 46px 0 28px;
+  display: grid;
+  grid-template-columns: 1.1fr 1.9fr;
+  gap: 28px;
+}
+
+.footer__brand {
+  display: flex;
+  gap: 14px;
+}
+
+.footer__logo {
+  width: 44px;
+  height: 44px;
+
+  background: radial-gradient(
+    circle at 30% 30%,
+    var(--brand-200),
+    var(--brand-600)
+  );
+  box-shadow: 0 12px 20px rgba(29, 78, 216, 0.18);
+  flex: 0 0 auto;
+}
+
+.footer__brandName {
+  font-weight: 850;
+  letter-spacing: -0.02em;
+  margin-bottom: 6px;
+  color: #ffffff;
+}
+
+.footer__badges {
+  margin-top: 12px;
+  display: flex;
+  flex-wrap: wrap;
+  gap: 10px;
+}
+
+.footer__cols {
+  display: grid;
+  grid-template-columns: repeat(3, minmax(0, 1fr));
+  gap: 18px;
+}
+
+.footer__colTitle {
+  margin-bottom: 10px;
+  color: #ffffff;
+  text-align: left;
+}
+
+.footer__link {
+  display: grid;
+  padding: 10px 0px;
+  border-radius: 14px;
+  border: 1px solid transparent;
+  transition: 160ms ease;
+  color: #ffffff;
+}
+
+.footer__linkLabel {
+  color: #c5c8d0;
+  font-size: 14px;
+}
+
+.footer__linkLabel:hover {
+  color: #fff;
+}
+
+.footer__linkHint {
+  font-size: 12px;
+  color: rgba(255, 255, 255, 0.7);
+}
+
+.footer__bottom {
+  padding: 16px 0 20px;
+  border-top: 1px solid rgba(255, 255, 255, 0.1);
+  display: flex;
+  justify-content: space-between;
+  gap: 12px;
+  flex-wrap: wrap;
+}
+
+@media (max-width: 960px) {
+  .footer__top {
+    grid-template-columns: 1fr;
+  }
+
+  .footer__cols {
+    grid-template-columns: repeat(2, minmax(0, 1fr));
+  }
+}
+
+@media (max-width: 520px) {
+  .footer__cols {
+    grid-template-columns: 1fr;
+  }
+}
+</style>

+ 237 - 0
src/components/layout/AppHeader.vue

@@ -0,0 +1,237 @@
+<script setup>
+import { computed, ref, watch } from "vue";
+import { RouterLink, useRoute } from "vue-router";
+import { Icon } from "@iconify/vue";
+
+const route = useRoute();
+const mobileOpen = ref(false);
+
+const navItems = [
+  { label: "首页", to: "/" },
+  { label: "产品", to: "/products" },
+  { label: "解决方案", to: "/solutions" },
+  { label: "客户案例", to: "/cases" },
+  { label: "新闻动态", to: "/news" },
+  { label: "关于我们", to: "/about" },
+];
+
+watch(
+  () => route.fullPath,
+  () => {
+    mobileOpen.value = false;
+  },
+);
+
+const mobileLabel = computed(() =>
+  mobileOpen.value ? "关闭菜单" : "打开菜单",
+);
+</script>
+
+<template>
+  <header class="app-header">
+    <div class="app-header__inner">
+      <RouterLink class="brand" to="/" aria-label="工业互联网门户">
+        <img
+          src="../../assets//images/logo.png"
+          alt=""
+          style="width: auto; height: 36px"
+        />
+        <!-- <span class="brand__text">
+          <span class="brand__name">工业互联网门户</span>
+          <span class="brand__tag muted">Industrial Internet Portal</span>
+        </span> -->
+      </RouterLink>
+
+      <nav class="nav" aria-label="主导航">
+        <RouterLink
+          v-for="item in navItems"
+          :key="item.to"
+          class="nav__link"
+          :to="item.to"
+        >
+          {{ item.label }}
+        </RouterLink>
+      </nav>
+
+      <div class="actions">
+        <RouterLink class="btn actions__login" to="/contact">登录</RouterLink>
+        <RouterLink class="btn btn-primary" to="/contact">免费注册</RouterLink>
+
+        <button
+          class="hamburger"
+          type="button"
+          :aria-label="mobileLabel"
+          :aria-expanded="mobileOpen ? 'true' : 'false'"
+          @click="mobileOpen = !mobileOpen"
+        >
+          <Icon icon="lucide:menu" width="24" height="24" />
+        </button>
+      </div>
+    </div>
+
+    <div v-if="mobileOpen" class="mobile">
+      <div class="mobile__inner container">
+        <RouterLink
+          v-for="item in navItems"
+          :key="item.to"
+          class="mobile__link"
+          :to="item.to"
+        >
+          {{ item.label }}
+        </RouterLink>
+        <div class="divider"></div>
+        <RouterLink class="mobile__link" to="/contact">联系咨询</RouterLink>
+      </div>
+    </div>
+  </header>
+</template>
+
+<style scoped>
+.app-header {
+  position: fixed;
+  z-index: 50;
+  top: 0;
+  left: 0;
+  right: 0;
+  height: var(--header-h);
+  background: rgba(255, 255, 255, 0.86);
+  backdrop-filter: blur(14px);
+  border-bottom: 0.5px solid var(--border);
+}
+
+.app-header__inner {
+  height: var(--header-h);
+  display: flex;
+  align-items: center;
+  gap: 18px;
+  padding: 0 20px;
+}
+
+.brand {
+  display: inline-flex;
+  align-items: center;
+  gap: 12px;
+  min-width: 240px;
+}
+
+.brand__mark {
+  width: 34px;
+  height: 34px;
+  border-radius: 10px;
+  background: radial-gradient(
+    circle at 30% 30%,
+    var(--brand-200),
+    var(--brand-600)
+  );
+  box-shadow: 0 12px 20px rgba(29, 78, 216, 0.22);
+}
+
+.brand__text {
+  display: grid;
+  line-height: 1.1;
+}
+
+.brand__name {
+  font-weight: 800;
+  letter-spacing: -0.02em;
+}
+
+.brand__tag {
+  font-size: 12px;
+}
+
+.nav {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  gap: 2px;
+}
+
+.nav__link {
+  padding: 10px 12px;
+  border-radius: 10px;
+  color: var(--slate-700);
+  font-size: 14px;
+}
+
+.nav__link:hover {
+  background: rgba(15, 23, 42, 0.04);
+}
+
+.nav__link.router-link-exact-active {
+  background: rgba(37, 99, 235, 0.1);
+  color: var(--brand-700);
+}
+
+.actions {
+  display: inline-flex;
+  align-items: center;
+  justify-content: flex-end;
+  gap: 10px;
+}
+
+.hamburger {
+  display: none;
+  width: 42px;
+  height: 42px;
+  border-radius: 12px;
+  border: 1px solid var(--border);
+  background: #fff;
+  cursor: pointer;
+}
+
+.hamburger > span {
+  display: block;
+  height: 2px;
+  background: var(--slate-700);
+  margin: 5px 10px;
+  border-radius: 2px;
+}
+
+.mobile {
+  border-bottom: 1px solid var(--border);
+  background: #fff;
+}
+
+.mobile__inner {
+  padding: 14px 0 18px;
+  display: grid;
+  gap: 8px;
+}
+
+.mobile__link {
+  padding: 10px 12px;
+  border-radius: 12px;
+  border: 1px solid var(--border);
+  font-weight: 650;
+}
+
+.mobile__link.router-link-exact-active {
+  border-color: rgba(37, 99, 235, 0.35);
+  background: rgba(37, 99, 235, 0.08);
+  color: var(--brand-700);
+}
+
+@media (max-width: 1024px) {
+  .brand {
+    min-width: auto;
+  }
+
+  .nav {
+    display: none;
+  }
+
+  .actions__login {
+    display: none;
+  }
+
+  .actions__cta {
+    display: none;
+  }
+
+  .hamburger {
+    display: inline-block;
+  }
+}
+</style>

+ 220 - 0
src/components/layout/FormBanner.vue

@@ -0,0 +1,220 @@
+<template>
+  <div class="form-banner">
+    <div class="banner-content">
+      <div
+        style="
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          margin-bottom: 20px;
+        "
+      >
+        <img src="../../assets/images/form_img6.png" alt="" />
+        <h2 style="padding: 0 10px">了解更多企业的数字化实践案例</h2>
+        <img src="../../assets/images/form_img7.png" alt="" />
+      </div>
+
+      <div class="form-container">
+        <div class="form-row">
+          <div class="form-field">
+            <input type="text" placeholder="您的称呼" class="form-input" />
+          </div>
+          <div class="form-field">
+            <input type="tel" placeholder="您的手机号" class="form-input" />
+          </div>
+          <div class="form-field">
+            <div class="input-with-icon">
+              <input
+                type="text"
+                placeholder="请输入验证码"
+                class="form-input"
+              />
+              <img
+                src="@/assets/images/logo.png"
+                alt="MRNT"
+                class="verification-logo"
+              />
+            </div>
+          </div>
+        </div>
+
+        <div class="form-row">
+          <div class="form-field">
+            <div class="input-with-icon">
+              <input type="text" placeholder="短信验证码" class="form-input" />
+              <button class="btn-get-code">获取</button>
+            </div>
+          </div>
+          <div class="form-field">
+            <input type="text" placeholder="单位名称" class="form-input" />
+          </div>
+          <div class="form-field">
+            <input type="text" placeholder="所在部门" class="form-input" />
+          </div>
+        </div>
+
+        <div class="form-submit">
+          <button class="btn-submit">提交</button>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+// 表单逻辑可以在这里添加
+import { ref } from "vue";
+
+const formData = ref({
+  name: "",
+  phone: "",
+  verificationCode: "",
+  smsCode: "",
+  unitName: "",
+  department: "",
+});
+
+const handleGetCode = () => {
+  // 获取验证码逻辑
+  console.log("获取验证码");
+};
+
+const handleSubmit = () => {
+  // 提交表单逻辑
+  console.log("提交表单", formData.value);
+};
+</script>
+
+<style scoped>
+.form-banner {
+  position: relative;
+  height: 350px;
+  background-image: url("@/assets/images/form_back.png");
+
+  background-origin: padding-box;
+  background-position-x: 0%;
+  background-position-y: 0%;
+  background-repeat: no-repeat;
+  background-size: cover;
+  display: flex;
+  align-items: center;
+  /* padding: 40px 0; */
+}
+
+.form-banner::before {
+  content: "";
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+
+  z-index: 1;
+}
+
+.banner-content {
+  position: relative;
+  z-index: 2;
+  color: white;
+  padding: 0 20px;
+  max-width: 1000px;
+  margin: 0 auto;
+  width: 100%;
+}
+
+.banner-title {
+  font-size: 32px;
+  font-weight: 600;
+  margin-bottom: 16px;
+  text-align: center;
+}
+
+.banner-subtitle {
+  font-size: 25px;
+  opacity: 0.9;
+  font-weight: bold;
+  margin-bottom: 20px;
+  text-align: center;
+}
+
+/* .form-container {
+  background: rgba(255, 255, 255, 0.15);
+  border-radius: 8px;
+  padding: 32px;
+  backdrop-filter: blur(10px);
+} */
+
+.form-row {
+  display: flex;
+  gap: 20px;
+  margin-bottom: 20px;
+}
+
+.form-field {
+  flex: 1;
+  min-width: 0;
+}
+
+.form-input {
+  width: 100%;
+  padding: 16px 20px;
+  border: 0.5px solid rgba(255, 255, 255, 0.7);
+
+  background: rgba(255, 255, 255, 0.2);
+  color: white;
+  font-size: 14px;
+}
+
+.form-input::placeholder {
+  color: rgba(255, 255, 255, 0.7);
+}
+
+.form-input:focus {
+  outline: none;
+  border-color: white;
+}
+
+.input-with-icon {
+  position: relative;
+}
+
+.verification-logo {
+  position: absolute;
+  right: 16px;
+  top: 50%;
+  transform: translateY(-50%);
+  height: 24px;
+}
+
+.btn-get-code {
+  position: absolute;
+  right: 16px;
+  top: 50%;
+  transform: translateY(-50%);
+  background: transparent;
+  border: none;
+  color: #4a90e2;
+  font-size: 14px;
+  cursor: pointer;
+}
+
+.form-submit {
+  text-align: left;
+}
+
+.btn-submit {
+  background: #fff;
+  color: #1b54a7;
+  border: none;
+  padding: 10px 60px;
+  width: 32%;
+  font-size: 14px;
+
+  cursor: pointer;
+  transition: background 0.3s;
+}
+
+.btn-submit:hover {
+  background: #3a7bc8;
+}
+</style>

+ 106 - 0
src/components/layout/SideButtons.vue

@@ -0,0 +1,106 @@
+<script setup>
+import { ref } from "vue";
+import { Icon } from "@iconify/vue";
+const showSideButtons = ref(true);
+
+const handleFreeExperience = () => {
+  // 免费体验按钮点击事件处理
+  console.log("免费体验点击");
+};
+
+const handleOnlineConsultation = () => {
+  // 在线咨询按钮点击事件处理
+  console.log("在线咨询点击");
+};
+</script>
+
+<template>
+  <div v-if="showSideButtons" class="side-buttons">
+    <button
+      class="button-item free-experience"
+      @click="handleFreeExperience"
+      aria-label="免费体验"
+    >
+      <Icon icon="mynaui:edit-one" width="24" height="24" />
+      <span>免费体验</span>
+    </button>
+
+    <button
+      class="button-item online-consultation"
+      @click="handleOnlineConsultation"
+      aria-label="在线咨询"
+    >
+      <Icon icon="mynaui:headphones" width="24" height="24" />
+      <span>在线咨询</span>
+    </button>
+  </div>
+</template>
+
+<style scoped>
+.side-buttons {
+  position: fixed;
+  right: 10px;
+  bottom: 40%;
+  z-index: 1000;
+  display: flex;
+  border-radius: 15px;
+  height: 200px;
+  flex-direction: column;
+  /* gap: 12px; */
+  width: 55px;
+}
+
+.button-item {
+  display: flex;
+  align-items: center;
+  flex-direction: column;
+  gap: 8px;
+  padding: 12px 12px;
+  /* border-radius: 8px; */
+  background: white;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+  cursor: pointer;
+  transition: all 0.3s ease;
+  border: none;
+  font-size: 14px;
+
+  color: #333;
+  text-decoration: none;
+}
+
+.button-item:hover {
+  /* transform: translateY(-2px); */
+  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15);
+}
+
+/* .button-item:active {
+  transform: translateY(0);
+} */
+
+.free-experience {
+  background: linear-gradient(135deg, #00a9ff, #007aff);
+  color: white;
+}
+
+.online-consultation {
+  background: linear-gradient(135deg, #00a9ff, #007aff);
+  color: white;
+}
+
+@media (max-width: 768px) {
+  .side-buttons {
+    right: 12px;
+    bottom: 12px;
+  }
+
+  .button-item {
+    padding: 10px 12px;
+    font-size: 13px;
+  }
+
+  .button-item svg {
+    width: 18px;
+    height: 18px;
+  }
+}
+</style>

+ 64 - 0
src/components/motion/BackToTop.vue

@@ -0,0 +1,64 @@
+<script setup>
+import { onBeforeUnmount, onMounted, ref } from "vue";
+import { Icon } from "@iconify/vue";
+
+const visible = ref(false);
+let onScroll = null;
+
+function scrollToTop() {
+  window.scrollTo({ top: 0, behavior: "smooth" });
+}
+
+onMounted(() => {
+  if (typeof window === "undefined") return;
+  onScroll = () => {
+    visible.value = window.scrollY > 460;
+  };
+  window.addEventListener("scroll", onScroll, { passive: true });
+  onScroll();
+});
+
+onBeforeUnmount(() => {
+  if (!onScroll) return;
+  window.removeEventListener("scroll", onScroll);
+});
+</script>
+
+<template>
+  <button
+    v-show="visible"
+    class="backTop"
+    type="button"
+    aria-label="返回顶部"
+    @click="scrollToTop"
+  >
+    <!-- <Icon icon="mdi-light:home" style="color: #0951ad" /> -->
+    <Icon icon="lucide:chevron-up" width="24" height="24" />
+  </button>
+</template>
+
+<style scoped>
+.backTop {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  position: fixed;
+  z-index: 60;
+  right: 10px;
+  bottom: 30%;
+  width: 53px;
+  height: 50px;
+  border: none;
+  background-color: #fff;
+  box-shadow: var(--back-top);
+  cursor: pointer;
+  font-weight: 900;
+  color: var(--slate-700);
+  transition: 160ms ease;
+}
+
+.backTop:hover {
+  transform: translateY(-2px);
+  color: var(--brand-700);
+}
+</style>

+ 85 - 0
src/components/motion/CountUp.vue

@@ -0,0 +1,85 @@
+<script setup>
+import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
+
+const props = defineProps({
+  end: { type: Number, required: true },
+  duration: { type: Number, default: 900 },
+  prefix: { type: String, default: '' },
+  suffix: { type: String, default: '' },
+  decimals: { type: Number, default: 0 },
+})
+
+const el = ref(null)
+const current = ref(0)
+const started = ref(false)
+
+let rafId = null
+let observer = null
+
+const prefersReducedMotion = () =>
+  typeof window !== 'undefined' &&
+  window.matchMedia &&
+  window.matchMedia('(prefers-reduced-motion: reduce)').matches
+
+function formatNumber(value) {
+  const fixed = Number(value).toFixed(props.decimals)
+  const numberValue = Number(fixed)
+  return new Intl.NumberFormat('zh-CN', { maximumFractionDigits: props.decimals }).format(numberValue)
+}
+
+const text = computed(() => `${props.prefix}${formatNumber(current.value)}${props.suffix}`)
+
+function start() {
+  if (started.value) return
+  started.value = true
+
+  if (prefersReducedMotion()) {
+    current.value = props.end
+    return
+  }
+
+  const startTs = performance.now()
+  const from = 0
+  const to = props.end
+
+  const tick = (ts) => {
+    const t = Math.min(1, (ts - startTs) / props.duration)
+    const eased = 1 - Math.pow(1 - t, 3)
+    current.value = from + (to - from) * eased
+    if (t < 1) rafId = requestAnimationFrame(tick)
+  }
+
+  rafId = requestAnimationFrame(tick)
+}
+
+onMounted(() => {
+  if (typeof window === 'undefined') return
+  if (!('IntersectionObserver' in window)) {
+    start()
+    return
+  }
+
+  observer = new IntersectionObserver(
+    (entries) => {
+      for (const entry of entries) {
+        if (!entry.isIntersecting) continue
+        start()
+        if (observer) observer.disconnect()
+      }
+    },
+    { threshold: 0.5 },
+  )
+
+  if (el.value) observer.observe(el.value)
+})
+
+onBeforeUnmount(() => {
+  if (observer) observer.disconnect()
+  if (rafId) cancelAnimationFrame(rafId)
+})
+</script>
+
+<template>
+  <span ref="el">{{ text }}</span>
+</template>
+

+ 56 - 0
src/components/motion/Reveal.vue

@@ -0,0 +1,56 @@
+<script setup>
+import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
+
+const props = defineProps({
+  as: { type: String, default: 'div' },
+  delay: { type: Number, default: 0 },
+  y: { type: Number, default: 14 },
+  once: { type: Boolean, default: true },
+  threshold: { type: Number, default: 0.12 },
+  rootMargin: { type: String, default: '0px 0px -10% 0px' },
+})
+
+const el = ref(null)
+const isVisible = ref(false)
+let observer = null
+
+onMounted(() => {
+  if (typeof window === 'undefined') return
+  if (!('IntersectionObserver' in window)) {
+    isVisible.value = true
+    return
+  }
+
+  observer = new IntersectionObserver(
+    (entries) => {
+      for (const entry of entries) {
+        if (!entry.isIntersecting) continue
+        isVisible.value = true
+        if (props.once && observer) observer.disconnect()
+      }
+    },
+    {
+      threshold: props.threshold,
+      rootMargin: props.rootMargin,
+    },
+  )
+
+  if (el.value) observer.observe(el.value)
+})
+
+onBeforeUnmount(() => {
+  if (observer) observer.disconnect()
+})
+
+const styleVars = computed(() => ({
+  '--reveal-delay': `${props.delay}ms`,
+  '--reveal-y': `${props.y}px`,
+}))
+</script>
+
+<template>
+  <component :is="as" ref="el" class="reveal" :class="{ 'is-visible': isVisible }" :style="styleVars">
+    <slot></slot>
+  </component>
+</template>
+

+ 11 - 0
src/main.js

@@ -0,0 +1,11 @@
+import './assets/main.css'
+
+import { createApp } from 'vue'
+import App from './App.vue'
+import router from './router'
+
+const app = createApp(App)
+
+app.use(router)
+
+app.mount('#app')

+ 68 - 0
src/router/index.js

@@ -0,0 +1,68 @@
+import { createRouter, createWebHistory } from 'vue-router'
+import HomeView from '../views/HomeView.vue'
+
+const router = createRouter({
+  history: createWebHistory(import.meta.env.BASE_URL),
+  scrollBehavior(to, from, savedPosition) {
+    if (savedPosition) return savedPosition
+    if (to.hash) return { el: to.hash, top: 84, behavior: 'smooth' }
+    return { top: 0 }
+  },
+  routes: [
+    {
+      path: '/',
+      name: 'home',
+      component: HomeView,
+      meta: { title: '首页' },
+    },
+    {
+      path: '/products',
+      name: 'products',
+      component: () => import('../views/ProductsView.vue'),
+      meta: { title: '产品' },
+    },
+    {
+      path: '/solutions',
+      name: 'solutions',
+      component: () => import('../views/SolutionsView.vue'),
+      meta: { title: '解决方案' },
+    },
+    {
+      path: '/cases',
+      name: 'cases',
+      component: () => import('../views/CasesView.vue'),
+      meta: { title: '客户案例' },
+    },
+    {
+      path: '/news',
+      name: 'news',
+      component: () => import('../views/NewsView.vue'),
+      meta: { title: '新闻动态' },
+    },
+    {
+      path: '/about',
+      name: 'about',
+      component: () => import('../views/AboutView.vue'),
+      meta: { title: '关于我们' },
+    },
+    {
+      path: '/contact',
+      name: 'contact',
+      component: () => import('../views/ContactView.vue'),
+      meta: { title: '联系咨询' },
+    },
+    {
+      path: '/:pathMatch(.*)*',
+      name: 'not-found',
+      component: () => import('../views/NotFoundView.vue'),
+      meta: { title: '页面不存在' },
+    },
+  ],
+})
+
+router.afterEach((to) => {
+  const pageTitle = to.meta?.title ? `${to.meta.title} · 工业互联网门户` : '工业互联网门户'
+  document.title = pageTitle
+})
+
+export default router

+ 210 - 0
src/views/AboutView.vue

@@ -0,0 +1,210 @@
+<script setup>
+import PageHero from '../components/PageHero.vue'
+import jiaohuIconUrl from '../assets/images/jiaohu.png?url'
+import planIconUrl from '../assets/images/方案.png?url'
+import caseIconUrl from '../assets/images/案例.png?url'
+import Reveal from '../components/motion/Reveal.vue'
+
+const values = [
+  { title: '专业', desc: '以工业现场为第一原则,强调稳定、可控与可落地。' },
+  { title: '开放', desc: '开放接口与生态合作,让能力可复用、可扩展、可持续。' },
+  { title: '可信', desc: '安全合规、可审计、可追溯,构建企业级信任体系。' },
+  { title: '高效', desc: '通过组件化与模板化交付,加速试点与规模化复制。' },
+]
+
+const milestones = [
+  { year: '2024', title: '平台底座完善', desc: '完成 IIoT、数据治理与权限体系建设。' },
+  { year: '2025', title: '行业方案沉淀', desc: '形成离散、流程、园区等可复制交付模板。' },
+  { year: '2026', title: '门户能力升级', desc: '统一产品、方案与案例展示,提升对外服务效率。' },
+]
+
+const honors = [
+  { id: 1, title: '生态伙伴合作', src: jiaohuIconUrl },
+  { id: 2, title: '行业方案沉淀', src: planIconUrl },
+  { id: 3, title: '客户案例实践', src: caseIconUrl },
+  { id: 4, title: '安全与合规', src: planIconUrl },
+  { id: 5, title: '开放接口能力', src: jiaohuIconUrl },
+  { id: 6, title: '交付体系认证', src: caseIconUrl },
+]
+</script>
+
+<template>
+  <div>
+    <PageHero
+      kicker="关于我们"
+      title="以工业级能力,服务产业数字化升级"
+      subtitle="我们致力于打造专业、稳定、开放的工业互联网门户与平台能力,帮助企业把数据变成可持续运营的生产力。"
+    >
+      <template #actions>
+        <RouterLink class="btn btn-primary" to="/contact">联系咨询</RouterLink>
+        <RouterLink class="btn btn-ghost" to="/cases">查看案例</RouterLink>
+      </template>
+    </PageHero>
+
+    <section class="section">
+      <div class="container">
+        <div class="grid aboutGrid">
+          <Reveal as="div" class="card card-pad aboutCard hover-lift" :delay="0">
+            <div class="aboutTitle">我们做什么</div>
+            <div class="muted">
+              通过工业互联网平台能力,打通设备、数据与业务流程,提供从连接、治理到应用运营的全链路服务,覆盖制造、能源、园区与供应链等场景。
+            </div>
+          </Reveal>
+          <Reveal as="div" class="card card-pad aboutCard hover-lift" :delay="80">
+            <div class="aboutTitle">我们如何交付</div>
+            <div class="muted">
+              以“快速接入 + 数据治理 + 应用闭环”为方法论,先试点、再复制;以组件化与模板化交付,保障周期、质量与可运营性。
+            </div>
+          </Reveal>
+        </div>
+      </div>
+    </section>
+
+    <section class="section section--soft">
+      <div class="container">
+        <Reveal as="div" class="sectionHead" :delay="0">
+          <div>
+            <div class="section-kicker">价值观</div>
+            <h2 class="h2">专业、开放、可信、高效</h2>
+          </div>
+        </Reveal>
+
+        <div class="grid grid-4">
+          <Reveal
+            v-for="(v, idx) in values"
+            :key="v.title"
+            as="div"
+            class="card card-pad hover-lift"
+            :delay="60 + idx * 70"
+          >
+            <div class="valueTitle">{{ v.title }}</div>
+            <div class="muted">{{ v.desc }}</div>
+          </Reveal>
+        </div>
+      </div>
+    </section>
+
+    <section class="section">
+      <div class="container">
+        <Reveal as="div" class="sectionHead" :delay="0">
+          <div>
+            <div class="section-kicker">里程碑</div>
+            <h2 class="h2">持续演进的产品与能力</h2>
+          </div>
+        </Reveal>
+
+        <div class="grid grid-3">
+          <Reveal
+            v-for="(m, idx) in milestones"
+            :key="m.year"
+            as="div"
+            class="card card-pad milestone hover-lift"
+            :delay="60 + idx * 80"
+          >
+            <div class="year">{{ m.year }}</div>
+            <div class="milestoneTitle">{{ m.title }}</div>
+            <div class="muted">{{ m.desc }}</div>
+          </Reveal>
+        </div>
+      </div>
+    </section>
+
+    <section class="section section--soft">
+      <div class="container">
+        <Reveal as="div" class="sectionHead" :delay="0">
+          <div>
+            <div class="section-kicker">资质与生态</div>
+            <h2 class="h2">能力认证与合作伙伴</h2>
+            <div class="muted">示例占位图,可替换为你的真实资质证书与合作 Logo。</div>
+          </div>
+        </Reveal>
+
+        <div class="grid honorGrid">
+          <Reveal v-for="(h, idx) in honors" :key="h.id" as="div" class="honor hover-lift" :delay="60 + idx * 60">
+            <img :src="h.src" :alt="h.title" loading="lazy" />
+            <div class="honorTitle">{{ h.title }}</div>
+          </Reveal>
+        </div>
+      </div>
+    </section>
+  </div>
+</template>
+
+<style scoped>
+.sectionHead {
+  display: flex;
+  align-items: flex-end;
+  justify-content: space-between;
+  gap: 18px;
+  margin-bottom: 16px;
+}
+
+.aboutGrid {
+  grid-template-columns: repeat(2, minmax(0, 1fr));
+}
+
+.aboutTitle {
+  font-weight: 900;
+  letter-spacing: -0.02em;
+  margin-bottom: 8px;
+}
+
+.valueTitle {
+  font-weight: 900;
+  margin-bottom: 6px;
+}
+
+.milestone .year {
+  font-weight: 900;
+  color: var(--brand-700);
+  letter-spacing: -0.02em;
+}
+
+.milestoneTitle {
+  font-weight: 900;
+  margin-top: 6px;
+  margin-bottom: 6px;
+}
+
+.honorGrid {
+  grid-template-columns: repeat(3, minmax(0, 1fr));
+  gap: 14px;
+}
+
+.honor {
+  border: 1px solid var(--border);
+  border-radius: 18px;
+  background: #fff;
+  padding: 12px;
+  display: grid;
+  gap: 10px;
+}
+
+.honor img {
+  width: 100%;
+  display: block;
+  border-radius: 14px;
+  border: 1px solid var(--border);
+}
+
+.honorTitle {
+  font-weight: 850;
+  color: var(--slate-700);
+}
+
+@media (max-width: 960px) {
+  .aboutGrid {
+    grid-template-columns: 1fr;
+  }
+
+  .honorGrid {
+    grid-template-columns: repeat(2, minmax(0, 1fr));
+  }
+}
+
+@media (max-width: 520px) {
+  .honorGrid {
+    grid-template-columns: 1fr;
+  }
+}
+</style>

+ 202 - 0
src/views/CasesView.vue

@@ -0,0 +1,202 @@
+<script setup>
+import { computed, ref } from "vue";
+import PageHero from "../components/PageHero.vue";
+import bannerUrl from "../assets/images/banner.jpg?url";
+import bgUrl from "../assets/images/bg.jpg?url";
+import Reveal from "../components/motion/Reveal.vue";
+
+const industries = ["全部", "汽车", "化工", "装备", "电子", "能源", "园区"];
+const active = ref("全部");
+
+const allCases = [
+  {
+    industry: "汽车",
+    title: "过程质量追溯与异常闭环",
+    desc: "打通工序数据与质量规则,实现异常定位与闭环处理。",
+    cover: bannerUrl,
+    metrics: ["良率 +3.2%", "追溯时间 -80%", "异常闭环 T+1"],
+  },
+  {
+    industry: "化工",
+    title: "能效监测与对标优化",
+    desc: "构建能耗指标体系与异常分析模型,实现持续能效提升。",
+    cover: bgUrl,
+    metrics: ["能耗 -6.8%", "对标覆盖 12 装置", "异常预警 7 类"],
+  },
+  {
+    industry: "装备",
+    title: "预测性维护与停机治理",
+    desc: "多源数据融合评估健康度,提前预警故障风险。",
+    cover: bannerUrl,
+    metrics: ["停机 -20%", "维修成本 -12%", "告警准确率 +15%"],
+  },
+  {
+    industry: "电子",
+    title: "设备接入与 OEE 提升",
+    desc: "统一采集与运行监控,驱动 OEE 分析与产线瓶颈改善。",
+    cover: bgUrl,
+    metrics: ["OEE +5.5%", "采集点位 6,000+", "停机原因 100% 标准化"],
+  },
+  {
+    industry: "能源",
+    title: "设备巡检与工单联动",
+    desc: "巡检计划、移动端执行与工单闭环,形成运维知识沉淀。",
+    cover: bannerUrl,
+    metrics: ["工单闭环率 98%", "巡检漏检 0", "知识库 300+"],
+  },
+  {
+    industry: "园区",
+    title: "园区运营可视化",
+    desc: "统一态势大屏与多系统联动,实现事件快速响应。",
+    cover: bgUrl,
+    metrics: ["事件响应 -35%", "系统对接 10+", "指标 200+"],
+  },
+];
+
+const filtered = computed(() => {
+  if (active.value === "全部") return allCases;
+  return allCases.filter((c) => c.industry === active.value);
+});
+</script>
+
+<template>
+  <div>
+    <PageHero
+      kicker="客户案例"
+      title="以指标呈现价值"
+      subtitle="从设备接入、数据治理到应用运营,沉淀可复用的行业实践。"
+    >
+      <template #actions>
+        <RouterLink class="btn btn-primary" to="/contact"
+          >获取案例集</RouterLink
+        >
+        <RouterLink class="btn btn-ghost" to="/solutions">匹配方案</RouterLink>
+      </template>
+    </PageHero>
+
+    <section class="section">
+      <div class="container">
+        <Reveal as="div" class="filters" :delay="0">
+          <button
+            v-for="i in industries"
+            :key="i"
+            type="button"
+            class="filter"
+            :data-active="active === i ? 'true' : 'false'"
+            @click="active = i"
+          >
+            {{ i }}
+          </button>
+        </Reveal>
+
+        <div class="grid grid-3">
+          <Reveal
+            v-for="(c, idx) in filtered"
+            :key="c.title"
+            as="div"
+            class="card caseCard hover-lift"
+            :delay="60 + idx * 70"
+          >
+            <img
+              class="caseCover"
+              :src="c.cover"
+              :alt="c.title"
+              loading="lazy"
+            />
+            <div class="casePad">
+              <div class="caseTop">
+                <span class="pill">{{ c.industry }}</span>
+                <RouterLink class="btn btn-link" to="/contact"
+                  >对接同类项目 →</RouterLink
+                >
+              </div>
+              <div class="caseTitle">{{ c.title }}</div>
+              <div class="muted">{{ c.desc }}</div>
+              <div class="caseMetrics">
+                <span v-for="m in c.metrics" :key="m" class="metric">{{
+                  m
+                }}</span>
+              </div>
+            </div>
+          </Reveal>
+        </div>
+      </div>
+    </section>
+  </div>
+</template>
+
+<style scoped>
+.filters {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 10px;
+  margin-bottom: 16px;
+}
+
+.filter {
+  height: 38px;
+  padding: 0 14px;
+  /* border-radius: 999px; */
+  border: 1px solid var(--border);
+  background: #fff;
+  cursor: pointer;
+  font-weight: 700;
+  color: var(--slate-700);
+  transition: 160ms ease;
+}
+
+.filter:hover {
+  background: rgba(15, 23, 42, 0.02);
+}
+
+.filter[data-active="true"] {
+  border-color: rgba(37, 99, 235, 0.35);
+  background: rgba(37, 99, 235, 0.08);
+  color: var(--brand-700);
+}
+
+.caseTop {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  gap: 12px;
+  margin-bottom: 12px;
+}
+
+.caseCover {
+  width: 100%;
+  height: 140px;
+  object-fit: cover;
+  display: block;
+  border-bottom: 1px solid var(--border);
+}
+
+.casePad {
+  padding: 18px;
+}
+
+.caseTitle {
+  font-weight: 900;
+  letter-spacing: -0.02em;
+  margin-bottom: 6px;
+}
+
+.caseMetrics {
+  margin-top: 12px;
+  display: flex;
+  flex-wrap: wrap;
+  gap: 10px;
+}
+
+.metric {
+  display: inline-flex;
+  align-items: center;
+  padding: 6px 10px;
+  /* border-radius: 12px; */
+  background: rgba(15, 23, 42, 0.03);
+  border: 1px solid var(--border);
+  font-weight: 700;
+  color: var(--slate-700);
+  font-size: 12px;
+}
+</style>

+ 211 - 0
src/views/ContactView.vue

@@ -0,0 +1,211 @@
+<script setup>
+import { reactive, ref } from "vue";
+import PageHero from "../components/PageHero.vue";
+
+const submitted = ref(false);
+const form = reactive({
+  company: "",
+  name: "",
+  phone: "",
+  email: "",
+  need: "",
+});
+
+function submit() {
+  submitted.value = true;
+}
+</script>
+
+<template>
+  <div>
+    <PageHero
+      kicker="联系咨询"
+      title="获取演示与试点建议"
+      subtitle="填写需求信息,我们会在 1 个工作日内与你联系(示例页面,不会真实提交)。"
+    />
+
+    <section class="section">
+      <div class="container grid contactGrid">
+        <div class="card card-pad">
+          <div class="blockTitle">联系方式</div>
+          <div class="muted">热线:400-000-0000</div>
+          <div class="muted">邮箱:contact@example.com</div>
+          <div class="muted">地址:某省某市某区某路 88 号</div>
+          <div class="divider blockDivider"></div>
+          <div class="blockTitle">咨询方向</div>
+          <div class="tags">
+            <span class="pill">设备接入</span>
+            <span class="pill">数据治理</span>
+            <span class="pill">低代码应用</span>
+            <span class="pill">AI 质检</span>
+            <span class="pill">能效优化</span>
+          </div>
+        </div>
+
+        <div class="card card-pad">
+          <div class="blockTitle">需求表单</div>
+
+          <div v-if="submitted" class="success">
+            <div class="successTitle">已收到你的需求(模拟)</div>
+            <div class="muted">
+              你可以继续修改信息再次提交,或直接通过电话/邮箱联系我们。
+            </div>
+          </div>
+
+          <form class="form" @submit.prevent="submit">
+            <label class="field">
+              <span class="label">公司名称</span>
+              <input
+                v-model="form.company"
+                class="input"
+                type="text"
+                placeholder="例如:某某制造有限公司"
+              />
+            </label>
+            <label class="field">
+              <span class="label">联系人</span>
+              <input
+                v-model="form.name"
+                class="input"
+                type="text"
+                placeholder="你的姓名"
+              />
+            </label>
+            <label class="field">
+              <span class="label">联系电话</span>
+              <input
+                v-model="form.phone"
+                class="input"
+                type="tel"
+                placeholder="手机/座机"
+              />
+            </label>
+            <label class="field">
+              <span class="label">邮箱</span>
+              <input
+                v-model="form.email"
+                class="input"
+                type="email"
+                placeholder="name@company.com"
+              />
+            </label>
+            <label class="field fieldFull">
+              <span class="label">需求描述</span>
+              <textarea
+                v-model="form.need"
+                class="input textarea"
+                rows="4"
+                placeholder="简单描述你的场景与目标"
+              ></textarea>
+            </label>
+
+            <div class="formActions">
+              <button class="btn btn-primary" type="submit">提交需求</button>
+              <button
+                class="btn btn-ghost"
+                type="button"
+                @click="submitted = false"
+              >
+                清除提示
+              </button>
+            </div>
+          </form>
+        </div>
+      </div>
+    </section>
+  </div>
+</template>
+
+<style scoped>
+.contactGrid {
+  grid-template-columns: 0.9fr 1.1fr;
+  gap: 18px;
+}
+
+.blockTitle {
+  font-weight: 900;
+  letter-spacing: -0.02em;
+  margin-bottom: 10px;
+}
+
+.blockDivider {
+  margin: 16px 0;
+}
+
+.tags {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 10px;
+}
+
+.success {
+  margin-bottom: 14px;
+  padding: 12px;
+  /* border-radius: var(--radius-md); */
+  border: 1px solid rgba(16, 185, 129, 0.25);
+  background: rgba(16, 185, 129, 0.06);
+}
+
+.successTitle {
+  font-weight: 900;
+  margin-bottom: 4px;
+}
+
+.form {
+  display: grid;
+  grid-template-columns: repeat(2, minmax(0, 1fr));
+  gap: 12px;
+}
+
+.field {
+  display: grid;
+  gap: 6px;
+}
+
+.fieldFull {
+  grid-column: 1 / -1;
+}
+
+.label {
+  font-size: 12px;
+  font-weight: 800;
+  color: var(--slate-700);
+}
+
+.input {
+  width: 100%;
+  /* border-radius: 12px; */
+  border: 1px solid var(--border);
+  padding: 10px 12px;
+  outline: none;
+  background: #fff;
+  transition: 160ms ease;
+}
+
+.input:focus {
+  border-color: rgba(37, 99, 235, 0.4);
+  box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.1);
+}
+
+.textarea {
+  resize: vertical;
+}
+
+.formActions {
+  grid-column: 1 / -1;
+  display: flex;
+  gap: 12px;
+  flex-wrap: wrap;
+  justify-content: flex-start;
+}
+
+@media (max-width: 960px) {
+  .contactGrid {
+    grid-template-columns: 1fr;
+  }
+
+  .form {
+    grid-template-columns: 1fr;
+  }
+}
+</style>

+ 2009 - 0
src/views/HomeView.vue

@@ -0,0 +1,2009 @@
+<script setup>
+import banner1Url from "../assets/images/banner.jpg?url";
+import banner2Url from "../assets/images/banner2.jpg?url";
+import banner3Url from "../assets/images/banner3.jpg?url";
+import solutionsBgUrl from "../assets/images/bg.jpg?url";
+import capabilitiesBgUrl from "../assets/images/bg2.jpg?url";
+import sectionDataUrl from "../assets/illustrations/section-data.svg?url";
+import heroIndustrialUrl from "../assets/illustrations/hero-industrial.svg?url";
+import afterSalesUrl from "../assets/images/afterSales.jpg?url";
+import indexImg4BacksUrl from "../assets/images/index_img4_backs.png?url";
+import indexBack2Url from "../assets/images/index_back2.png?url";
+import jiaohuIconUrl from "../assets/images/jiaohu.png?url";
+import planIconUrl from "../assets/images/方案.png?url";
+import caseIconUrl from "../assets/images/案例.png?url";
+import CountUp from "../components/motion/CountUp.vue";
+import Reveal from "../components/motion/Reveal.vue";
+import { computed, onBeforeUnmount, onMounted, ref } from "vue";
+import { Icon } from "@iconify/vue";
+
+const highlights = [
+  { label: "接入井站", end: 200, suffix: "+" },
+  { label: "生产指标", end: 500, suffix: "+" },
+  { label: "服务单位", end: 300, suffix: "+" },
+  { label: "区域覆盖", end: 20, suffix: "+" },
+];
+
+const slides = [
+  {
+    bg: banner1Url,
+    kicker: "油田数智化 · 端边云协同 · 生产经营一体化",
+    headline1: "连接井站、设备与业务,",
+    headline2Before: "构建",
+    headline2Emphasis: "安全、可控",
+    headline2After: "的油田数智底座",
+    desc: "提供井站物联接入、数据治理、生产经营应用与智能分析一体化能力,支撑油田提质增效与本质安全。",
+  },
+  {
+    bg: banner2Url,
+    kicker: "油田数据治理 · 主数据/指标 · 统一口径",
+    headline1: "让采集数据可追溯、可复用,",
+    headline2Before: "把“",
+    headline2Emphasis: "数据资产",
+    headline2After: "”变成可持续能力",
+    desc: "构建井、站、管网等资产目录,打通血缘与质量体系,沉淀指标口径与标签体系,为分析、AI 与业务闭环提供可信底座。",
+  },
+  {
+    bg: banner3Url,
+    kicker: "场景方案 · 快速复制 · 价值闭环",
+    headline1: "用指标驱动持续优化与精细管理,",
+    headline2Before: "从试点到规模化,形成",
+    headline2Emphasis: "可运营闭环",
+    headline2After: "",
+    desc: "沉淀钻完井、采油采气、集输管网与能耗管理等场景模板,结合交付方法论与组件化能力,缩短落地周期,提升复制效率。",
+  },
+];
+
+const activeIndex = ref(0);
+const paused = ref(false);
+const autoplayMs = 6500;
+let timer = null;
+
+const activeSlide = computed(() => slides[activeIndex.value]);
+const bgStyle = computed(() => ({
+  backgroundImage: `url(${activeSlide.value.bg})`,
+}));
+
+function prefersReducedMotion() {
+  return (
+    typeof window !== "undefined" &&
+    window.matchMedia &&
+    window.matchMedia("(prefers-reduced-motion: reduce)").matches
+  );
+}
+
+function next() {
+  activeIndex.value = (activeIndex.value + 1) % slides.length;
+}
+
+function prev() {
+  activeIndex.value = (activeIndex.value - 1 + slides.length) % slides.length;
+}
+
+function goTo(index) {
+  activeIndex.value = index;
+}
+
+function start() {
+  if (prefersReducedMotion()) return;
+  stop();
+  timer = setInterval(() => {
+    if (!paused.value) next();
+  }, autoplayMs);
+}
+
+function stop() {
+  if (!timer) return;
+  clearInterval(timer);
+  timer = null;
+}
+
+onMounted(start);
+onBeforeUnmount(stop);
+
+const capabilityPlatforms = [
+  {
+    title: "连接井站平台",
+    desc: "打通井场、站控与 SCADA 数据链路,构建稳定可扩展的采集与边缘体系。",
+    art: heroIndustrialUrl,
+    variant: "connect",
+    modules: [
+      { title: "多协议采集", icon: "lucide:radio-tower" },
+      { title: "SCADA 接入", icon: "lucide:plug-zap" },
+      { title: "边缘计算", icon: "lucide:cpu" },
+      { title: "离线缓存", icon: "lucide:hard-drive-download" },
+      { title: "资产台账", icon: "lucide:barcode" },
+      { title: "运行监控", icon: "lucide:activity" },
+      { title: "告警联动", icon: "lucide:bell-ring" },
+      { title: "远程运维", icon: "lucide:wrench" },
+      { title: "时序存储", icon: "lucide:clock-3" },
+    ],
+  },
+  {
+    title: "数据治理平台",
+    desc: "统一资产与指标口径,完善血缘与质量体系,让数据资产可管、可用、可运营。",
+    art: sectionDataUrl,
+    variant: "connect",
+    modules: [
+      { title: "资产目录", icon: "lucide:library" },
+      { title: "主数据管理", icon: "lucide:id-card" },
+      { title: "血缘追踪", icon: "lucide:git-fork" },
+      { title: "质量校验", icon: "lucide:badge-check" },
+      { title: "指标中心", icon: "lucide:gauge" },
+      { title: "标签体系", icon: "lucide:tags" },
+      { title: "权限审计", icon: "lucide:shield-check" },
+      { title: "数据脱敏", icon: "lucide:eye-off" },
+      { title: "数据服务 API", icon: "lucide:braces" },
+    ],
+  },
+  {
+    title: "生产经营应用平台",
+    desc: "面向生产运行与经营管理,快速构建大屏、报表、预警与处置闭环应用。",
+    art: heroIndustrialUrl,
+    variant: "connect",
+    modules: [
+      { title: "生产指挥大屏", icon: "lucide:layout-dashboard" },
+      { title: "报表中心", icon: "lucide:file-bar-chart" },
+      { title: "异常预警", icon: "lucide:siren" },
+      { title: "工单闭环", icon: "lucide:clipboard-check" },
+      { title: "能耗管理", icon: "lucide:zap" },
+      {
+        title: "注采分析",
+        icon: "lucide:droplets",
+        badge: "新",
+        badgeTone: "new",
+      },
+      { title: "集输监测", icon: "lucide:route" },
+      {
+        title: "预测维护",
+        icon: "lucide:heart-pulse",
+        badge: "热",
+        badgeTone: "hot",
+      },
+      {
+        title: "智能问答",
+        icon: "lucide:messages-square",
+        badge: "新",
+        badgeTone: "new",
+      },
+    ],
+  },
+];
+
+const products = [
+  {
+    title: "油田数智底座(PaaS)",
+    desc: "面向油田场景的数字底座:模型、流程、权限、消息与开放接口。",
+    tags: ["组件化", "开放 API", "多租户"],
+  },
+  {
+    title: "井站物联与边缘网关",
+    desc: "统一接入、监控、告警与远程运维,沉淀井站资产与运行状态。",
+    tags: ["协议适配", "边缘采集", "运行监控"],
+  },
+  {
+    title: "数据资产与指标中心",
+    desc: "从采集到治理再到分析:资产目录、血缘、质量与指标口径管理。",
+    tags: ["主数据", "质量校验", "指标中心"],
+  },
+  {
+    title: "智能分析与预测维护",
+    desc: "结合油田机理与算法能力,落地工况识别、故障预警与能效优化。",
+    tags: ["工况识别", "预测维护", "能效优化"],
+  },
+];
+
+const solutions = [
+  { title: "钻完井", desc: "井场数据汇聚、施工过程可视化与风险预警。" },
+  { title: "采油采气", desc: "生产运行监控、工况分析与产量波动诊断。" },
+  { title: "集输管网", desc: "站库管网联动监测、泄漏/压降异常识别。" },
+  { title: "注水注气", desc: "注采平衡分析、配注优化与效益评估。" },
+  { title: "能耗与碳管理", desc: "能耗在线核算、节能评估与合规披露闭环。" },
+  { title: "设备运维", desc: "告警闭环、工单联动与知识沉淀,提升设备可靠性。" },
+];
+
+const cases = [
+  {
+    title: "采油厂",
+    desc: "生产运行监控、工况分析与异常处置闭环",
+    icon: "lucide:factory",
+    cover: banner1Url,
+    detail:
+      "以井站数据为底座,构建日/周/月报、重点井监控与异常处置闭环,支撑提质增效。",
+  },
+  {
+    title: "集输站",
+    desc: "站库管网联动监测、压降异常识别与能效优化",
+    icon: "lucide:route",
+    cover: banner2Url,
+    detail:
+      "打通站库管网关键指标,实现压降/泄漏异常识别与能耗核算,持续优化运行策略。",
+  },
+  {
+    title: "注水注气",
+    desc: "注采平衡分析、配注优化与效果评估",
+    icon: "lucide:droplets",
+    cover: banner3Url,
+    detail:
+      "构建注采指标体系与可视化分析,形成配注优化建议与效果评估闭环,支撑精细开发。",
+  },
+  {
+    title: "设备运维",
+    desc: "远程运维、预测维护与可靠性提升",
+    icon: "lucide:wrench",
+    cover: afterSalesUrl,
+    detail:
+      "告警联动工单与知识库沉淀,结合预测维护模型,降低非计划停机与运维成本。",
+  },
+];
+
+const valueCaseActiveIndex = ref(-1);
+function activateValueCase(index) {
+  valueCaseActiveIndex.value = index;
+}
+
+const news = [
+  {
+    date: "2026-02-12",
+    tag: "发布",
+    title: "门户新版上线:油田数智化产品与方案展示",
+    desc: "全新门户界面设计,优化用户体验,增强产品展示效果。",
+    cover: banner1Url,
+    type: "featured", // 上部大图新闻
+  },
+  {
+    date: "2026-01-28",
+    tag: "活动",
+    title: "油田数据治理与指标体系专题沙龙报名启动",
+    desc: "深入探讨油田数据治理最佳实践与指标体系建设方法。",
+    cover: banner2Url,
+    type: "featured", // 上部大图新闻
+  },
+  {
+    date: "2026-01-10",
+    tag: "更新",
+    title: "井站接入能力升级:新增 SCADA 协议适配与边缘缓存",
+    desc: "提升井站数据采集稳定性与实时性,支持更多工业协议。",
+    cover: banner3Url,
+    type: "list", // 下部列表新闻
+  },
+  {
+    date: "2025-12-20",
+    tag: "案例",
+    title: "某采油厂实现从采集到指标的全链路治理",
+    desc: "通过数据治理平台,实现井场数据到业务指标的全流程管理。",
+    cover: afterSalesUrl,
+    type: "list", // 下部列表新闻
+  },
+];
+
+const marketActivities = [
+  {
+    title: "浪潮云洲亮相2025中国5G+工业互联网大会",
+    desc: "2025中国5G+工业互联网大会在武汉开幕,浪潮云洲精彩亮相。",
+    cover: banner1Url,
+  },
+  {
+    title: "浪潮云洲成功协办第十四届中国创新创业大赛工业智能体赛",
+    desc: "推动工业智能化发展,助力企业创新转型。",
+    cover: banner2Url,
+  },
+  {
+    title: "2025第二届中国(郑州)数字化与先进装备制造业博览会",
+    desc: "打造“人工智能+工业互联网”赋能制造业转型发展新范式",
+    cover: banner3Url,
+  },
+];
+
+const partnerSources = [jiaohuIconUrl, planIconUrl, caseIconUrl];
+const partners = Array.from({ length: 12 }).map((_, idx) => ({
+  id: idx + 1,
+  src: partnerSources[idx % partnerSources.length],
+  alt: `伙伴标识 ${idx + 1}`,
+}));
+</script>
+
+<template>
+  <div class="home">
+    <section
+      class="hero"
+      @mouseenter="paused = true"
+      @mouseleave="paused = false"
+    >
+      <Transition name="heroBg" mode="out-in">
+        <div
+          :key="activeIndex"
+          class="hero__bg"
+          :style="bgStyle"
+          aria-hidden="true"
+        ></div>
+      </Transition>
+      <div class="hero__veil" aria-hidden="true"></div>
+      <div class="container hero__inner">
+        <div class="hero__content">
+          <Transition name="heroText" mode="out-in">
+            <div :key="activeIndex" class="hero__copy">
+              <div class="section-kicker">{{ activeSlide.kicker }}</div>
+              <h1 class="hero__title">
+                {{ activeSlide.headline1 }}<br />
+                {{ activeSlide.headline2Before
+                }}<span class="hero__em">{{
+                  activeSlide.headline2Emphasis
+                }}</span
+                >{{ activeSlide.headline2After }}
+              </h1>
+              <p class="hero__desc muted">{{ activeSlide.desc }}</p>
+              <div class="hero__cta">
+                <RouterLink class="btn btn-primary" to="/contact"
+                  >申请演示</RouterLink
+                >
+                <RouterLink class="btn btn-ghost" to="/solutions"
+                  >查看解决方案</RouterLink
+                >
+                <!-- <RouterLink class="btn btn-link" to="/products"
+                  >了解产品 →</RouterLink
+                > -->
+              </div>
+            </div>
+          </Transition>
+
+          <div class="hero__stats">
+            <div v-for="item in highlights" :key="item.label" class="stat">
+              <div class="stat__value">
+                <CountUp :end="item.end" :suffix="item.suffix" />
+              </div>
+              <div class="stat__label muted">{{ item.label }}</div>
+            </div>
+          </div>
+
+          <div class="hero__controls" aria-label="首页轮播控制">
+            <div class="dots" role="tablist" aria-label="轮播指示器">
+              <button
+                v-for="(s, idx) in slides"
+                :key="s.bg"
+                class="dotBtn"
+                type="button"
+                role="tab"
+                :aria-selected="activeIndex === idx ? 'true' : 'false'"
+                :aria-label="`切换到第 ${idx + 1} 张`"
+                :data-active="activeIndex === idx ? 'true' : 'false'"
+                @click="goTo(idx)"
+              ></button>
+            </div>
+          </div>
+        </div>
+      </div>
+    </section>
+
+    <section
+      class="section capabilitiesBg"
+      :style="{ backgroundImage: `url(${capabilitiesBgUrl})` }"
+    >
+      <div class="container">
+        <Reveal as="div" class="sectionHead" :delay="0">
+          <div style="display: flex; align-items: center">
+            <img src="../assets/images/title1.png" alt="" />
+            <h2 class="h2" style="padding: 0 10px; color: #696969">
+              驱动油田价值闭环
+            </h2>
+            <img src="../assets/images/title2.png" alt="" />
+          </div>
+        </Reveal>
+
+        <div class="capPlatformGrid" aria-label="油田数智化能力九宫格">
+          <Reveal
+            v-for="(p, idx) in capabilityPlatforms"
+            :key="p.title"
+            as="div"
+            class="capPlatformCard card hover-lift"
+            :data-variant="p.variant"
+            :delay="80 + idx * 80"
+          >
+            <div class="capPlatformHead">
+              <div class="capPlatformCopy">
+                <div class="capPlatformTitle">{{ p.title }}</div>
+                <div class="capPlatformDesc">{{ p.desc }}</div>
+              </div>
+            </div>
+
+            <div class="capModuleGrid" role="list">
+              <div
+                v-for="m in p.modules"
+                :key="`${p.title}-${m.title}`"
+                class="capModuleTile"
+                role="listitem"
+              >
+                <div class="capModuleIcon" aria-hidden="true">
+                  <Icon :icon="m.icon" width="26" height="26" />
+                </div>
+                <div class="capModuleName">{{ m.title }}</div>
+              </div>
+            </div>
+          </Reveal>
+        </div>
+      </div>
+    </section>
+
+    <section class="section">
+      <div class="container">
+        <Reveal as="div" class="sectionHead" :delay="0">
+          <div>
+            <div style="display: flex; align-items: center">
+              <img src="../assets/images/title1.png" alt="" />
+              <h2 class="h2" style="padding: 0 10px; color: #696969">
+                覆盖油田生产全链路
+              </h2>
+              <img src="../assets/images/title2.png" alt="" />
+            </div>
+            <div class="muted" style="text-align: center; padding-top: 20px">
+              从井场到站控,从数据到应用,按需组合,快速交付。
+            </div>
+          </div>
+        </Reveal>
+
+        <div class="grid grid-4">
+          <Reveal
+            v-for="(p, idx) in products"
+            :key="p.title"
+            as="div"
+            class="card card-pad productCard hover-lift"
+            :delay="80 + idx * 70"
+          >
+            <div class="productTitle">{{ p.title }}</div>
+            <div class="muted productDesc">{{ p.desc }}</div>
+            <div class="productTags">
+              <span v-for="t in p.tags" :key="t" class="pill">{{ t }}</span>
+            </div>
+          </Reveal>
+        </div>
+      </div>
+    </section>
+
+    <section
+      class="section section--soft solutionsBg"
+      :style="{ backgroundImage: `url(${solutionsBgUrl})` }"
+    >
+      <div class="container">
+        <Reveal as="div" class="sectionHead" :delay="0">
+          <div style="display: flex; align-items: center">
+            <img src="../assets/images/title1.png" alt="" />
+            <h2 class="h2" style="padding: 0 10px; color: #696969">
+              面向场景的可复制实践
+            </h2>
+            <img src="../assets/images/title2.png" alt="" />
+          </div>
+        </Reveal>
+
+        <div class="grid grid-3">
+          <Reveal
+            v-for="(s, idx) in solutions"
+            :key="s.title"
+            as="div"
+            class="hoverWrap"
+            :delay="80 + idx * 60"
+          >
+            <RouterLink
+              class="card card-pad solutionCard hover-lift"
+              to="/solutions"
+            >
+              <div class="solutionTitle">{{ s.title }}</div>
+              <div class="muted">{{ s.desc }}</div>
+              <div class="solutionMore">了解更多 →</div>
+            </RouterLink>
+          </Reveal>
+        </div>
+        <div style="display: flex; justify-content: center; padding-top: 30px">
+          <RouterLink class="btn btn-link" to="/news"
+            >查看全部方案
+            <Icon icon="lucide:chevron-right" width="24" height="24"
+          /></RouterLink>
+        </div>
+      </div>
+    </section>
+
+    <section class="section">
+      <div class="container">
+        <Reveal as="div" class="sectionHead" :delay="0">
+          <div style="display: flex; align-items: center">
+            <img src="../assets/images/title1.png" alt="" />
+            <h2 class="h2" style="padding: 0 10px; color: #696969">
+              用可量化指标呈现业务价值
+            </h2>
+            <img src="../assets/images/title2.png" alt="" />
+          </div>
+        </Reveal>
+
+        <div
+          class="valueAcc"
+          role="list"
+          aria-label="业务价值横向手风琴"
+          @mouseleave="activateValueCase(-1)"
+        >
+          <Reveal
+            v-for="(c, idx) in cases"
+            :key="c.title"
+            as="div"
+            class="valueAccItem hover-lift"
+            role="listitem"
+            tabindex="0"
+            :data-active="valueCaseActiveIndex === idx ? 'true' : 'false'"
+            :aria-label="`价值案例:${c.title}`"
+            :delay="60 + idx * 70"
+            @mouseenter="activateValueCase(idx)"
+            @focusin="activateValueCase(idx)"
+            @click="activateValueCase(idx)"
+            @keydown.enter.prevent="activateValueCase(idx)"
+            @keydown.space.prevent="activateValueCase(idx)"
+          >
+            <div class="valueAccInner">
+              <div
+                class="valueAccCollapsed"
+                :aria-hidden="valueCaseActiveIndex === idx ? 'true' : 'false'"
+                :style="{ '--value-collapsed-bg': `url(${indexBack2Url})` }"
+              >
+                <div class="valueAccIcon" aria-hidden="true">
+                  <Icon :icon="c.icon" width="28" height="28" />
+                </div>
+                <div class="valueAccTitle">{{ c.title }}</div>
+                <div class="valueAccLine" aria-hidden="true"></div>
+                <div class="muted valueAccDesc">{{ c.desc }}</div>
+                <div class="valueAccPlus" aria-hidden="true">
+                  <Icon icon="ri:add-fill" width="24" height="24" />
+                </div>
+              </div>
+
+              <div
+                class="valueAccExpanded"
+                :aria-hidden="valueCaseActiveIndex === idx ? 'false' : 'true'"
+              >
+                <div class="valueAccCover">
+                  <img
+                    :src="c.cover"
+                    :alt="`${c.title} 场景图`"
+                    loading="lazy"
+                  />
+                </div>
+                <div
+                  class="valueAccBottom"
+                  :style="{ '--value-bottom-bg': `url(${indexImg4BacksUrl})` }"
+                >
+                  <div class="valueAccBottomTitle">{{ c.title }}</div>
+                  <div class="valueAccBottomText">{{ c.detail }}</div>
+                  <RouterLink class="valueAccBtn" to="/cases"
+                    >了解更多</RouterLink
+                  >
+                </div>
+              </div>
+            </div>
+          </Reveal>
+        </div>
+
+        <div style="display: flex; justify-content: center; padding-top: 30px">
+          <RouterLink class="btn btn-link" to="/cases"
+            >查看更多案例
+            <Icon icon="lucide:chevron-right" width="24" height="24"
+          /></RouterLink>
+        </div>
+      </div>
+    </section>
+
+    <!-- 平台更新与行业观点 - 左右两栏布局 -->
+    <section class="section">
+      <div class="container">
+        <Reveal as="div" class="sectionHead" :delay="0">
+          <div>
+            <h2 class="h2">新闻资讯与市场活动</h2>
+          </div>
+        </Reveal>
+
+        <!-- 左右两栏布局 -->
+        <div class="news-market-grid">
+          <!-- 左侧:新闻资讯 -->
+          <div class="news-column">
+            <div style="display: flex; justify-content: space-between">
+              <h3>新闻资讯</h3>
+              <RouterLink
+                class="btn btn-link"
+                style="font-size: 14px; color: #595959"
+                to="/news"
+                >查看更多
+                <Icon icon="lucide:chevron-right" width="20" height="20"
+              /></RouterLink>
+            </div>
+            <div class="news-featured">
+              <!-- 上部:2个带缩略图的新闻(图片全屏+文字覆盖) -->
+              <Reveal
+                v-for="(n, idx) in news.filter(
+                  (item) => item.type === 'featured',
+                )"
+                :key="n.title"
+                as="div"
+                class="news-featured-item"
+                :delay="80 + idx * 60"
+              >
+                <RouterLink class="news-featured-link" to="/news">
+                  <div class="news-featured-image-wrapper">
+                    <img
+                      :src="n.cover"
+                      :alt="n.title"
+                      class="news-featured-image"
+                      loading="lazy"
+                    />
+                  </div>
+                  <div class="news-featured-overlay">
+                    <div class="news-featured-meta">
+                      <!-- <span class="news-featured-tag">{{ n.tag }}</span> -->
+                      <span class="news-featured-date">{{ n.date }}</span>
+                    </div>
+                    <h3 class="news-featured-title">{{ n.title }}</h3>
+                    <p class="news-featured-desc">{{ n.desc }}</p>
+                  </div>
+                </RouterLink>
+              </Reveal>
+            </div>
+
+            <!-- 下部:列表形式的新闻 -->
+            <div class="news-list">
+              <Reveal
+                v-for="(n, idx) in news.filter((item) => item.type === 'list')"
+                :key="n.title"
+                as="div"
+                class="news-list-item"
+                :delay="140 + idx * 60"
+              >
+                <RouterLink class="news-list-link" to="/news">
+                  <div class="news-list-content">
+                    <div class="news-meta">
+                      <!-- <span class="pill">{{ n.tag }}</span> -->
+                      <span class="muted news-date">{{ n.date }}</span>
+                    </div>
+                    <p class="news-title">{{ n.title }}</p>
+                    <p
+                      class="news-desc muted"
+                      style="padding-top: 10px; font-size: 12px"
+                    >
+                      {{ n.desc }}
+                    </p>
+                  </div>
+                </RouterLink>
+              </Reveal>
+            </div>
+          </div>
+
+          <!-- 右侧:市场活动 -->
+          <div class="market-column">
+            <div style="display: flex; justify-content: space-between">
+              <h3>市场活动</h3>
+              <RouterLink
+                class="btn btn-link"
+                to="/news"
+                style="font-size: 14px; color: #595959"
+                >查看更多
+                <Icon icon="lucide:chevron-right" width="20" height="20"
+              /></RouterLink>
+            </div>
+            <Reveal
+              v-for="(activity, idx) in marketActivities"
+              :key="activity.title"
+              as="div"
+              class="market-activity"
+              :delay="80 + idx * 60"
+            >
+              <RouterLink class="market-activity-link" to="/news">
+                <div class="market-activity-image-wrapper">
+                  <img
+                    :src="activity.cover"
+                    :alt="activity.title"
+                    class="market-activity-image"
+                    loading="lazy"
+                  />
+                </div>
+                <div class="market-activity-overlay">
+                  <h3 class="market-activity-title">{{ activity.title }}</h3>
+                  <p class="market-activity-desc">{{ activity.desc }}</p>
+                </div>
+              </RouterLink>
+            </Reveal>
+          </div>
+        </div>
+      </div>
+    </section>
+
+    <section class="section section--soft partnersBg">
+      <div class="container">
+        <Reveal as="div" class="sectionHead" :delay="0">
+          <div>
+            <h2 class="h2" style="color: aliceblue">合作共建开放生态</h2>
+            <!-- <div class="muted">
+              示例占位图,可替换为你的真实客户/伙伴 Logo。
+            </div> -->
+          </div>
+        </Reveal>
+
+        <div class="partnerGrid">
+          <Reveal
+            v-for="(p, idx) in partners"
+            :key="p.id"
+            as="div"
+            class="partner"
+            :delay="80 + idx * 40"
+          >
+            <img :src="p.src" :alt="p.alt" loading="lazy" />
+          </Reveal>
+        </div>
+      </div>
+    </section>
+
+    <!-- <section class="section">
+      <div class="container cta">
+        <Reveal
+          as="div"
+          class="cta__card card hover-lift"
+          :delay="0"
+          :style="{ '--cta-bg': `url(${ctaBgUrl})` }"
+        >
+          <div class="cta__pad">
+            <div class="cta__title">让油田数据真正“可用、可管、可运营”</div>
+            <div class="muted">
+              我们可以基于你的油田业务现状,给出 2–4
+              周可落地的试点方案与演示环境。
+            </div>
+            <div class="cta__btns">
+              <RouterLink class="btn btn-primary" to="/contact"
+                >预约咨询</RouterLink
+              >
+              <RouterLink class="btn btn-ghost" to="/cases"
+                >参考案例</RouterLink
+              >
+            </div>
+          </div>
+        </Reveal>
+      </div>
+    </section> -->
+  </div>
+</template>
+
+<style scoped>
+.hero {
+  position: relative;
+  padding: 54px 0 28px;
+  overflow: hidden;
+}
+
+.hero__bg {
+  position: absolute;
+  inset: 0;
+  background-size: cover;
+  background-position: center;
+  filter: saturate(0.98) contrast(1.02);
+  transform: scale(1.02);
+}
+
+.hero__veil {
+  display: none; /* 完全隐藏遮罩层 */
+}
+
+.hero__inner {
+  position: relative;
+  z-index: 2;
+  display: grid;
+  grid-template-columns: 1.2fr 0.8fr;
+  gap: 22px;
+  align-items: stretch;
+}
+
+.hero__copy {
+  padding: 16px 14px;
+  border-radius: var(--radius-lg);
+  border: none;
+  background: transparent;
+  backdrop-filter: none;
+  /* color: white; */
+  /* text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5); */
+}
+
+.hero__title {
+  margin-top: 14px;
+  font-size: 40px;
+  line-height: 1.12;
+  letter-spacing: -0.03em;
+}
+
+.hero__em {
+  background: linear-gradient(90deg, var(--brand-700), var(--brand-500));
+  -webkit-background-clip: text;
+  background-clip: text;
+  color: transparent;
+}
+
+.hero__desc {
+  margin-top: 12px;
+  max-width: 52ch;
+}
+
+.hero__cta {
+  margin-top: 18px;
+  display: flex;
+  flex-wrap: wrap;
+  gap: 12px;
+  align-items: center;
+}
+
+.hero__stats {
+  margin-top: 22px;
+  display: grid;
+  grid-template-columns: repeat(4, minmax(0, 1fr));
+  gap: 12px;
+  padding: 14px 12px;
+  border-radius: 10px;
+  border: 1px solid rgba(255, 255, 255, 0.3); /* 半透明白色边框 */
+  background: rgba(0, 0, 0, 0.2); /* 半透明黑色背景 */
+  backdrop-filter: blur(10px);
+}
+
+.stat {
+  padding: 8px 10px;
+}
+
+.stat__value {
+  font-weight: 850;
+  font-size: 18px;
+  color: #1f45b7;
+  letter-spacing: -0.02em;
+  font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
+}
+
+.stat__label {
+  font-size: 12px;
+}
+
+.hero__panel {
+  align-self: stretch;
+  background:
+    radial-gradient(
+      700px 220px at 40% 0%,
+      rgba(37, 99, 235, 0.12),
+      transparent 60%
+    ),
+    #ffffff;
+}
+
+.hero__panelPad {
+  padding: 18px;
+}
+
+.hero__panelTitle {
+  display: inline-flex;
+  align-items: center;
+  gap: 10px;
+  font-weight: 850;
+  letter-spacing: -0.02em;
+  margin-bottom: 10px;
+}
+
+.hero__controls {
+  margin-top: 14px;
+  display: flex;
+  position: relative;
+  left: 43%;
+  align-items: center;
+  justify-content: center;
+  gap: 10px;
+  width: 100%;
+}
+
+.ctrlBtn {
+  width: 40px;
+  height: 40px;
+  border-radius: 14px;
+  border: 1px solid rgba(255, 255, 255, 0.3); /* 半透明白色边框 */
+  background: rgba(0, 0, 0, 0.2); /* 半透明黑色背景 */
+  backdrop-filter: blur(10px);
+  cursor: pointer;
+  font-weight: 900;
+  color: white; /* 白色文字 */
+  transition: 160ms ease;
+}
+
+.ctrlBtn:hover {
+  color: var(--brand-300); /* 浅蓝色悬停效果 */
+  background: rgba(0, 0, 0, 0.3);
+  transform: translateY(-1px);
+}
+
+.dots {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  padding: 10px 12px;
+  border-radius: 999px;
+}
+
+.dotBtn {
+  width: 10px;
+  height: 10px;
+  border-radius: 999px;
+  border: 0;
+  background: #8391a5; /* 半透明白色 */
+  cursor: pointer;
+  transition: 160ms ease;
+}
+
+.dotBtn[data-active="true"] {
+  width: 28px;
+  background: #004baa; /* 品牌色激活状态 */
+}
+
+.dotBtn:focus-visible {
+  outline: none;
+  box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.14);
+}
+
+.heroBg-enter-active,
+.heroBg-leave-active {
+  transition: opacity 520ms ease;
+}
+
+.heroBg-enter-from,
+.heroBg-leave-to {
+  opacity: 0;
+}
+
+.heroText-enter-active,
+.heroText-leave-active {
+  transition:
+    opacity 420ms ease,
+    transform 420ms ease;
+}
+
+.heroText-enter-from,
+.heroText-leave-to {
+  opacity: 0;
+  transform: translate3d(0, 10px, 0);
+}
+
+.kickerIcon {
+  width: 18px;
+  height: 18px;
+  flex: 0 0 auto;
+  display: inline-block;
+}
+
+.hero__panelList {
+  display: grid;
+  gap: 12px;
+}
+
+.hero__panelItem {
+  padding: 12px;
+  border-radius: var(--radius-md);
+  border: 1px solid var(--border);
+  background: rgba(15, 23, 42, 0.01);
+}
+
+.hero__panelKey {
+  font-weight: 700;
+  margin-bottom: 4px;
+}
+
+.hero__panelBtns {
+  display: grid;
+  grid-template-columns: 1fr 1fr;
+  gap: 12px;
+  margin-top: 14px;
+}
+
+.sectionHead {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  gap: 18px;
+  margin-bottom: 30px;
+}
+
+.capGrid {
+  margin-top: 18px;
+}
+
+.capPlatformGrid {
+  margin-top: 6px;
+  display: grid;
+  grid-template-columns: repeat(3, minmax(0, 1fr));
+  gap: 16px;
+  align-items: stretch;
+}
+
+.capPlatformCard {
+  position: relative;
+  overflow: hidden;
+  padding: 18px;
+
+  background:
+    linear-gradient(
+      180deg,
+      rgb(var(--cap-accent, 37 99 235) / 0.08),
+      rgba(255, 255, 255, 0.92) 46%,
+      #ffffff
+    ),
+    radial-gradient(
+      900px circle at 85% 0%,
+      rgb(var(--cap-accent, 37 99 235) / 0.16)
+    );
+  box-shadow:
+    0 8px 16px rgba(2, 6, 23, 0.4),
+    0 0 0 1px rgba(255, 255, 255, 0.08) inset;
+}
+
+.capPlatformCard::before {
+  content: "";
+  position: absolute;
+  inset: -20px;
+
+  filter: blur(28px);
+  opacity: 0;
+  transition: opacity 240ms ease;
+  pointer-events: none;
+}
+
+.capPlatformCard:hover::before {
+  opacity: 1;
+}
+
+.capPlatformCard[data-variant="connect"] {
+  --cap-accent: 37 99 235;
+}
+
+.capPlatformCard[data-variant="govern"] {
+  --cap-accent: 16 185 129;
+}
+
+.capPlatformCard[data-variant="app"] {
+  --cap-accent: 245 158 11;
+}
+
+.capPlatformHead {
+  position: relative;
+  display: flex;
+  align-items: flex-start;
+  justify-content: space-between;
+  gap: 12px;
+  padding-bottom: 14px;
+  border-bottom: 1px dashed rgba(15, 23, 42, 0.14);
+}
+
+.capPlatformCopy {
+  min-width: 0;
+}
+
+.capPlatformTitle {
+  font-weight: bold;
+  letter-spacing: -0.03em;
+  font-size: 22px;
+  /* color: rgb(var(--cap-accent, 37 99 235) / 1); */
+}
+
+.capPlatformDesc {
+  margin-top: 8px;
+  font-size: 13px;
+  line-height: 1.55;
+  max-width: 40ch;
+}
+
+.capPlatformArt {
+  width: 140px;
+  height: auto;
+  flex: 0 0 auto;
+  opacity: 0.92;
+  filter: drop-shadow(0 14px 22px rgba(2, 6, 23, 0.12)) saturate(1.05);
+  transform: translateY(-2px);
+  pointer-events: none;
+  user-select: none;
+}
+
+.capModuleGrid {
+  margin-top: 14px;
+  display: grid;
+  grid-template-columns: repeat(3, minmax(0, 1fr));
+  gap: 12px;
+}
+
+.capModuleTile {
+  position: relative;
+  border-radius: 5px;
+  padding: 12px 10px 10px;
+  border: 1px solid rgba(15, 23, 42, 0.06);
+  background: rgba(248, 250, 252, 0.9);
+  display: grid;
+  place-items: center;
+  gap: 8px;
+  text-align: center;
+  min-height: 106px;
+  transition:
+    transform 180ms ease,
+    box-shadow 180ms ease,
+    border-color 180ms ease;
+}
+
+.capModuleTile:hover {
+  transform: translateY(-2px);
+  border-color: rgb(var(--cap-accent, 37 99 235) / 0.18);
+  box-shadow: 0 16px 30px rgba(2, 6, 23, 0.08);
+}
+
+.capModuleIcon {
+  width: 46px;
+  height: 46px;
+  border-radius: 16px;
+  display: grid;
+  place-items: center;
+  border: 1px solid rgb(var(--cap-accent, 37 99 235) / 0.16);
+  background: radial-gradient(
+    circle at 30% 30%,
+    rgb(var(--cap-accent, 37 99 235) / 0.22),
+    rgb(var(--cap-accent, 37 99 235) / 0.06)
+  );
+  color: rgb(var(--cap-accent, 37 99 235) / 1);
+}
+
+.capModuleName {
+  /* font-weight: 850; */
+  letter-spacing: -0.02em;
+  font-size: 13px;
+  line-height: 1.25;
+}
+
+.capModuleBadge {
+  position: absolute;
+  top: 10px;
+  right: 10px;
+  font-size: 12px;
+  font-weight: 850;
+  padding: 4px 8px;
+  border-radius: 999px;
+  border: 1px solid transparent;
+}
+
+.capModuleBadge[data-tone="hot"] {
+  color: #ef4444;
+  background: rgba(239, 68, 68, 0.12);
+  border-color: rgba(239, 68, 68, 0.18);
+}
+
+.capModuleBadge[data-tone="new"] {
+  color: #f97316;
+  background: rgba(249, 115, 22, 0.12);
+  border-color: rgba(249, 115, 22, 0.18);
+}
+
+.capLayout {
+  margin-top: 18px;
+  display: grid;
+  grid-template-columns: 0.9fr 1.1fr;
+  gap: 18px;
+  align-items: stretch;
+}
+
+.capArt {
+  border-radius: var(--radius-lg);
+  overflow: hidden;
+  border: 1px solid var(--border);
+  background: #ffffff;
+}
+
+.capArt img {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+  display: block;
+}
+
+.capCard {
+  position: relative;
+  overflow: hidden;
+}
+
+.capIcon {
+  width: 44px;
+  height: 44px;
+  /* border-radius: 14px; */
+  margin-bottom: 10px;
+  background: rgba(37, 99, 235, 0.1);
+  border: 1px solid rgba(37, 99, 235, 0.16);
+}
+
+.capIcon[data-icon="edge"] {
+  background: radial-gradient(
+    circle at 30% 30%,
+    rgba(37, 99, 235, 0.2),
+    rgba(37, 99, 235, 0.08)
+  );
+}
+.capIcon[data-icon="data"] {
+  background: radial-gradient(
+    circle at 30% 30%,
+    rgba(56, 189, 248, 0.2),
+    rgba(56, 189, 248, 0.06)
+  );
+}
+.capIcon[data-icon="app"] {
+  background: radial-gradient(
+    circle at 30% 30%,
+    rgba(16, 185, 129, 0.16),
+    rgba(16, 185, 129, 0.06)
+  );
+}
+.capIcon[data-icon="security"] {
+  background: radial-gradient(
+    circle at 30% 30%,
+    rgba(245, 158, 11, 0.16),
+    rgba(245, 158, 11, 0.06)
+  );
+}
+
+.capTitle {
+  font-weight: 800;
+  margin-bottom: 6px;
+}
+
+.productTitle {
+  font-weight: 850;
+  letter-spacing: -0.02em;
+}
+
+.productDesc {
+  margin-top: 8px;
+}
+
+.productTags {
+  margin-top: 12px;
+  display: flex;
+  flex-wrap: wrap;
+  gap: 10px;
+}
+
+.solutionCard {
+  display: grid;
+  gap: 8px;
+}
+
+.news-list-item {
+  margin-bottom: 18px;
+  border-bottom: #ccc 1px solid;
+  padding-bottom: 18px;
+}
+.hoverWrap {
+  display: block;
+}
+
+.solutionTitle {
+  font-weight: 850;
+}
+
+.solutionMore {
+  color: var(--brand-700);
+  font-weight: 650;
+  font-size: 13px;
+}
+
+.solutionsBg {
+  position: relative;
+  overflow: hidden;
+  background-size: cover;
+  background-position: center;
+}
+
+.solutionsBg::before {
+  content: "";
+  position: absolute;
+  inset: 0;
+  background-size: cover;
+  background-position: center;
+  opacity: 1;
+  filter: saturate(0.95);
+}
+
+/* “连接井站 + 治理 + 应用”模块背景图 */
+.capabilitiesBg {
+  position: relative;
+  overflow: hidden;
+  background-size: cover;
+  background-position: center;
+  background-repeat: no-repeat;
+}
+
+.capabilitiesBg::before {
+  content: "";
+  position: absolute;
+  inset: 0;
+  background: linear-gradient(
+    180deg,
+    rgba(248, 250, 252, 0.5),
+    rgba(248, 250, 252, 0.7)
+  );
+}
+
+.capabilitiesBg > .container {
+  position: relative;
+  z-index: 1;
+}
+
+/* .solutionsBg::after {
+  content: "";
+  position: absolute;
+  inset: 0;
+  background: linear-gradient(
+    180deg,
+    rgba(248, 250, 252, 0.4),
+    rgba(248, 250, 252, 0.6)
+  );
+} */
+
+.solutionsBg > .container {
+  position: relative;
+  z-index: 1;
+}
+
+.valueAcc {
+  margin-top: 8px;
+  display: flex;
+  gap: 18px;
+  height: 580px;
+  align-items: stretch;
+}
+
+.valueAccItem {
+  flex: 1 1 0%;
+  /* border-radius: var(--radius-lg); */
+  overflow: hidden;
+  border: 1px solid rgba(15, 23, 42, 0.1);
+  background:
+    radial-gradient(
+      1200px circle at 0% 0%,
+      rgba(37, 99, 235, 0.12),
+      transparent 55%
+    ),
+    rgba(248, 250, 252, 0.95);
+  position: relative;
+  cursor: pointer;
+  transition:
+    flex 520ms cubic-bezier(0.22, 1, 0.36, 1),
+    transform 180ms ease;
+  min-width: 180px;
+}
+
+.valueAccItem:focus-visible {
+  outline: 3px solid rgba(37, 99, 235, 0.35);
+  outline-offset: 2px;
+}
+
+.valueAccItem[data-active="true"] {
+  flex: 3.2 1 0%;
+}
+
+.valueAccInner {
+  position: relative;
+  width: 100%;
+  height: 100%;
+}
+
+.valueAccCollapsed,
+.valueAccExpanded {
+  position: absolute;
+  inset: 0;
+  transition:
+    opacity 220ms ease,
+    transform 320ms ease;
+}
+
+.valueAccCollapsed {
+  padding: 52px 30px 66px;
+  display: grid;
+  align-content: start;
+  gap: 18px;
+  background-image: var(--value-collapsed-bg);
+  background-size: cover;
+  background-position: center;
+  background-repeat: no-repeat;
+}
+
+.valueAccCollapsed::before {
+  content: "";
+  position: absolute;
+  inset: 0;
+  background:
+    radial-gradient(
+      900px circle at 100% 0%,
+      rgba(37, 99, 235, 0.18),
+      transparent 55%
+    ),
+    linear-gradient(
+      180deg,
+      rgba(248, 250, 252, 0.92),
+      rgba(248, 250, 252, 0.86)
+    );
+  pointer-events: none;
+  z-index: 0;
+}
+
+.valueAccCollapsed > * {
+  position: relative;
+  z-index: 1;
+}
+
+.valueAccIcon {
+  width: 54px;
+  height: 54px;
+  border-radius: 18px;
+  display: grid;
+  place-items: center;
+  /* border: 1px solid rgba(15, 23, 42, 0.08);
+  background: rgba(255, 255, 255, 0.65); */
+  color: var(--slate-800);
+}
+
+.valueAccTitle {
+  font-size: 22px;
+  font-weight: 950;
+  letter-spacing: -0.03em;
+}
+
+.valueAccLine {
+  width: 32px;
+  height: 4px;
+  border-radius: 999px;
+  background: linear-gradient(90deg, var(--brand-700), var(--brand-500));
+}
+
+.valueAccDesc {
+  font-size: 14px;
+  line-height: 1.7;
+  max-width: 18ch;
+}
+
+.valueAccPlus {
+  position: absolute;
+  left: 18px;
+  bottom: 18px;
+  width: 36px;
+  height: 36px;
+  /* border-radius: 14px; */
+  display: grid;
+  place-items: center;
+  background: var(--brand-700);
+  color: #ffffff;
+  font-size: 26px;
+  line-height: 1;
+  box-shadow: 0 14px 26px rgba(2, 6, 23, 0.16);
+}
+
+.valueAccExpanded {
+  opacity: 0;
+  transform: scale(0.985);
+  display: grid;
+  grid-template-rows: 280px 1fr;
+  background: #ffffff;
+  pointer-events: none;
+}
+
+.valueAccCover {
+  position: relative;
+  overflow: hidden;
+}
+
+.valueAccCover img {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+  display: block;
+  transform: scale(1.03);
+  filter: saturate(1.05) contrast(1.02);
+}
+
+.valueAccBottom {
+  position: relative;
+  overflow: hidden;
+  padding: 30px;
+  color: #ffffff;
+  background-image: var(--value-bottom-bg);
+  background-size: cover;
+  background-position: center;
+  display: grid;
+  gap: 14px;
+  align-content: start;
+}
+
+.valueAccBottom::before {
+  content: "";
+  position: absolute;
+  inset: 0;
+  background: linear-gradient(
+    135deg,
+    rgba(2, 72, 185, 0.86),
+    rgba(0, 125, 255, 0.72)
+  );
+  opacity: 0.78;
+}
+
+.valueAccBottom > * {
+  position: relative;
+  z-index: 1;
+}
+
+.valueAccBottomTitle {
+  font-size: 26px;
+  font-weight: 950;
+  letter-spacing: -0.03em;
+}
+
+.valueAccBottomText {
+  font-size: 14px;
+  line-height: 1.75;
+  max-width: 56ch;
+  opacity: 0.98;
+}
+
+.valueAccBtn {
+  margin-top: 8px;
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  width: 128px;
+  height: 44px;
+  border-radius: 12px;
+  background: rgba(255, 255, 255, 0.92);
+  color: #0b63ff;
+  font-weight: 850;
+  border: 1px solid rgba(255, 255, 255, 0.32);
+}
+
+.valueAccBtn:hover {
+  background: #ffffff;
+  transform: translateY(-1px);
+}
+
+.valueAccItem[data-active="true"] .valueAccCollapsed {
+  opacity: 0;
+  transform: translateY(10px);
+  pointer-events: none;
+}
+
+.valueAccItem[data-active="true"] .valueAccExpanded {
+  opacity: 1;
+  transform: scale(1);
+  pointer-events: auto;
+}
+
+.newsCard {
+  overflow: hidden;
+}
+
+.newsRow {
+  display: grid;
+  grid-template-columns: 240px 1fr 40px;
+  align-items: center;
+  padding: 14px 18px;
+  border-top: 1px solid var(--border);
+  transition: 160ms ease;
+}
+
+.newsRow:first-child {
+  border-top: 0;
+}
+
+.newsRow:hover {
+  background: rgba(15, 23, 42, 0.02);
+}
+
+.newsMeta {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+}
+
+.newsDate {
+  font-size: 12px;
+}
+
+.newsArrow {
+  text-align: right;
+  color: var(--slate-500);
+}
+
+.partnerGrid {
+  margin-top: 16px;
+  display: grid;
+  grid-template-columns: repeat(5, minmax(0, 1fr));
+  gap: 14px;
+}
+
+.partner {
+  /* border: 1px solid var(--border); */
+  /* border-radius: 18px; */
+  background: transparent;
+  padding: 10px;
+  cursor: pointer;
+}
+
+.partner img {
+  width: 100%;
+  display: block;
+  height: 56px;
+  object-fit: contain;
+  filter: saturate(0.96);
+  opacity: 0.94;
+}
+
+.partner:hover img {
+  opacity: 1;
+  transform: scale(1.5);
+  transition: all 0.2s ease;
+}
+
+.cta__card {
+  background: var(--cta-bg);
+  background-size: cover;
+  background-position: center;
+  background-repeat: no-repeat;
+  overflow: hidden;
+}
+
+.cta__pad {
+  padding: 26px;
+  display: grid;
+  gap: 12px;
+}
+
+.cta__title {
+  font-size: 22px;
+  font-weight: 900;
+  letter-spacing: -0.02em;
+}
+
+.cta__btns {
+  margin-top: 4px;
+  display: flex;
+  flex-wrap: wrap;
+  gap: 12px;
+}
+
+@media (max-width: 960px) {
+  .hero__inner {
+    grid-template-columns: 1fr;
+  }
+
+  .hero__title {
+    font-size: 34px;
+  }
+
+  .hero__stats {
+    grid-template-columns: repeat(2, minmax(0, 1fr));
+  }
+
+  .newsRow {
+    grid-template-columns: 1fr;
+    gap: 8px;
+  }
+
+  .newsArrow {
+    display: none;
+  }
+
+  .capLayout {
+    grid-template-columns: 1fr;
+  }
+
+  .capPlatformGrid {
+    grid-template-columns: 1fr;
+  }
+
+  .valueAcc {
+    flex-direction: column;
+    height: auto;
+  }
+
+  .valueAccItem {
+    min-width: 0;
+    min-height: 220px;
+  }
+
+  .valueAccItem[data-active="true"] {
+    flex: 1 1 auto;
+  }
+
+  .valueAccExpanded {
+    grid-template-rows: 220px 1fr;
+  }
+
+  .partnerGrid {
+    grid-template-columns: repeat(2, minmax(0, 1fr));
+  }
+}
+
+@media (max-width: 520px) {
+  .hero__panelBtns {
+    grid-template-columns: 1fr;
+  }
+
+  .hero__controls {
+    margin-top: 14px;
+    /* display: flex;
+    position: fixed;
+    left: 10%;
+    align-items: center;
+    justify-content: center;
+    gap: 10px;
+    width: 100%; */
+  }
+
+  .capPlatformArt {
+    display: none;
+  }
+
+  .capModuleGrid {
+    grid-template-columns: repeat(2, minmax(0, 1fr));
+  }
+
+  .valueAccCollapsed {
+    padding: 38px 22px 62px;
+  }
+
+  .valueAccTitle {
+    font-size: 28px;
+  }
+
+  .valueAccBottom {
+    padding: 22px;
+  }
+}
+
+@media (prefers-reduced-motion: reduce) {
+  .capPlatformCard::before,
+  .capModuleTile,
+  .valueAccItem,
+  .valueAccCollapsed,
+  .valueAccExpanded,
+  .valueAccBtn {
+    transition: none !important;
+  }
+}
+
+/* 生态伙伴背景图样式 - 能源风格 */
+.partnersBg {
+  position: relative;
+  overflow: hidden;
+}
+
+.partnersBg::before {
+  content: "";
+  position: absolute;
+  inset: 0;
+  background: url("../assets/images/bg-index-3.jpg");
+  background-size: cover;
+  background-position: center;
+  /* opacity: 0.35;
+  filter: saturate(0.85); */
+}
+
+.partnersBg::after {
+  content: "";
+  position: absolute;
+  inset: 0;
+}
+
+.partnersBg > .container {
+  position: relative;
+  z-index: 1;
+}
+
+/* 平台更新与行业观点模块样式 */
+.news-market-grid {
+  display: grid;
+  grid-template-columns: 3fr 3fr;
+  gap: 32px;
+}
+
+.news-column {
+  display: flex;
+  flex-direction: column;
+  gap: 24px;
+}
+
+.news-featured {
+  display: grid;
+  grid-template-columns: 1fr 1fr;
+  gap: 24px;
+}
+
+.news-featured-item {
+  overflow: hidden;
+  background: #ffffff;
+  box-shadow: 0 4px 16px rgba(15, 23, 42, 0.08);
+  position: relative;
+  height: 160px;
+}
+
+.news-featured-link {
+  display: block;
+  text-decoration: none;
+  color: inherit;
+  width: 100%;
+  height: 100%;
+}
+
+.news-featured-image-wrapper {
+  position: absolute;
+  inset: 0;
+  height: 100%;
+  overflow: hidden;
+}
+
+.news-featured-image {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+  display: block;
+}
+
+/* 新增:文字覆盖层 */
+.news-featured-overlay {
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  padding: 20px;
+  background: rgba(0, 0, 0, 0.6);
+  color: white;
+  z-index: 2;
+}
+
+.news-featured-title {
+  font-size: 20px;
+  font-weight: 700;
+  line-height: 1.3;
+  margin-bottom: 8px;
+  display: -webkit-box;
+  -webkit-line-clamp: 2;
+  -webkit-box-orient: vertical;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.news-featured-desc {
+  font-size: 14px;
+  line-height: 1.5;
+  opacity: 0.9;
+  display: -webkit-box;
+  -webkit-line-clamp: 2;
+  -webkit-box-orient: vertical;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.news-featured-meta {
+  display: flex;
+  align-items: center;
+  gap: 12px;
+  margin-bottom: 8px;
+}
+
+.news-featured-tag {
+  background: rgba(255, 255, 255, 0.8);
+  color: var(--slate-800);
+  padding: 2px 8px;
+  border-radius: 4px;
+  font-size: 12px;
+  font-weight: 600;
+}
+
+.news-featured-date {
+  color: rgba(255, 255, 255, 0.8);
+  font-size: 12px;
+}
+
+.market-column {
+  display: flex;
+  flex-direction: column;
+  gap: 24px;
+  /* 确保与左侧高度对齐 */
+  min-height: 500px;
+}
+
+.market-activity {
+  border-radius: 5px;
+  overflow: hidden;
+  background: #ffffff;
+  position: relative;
+  height: 120px;
+}
+
+.market-activity-link {
+  display: block;
+  text-decoration: none;
+  color: inherit;
+  width: 100%;
+  height: 100%;
+}
+
+.market-activity-image-wrapper {
+  position: absolute;
+  inset: 0;
+  height: 100%;
+  overflow: hidden;
+}
+
+.market-activity-image {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+  display: block;
+}
+
+.market-activity-overlay {
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  padding: 16px;
+  background: linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, 0.8) 100%);
+  /* background: rgba(0, 0, 0, 0.5); */
+  color: white;
+  z-index: 2;
+}
+
+.market-activity-title {
+  font-size: 16px;
+  font-weight: 700;
+  line-height: 1.3;
+  margin-bottom: 4px;
+  display: -webkit-box;
+  -webkit-line-clamp: 2;
+  -webkit-box-orient: vertical;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.market-activity-desc {
+  font-size: 12px;
+  line-height: 1.4;
+  opacity: 0.9;
+  display: -webkit-box;
+  -webkit-line-clamp: 2;
+  -webkit-box-orient: vertical;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.sectionHead-actions {
+  display: flex;
+  align-items: center;
+  gap: 16px;
+}
+
+@media (max-width: 960px) {
+  .news-market-grid {
+    grid-template-columns: 1fr;
+  }
+
+  .news-column {
+    gap: 16px;
+  }
+
+  .news-featured {
+    grid-template-columns: 1fr;
+    gap: 16px;
+  }
+
+  .market-column {
+    gap: 16px;
+    min-height: auto;
+  }
+
+  .news-featured-image-wrapper {
+    height: 140px;
+  }
+
+  .market-activity-image-wrapper {
+    height: 100px;
+  }
+}
+</style>

+ 102 - 0
src/views/NewsView.vue

@@ -0,0 +1,102 @@
+<script setup>
+import PageHero from '../components/PageHero.vue'
+import Reveal from '../components/motion/Reveal.vue'
+
+const items = [
+  {
+    date: '2026-02-12',
+    tag: '发布',
+    title: '工业互联网门户新版上线',
+    desc: '统一导航、产品矩阵与行业方案展示,增强案例与新闻聚合能力。',
+  },
+  {
+    date: '2026-01-28',
+    tag: '活动',
+    title: '工业数据治理专题沙龙报名启动',
+    desc: '围绕资产目录、指标口径与数据质量治理,分享落地方法与实践。',
+  },
+  {
+    date: '2026-01-10',
+    tag: '更新',
+    title: '设备接入能力升级:新增边缘缓存与多协议适配',
+    desc: '提升现场环境稳定性,支持断点续传与离线数据补传。',
+  },
+  {
+    date: '2025-12-20',
+    tag: '案例',
+    title: '从采集到指标:制造企业数据治理全链路实践',
+    desc: '以“口径统一 + 质量可控”为目标,推动数据资产规模化生产。',
+  },
+]
+</script>
+
+<template>
+  <div>
+    <PageHero
+      kicker="新闻动态"
+      title="平台更新与行业观点"
+      subtitle="及时了解平台能力演进、活动与行业实践。"
+    >
+      <template #actions>
+        <RouterLink class="btn btn-primary" to="/contact">订阅更新</RouterLink>
+        <RouterLink class="btn btn-ghost" to="/cases">查看案例</RouterLink>
+      </template>
+    </PageHero>
+
+    <section class="section">
+      <div class="container">
+        <div class="grid newsGrid">
+          <Reveal
+            v-for="(n, idx) in items"
+            :key="n.title"
+            as="div"
+            class="card card-pad newsItem hover-lift"
+            :delay="60 + idx * 70"
+          >
+            <div class="newsTop">
+              <span class="pill">{{ n.tag }}</span>
+              <span class="muted newsDate">{{ n.date }}</span>
+            </div>
+            <div class="newsTitle">{{ n.title }}</div>
+            <div class="muted">{{ n.desc }}</div>
+            <RouterLink class="btn btn-link newsMore" to="/contact">获取详情 →</RouterLink>
+          </Reveal>
+        </div>
+      </div>
+    </section>
+  </div>
+</template>
+
+<style scoped>
+.newsGrid {
+  grid-template-columns: repeat(2, minmax(0, 1fr));
+}
+
+.newsTop {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  gap: 12px;
+  margin-bottom: 10px;
+}
+
+.newsDate {
+  font-size: 12px;
+}
+
+.newsTitle {
+  font-weight: 900;
+  letter-spacing: -0.02em;
+  margin-bottom: 6px;
+}
+
+.newsMore {
+  margin-top: 10px;
+}
+
+@media (max-width: 960px) {
+  .newsGrid {
+    grid-template-columns: 1fr;
+  }
+}
+</style>

+ 28 - 0
src/views/NotFoundView.vue

@@ -0,0 +1,28 @@
+<script setup>
+import PageHero from '../components/PageHero.vue'
+</script>
+
+<template>
+  <div>
+    <PageHero
+      kicker="404"
+      title="页面不存在"
+      subtitle="你访问的页面可能已更名、删除或暂时不可用。"
+    >
+      <template #actions>
+        <RouterLink class="btn btn-primary" to="/">返回首页</RouterLink>
+        <RouterLink class="btn btn-ghost" to="/contact">联系咨询</RouterLink>
+      </template>
+    </PageHero>
+
+    <section class="section">
+      <div class="container">
+        <div class="card card-pad">
+          <div style="font-weight: 900; margin-bottom: 6px">建议</div>
+          <div class="muted">你可以从首页进入产品、解决方案与案例,也可以直接联系我们获取帮助。</div>
+        </div>
+      </div>
+    </section>
+  </div>
+</template>
+

+ 147 - 0
src/views/ProductsView.vue

@@ -0,0 +1,147 @@
+<script setup>
+import PageHero from '../components/PageHero.vue'
+
+const modules = [
+  {
+    title: '设备接入(IIoT)',
+    desc: '覆盖 PLC/仪表/传感器/网关等多类型设备,支持边缘计算、离线缓存与断点续传。',
+    points: ['协议适配与采集', '运行监控与告警', '远程运维与工单'],
+  },
+  {
+    title: '工业数据治理',
+    desc: '沉淀可复用的数据资产:统一资产、口径与血缘,推动“可用数据”规模化生产。',
+    points: ['资产目录与标签', '数据质量与校验', '指标中心与口径管理'],
+  },
+  {
+    title: '工业应用(低代码)',
+    desc: '面向生产、质量、能源与设备运维,提供组件库与模板,快速搭建可运营应用。',
+    points: ['表单/流程/看板', '权限与审计', '应用市场与复用'],
+  },
+  {
+    title: '智能分析(AI)',
+    desc: '结合工业机理与算法模型,落地质检、预测维护、异常检测与能效优化。',
+    points: ['视觉质检', '预测性维护', '异常与根因分析'],
+  },
+]
+
+const deliver = [
+  { title: 'SaaS', desc: '开箱即用,按需订阅,快速试点与复制。' },
+  { title: '私有化', desc: '数据本地化部署,适配企业安全与合规要求。' },
+  { title: '混合云', desc: '核心数据本地,弹性算力上云,兼顾成本与性能。' },
+]
+</script>
+
+<template>
+  <div>
+    <PageHero
+      kicker="产品矩阵"
+      title="工业互联网能力中台"
+      subtitle="以工业 PaaS 为底座,叠加 IIoT 接入、数据治理、低代码应用与智能分析,形成从“连接”到“运营”的全链路能力。"
+    >
+      <template #actions>
+        <RouterLink class="btn btn-primary" to="/contact">获取产品资料</RouterLink>
+        <RouterLink class="btn btn-ghost" to="/solutions">查看方案</RouterLink>
+      </template>
+    </PageHero>
+
+    <section class="section">
+      <div class="container">
+        <div class="sectionHead">
+          <div>
+            <div class="section-kicker">模块能力</div>
+            <h2 class="h2">面向落地的可组合能力</h2>
+            <div class="muted">每个模块都可独立交付,也可与其他模块组合,形成端到端解决方案。</div>
+          </div>
+        </div>
+
+        <div class="grid grid-2 moduleGrid">
+          <div v-for="m in modules" :key="m.title" class="card card-pad moduleCard">
+            <div class="moduleTitle">{{ m.title }}</div>
+            <div class="muted moduleDesc">{{ m.desc }}</div>
+            <div class="modulePoints">
+              <div v-for="p in m.points" :key="p" class="modulePoint">
+                <span class="dot" aria-hidden="true"></span>
+                <span>{{ p }}</span>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </section>
+
+    <section class="section section--soft">
+      <div class="container">
+        <div class="sectionHead">
+          <div>
+            <div class="section-kicker">交付方式</div>
+            <h2 class="h2">灵活适配企业 IT 架构</h2>
+          </div>
+        </div>
+
+        <div class="grid grid-3">
+          <div v-for="d in deliver" :key="d.title" class="card card-pad deliverCard">
+            <div class="deliverTitle">{{ d.title }}</div>
+            <div class="muted">{{ d.desc }}</div>
+          </div>
+        </div>
+      </div>
+    </section>
+  </div>
+</template>
+
+<style scoped>
+.sectionHead {
+  display: flex;
+  align-items: flex-end;
+  justify-content: space-between;
+  gap: 18px;
+  margin-bottom: 16px;
+}
+
+.moduleGrid {
+  grid-template-columns: repeat(2, minmax(0, 1fr));
+}
+
+.moduleTitle {
+  font-weight: 900;
+  letter-spacing: -0.02em;
+}
+
+.moduleDesc {
+  margin-top: 8px;
+}
+
+.modulePoints {
+  margin-top: 12px;
+  display: grid;
+  gap: 10px;
+}
+
+.modulePoint {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+  color: var(--slate-700);
+  font-weight: 600;
+}
+
+.dot {
+  width: 8px;
+  height: 8px;
+  border-radius: 50%;
+  background: var(--brand-600);
+  box-shadow: 0 8px 14px rgba(29, 78, 216, 0.20);
+}
+
+.deliverTitle {
+  font-weight: 900;
+  margin-bottom: 6px;
+}
+
+@media (max-width: 960px) {
+  .moduleGrid {
+    grid-template-columns: 1fr;
+  }
+}
+</style>
+

+ 192 - 0
src/views/SolutionsView.vue

@@ -0,0 +1,192 @@
+<script setup>
+import PageHero from '../components/PageHero.vue'
+import solutionsBgUrl from '../assets/images/bg.jpg?url'
+import Reveal from '../components/motion/Reveal.vue'
+
+const solutions = [
+  {
+    title: '离散制造 · 质量与效率提升',
+    desc: '聚焦工序追溯、质量闭环与设备稳定性,提升良率与交付稳定性。',
+    scenes: ['工序追溯与过程控制', 'OEE 与停机分析', '质量异常闭环与 8D'],
+  },
+  {
+    title: '流程工业 · 能效与安全协同',
+    desc: '围绕工艺优化与运行安全,形成指标体系与异常分析闭环。',
+    scenes: ['能耗监测与对标', '工艺参数波动预警', '装置运行监控与告警'],
+  },
+  {
+    title: '园区与能源 · 运营可视化',
+    desc: '统一园区数据与应用入口,联动安环、能耗、资产与运维。',
+    scenes: ['园区综合态势大屏', '能源计量与分摊', '设备巡检与工单'],
+  },
+  {
+    title: '供应链协同 · 透明与协同',
+    desc: '打通订单、库存与交付状态,提升响应速度与协同效率。',
+    scenes: ['订单跟踪与交付预警', '库存可视化与周转分析', '供应商协同门户'],
+  },
+  {
+    title: '碳管理 · 合规披露与减排',
+    desc: '以数据治理为基础,构建碳核算、减排评估与合规披露。',
+    scenes: ['组织/产品碳核算', '减排项目评估', '合规披露与审计留痕'],
+  },
+  {
+    title: '设备运维 · 预测维护',
+    desc: '多源数据融合,落地预测性维护,降低停机与维护成本。',
+    scenes: ['多指标健康度', '故障预测与诊断', '备件与工单联动'],
+  },
+]
+
+const approach = [
+  { step: '01', title: '梳理现状', desc: '明确目标与关键指标,识别可快速见效的试点场景。' },
+  { step: '02', title: '快速接入', desc: '优先打通关键设备与系统,形成可用数据最小闭环。' },
+  { step: '03', title: '治理沉淀', desc: '统一资产、口径与质量规则,沉淀可复用的数据资产。' },
+  { step: '04', title: '应用运营', desc: '以看板与流程闭环驱动持续改进,形成规模化复制能力。' },
+]
+</script>
+
+<template>
+  <div>
+    <PageHero
+      kicker="解决方案"
+      title="面向行业场景的可复制实践"
+      subtitle="围绕制造、流程、园区、供应链、碳管理与运维等场景,提供“平台能力 + 行业模板 + 交付方法”的一体化方案。"
+    >
+      <template #actions>
+        <RouterLink class="btn btn-primary" to="/contact">获取方案白皮书</RouterLink>
+        <RouterLink class="btn btn-ghost" to="/cases">参考案例</RouterLink>
+      </template>
+    </PageHero>
+
+    <section class="section">
+      <div class="container">
+        <Reveal as="div" class="sectionHead" :delay="0">
+          <div>
+            <div class="section-kicker">方案清单</div>
+            <h2 class="h2">从试点到复制的交付体系</h2>
+          </div>
+        </Reveal>
+
+        <div class="grid grid-3">
+          <Reveal
+            v-for="(s, idx) in solutions"
+            :key="s.title"
+            as="div"
+            class="card card-pad solutionCard hover-lift"
+            :delay="60 + idx * 70"
+          >
+            <div class="solutionTitle">{{ s.title }}</div>
+            <div class="muted">{{ s.desc }}</div>
+            <div class="solutionScenes">
+              <div v-for="sc in s.scenes" :key="sc" class="scene">
+                <span class="dot" aria-hidden="true"></span>
+                <span>{{ sc }}</span>
+              </div>
+            </div>
+          </Reveal>
+        </div>
+      </div>
+    </section>
+
+    <section class="section section--soft solutionsBg" :style="{ '--solutions-bg': `url(${solutionsBgUrl})` }">
+      <div class="container">
+        <Reveal as="div" class="sectionHead" :delay="0">
+          <div>
+            <div class="section-kicker">落地方法</div>
+            <h2 class="h2">以数据闭环驱动持续改进</h2>
+          </div>
+        </Reveal>
+
+        <div class="grid grid-4">
+          <Reveal
+            v-for="(a, idx) in approach"
+            :key="a.step"
+            as="div"
+            class="card card-pad approachCard hover-lift"
+            :delay="60 + idx * 70"
+          >
+            <div class="approachStep">{{ a.step }}</div>
+            <div class="approachTitle">{{ a.title }}</div>
+            <div class="muted">{{ a.desc }}</div>
+          </Reveal>
+        </div>
+      </div>
+    </section>
+  </div>
+</template>
+
+<style scoped>
+.sectionHead {
+  display: flex;
+  align-items: flex-end;
+  justify-content: space-between;
+  gap: 18px;
+  margin-bottom: 16px;
+}
+
+.solutionTitle {
+  font-weight: 900;
+  letter-spacing: -0.02em;
+  margin-bottom: 6px;
+}
+
+.solutionScenes {
+  margin-top: 12px;
+  display: grid;
+  gap: 10px;
+}
+
+.scene {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+  color: var(--slate-700);
+  font-weight: 600;
+}
+
+.dot {
+  width: 8px;
+  height: 8px;
+  border-radius: 50%;
+  background: var(--brand-600);
+}
+
+.approachStep {
+  color: var(--brand-700);
+  font-weight: 900;
+  letter-spacing: -0.02em;
+}
+
+.approachTitle {
+  margin-top: 4px;
+  font-weight: 900;
+  margin-bottom: 6px;
+}
+
+.solutionsBg {
+  position: relative;
+  overflow: hidden;
+}
+
+.solutionsBg::before {
+  content: '';
+  position: absolute;
+  inset: 0;
+  background-image: var(--solutions-bg);
+  background-size: cover;
+  background-position: center;
+  opacity: 0.45;
+  filter: saturate(0.95);
+}
+
+.solutionsBg::after {
+  content: '';
+  position: absolute;
+  inset: 0;
+  background: linear-gradient(180deg, rgba(248, 250, 252, 0.78), rgba(248, 250, 252, 0.92));
+}
+
+.solutionsBg > .container {
+  position: relative;
+  z-index: 1;
+}
+</style>

+ 22 - 0
vite.config.js

@@ -0,0 +1,22 @@
+import { fileURLToPath, URL } from 'node:url'
+
+import { defineConfig } from 'vite'
+import vue from '@vitejs/plugin-vue'
+import vueDevTools from 'vite-plugin-vue-devtools'
+
+// https://vite.dev/config/
+export default defineConfig({
+  plugins: [
+    vue(),
+    vueDevTools(),
+  ],
+  resolve: {
+    alias: {
+      '@': fileURLToPath(new URL('./src', import.meta.url))
+    },
+  },
+  server: {
+    port: 8081,
+    open: true,
+  }
+})