Explorar el Código

feat(index-home): 首页重设计 B1 - 设计令牌 + 问候条 + 五维状态带 + 按钮八态

B1 落地(cfc-frontend):
- uni.scss §18:暖白底色系/文本描边/圆角四档/按钮八态/状态chip语义色/动效令牌(120·200·260ms + prefers-reduced-motion 降级)
- uni.scss §5:五维'身'色统一土系 #C2703D(C2 决议),新增五维深档
- index-home.vue:问候条(头像组+时段问候语+铃铛角标)、五维能量状态带(健康指数+五行状态行,线性序 身→智→富→行→心,标签 平稳/略偏/需关注/未记录)、按钮八态样式(白字;禁用暖灰底深字不淡出;触控≥88rpx)
- 新增 static/icons/ 6 个 SVG 矢量图标(小程序不支持内联 svg/emoji 禁)

验收:npm run build:mp-weixin exit 0;verify-vue-compile 全站 PASS;audit-mp-antipatterns ERROR 0;
自查无 emoji/无硬编码色值/五维顺序正确/按钮白字+禁用深字。沙盘引用未动。
Agnes Agent hace 2 semanas
padre
commit
2625f149f6

+ 379 - 0
cfc-frontend/pages/index-home/index.vue

@@ -51,6 +51,61 @@
     <!-- ⓪ 新手成长礼包进度条(新用户引导,全部领取后自动隐藏) -->
     <OnboardingProgressBar ref="onboardingProgress" />
 
+    <!-- ⓪.b 问候条 — 家庭成员 + 按时间问候语(设计稿 §2 视觉焦点) -->
+    <view class="greet-bar">
+      <view class="greet-avatars">
+        <image
+          v-for="m in greetAvatarMembers"
+          :key="m._key"
+          class="greet-avatar"
+          :src="m.avatar || '/static/default-avatar.png'"
+          mode="aspectFill" />
+        <view v-if="greetExtraCount > 0" class="greet-avatar greet-avatar-more">
+          <text class="greet-avatar-more-text">+{{ greetExtraCount }}</text>
+        </view>
+      </view>
+      <view class="greet-main">
+        <text class="greet-title">{{ greetTitle }}</text>
+        <text class="greet-line">{{ greetLine }}</text>
+      </view>
+      <view class="greet-bell" @click="goNotifications">
+        <image class="greet-bell-icon" src="/static/icons/bell.svg" mode="aspectFit" />
+        <text v-if="unreadNoticeCount > 0" class="greet-bell-badge">{{ unreadNoticeCount }}</text>
+      </view>
+    </view>
+
+    <!-- ⓪.c 五维能量状态带 — 健康指数 + 五行状态行(线性序 身→智→富→行→心,设计稿 §3) -->
+    <view class="dim-band" :class="{ 'dim-band--locked': sandboxLocked }">
+      <view class="dim-band-head">
+        <text class="dim-band-kicker">浠艾福能量沙盘</text>
+        <text class="dim-band-index">
+          <text class="dim-band-index-num">{{ dimBandHealthIndex }}</text>
+          <text class="dim-band-index-label">健康指数</text>
+        </text>
+      </view>
+      <view v-if="!sandboxLocked && dimBandRows.length > 0" class="dim-band-rows">
+        <view
+          v-for="row in dimBandRows"
+          :key="row._key"
+          class="dim-row"
+          :class="'dim-row--' + row.code">
+          <image class="dim-row-icon" :src="row.icon" mode="aspectFit" />
+          <view class="dim-row-main">
+            <view class="dim-row-line">
+              <text class="dim-row-name">{{ row.name }}</text>
+              <text v-if="row.value !== null" class="dim-row-value">{{ row.value }}</text>
+            </view>
+            <text class="dim-row-detail">{{ row.detail }}</text>
+          </view>
+          <text class="dim-row-chip" :class="'chip-' + row.statusCss">{{ row.statusText }}</text>
+        </view>
+      </view>
+      <view v-else class="dim-band-empty" @click="goSelfTest">
+        <text class="dim-band-empty-title">{{ sandboxLocked ? '尚未完成健康自检' : '正在获取能量数据…' }}</text>
+        <text class="dim-band-empty-sub">{{ sandboxLocked ? '完成 4 步问卷,解锁全家能量报告' : '请稍候刷新' }}</text>
+      </view>
+    </view>
+
     <!-- ① 了解区 — 自测大卡(首屏,引导"从了解开始") -->
     <view class="self-test-card" @click="goSelfTest">
       <view class="self-test-head">
@@ -698,6 +753,85 @@ title: '添加家庭成员',
         color: 'gray'
       }
     },
+    // ===== ⓪.b 问候条数据(设计稿 §2)=====
+    // 头像组:最多展示 4 个成员头像,超出显示 +N
+    greetAvatarMembers: function() {
+      var arr = this.familyMembersVisible || []
+      var out = []
+      for (var i = 0; i < arr.length && i < 4; i++) {
+        var m = arr[i] || {}
+        out.push({
+          _key: 'ga-' + i + '-' + (m.id || m.memberId || 'x'),
+          avatar: m.avatar || m.headImg || m.headImage || ''
+        })
+      }
+      return out
+    },
+    greetExtraCount: function() {
+      var arr = this.familyMembersVisible || []
+      return arr.length > 4 ? (arr.length - 4) : 0
+    },
+    // 问候语:按当前小时分时段(凌晨/早上/中午/下午/晚上)
+    greetTitle: function() {
+      var h = new Date().getHours()
+      if (h >= 0 && h < 6) return '夜深了'
+      if (h >= 6 && h < 9) return '早上好'
+      if (h >= 9 && h < 12) return '上午好'
+      if (h >= 12 && h < 14) return '中午好'
+      if (h >= 14 && h < 18) return '下午好'
+      return '晚上好'
+    },
+    greetLine: function() {
+      var count = (this.familyMembersVisible || []).length
+      var me = null
+      var arr = this.familyMembersVisible || []
+      for (var i = 0; i < arr.length; i++) {
+        if (arr[i] && arr[i].isSelf) { me = arr[i]; break }
+      }
+      var name = me ? (me.nickname || '家人') : '家人'
+      if (count === 0) return '欢迎回家,开启今天的健康管理'
+      return name + ',今天家里有 ' + count + ' 位成员一起守护健康'
+    },
+    unreadNoticeCount: function() {
+      var n = 0
+      var arr = this.notices || []
+      for (var i = 0; i < arr.length; i++) {
+        if (arr[i] && arr[i].unread) n++
+      }
+      return n
+    },
+    // ===== ⓪.c 五维能量状态带(设计稿 §3,线性序 身→智→富→行→心)=====
+    dimBandHealthIndex: function() {
+      if (this.sandboxLocked) return '--'
+      var v = this.totalHealthIndex || 0
+      return v > 0 ? String(v) : '--'
+    },
+    dimBandRows: function() {
+      if (this.sandboxLocked) return []
+      // 线性顺序(与沙盘星图环形序不同,B1 明确 身→智→富→行→心)
+      var order = ['body', 'wisdom', 'wealth', 'action', 'mind']
+      var scores = this.familySandboxScores || {}
+      var members = this.familySandboxMembers || []
+      var self = this
+      var rows = []
+      for (var i = 0; i < order.length; i++) {
+        var code = order[i]
+        var meta = self._dimMeta(code)
+        var val = scores[code]
+        var hasVal = (typeof val === 'number' && val > 0)
+        rows.push({
+          _key: 'db-' + code,
+          code: code,
+          name: meta.name,
+          icon: meta.icon,
+          value: hasVal ? val : null,
+          detail: self._dimDetail(code, val, members),
+          statusCss: hasVal ? self._dimStatusCss(val) : 'muted',
+          statusText: hasVal ? self._dimStatusText(val) : '未记录'
+        })
+      }
+      return rows
+    },
     // ===== 首页动态提醒列表(含具体值)=====
     // 顺序:今日能量/积分/CF 变更(带数值)→ 家庭动态(通知/公告/任务完成)
     feedItems: function() {
@@ -1719,6 +1853,50 @@ title: '添加家庭成员',
         uni.navigateTo({ url: '/pages/health/health-survey?modules=basic,status,diet,disease,bowel,sleep,med,allergy' })
       }
     },
+    // ===== ⓪.b 问候条 — 通知入口 =====
+    goNotifications: function() {
+      uni.navigateTo({ url: '/pages/teacher/messages' })
+    },
+    // ===== ⓪.c 五维能量状态带辅助方法 =====
+    // 维度元信息(图标为静态 SVG 资源;小程序不支持模板内联 svg)
+    _dimMeta: function(code) {
+      var map = {
+        body: { name: '身', icon: '/static/icons/dim-body.svg' },
+        wisdom: { name: '智', icon: '/static/icons/dim-wisdom.svg' },
+        wealth: { name: '富', icon: '/static/icons/dim-wealth.svg' },
+        action: { name: '行', icon: '/static/icons/dim-action.svg' },
+        mind: { name: '心', icon: '/static/icons/dim-mind.svg' }
+      }
+      return map[code] || { name: '', icon: '' }
+    },
+    // 详情文案:优先取该维度贡献最高的成员昵称,落到一句可读状态
+    _dimDetail: function(code, val, members) {
+      var list = members || []
+      var pick = null
+      for (var i = 0; i < list.length; i++) {
+        var m = list[i] || {}
+        var v = m[code + 'Score']
+        if (typeof v === 'number' && v > 0) {
+          if (!pick || v > pick.v) pick = { v: v, name: m.nickname || m.name || '成员' }
+        }
+      }
+      if (!pick) return '暂无数据'
+      var level = this._dimStatusText(val)
+      return pick.name + ' · ' + level
+    },
+    // 状态标签:平稳 / 略偏 / 需关注(阈值与沙盘读数口径一致)
+    _dimStatusText: function(val) {
+      if (typeof val !== 'number' || val <= 0) return '未记录'
+      if (val >= 80) return '平稳'
+      if (val >= 60) return '略偏'
+      return '需关注'
+    },
+    _dimStatusCss: function(val) {
+      if (typeof val !== 'number' || val <= 0) return 'muted'
+      if (val >= 80) return 'ok'
+      if (val >= 60) return 'warn'
+      return 'danger'
+    },
     // ===== Next Best Action 引导条点击 =====
     onGuideTap: function(action) {
       if (!action) return
@@ -2834,6 +3012,207 @@ $c-warm-tint:     #FFF3E7;
   padding-bottom: 120rpx;
 }
 
+/* ===== ⓪.b 问候条(设计稿 §2) ===== */
+.greet-bar {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  padding: 20rpx $uni-space-lg;
+  background: $warm-base;
+}
+.greet-avatars {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  margin-right: 16rpx;
+}
+.greet-avatar {
+  width: 72rpx;
+  height: 72rpx;
+  border-radius: $radius-full;
+  border: 3rpx solid $warm-base;
+  margin-left: -16rpx;
+  background: $warm-base-alt;
+  flex-shrink: 0;
+}
+.greet-avatar:first-child { margin-left: 0; }
+.greet-avatar-more {
+  background: $brand-primary-soft;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+.greet-avatar-more-text {
+  font-size: 22rpx;
+  color: $brand-primary-deep;
+  font-weight: 600;
+}
+.greet-main { flex: 1; min-width: 0; }
+.greet-title {
+  display: block;
+  font-size: calc(38rpx * var(--font-scale, 1));
+  font-weight: bold;
+  color: $ink-main;
+  line-height: 1.2;
+}
+.greet-line {
+  display: block;
+  font-size: calc(24rpx * var(--font-scale, 1));
+  color: $ink-subtle;
+  margin-top: 6rpx;
+}
+.greet-bell {
+  position: relative;
+  width: 88rpx;
+  height: 88rpx;
+  min-width: 88rpx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+.greet-bell-icon {
+  width: 48rpx;
+  height: 48rpx;
+}
+.greet-bell-badge {
+  position: absolute;
+  top: 4rpx;
+  right: 8rpx;
+  min-width: 32rpx;
+  height: 32rpx;
+  padding: 0 6rpx;
+  border-radius: $radius-full;
+  background: $brand-primary;
+  color: $ink-on-dark;
+  font-size: 20rpx;
+  line-height: 32rpx;
+  text-align: center;
+  font-weight: 600;
+}
+
+/* ===== ⓪.c 五维能量状态带(设计稿 §3,线性序 身→智→富→行→心) ===== */
+.dim-band {
+  margin: 0 $uni-space-lg 16rpx;
+  background: $app-surface;
+  border-radius: $radius-lg;
+  padding: 24rpx 28rpx;
+  border: 1rpx solid rgba($brand-primary, 0.1);
+  box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.03);
+}
+.dim-band--locked { opacity: 0.9; }
+.dim-band-head {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: space-between;
+  margin-bottom: 20rpx;
+}
+.dim-band-kicker {
+  font-size: calc(26rpx * var(--font-scale, 1));
+  font-weight: 600;
+  color: $brand-primary-deep;
+}
+.dim-band-index { display: flex; flex-direction: row; align-items: baseline; }
+.dim-band-index-num {
+  font-size: calc(48rpx * var(--font-scale, 1));
+  font-weight: bold;
+  color: $c-brand-ink;
+  margin-right: 8rpx;
+}
+.dim-band-index-label {
+  font-size: calc(22rpx * var(--font-scale, 1));
+  color: $ink-subtle;
+}
+.dim-band-rows { display: flex; flex-direction: column; }
+.dim-row {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  min-height: 88rpx;
+  padding: 12rpx 0;
+}
+.dim-row-icon {
+  width: 44rpx;
+  height: 44rpx;
+  margin-right: 16rpx;
+  flex-shrink: 0;
+}
+.dim-row-main { flex: 1; min-width: 0; }
+.dim-row-line { display: flex; flex-direction: row; align-items: baseline; }
+.dim-row-name {
+  font-size: calc(28rpx * var(--font-scale, 1));
+  font-weight: 600;
+  color: $ink-main;
+  margin-right: 12rpx;
+}
+.dim-row-value {
+  font-size: calc(28rpx * var(--font-scale, 1));
+  font-weight: bold;
+  color: $c-brand-ink;
+}
+.dim-row-detail {
+  display: block;
+  font-size: calc(22rpx * var(--font-scale, 1));
+  color: $ink-subtle;
+  margin-top: 4rpx;
+}
+.dim-row-chip {
+  flex-shrink: 0;
+  min-width: 88rpx;
+  text-align: center;
+  padding: 8rpx 16rpx;
+  border-radius: $radius-full;
+  font-size: calc(22rpx * var(--font-scale, 1));
+  font-weight: 600;
+}
+.chip-ok     { background: $status-ok-tint;     color: $status-ok-bg; }
+.chip-warn   { background: $status-warn-tint;   color: $status-warn-bg; }
+.chip-danger { background: $status-danger-tint; color: $status-danger-bg; }
+.chip-muted  { background: $status-neutral-tint; color: $status-neutral-bg; }
+.dim-band-empty {
+  padding: 32rpx 0;
+  text-align: center;
+}
+.dim-band-empty-title {
+  display: block;
+  font-size: calc(28rpx * var(--font-scale, 1));
+  font-weight: 600;
+  color: $ink-main;
+}
+.dim-band-empty-sub {
+  display: block;
+  font-size: calc(22rpx * var(--font-scale, 1));
+  color: $ink-subtle;
+  margin-top: 8rpx;
+}
+
+/* ===== 按钮八态(设计稿 §4:默认/悬停/焦点/按下/加载中/出错/成功白字;禁用=暖灰底+深字) ===== */
+.btn {
+  min-height: 88rpx;
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  border-radius: $radius-md;
+  font-size: calc(28rpx * var(--font-scale, 1));
+  font-weight: 600;
+  border: none;
+  transition: background-color $duration-base ease-out;
+}
+.btn--default  { background: $btn-default-bg;  color: $btn-default-ink; }
+.btn--hover    { background: $btn-hover-bg;    color: $btn-hover-ink; }
+.btn--focus    { background: $btn-focus-bg;    color: $btn-focus-ink; }
+.btn--press    { background: $btn-press-bg;    color: $btn-press-ink; }
+.btn--loading  { background: $btn-loading-bg;  color: $btn-loading-ink; }
+.btn--error    { background: $btn-error-bg;    color: $btn-error-ink; }
+.btn--success  { background: $btn-success-bg;  color: $btn-success-ink; }
+.btn--disabled { background: $btn-disabled-bg; color: $btn-disabled-ink; opacity: 1; }
+/* 触控目标 ≥44px(88rpx 基准),禁用态不降透明度 */
+.btn--disabled, .btn--disabled:active { opacity: 1; }
+/* 降低动效偏好:按钮/状态带/问候条过渡全局降级 */
+@media (prefers-reduced-motion: reduce) {
+  .btn, .dim-row, .greet-bar { transition-duration: 0.01ms !important; }
+}
+
 /* ===== ① 了解区 — 自测大卡(引导"从了解开始") ===== */
 .self-test-card {
   margin: 20rpx $uni-space-lg 16rpx;

+ 4 - 0
cfc-frontend/static/icons/bell.svg

@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-hidden="true">
+  <path d="M12 4a5 5 0 0 0-5 5v3.2L5.4 15h13.2L17 12.2V9a5 5 0 0 0-5-5z" fill="none" stroke="#F97316" stroke-width="1.8" stroke-linejoin="round"/>
+  <path d="M10 18a2 2 0 0 0 4 0" fill="none" stroke="#F97316" stroke-width="1.8" stroke-linecap="round"/>
+</svg>

+ 4 - 0
cfc-frontend/static/icons/dim-action.svg

@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-hidden="true">
+  <path d="M5 19C5 11 11 5 19 5c0 8-6 14-14 14z" fill="none" stroke="#10B981" stroke-width="1.8" stroke-linejoin="round"/>
+  <path d="M8.4 15.6 19 5" fill="none" stroke="#10B981" stroke-width="1.8" stroke-linecap="round"/>
+</svg>

+ 4 - 0
cfc-frontend/static/icons/dim-body.svg

@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-hidden="true">
+  <circle cx="12" cy="8" r="3.2" fill="none" stroke="#C2703D" stroke-width="1.8"/>
+  <path d="M5.5 19c0-3.3 2.9-5.5 6.5-5.5s6.5 2.2 6.5 5.5" fill="none" stroke="#C2703D" stroke-width="1.8" stroke-linecap="round"/>
+</svg>

+ 3 - 0
cfc-frontend/static/icons/dim-mind.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-hidden="true">
+  <path d="M12 20s-7-4.3-7-9.2A3.9 3.9 0 0 1 12 8a3.9 3.9 0 0 1 7 2.8C19 15.7 12 20 12 20z" fill="none" stroke="#FF6B9D" stroke-width="1.8" stroke-linejoin="round"/>
+</svg>

+ 3 - 0
cfc-frontend/static/icons/dim-wealth.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-hidden="true">
+  <path d="M12 3.5c3.2 3.6 5.5 6.4 5.5 9.3a5.5 5.5 0 0 1-11 0c0-2.9 2.3-5.7 5.5-9.3z" fill="none" stroke="#F59E0B" stroke-width="1.8" stroke-linejoin="round"/>
+</svg>

+ 3 - 0
cfc-frontend/static/icons/dim-wisdom.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-hidden="true">
+  <path d="M13 3 6.5 13H11l-1 8 6.5-10H12z" fill="none" stroke="#6366F1" stroke-width="1.8" stroke-linejoin="round"/>
+</svg>

+ 66 - 2
cfc-frontend/uni.scss

@@ -397,18 +397,26 @@ $brand-primary-dark: #EA580C;
 $brand-primary-soft: rgba(249, 115, 22, 0.12);
 
 // 五维身份色:页面 PageBanner / 分段左条 / CTA / 价值卡浅底统一取用
-$dim-body:   #FF8C42;
+// 身 = 赤陶/土调 #C2703D(2026-10-27 设计稿定稿,替代旧 #FF8C42 亮橙;C2 统一土系)
+$dim-body:   #C2703D;
 $dim-mind:   #FF6B9D;
 $dim-wisdom: #6366F1;
 $dim-action: #10B981;
 $dim-wealth: #F59E0B;
 
-$dim-body-soft:   rgba(255, 140, 66, 0.15);
+$dim-body-soft:   rgba(194, 112, 61, 0.15);
 $dim-mind-soft:   rgba(255, 107, 157, 0.15);
 $dim-wisdom-soft: rgba(99, 102, 241, 0.15);
 $dim-action-soft: rgba(16, 185, 129, 0.15);
 $dim-wealth-soft: rgba(245, 158, 11, 0.15);
 
+// 五维深档(承载 badge 文字;与设计稿定稿值逐档对齐)
+$dim-body-deep:   #9C4A1A;  // 身·赭石深档(badge 文字用)
+$dim-mind-deep:   #9D174D;  // 心·玫红深档(badge 文字用)
+$dim-wisdom-deep: #4338CA;  // 智·靛蓝深档(badge 文字用)
+$dim-action-deep: #047857;  // 行·森林绿深档(badge 文字用)
+$dim-wealth-deep: #92400E;  // 富·黄土深档(badge 文字用)
+
 // 语义角色(与应用真实观感一致)
 $app-bg:             #F5F7FA;
 $app-bg-2:           #f5f6fa; // 浅灰蓝底·副档(3 文件;vs $app-bg #F5F7FA)
@@ -763,3 +771,59 @@ $uni-space-2xl: 40rpx;  /* 页面区块分隔 */
 $uni-space-3xl: 60rpx;  /* 大留白 */
 $uni-space-4xl: 80rpx;  /* 空状态留白 */
 $uni-space-page: 30rpx; /* 页面左右安全边距(兼容存量,不归并) */
+
+// ============================================================
+// §18 首页重设计 B1 设计令牌(2026-10-27 设计稿定稿)
+// 唯一事实源:cfc-frontend/design/cfc-home-redesign.html
+// 所有组件硬编码 hex 逐步收敛到本段;B1 只新增,不改存量
+// ============================================================
+
+// 18.1 暖白底色系(非点缀;页面/卡片/徽章基准)
+$warm-base:     #FAFAF5; // 暖白页面背景(cookie/分段/卡片基准)
+$warm-base-alt: #F5F5F0; // 暖白辅底(徽章/轻提示)
+
+// 18.2 文本/描边令牌组
+$ink-main:    #333333; // 正文/标题主色
+$ink-subtle:  #666666; // 副文/描边
+$ink-on-dark: #FFFFFF; // 暖底/深色背景上白字
+
+// 18.3 圆角四档(设计稿唯一圆角口径)
+$radius-sm:   8rpx;   // 标签/小徽章
+$radius-md:   16rpx;  // 输入框/小卡片
+$radius-lg:   24rpx;  // 卡片/大容器
+$radius-full: 999rpx; // 胶囊/头像/按钮圆角
+
+// 18.4 按钮八态色令牌(亮背景下白字;禁用态=暖灰中性底+深字,不淡出)
+$btn-default-bg:  $brand-primary;  $btn-default-ink:  $ink-on-dark; // 默认
+$btn-hover-bg:    $brand-primary-dark; $btn-hover-ink: $ink-on-dark; // 悬停(略深)
+$btn-focus-bg:    darken($brand-primary, 10%); $btn-focus-ink: $ink-on-dark; // 焦点
+$btn-press-bg:    darken($brand-primary, 15%); $btn-press-ink: $ink-on-dark; // 按下
+$btn-loading-bg:  $brand-primary;  $btn-loading-ink: $ink-on-dark; // 加载中
+$btn-error-bg:    #EF4444;         $btn-error-ink:    $ink-on-dark; // 错误
+$btn-success-bg:  #059669;         $btn-success-ink:  $ink-on-dark; // 成功
+$btn-disabled-bg: #D9D9D9;         $btn-disabled-ink: #6B6B6B;     // 禁用:暖灰中性底+深字
+
+// 18.5 状态 chip 语义色(五维带标签 平稳/略偏/需关注/待补录/未记录)
+$status-ok-bg:     #166534; // 平稳(深绿底)
+$status-ok-tint:   #DCFCE7; // 平稳浅底
+$status-warn-bg:   #92400E; // 略偏/需关注(深黄褐底)
+$status-warn-tint: #FEF3C7; // 略偏/需关注浅底
+$status-danger-bg: #B91C1C; // 需关注-重(深红底)
+$status-danger-tint:#FEE2E2;// 需关注-重浅底
+$status-info-bg:   #1E3A8A; // 待补录(深蓝底)
+$status-info-tint: #DBEAFE; // 待补录浅底
+$status-neutral-bg: #6B7280;// 未记录(暖灰底)
+$status-neutral-tint:#F3F4F6;// 未记录浅底
+
+// 18.6 动效令牌(120/200/260ms)
+$duration-fast:   120ms;
+$duration-base:   200ms;
+$duration-slow:   260ms;
+// prefers-reduced-motion 降级:全局统一关闭非必要动效(配合页面 .transition-reduced)
+@media (prefers-reduced-motion: reduce) {
+  .transition-reduced {
+    animation-duration: 0.01ms !important;
+    animation-iteration-count: 1 !important;
+    transition-duration: 0.01ms !important;
+  }
+}