---
description: mvframe 项目 src/style 样式系统规范
globs: src/**/*.{vue,scss,css}
alwaysApply: true
---

# mvframe 样式系统

## 关于 frontmatter 里的 `alwaysApply`

- **`alwaysApply: true` 只作用于 Cursor**：把本文件当作对话上下文里的规范读给 AI，**不会**在构建时自动给任何 `.vue` 挂上样式，也**不等于**工具类已生效。
- **运行时要用工具类**，必须在应用入口（如 demo `main.js`、宿主项目）**已 `import` `mvframe` 的 `src/style/index.scss`（或包导出的 `style`）**；然后在组件 **template 里写上工具类名**（如 `flexMode`、`g16`、`fs14`），尽量少写与工具类等价的 scoped 声明。

样式入口为 `src/style/index.scss`，按模块拆分为 `chip/*.scss`。宿主项目如果只消费发布包，直接 `import "mvframe/style"` 即可拿到全局工具类；如果要在业务 SCSS 里复用框架断点 mixin，用 `@use "mvframe/style/mixin" as *;`。

## 1. 变量与颜色（var.scss）

### :root 变量

| 变量 | 用途 |
|------|------|
| `--color-txt-h1` ~ `--color-txt-tip` | 文本层级色（#111→#999） |
| `--color-primary` / `--color-green` 等 | 主题色、状态色 |
| `--color-bg-body` / `--color-bg-menu*` | 背景色 |
| `--border-d` | 默认边框 `1px solid` |
| `--trans` / `--trans-all` | 过渡：`--trans` 为 `100ms ease-in`；`--trans-all` 为 `all var(--trans)` |

### 文本与背景工具类

- `txt-h1` / `txt-h2` / `txt-p` / `txt-tip` / `txt-gray`：文本色
- `txt-{color}` / `bg-{color}` / `border-{color}`：`primary`, `blue`, `green`, `orange`, `red`, `purple`, `pink`, `yellow`, `white`, `black`, `body`, `dark`, `gray`（见 `var.scss` 中 `$colorNames`）
- `bg-page-header`：读 `--color-bg-page-header`，与页头/卡片面一致（无 glow）
- `bg-group`：读 `--color-group-bg`，用于分组容器底色
- `trans-all`：应用 `--trans-all` 过渡

### 边框工具类（`var.scss` 工具类段）

- `border`：四边 `var(--border-d)`
- `border-l` / `border-r` / `border-t` / `border-b`：单边
- `border-{color}`：色值边框工具类，颜色集合与 `txt-{color}` 一致
- `border-none`：清除边框（`!important`）

### 过渡规则

- **单个 CSS 属性**：使用 `transition: <属性> var(--trans)`，如 `transition: opacity var(--trans)`
- **多个 CSS 属性**：使用 `transition: var(--trans-all)`

### 单位规范

- **1px、2px**：使用 `px`
- **其余尺寸**：使用 `rem`
- **root 字号**：16px（`1rem = 16px`）
- **换算**：`Npx → N/16rem`，如 `8px → 0.5rem`、`24px → 1.5rem`

## 2. 内外边距与尺寸（distance.scss）

### 间距 $pm: 0, 2, 4, 6, 8, 10, 12, 16, 20, 24, 30, 32, 36, 40, 48

| 类名 | 用途 |
|------|------|
| `pt{N}` / `pr{N}` / `pb{N}` / `pl{N}` | padding 单边（逻辑属性） |
| `mt{N}` / `mr{N}` / `mb{N}` / `ml{N}` | margin 单边 |
| `p{N}` / `m{N}` | 四边相同 |
| `p{N}-{M}` / `m{N}-{M}` | 上下=N，左右=M |
| `p0` / `pt0` 等 | 带 `!important` 的零值 |

### margin / padding 与奇数 px

- **禁止**在样式（含 scoped、`@apply`、内联 style）中为 **`margin` / `padding`** 使用 **奇数 px**（如 `3px`、`5px`、`7px`、`9px`、`11px`…），以免与栅格、子像素对齐和工具类刻度不一致。
- **例外**：`1px`、`2px` 仅用于边框、分割线、hairline 等，**不**作为常规留白；常规留白用本节 **`pt{N}` / `m{N}`** 等工具类或 **`rem`**，且数值应对齐 **`$pm`**（均为 **0 或偶数 px** 档位）。
- 新增或修改 `distance.scss` 中的间距档位时，**不得**加入奇数 px。

### 尺寸 $dis: 16~800

| 类名 | 用途 |
|------|------|
| `w{N}` / `h{N}` | 固定宽高 px |
| `minw{N}` / `maxw{N}` / `minh{N}` / `maxh{N}` | 最小/最大宽高 |
| `minw0` / `minh0` | `min-width` / `min-height: 0`，flex/grid 子项防溢出 |
| `w1` | 1×1px 占位，flex-shrink: 0 |
| `grid-minw{N}` | `grid-template-columns: repeat(auto-fill, minmax(Npx→rem, 1fr))` |

### 百分比与视口

| 类名 | 用途 |
|------|------|
| `wp{N}` / `hp{N}` | N=10~100 的百分比宽高 |
| `wp25` / `wp30` / `wp50` / `wp75` / `wp100` | 常用百分比 |
| `vh50`~`vh100` | 视口高度 |
| `vw90` | 视口宽度 |
| `hauto` | height: auto |

## 3. 字体与文本（font.scss）

### 字体大小 $font: 10~96

- `fs{N}`：font-size Npx

### 字间距与行高

- `space{N}`：letter-spacing，N=1~5
- `lh{N}`：line-height，N=14~48（步长 2）

### 文本截断与换行

| 类名 | 用途 |
|------|------|
| `txt-nowrap` | 单行省略 |
| `txt-nowrap{N}` | 多行截断，N=1~10 |
| `txt-line{N}` | 多行截断，N=2~9 |
| `txt-wrap` / `txt-prewrap` | 自动换行 |

### 字重与其它

- `fw300` / `fw500` / `fw700`：lighter / normal / bold
- `block` / `indent2`：display block / text-indent 2rem
- `cursor-disabled`：cursor not-allowed
- `opacity{N}`：N=2~9，opacity 0.2~0.9

### 渐变色字体 .colorfulFont

需配合 `background-clip: text`；颜色变体与 `var.scss` 中 `$colorNames` 自动同步，当前会为 `primary`、`blue`、`green`、`orange`、`red`、`purple`、`pink`、`yellow` 生成渐变类，不为 `white` / `black` / `body` / `dark` / `gray` 生成。

## 4. 布局（layout.scss）

### 定位

| 类名 | 用途 |
|------|------|
| `relative` / `fixed` / `abs` | position |
| `t` / `l` / `r` / `b` | top/left/right/bottom: 0 |
| `absCenter` | 绝对居中 |
| `absFull` | 铺满四边 |
| `sticky` | position sticky, top: 0 |
| `z0` / `z1` / `z2` / `z9` | z-index |

### Flex

| 类名 | 用途 |
|------|------|
| `flexMode` | display flex；`.inline` → inline-flex |
| `flex1` / `flexGrow` / `noShrink` | flex 相关 |
| `flexV` / `flexV-1` | column / column-reverse |
| `flexWrap` / `flexWrap-1` | wrap / wrap-reverse |
| `hl` / `hc` / `hr` / `hb` / `ha` | 主轴 `justify-content`（`hl` = flex-start） |
| `vl` / `vc` / `vr` / `vs` | 交叉轴 `align-items`（`vl` = flex-start；CSS 初始为 stretch，需顶对齐时用 `vl`） |
| `acl` / `acc` / `acr` / `acb` / `aca` / `acs` | 多行时 `align-content`（`acl` = flex-start；CSS 初始为 stretch，与 `flexWrap` 同用） |

### Grid（`layout.scss`）

| 类名 | 用途 |
|------|------|
| `grid` | `display: grid` |
| `grid col{N}` / `grid row{N}`（N=1~12） | 组合在**同一元素**上：`grid-template-columns` / `rows` 为 `repeat(N, 1fr)` |
| `col{N}` / `row{N}`（单独使用） | `grid-column` / `grid-row`：跨 N 列/行 |

**注意**：同一元素上同时有 `grid` 与 `col7` 时，除 `.grid.col7` 外还会命中单独的 `.col7 { grid-column: span 7 }`（`layout.scss` 第二段 `@for`）。需要「7 列等宽、自身作为 grid 容器」时，优先 `:style` 写 `gridTemplateColumns: repeat(7, minmax(0, 1fr))`，避免再叠 `col7` 类。

行高、首行 `auto` 等需写在 **scoped** 或 **`:style`**，与工具类叠加即可。

### 其它

- `clear` / `txt-c` / `txt-r`：clear、text-align
- `fadeout`：水平渐变遮罩；`.v` 为垂直
- `fadeout-h16`：配合 fadeout 的 margin/padding
- `g{N}`：gap，N=2~40（步长 2）
- `mauto`：margin-inline auto

## 4.1 响应式（media.scss + mixin.scss）

### 断点

| 名称 | 范围 |
|------|------|
| `xs` | `< 40rem`（< 640px） |
| `sm` | `40rem ~ 47.99875rem`（640px ~ 767.98px） |
| `md` | `48rem ~ 63.99875rem`（768px ~ 1023.98px） |
| `lg` | `64rem ~ 79.99875rem`（1024px ~ 1279.98px） |
| `xl` | `80rem ~ 95.99875rem`（1280px ~ 1535.98px） |
| `xxl` | `>= 96rem`（>= 1536px） |

### SCSS mixin

- `@include media-up(md) { ... }`：`md` 及以上
- `@include media-down(md) { ... }`：`md` 及以下
- `@include media-only(md) { ... }`：仅 `md`
- `@include media-between(sm, lg) { ... }`：`sm` 到 `lg`

宿主项目若使用发布包，可直接在业务 SCSS 中：

```scss
@use "mvframe/style/mixin" as *;

.panel {
  padding: 1.5rem;

  @include media-down(sm) {
    padding: 1rem;
  }
}
```

### 响应式工具类

`media.scss` 额外提供一批按断点包裹的全局工具类，命名为 `断点-范围-工具类`：

- 范围：`up` / `down` / `only`
- 工具类：`hide`、`block`、`inline`、`inlineBlock`、`flexMode`、`inlineFlex`、`grid`、`flexV`、`flexV-1`、`flexWrap`、`flexWrap-1`、`hl`、`hb`、`ha`、`hc`、`hr`、`vl`、`vr`、`vc`、`vs`、`txt-c`、`txt-r`

示例：

- `class="md-down-hide"`：`md` 及以下隐藏
- `class="lg-up-flexMode lg-up-hb lg-up-vc"`：`lg` 及以上切到横向 flex 并两端对齐
- `class="xs-only-block sm-only-hide"`：只在手机端显示

### Grid 断点列数类

如果容器同时带有 `grid`，可直接写 `断点+列数` 来按屏宽切列数：

- `grid col2 md2 lg3 sm1`
- `grid col1 md2 xl4`

规则：

- `col{N}`：默认列数（所有屏宽的基础值）
- `xs{N}` / `sm{N}` / `md{N}` / `lg{N}` / `xl{N}` / `xxl{N}`：仅在该断点区间覆盖 `grid-template-columns`
- 列数当前支持 `1~12`

示例：

```html
<div class="grid col2 md2 lg3 sm1 g16">
  ...
</div>
```

含义：

- 默认 2 列
- `sm` 屏 1 列
- `md` 屏 2 列
- `lg` 屏 3 列

## 5. 其它样式（other.scss / static.scss）

### 全局重置与基础

- `*`：box-sizing border-box
- `body`：margin 0，背景 `--color-bg-body`
- `button`：outline none

### 图标字体

- `imicon`：mvframe 图标字体，16px

### 交互与显示

| 类名 | 用途 |
|------|------|
| `point` | cursor pointer |
| `opacity0` | opacity 0 |
| `yscroll` / `xscroll` | 纵向/横向滚动 |
| `noscroll` / `nobar` | 滚动锚点 / 隐藏滚动条 |
| `noselect` / `noevent` | 不可选 / 不响应事件 |
| `notrans` | transition none |
| `bg-none` / `hide` | 透明背景 / display none |

### 静态效果（`static.scss`）

| 类名 | 用途 |
|------|------|
| `backdrop` | `backdrop-filter: blur(8px)`，常配合半透明底栏 |

### 圆角

- `radius{N}`：border-radius，N=0~16
- `radius`：overflow hidden
- `radiusP50`：50% 圆形

### 悬停

- `hover`：hover 时 opacity 0.6 + 过渡

## 6. 主题专用样式（theme.scss）

### Glass Rect Area

`rectArea` 是 `html.mv-theme-glass` 下专用的矩形玻璃区域样式，适合快捷入口、小卡片、色块、状态块等需要跟随 glass 主题背景、阴影、hover 和 active 状态的矩形容器。

| 类名 | 用途 |
|------|------|
| `rectArea` | 默认 gray 玻璃矩形面 |
| `rectArea active` | 激活态 |
| `rectArea primary/blue/green/yellow/orange/red/purple/pink/black/dark/body/white/gray` | 颜色变体，色值与 `var.scss` 的全局颜色体系一致 |

使用建议：

- `rectArea` 只在 glass 主题下承担背景和阴影视觉；其它主题下不要依赖它作为唯一背景
- 直接组合布局、尺寸、圆角工具类：`class="rectArea w88 h88 radius8"`、`class="rectArea primary active"`
- 需要 glass 主题矩形区域时，优先使用 `rectArea`，不要在业务 scoped 样式里重复写 `--glass-bg-*` / `--glass-shadow-*`
- hover / active 已由 `theme.scss` 统一处理，业务侧只需要切换颜色类和 `active` 类

## 7. 组件通用样式（cpt.scss）

### 组件变量

- `--btn-radius`：按钮圆角，与 `BtnGroup` 等组件保持一致
- `--loading-radius`：Loading 圆角
- `--card-radius` / `--card-header-border` / `--card-footer-border`：Card 相关变量

### Tag

全局 `.tag` 是通用标签样式，不是单独的 Vue 组件。遇到数量徽标、状态短标签、固定字段小块时，优先复用它，而不是重新写一套 pill/tag CSS。

| 类名 | 用途 |
|------|------|
| `tag` | 基础标签：灰底、提示色文字、胶囊圆角 |
| `tag rect` | 直角矩形标签 |
| `tag small` | 更小字号标签 |
| `tag backdrop` | 半透明毛玻璃标签 |
| `tag primary/blue/green/orange/red/purple/pink/yellow/white/black/body/dark/gray` | 标签颜色变体，色值与 `var.scss` 的全局颜色体系一致 |

使用建议：

- 默认直接在模板中组合类名：`class="tag blue"`、`class="tag rect small"`、`class="tag small backdrop"`
- 如果只是标签颜色或形态变化，不要重写 scoped tag 样式，直接叠加现有变体
- 只有在 `tag` 无法覆盖的专属视觉下，才在局部补 scoped 样式

### Dot

全局 `dot{N}` 是通用圆点样式，适合状态点、图例点、时间轴节点等纯色圆形标识。

| 类名 | 用途 |
|------|------|
| `dot4/dot8/dot10/dot12/dot14/dot16/dot18/dot20/dot24/dot28/dot30/dot32` | 圆点尺寸，源码按 px 设计稿维护，输出为 rem |
| `dot{N} primary/blue/green/yellow/orange/red/purple/pink/black/dark/body/white/gray` | 圆点颜色变体，默认 `primary` |

使用建议：

- 直接组合类名：`class="dot8 orange"`、`class="dot12"`、`class="dot20 gray"`
- `dot{N}` 默认就是主色圆点；只有需要别的颜色时再叠加颜色类
- 这组样式只负责纯圆点本体；如果需要边框、发光、外层容器，优先额外包一层而不是改写 `dot{N}` 自身

### Tip 按钮与图标

| 类名 | 用途 |
|------|------|
| `tipbtn` | hover 时通过 `::after` 显示简易文本提示，文案取 `txt` 属性 |
| `tipbtn bottom/left/right` | 控制提示方向 |
| `MvcIcon` | 组件图标类，默认 `flex-shrink: 0` |

### 表单 Label（element.scss）

`Input`、`InputNumber`、`Textarea`、`Mention`、`Select`、`SelectV2` 支持统一的 label 接口：

| 属性 | 用途 |
|------|------|
| `label` | 显示表单标题 |
| `material-label` | 启用 Material 风格浮动 label |

使用规则：

- 只传 `label`：渲染为普通上方标题
- 传 `label` + `material-label`：渲染为 Material 风格浮动标签
- 不传 `label`：保持原组件默认外观

Material 风格的上浮条件：

- 当前控件有值
- 当前控件有 placeholder
- 当前控件处于 focus / 打开状态（Select / SelectV2）

推荐写法：

```vue
<Input v-model="form.name" label="Name" />
<Input v-model="form.name" label="Material Name" material-label />

<InputNumber v-model="form.count" label="Count" />
<InputNumber v-model="form.count" label="Material Count" material-label />

<Textarea v-model="form.remark" label="Remark" />
<Textarea v-model="form.remark" label="Material Remark" material-label />

<Mention v-model="form.owner" :options="users" label="Owner" />
<Mention v-model="form.owner" :options="users" label="Material Owner" material-label />

<Select v-model="form.type" :options="options" label="Type" />
<Select
  v-model="form.type"
  :options="options"
  label="Material Type"
  material-label
/>
```

约束：

- Material label 的壳样式统一在 `src/style/chip/element.scss`，不要在业务组件里重复写一套 scoped 浮动 label
- 如果要做 Material 风格，优先直接使用 `label` + `material-label`，不要再额外包一层自定义标题
- 如需特殊背景色，优先通过 field surface 相关变量覆写，不要直接把 label 写死成固定背景色

## 8. 动画（ani.scss）

| 类名 | 用途 |
|------|------|
| `rotateZ90` / `rotateZ180` | transform rotate |
| `ani-rotate` | 无限旋转动画 |
| `trans-all` | 过渡（在 var.scss） |

## 使用建议

- 优先使用工具类组合，避免重复写内联样式
- 新增样式时优先扩展 chip 内对应模块，保持命名一致
- 颜色类与 `--color-*` 变量对应，主题切换时统一生效
