@use 'variables' as *; @use 'code-block'; *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; } button, input, select, textarea { font-family: inherit; } :root { --vh: 1vh; } // Fix mobile viewport height (address bar) @supports (height: 100dvh) { :root { --vh: 1dvh; } } // ─── Arco Design token bridge ────────────────────────────────── // arco-theme.ts 不是运行时来源(没有 ConfigProvider),Arco 的实际外观由 arco.css // 里的 CSS 变量决定。这里把 CYBER 令牌翻译成 Arco 变量。 // // 关键:Arco 有两套命名。--primary-6 是 rgb 三元组,--color-primary 是颜色值。 // a-button / a-tag / a-switch 的底色走 rgb(var(--primary-6)),也就是 // --primary-6 → --arcoblue-6 这一族;只覆盖 --color-primary 不会改变按钮底色。 // 两套都必须覆盖,否则会残留 Arco 蓝(22,93,255)。 // 变量表见 node_modules/@arco-design/web-vue/dist/arco.css 的 :root 块。 html[arco-theme='dark'], :root { // Arco 的 rgb 三元组族 —— 实心控件(按钮底、开关滑块、进度条)的真正来源。 // 霓虹青 oklch(0.805 0.148 188) ≈ rgb(45,212,191),按亮度排 1→10。 --arcoblue-1: 12, 58, 56; --arcoblue-2: 16, 84, 78; --arcoblue-3: 22, 118, 108; --arcoblue-4: 28, 148, 135; --arcoblue-5: 34, 172, 156; --arcoblue-6: 45, 212, 191; --arcoblue-7: 70, 229, 209; --arcoblue-8: 120, 239, 224; --arcoblue-9: 172, 246, 238; --arcoblue-10: 218, 250, 246; --green-6: 47, 197, 138; --green-5: 56, 184, 130; --green-7: 38, 178, 122; --orange-6: 226, 175, 32; --orange-5: 214, 165, 34; --orange-7: 236, 190, 44; --red-6: 232, 78, 61; --red-5: 222, 74, 58; --red-7: 240, 96, 78; // Arco 的颜色值族 —— 描边、文字、浅底 --color-primary-light-1: oklch(0.30 0.060 188); --color-primary-light-2: oklch(0.39 0.075 188); --color-primary-light-3: oklch(0.50 0.095 188); --color-primary-light-4: oklch(0.60 0.115 188); --color-primary-light-5: oklch(0.68 0.130 188); --color-primary-light-6: oklch(0.805 0.148 188); --color-primary: oklch(0.805 0.148 188); --color-primary-dark-1: oklch(0.760 0.144 188); --color-primary-dark-2: oklch(0.700 0.138 188); --color-primary-dark-3: oklch(0.640 0.130 188); --color-primary-dark-4: oklch(0.580 0.120 188); --color-primary-dark-5: oklch(0.520 0.108 188); --color-primary-dark-6: oklch(0.460 0.094 188); --color-success-light-1: oklch(0.28 0.050 165); --color-success-light-2: oklch(0.42 0.078 165); --color-success-light-3: oklch(0.58 0.108 165); --color-success: oklch(0.760 0.140 165); --color-warning-light-1: oklch(0.30 0.052 85); --color-warning-light-2: oklch(0.46 0.082 85); --color-warning-light-3: oklch(0.62 0.112 85); --color-warning: oklch(0.810 0.145 85); --color-danger-light-1: oklch(0.28 0.062 22); --color-danger-light-2: oklch(0.42 0.096 22); --color-danger-light-3: oklch(0.56 0.138 22); --color-danger: oklch(0.665 0.185 22); --color-link-light-1: oklch(0.30 0.060 188); --color-link-light-2: oklch(0.42 0.084 188); --color-link-light-3: oklch(0.54 0.110 188); --color-link-light-4: oklch(0.66 0.136 188); --color-link-light-5: oklch(0.74 0.148 188); --color-link-light-6: oklch(0.805 0.148 188); --color-link: oklch(0.805 0.148 188); // 容器与文字 --color-text-1: oklch(0.945 0.006 200); --color-text-2: oklch(0.860 0.008 210); --color-text-3: oklch(0.705 0.014 230); --color-text-4: oklch(0.520 0.014 236); --color-text-disabled: oklch(0.420 0.012 238); --color-bg-1: oklch(0.155 0.012 250); --color-bg-2: oklch(0.130 0.012 250); --color-bg-3: oklch(0.185 0.014 248); --color-bg-4: oklch(0.225 0.016 246); --color-bg-5: oklch(0.255 0.018 247); --color-fill-1: oklch(0.185 0.014 248); --color-fill-2: oklch(0.225 0.016 246); --color-fill-3: oklch(0.255 0.018 247); --color-fill-4: oklch(0.285 0.018 246); --color-border-1: oklch(0.305 0.018 242); --color-border-2: oklch(0.255 0.016 244); --color-border-3: oklch(0.225 0.014 246); --color-border-4: oklch(0.195 0.014 248); --color-fill-2-hover: oklch(0.255 0.018 247); --color-fill-3-hover: oklch(0.285 0.018 246); --radius-small: 4px; --radius-medium: 6px; --radius-large: 8px; --font-size-body-1: 14px; --font-size-body-2: 13px; --font-size-body-3: 12px; // CYBER 的核心排版特征:标题、页头、数据用等宽 --font-family: #{$font-ui}; --font-family-body: #{$font-ui}; --font-family-code: #{$font-code}; } // Arco 暗色态:强制走暗色变量(属性挂在 上,Arco 官方选择器可能匹配 body) body { color: $text-primary; background-color: $bg-primary; } // Arco 组件里的滚动条与焦点环对齐 CYBER .arco-scrollbar-thumb { background-color: $border-color !important; } // ─── Neon tube buttons ───────────────────────────────────────── // CYBER 的按钮是「霓虹灯管」而不是实心色块:底色透明 / 内部暗,只有 1px 青色管壁 // 与外发光。hover / active 时管壁增亮、光晕收紧,模拟通电。 // 这里直接覆盖 Arco 的按钮外观类,因为 a-button 的默认样式来自 arco.css, // token 桥接改不到「实心 vs 镂空」这一层。 $neon: var(--accent-primary); $neon-hv: var(--accent-hover); // 镂空管壁 + 双层外发光(内紧外散) @mixin neon-tube($glow: 0.32, $wall: 1px) { position: relative; overflow: hidden; color: $neon; background: transparent; border: $wall solid rgba(var(--accent-primary-rgb), 0.55); box-shadow: inset 0 0 12px rgba(var(--accent-primary-rgb), $glow * 0.35), 0 0 10px rgba(var(--accent-primary-rgb), $glow), 0 0 22px rgba(var(--accent-primary-rgb), $glow * 0.5); text-shadow: 0 0 8px rgba(var(--accent-primary-rgb), 0.45); } // 扫光:一道白光从左扫到右。周期大部分时间停在暗处,只在 62%→86% 之间走一趟, // 避免常驻动画造成视觉噪音。 @keyframes neon-sheen { 0%, 62% { transform: translateX(-140%); } 86%, 100% { transform: translateX(320%); } } @mixin neon-sheen() { &::after { content: ''; position: absolute; top: 0; bottom: 0; left: 0; width: 38%; background: linear-gradient(90deg, transparent, oklch(1 0 0 / 0.28), transparent); transform: translateX(-140%); animation: neon-sheen 3.4s ease-in-out infinite; pointer-events: none; } } // Arco 为按钮写了 `.arco-btn-primary[type='button']` / `[type='submit']` / `[type='reset']` // 三个属性选择器变体,把特异性从 (0,1,0) 抬到 (0,2,0);它的 hover 变体则是 // `.arco-btn-primary[type='submit']:hover` → (0,3,0)。所以下面每条规则都用 // `.arco-btn.arco-btn-X[type='...']`(0,3,0)打底,状态规则用 (0,4,0), // 稳压过 Arco 的一整族变体。只写 `.arco-btn-primary` 会被压过,而 a-button // 默认 html-type 就是 button —— 漏掉属性选择器等于所有按钮都不生效。 // 默认按钮(secondary / 默认态):不发光的幽灵按钮,只在 hover 时点亮管壁 .arco-btn.arco-btn-secondary, .arco-btn.arco-btn-secondary[type='button'], .arco-btn.arco-btn-secondary[type='submit'], .arco-btn.arco-btn-secondary[type='reset'], .arco-btn.arco-btn-outline, .arco-btn.arco-btn-outline[type='button'], .arco-btn.arco-btn-outline[type='submit'], .arco-btn.arco-btn-outline[type='reset'], .arco-btn.arco-btn-default, .arco-btn.arco-btn-default[type='button'], .arco-btn.arco-btn-default[type='submit'], .arco-btn.arco-btn-default[type='reset'] { color: $text-secondary; background: transparent; border: 1px solid $border-color; box-shadow: none; transition: color 0.16s ease, border-color 0.16s ease, box-shadow 0.16s ease, background-color 0.16s ease; &:not(.arco-btn-disabled):hover { color: $neon; border-color: rgba(var(--accent-primary-rgb), 0.55); background: rgba(var(--accent-primary-rgb), 0.05); box-shadow: 0 0 10px rgba(var(--accent-primary-rgb), 0.22); text-shadow: 0 0 8px rgba(var(--accent-primary-rgb), 0.35); } } // 主按钮:霓虹管 .arco-btn.arco-btn-primary, .arco-btn.arco-btn-primary[type='button'], .arco-btn.arco-btn-primary[type='submit'], .arco-btn.arco-btn-primary[type='reset'] { @include neon-tube(0.34); @include neon-sheen; font-weight: 600; &:not(.arco-btn-disabled):hover { @include neon-tube(0.52); color: $neon-hv; border-color: rgba(var(--accent-primary-rgb), 0.85); } &:not(.arco-btn-disabled):active { // 按下时管壁收窄、光晕内收,像灯管被压住 box-shadow: inset 0 0 16px rgba(var(--accent-primary-rgb), 0.22), 0 0 6px rgba(var(--accent-primary-rgb), 0.34); transform: translateY(1px); } &:not(.arco-btn-disabled):focus-visible { outline: none; box-shadow: inset 0 0 12px rgba(var(--accent-primary-rgb), 0.12), 0 0 0 3px rgba(var(--accent-primary-rgb), 0.16), 0 0 16px rgba(var(--accent-primary-rgb), 0.4); } } // 危险操作:同构的霓虹管,颜色换成红 @mixin neon-tube-danger($glow: 0.28) { position: relative; overflow: hidden; color: $error; background: transparent; border: 1px solid rgba(var(--error-rgb), 0.5); box-shadow: inset 0 0 12px rgba(var(--error-rgb), $glow * 0.3), 0 0 10px rgba(var(--error-rgb), $glow); text-shadow: 0 0 8px rgba(var(--error-rgb), 0.4); } .arco-btn.arco-btn-dangerous, .arco-btn.arco-btn-dangerous[type='button'], .arco-btn.arco-btn-dangerous[type='submit'], .arco-btn.arco-btn-dangerous[type='reset'] { @include neon-tube-danger(0.26); font-weight: 500; &:not(.arco-btn-disabled):hover { @include neon-tube-danger(0.44); background: rgba(var(--error-rgb), 0.06); } } .arco-btn-dangerous.arco-btn-secondary, .arco-btn-dangerous.arco-btn-outline { color: rgba(var(--error-rgb), 0.85); border-color: rgba(var(--error-rgb), 0.38); background: transparent; box-shadow: none; &:not(.arco-btn-disabled):hover { @include neon-tube-danger(0.4); } } // 文字 / 链接按钮:无管壁,只让文字带辉光 .arco-btn.arco-btn-text, .arco-btn.arco-btn-link, .arco-btn.arco-btn-text[type='button'], .arco-btn.arco-btn-text[type='submit'], .arco-btn.arco-btn-text[type='reset'], .arco-btn.arco-btn-link[type='button'], .arco-btn.arco-btn-link[type='submit'], .arco-btn.arco-btn-link[type='reset'] { background: transparent; border: 1px solid transparent; box-shadow: none; color: $neon; text-shadow: 0 0 8px rgba(var(--accent-primary-rgb), 0.3); &:not(.arco-btn-disabled):hover { color: $neon-hv; background: rgba(var(--accent-primary-rgb), 0.07); text-shadow: 0 0 12px rgba(var(--accent-primary-rgb), 0.55); } } // 禁用态:灯管熄灭 .arco-btn.arco-btn-primary.arco-btn-disabled, .arco-btn.arco-btn-secondary.arco-btn-disabled, .arco-btn.arco-btn-outline.arco-btn-disabled, .arco-btn.arco-btn-dangerous.arco-btn-disabled, .arco-btn.arco-btn-text.arco-btn-disabled, .arco-btn.arco-btn-link.arco-btn-disabled, .arco-btn.arco-btn-primary[type='button'].arco-btn-disabled, .arco-btn.arco-btn-primary[type='submit'].arco-btn-disabled, .arco-btn.arco-btn-secondary[type='button'].arco-btn-disabled, .arco-btn.arco-btn-secondary[type='submit'].arco-btn-disabled, .arco-btn.arco-btn-dangerous[type='button'].arco-btn-disabled, .arco-btn.arco-btn-dangerous[type='submit'].arco-btn-disabled { color: var(--text-faint); background: transparent; border-color: var(--border-light); box-shadow: none; text-shadow: none; cursor: not-allowed; } // 加载态:保留管壁不熄灭,用脉冲表示"通电中" @keyframes neon-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.62; } } .arco-btn.arco-btn-primary.arco-btn-loading, .arco-btn.arco-btn-primary[type='button'].arco-btn-loading, .arco-btn.arco-btn-primary[type='submit'].arco-btn-loading { @include neon-tube(0.4); // 提交中扫光暂停,用脉冲表示"通电中",避免两个动画叠加 &::after { animation: none; opacity: 0; } animation: neon-pulse 1.1s ease-in-out infinite; } // 尺寸统一:CYBER 的按钮偏小方硬 .arco-btn { border-radius: $radius-sm; font-family: $font-code; letter-spacing: 0.02em; transition: color 0.16s ease, border-color 0.16s ease, box-shadow 0.16s ease, background-color 0.16s ease, transform 0.08s ease; } // 兜底:任何未显式分类的实心底按钮(Arco 的 .arco-btn 默认无 type class 时) // 也不能漏成白块或蓝块。 .arco-btn:not([class*='arco-btn-primary']):not([class*='arco-btn-secondary']):not([class*='arco-btn-outline']):not([class*='arco-btn-text']):not([class*='arco-btn-link']):not([class*='arco-btn-dangerous']) { background: transparent; color: $text-secondary; border: 1px solid $border-color; &:not(.arco-btn-disabled):hover { color: $neon; border-color: rgba(var(--accent-primary-rgb), 0.55); } } // ─── Neon inputs / selects / tags ─────────────────────────────── // 输入区是「凹陷」的:底色比卡片更沉,聚焦时管壁点亮并带一圈内发光。 .arco-input-wrapper, .arco-textarea-wrapper, .arco-select-view, .arco-picker, .arco-input-tag { background-color: $bg-input !important; border-color: $border-color; box-shadow: none; transition: border-color 0.16s ease, box-shadow 0.16s ease; &:hover { border-color: rgba(var(--accent-primary-rgb), 0.4); } } .arco-input-wrapper-focus, .arco-textarea-wrapper-focus, .arco-select-view-focus, .arco-picker-focused, .arco-input-tag-focus { border-color: rgba(var(--accent-primary-rgb), 0.85); box-shadow: 0 0 0 3px rgba(var(--accent-primary-rgb), 0.12), inset 0 0 14px rgba(var(--accent-primary-rgb), 0.06); } .arco-input, .arco-textarea, .arco-select-view-single, .arco-select-view-value { color: $text-primary; } .arco-input::placeholder, .arco-textarea::placeholder { color: var(--text-faint); } // 标签:状态语义用发丝线底 + 彩色字,不用实心块 .arco-tag { border-radius: 4px; font-family: $font-code; font-size: 11.5px; background: transparent; border: 1px solid currentColor; } // 开关 / 复选 / 单选的滑块用霓虹青 .arco-switch-checked { background-color: rgba(var(--accent-primary-rgb), 0.22); border-color: rgba(var(--accent-primary-rgb), 0.7); box-shadow: 0 0 10px rgba(var(--accent-primary-rgb), 0.3); } .arco-switch-checked .arco-switch-slider { background-color: var(--accent-primary); box-shadow: 0 0 10px rgba(var(--accent-primary-rgb), 0.7); } .arco-checkbox-checked .arco-checkbox-inner { background-color: var(--accent-primary); border-color: var(--accent-primary); box-shadow: 0 0 8px rgba(var(--accent-primary-rgb), 0.5); } // 下拉 / 弹层的浮层背景 .arco-trigger-popup, .arco-select-popup, .arco-picker-dropdown, .arco-dropdown, .arco-modal, .arco-drawer { background-color: var(--surface-2); border: 1px solid var(--border-color); box-shadow: var(--shadow, 0 18px 48px oklch(0 0 0 / 0.55)); } // 表格:去掉亮色分隔线的突兀感,表头沉下去 .arco-table-th { background-color: var(--surface-2); color: $text-muted; border-color: $border-color; font-family: $font-code; font-weight: 600; } .arco-table-td { border-color: var(--border-light); } .arco-table-tr:hover .arco-table-td { background-color: rgba(var(--accent-primary-rgb), 0.04); } // 进度条 / 加载条 .arco-progress-line .arco-progress-line-bar, .arco-slider-track-bar { background-color: var(--accent-primary); box-shadow: 0 0 8px rgba(var(--accent-primary-rgb), 0.5); } html, body { position: fixed; top: 0; left: 0; width: 100%; height: 100%; overflow: hidden; } #app { height: 100%; width: 100%; overflow: hidden; } body { font-family: $font-ui; background-color: $bg-primary; color: $text-primary; font-size: 14px; line-height: 1.6; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } // Chat input route CSS is code-split; keep the footer color stable before the // component-scoped chunk arrives so entering chat does not flash the page bg. .chat-input-area, .chat-input-area .input-wrapper { background-color: $bg-card; } .settings-check { display: inline-flex; align-items: center; justify-content: center; width: 16px; min-width: 16px; height: 16px; color: transparent; font-size: 13px; line-height: 16px; } .settings-check.active { color: $accent-primary; } code, pre, .mono { font-family: $font-code; } a { color: $accent-primary; text-decoration: none; &:hover { color: $accent-hover; } } ::-webkit-scrollbar { width: 8px; height: 8px; background: transparent; } ::-webkit-scrollbar-track, ::-webkit-scrollbar-track-piece { background: transparent; } ::-webkit-scrollbar-thumb { background: $border-color; border-radius: 4px; &:hover { background: rgba(var(--accent-primary-rgb), 0.5); } } ::-webkit-scrollbar-corner { background: transparent; } * { scrollbar-width: thin; scrollbar-color: $border-color transparent; } ::selection { background: rgba(var(--accent-primary-rgb), 0.3); } // Shared page header // 页面顶栏:发丝线分隔 + 极淡的青色底,标题用等宽字体带字距。 // 高度保持 64px(ui-baseline 契约,测试有断言)。 .page-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 64px; padding: 14px 20px; border-bottom: 1px solid var(--border-light); flex-shrink: 0; background: linear-gradient(180deg, rgba(var(--accent-primary-rgb), 0.035), transparent 70%); } .header-title { margin: 0; font-family: $font-code; font-size: 15px; font-weight: 600; line-height: 1.4; letter-spacing: 0.04em; color: $text-primary; } .page-header > .header-actions { display: flex; align-items: center; justify-content: flex-end; gap: 8px; } // Responsive utility classes for inline width replacement .input-sm { width: 90px; } .input-md { width: 200px; } .input-lg { width: 300px; } // Mobile drawer backdrop .mobile-backdrop { display: none; position: fixed; inset: 0; background: rgba(0, 0, 0, 0.4); z-index: 999; } // Hamburger button (mobile only) .hamburger-btn { display: none; position: fixed; top: calc(10px + env(safe-area-inset-top, 0px)); left: 12px; z-index: 99; width: 36px; height: 36px; border: none; background: $bg-card; border-radius: $radius-sm; cursor: pointer; align-items: center; justify-content: center; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1); } // Mobile responsive @media (max-width: $breakpoint-mobile) { .mobile-backdrop { display: block; } .hamburger-btn { display: flex; } .page-header { padding: calc(16px + env(safe-area-inset-top, 0px)) 12px 16px 52px !important; } .input-sm, .input-md, .input-lg { width: 100%; } } // Prevent iOS Safari auto-zoom on input focus by ensuring font-size is at least 16px // Arco 的 a-input 渲染原生 ,已被上面的元素选择器覆盖; // 需要额外兜住的是 a-textarea(渲染 textarea,字体继承自容器)与 Arco 包装层。 @media (max-width: 768px) { input, textarea, select, .arco-input, .arco-textarea { font-size: 16px !important; } }