The nav still used the ink palette: flat fills, oversized rows, and a tinted background with no marker for the active route. Adopt the CYBER treatment from the prototype — a 2px glowing cyan bar on the left of the active item, hairline borders instead of full-contrast ones, monospace group labels with wide tracking, and a faint cyan wash at the top of the rail so it does not read as a dead dark slab. PageSidebarNav gets the same active treatment as AppSidebar so the conversation routes do not feel like a different product. Header height stays at 64px — style-system.test.ts asserts it as a layout contract.
681 lines
19 KiB
SCSS
681 lines
19 KiB
SCSS
@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 暗色态:强制走暗色变量(属性挂在 <html> 上,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 渲染原生 <input>,已被上面的元素选择器覆盖;
|
||
// 需要额外兜住的是 a-textarea(渲染 textarea,字体继承自容器)与 Arco 包装层。
|
||
@media (max-width: 768px) {
|
||
input,
|
||
textarea,
|
||
select,
|
||
.arco-input,
|
||
.arco-textarea {
|
||
font-size: 16px !important;
|
||
}
|
||
}
|