diff --git a/artifacts/ui-redesign/miniapp/preview.html b/artifacts/ui-redesign/miniapp/preview.html index 8a74674..ee87e8e 100644 --- a/artifacts/ui-redesign/miniapp/preview.html +++ b/artifacts/ui-redesign/miniapp/preview.html @@ -22,76 +22,191 @@ .phone { background:#fff; border-radius:36px; padding:12px; box-shadow:0 20px 60px rgba(28,30,88,.18); } .phone-screen { width:100%; height:760px; overflow-y:auto; border-radius:26px; background:#F4F5FA; } .wx-page { min-height:100%; } + /* 原生 tabBar 复刻。颜色/边框取 app.json 的 tabBar 字段: + color #999999 / selectedColor #E96B6B / backgroundColor #FFFFFF / borderStyle black。 + 图标按微信客户端实际渲染尺寸(约 26px)呈现,与 81px 源图尺寸不同;文字 10px 同理。 */ + .mini-tabbar { position:sticky; bottom:0; z-index:20; display:flex; align-items:stretch; + background:#FFFFFF; border-top:1px solid rgba(0,0,0,.2); padding-bottom:20px; } + .mini-tabbar__item { flex:1 1 0; min-width:0; display:flex; flex-direction:column; + align-items:center; justify-content:center; gap:2px; padding:6px 0 0; } + .mini-tabbar__icon { width:26px; height:26px; display:block; } + .mini-tabbar__label { font-size:10px; line-height:14px; color:#999999; } + .mini-tabbar__item.is-active .mini-tabbar__label { color:#E96B6B; } /* ====== 以下为页面 WXSS 转换结果(rpx 已按 375 宽换算) ====== */ /** * 丹阳公益婚恋服务平台 - 全局 Design Token * - * 依据《前端组件库与 Design Token 规范 V1.0》 - * 单位说明:rpx(375.00px = 屏幕宽度),规范 px 值按 2x 映射为 rpx - * 禁止页面层写死颜色/间距/圆角,必须引用 var(--token) + * v2(2026-09-22 设计系统夯实) + * --------------------------------------------------------------- + * 本次修订针对审计发现的系统性问题,逐条给出依据: + * + * 1) 品牌色不能承载文字 → 引入「基础色 / -strong」分级 + * #E96B6B on 白 = 3.10:1,白字 on #E96B6B = 3.10:1,on #FFF3F2 = 2.85:1, + * 三条路径都不满足正文 4.5:1。故: + * --color-primary 仅用于大色块、渐变、光晕、装饰(非文字) + * --color-primary-strong 用于文字、小图标、纯文字链接(5.33:1 ✓) + * --color-primary-solid 实心按钮底(白字 ≥4.5:1 ✓) + * 功能色(success/warning/danger/info)同此分级。 + * + * 2) 次要文字对比度过低 + * 旧 --color-text-tertiary(#777) = 4.48(on 白,勉强)/ #999 实测 2.85 却被用了 71 次。 + * 现将三级文字压到 #646C85 = 5.22:1,占位符保留浅色(占位符非正文)。 + * + * 3) 颜色碎片化 + * 审计前全站 182 种 hex、770 次硬编码(54 种灰、60 种蓝紫、40 种红橙)。 + * 本文件是唯一的颜色事实源;页面层禁止再写 hex,一律 var(--token)。 + * + * 4) 触摸目标 + * 组件库默认按钮只有 40px、小号 28px、"喜欢"按钮 31px。 + * 统一以 --tap-min(44.00px=44px) 为下限,--tap-gap 为最小间距。 + * + * 5) 动效几乎未落地(--motion-* 全站仅 5 次引用) + * 补充 --ease-spring 与 --press-scale,让点击有即时反馈。 + * + * 6) 夜间氛围层缺失(参考图有明显的光晕/星点,代码只有纯渐变) + * 新增 --mini-glow-* / --mini-star / --mini-glass / --mini-hairline。 + * + * 单位说明:rpx(375.00px = 屏幕宽度,0.50px ≈ 0.5px @375pt) + * 旧 token 名全部保留(88 个 wxss 共 909 处引用),只更新取值,避免大范围失效。 */ .wx-page { - /* ============ 品牌主色(规范 §3) ============ */ - --color-primary: #E96B6B; - --color-primary-active: #D95F5F; + /* ============ 品牌主色(分级:色块 / 文字 / 实心按钮) ============ */ + --color-primary: #E96B6B; /* 基础色:渐变、光晕、装饰、非文字图形 */ + --color-primary-strong: #B8434A; /* 文字与小图标(5.33:1 on 白,4.91:1 on 浅粉底) */ + --color-primary-solid: #C24C50; /* 实心按钮底(白字 4.62:1) */ + --color-primary-active: #D95F5F; /* 按压态(配合 --color-primary 使用) */ --color-primary-light: #FFF3F2; --color-primary-lighter: #FFF8F7; - /* ============ 小程序参考图品牌主题 ============ */ + /* ============ 小程序参考图品牌主题(夜间紫蓝) ============ */ --mini-night-start: #172A72; --mini-night-end: #25104F; --mini-night-soft: #3445A1; - --mini-accent-pink: #FF4F91; + --mini-accent-pink: #FF4F91; /* 点缀色:仅用于色块/装饰,不作正文 */ --mini-accent-coral: #FF6A78; --mini-card-bg: rgba(255, 255, 255, 0.98); --mini-text: #1F2744; --mini-muted: #7D839B; --mini-card-radius: 12.00px; - --mini-text-on-night: #FFFFFF; - --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); + --mini-text-on-night: #FFFFFF; /* on 深底 13.04:1 ✓ */ + --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); /* on 深底 ≈8:1 ✓ */ --mini-shadow: 0 8.00px 20.00px rgba(28, 30, 88, 0.14); - /* ============ 功能色(规范 §4) ============ */ - --color-success: #2E9B68; + /* ---- 渐变(集中定义:此前 4 个页面各写了一份「橙红渐变」按钮) ---- */ + /* --gradient-brand 明亮活泼,但白字仅 2.77:1 —— 只能用于无文字的装饰填充。 */ + --gradient-brand: linear-gradient(135deg, #FF6A78 0%, #E96B6B 100%); + /* 承载白字的 CTA 渐变:两端 #C24C50(4.73:1) / #B8434A(5.33:1) 均达标。 */ + --gradient-brand-solid: linear-gradient(135deg, #C24C50 0%, #B8434A 100%); + --gradient-night: linear-gradient(160deg, #172A72 0%, #25104F 100%); + --gradient-night-soft: linear-gradient(160deg, #3445A1 0%, #172A72 100%); + + /* ---- 首页 4×2 入口宫格图标渐变(参考图 2:高饱和圆角砖 + 白色描画图标) ---- + 白图标的对比度判据是**非文本图形 3:1**(WCAG 1.4.11)。渐变是斜向的、图标又跨在 + 两色之间,所以**较亮的一端也必须达标** —— 下表注释给的是 0% 处实算值,100% 更暗只会更高。 + 色相按业务语义固定(不随 tone 名漂移):找对象/婚前辅导=玫瑰粉系、公益红娘/服务站=暖橙系、 + 公益活动=紫罗兰、婚恋咨询=蓝、婚恋课堂=紫、婚恋反诈=绿。 */ + --gradient-entry-rose: linear-gradient(135deg, #F56287 0%, #F34671 100%); /* 3.01:1 / 3.54:1 */ + --gradient-entry-orange: linear-gradient(135deg, #F66A06 0%, #D95E06 100%); /* 3.01:1 / 3.78:1 */ + --gradient-entry-violet: linear-gradient(135deg, #A380F5 0%, #8F64F2 100%); /* 3.02:1 / 3.98:1 */ + --gradient-entry-blue: linear-gradient(135deg, #5195F6 0%, #3484F4 100%); /* 3.01:1 / 3.65:1 */ + --gradient-entry-purple: linear-gradient(135deg, #B27BF0 0%, #A260ED 100%); /* 3.01:1 / 3.87:1 */ + --gradient-entry-pink: linear-gradient(135deg, #F2619E 0%, #F0458C 100%); /* 3.01:1 / 3.54:1 */ + --gradient-entry-green: linear-gradient(135deg, #18A979 0%, #148F66 100%); /* 3.00:1 / 4.08:1 */ + --gradient-entry-amber: linear-gradient(135deg, #E9740C 0%, #CC650B 100%); /* 3.01:1 / 3.86:1 */ + /* 图标砖落影:比 --mini-shadow 更小,避免 4 列宫格里相邻砖块的投影互相压边 */ + --mini-entry-shadow: 0 4.00px 9.00px rgba(28, 30, 88, 0.18); + + /* ---- 夜间氛围层(v2 新增;参考图有光晕与星点,此前完全没有) ---- */ + --mini-glow-coral: rgba(255, 79, 145, 0.40); + --mini-glow-indigo: rgba(94, 124, 255, 0.32); + --mini-glow-soft: rgba(255, 255, 255, 0.10); + --mini-star: rgba(255, 255, 255, 0.70); + --mini-glass: rgba(255, 255, 255, 0.10); /* 深底玻璃面 */ + --mini-glass-strong: rgba(255, 255, 255, 0.16); + --mini-hairline: rgba(255, 255, 255, 0.16); /* 深底分隔线 */ + --mini-glass-success: rgba(90, 226, 184, 0.16); /* 深底上的成功态玻璃面 */ + + /* 星点层:多个小径向渐变叠在夜空渐变之上。用 radial-gradient 而非图片, + 避免额外请求,也便于随主题换色(index 页脚注:装饰层不承载信息)。 */ + --mini-starfield: + radial-gradient(circle at 12% 18%, var(--mini-star) 0, transparent 1.25px), + radial-gradient(circle at 31% 66%, var(--mini-star) 0, transparent 1.00px), + radial-gradient(circle at 57% 12%, var(--mini-star) 0, transparent 1.00px), + radial-gradient(circle at 79% 52%, var(--mini-star) 0, transparent 1.50px), + radial-gradient(circle at 93% 84%, var(--mini-star) 0, transparent 1.00px); + + /* 横幅压暗层:保证任何底图上的白色标题都有足够对比度 */ + --mini-banner-scrim: linear-gradient(90deg, rgba(23, 42, 114, 0.84) 0%, rgba(37, 16, 79, 0.40) 56%, rgba(255, 79, 145, 0.12) 100%); + + /* ============ 功能色(同样分级) ============ */ + --color-success: #2E9B68; /* 色块/图标 */ + --color-success-strong: #17805A; /* 文字(4.92:1 ✓) */ --color-success-light: #ECF8F2; - --color-warning: #E59A32; + --color-warning: #E59A32; /* 色块/图标(作文字仅 2.33:1) */ + --color-warning-strong: #9C5F14; /* 文字(5.17:1 ✓) */ --color-warning-light: #FFF7E9; - --color-danger: #D94A4A; + --color-danger: #D94A4A; /* 色块/图标 */ + --color-danger-strong: #C62828; /* 文字(5.62:1 ✓) */ --color-danger-light: #FFF0F0; - --color-info: #4A7CD4; + --color-info: #4A7CD4; /* 色块/图标 */ + --color-info-strong: #2A5DB0; /* 文字(6.38:1 ✓) */ --color-info-light: #EEF4FF; - /* ============ 中性色(规范 §5-6) ============ */ - --color-text-primary: #222222; - --color-text-secondary: #444444; - --color-text-tertiary: #777777; - --color-text-placeholder: #999999; - --color-text-disabled: #B5B5B5; - --color-text-inverse: #FFFFFF; /* 用于 primary/success 等深色背景上的文字 */ + /* ============ 强调紫(参考图的标签语言;此前散落成 6 种写法) ============ */ + --color-accent-purple: #8B63BC; /* 色块/装饰 */ + --color-accent-purple-strong: #7C60BC; /* 文字(5.03:1 ✓) */ + --color-accent-purple-light: #F3EEFF; - --color-border: #EEEEEE; - --color-divider: #F0F0F0; - --color-border-focus: #E96B6B; - --color-border-error: #D94A4A; + /* 深色夜空底上的强调色(不可用于浅色底) */ + --color-success-on-night: #A6F5D7; /* on #172A72 = 10.35:1 ✓ */ - --color-bg-page: #FAFAF8; + /* ============ 文字色(实测对比度 on 白 / on 页面底) ============ */ + --color-text-strong: #1A1F36; /* 标题 16.24 / 14.90 ✓ */ + --color-text-primary: #2A3050; /* 正文 12.83 / 11.77 ✓ */ + --color-text-secondary: #4A5169; /* 次要正文 7.86 / 7.21 ✓ */ + --color-text-tertiary: #646C85; /* 说明文字 5.22 / 4.79 ✓(旧 #777 为 4.48) */ + --color-text-placeholder: #9AA1B4; /* 占位符(非正文,可浅) */ + --color-text-disabled: #B8BDC9; + --color-text-inverse: #FFFFFF; /* 深色背景上的文字 */ + + /* ============ 边框与分割线 ============ */ + --color-border: #E6E8EF; + --color-border-strong: #D8DBE5; + --color-divider: #EFF0F5; + --color-border-focus: #B8434A; /* 焦点环用 strong,保证 3:1 可见度 */ + --color-border-error: #C62828; + + /* ============ 背景(避免纯白/纯灰平铺,页面底为暖白) ============ */ + --color-bg-page: #F6F5F3; --color-bg-card: #FFFFFF; - --color-bg-disabled: #F3F3F3; + --color-bg-subtle: #F5F6FA; /* 次级区块、内嵌列表 */ + --color-bg-muted: #EEF0F6; /* 更弱的填充 */ + --color-bg-input: #F7F8FB; /* 表单输入框底(此前被引用但从未定义,导致背景失效) */ + --color-bg-disabled: #F3F4F7; --color-bg-overlay: rgba(0, 0, 0, 0.45); - /* ============ 字体(规范 §7-11) ============ */ + /* ============ 字体 ============ */ + /* 小程序无法可靠加载 Web Font(wx.loadFontFace 依赖 HTTPS 白名单且有闪动风险), + 故使用中文系统字栈:iOS 走苹方、Android 走思源/系统黑体。 + 排版辨识度靠字号阶梯与字重建立,而非依赖字体本身。 */ --font-family-cn: -apple-system, "PingFang SC", "Noto Sans SC", "Hiragino Sans GB", "Microsoft YaHei", system-ui, sans-serif; + --font-family-number: "SF Pro Display", -apple-system, "DIN Alternate", "PingFang SC", sans-serif; - --font-size-xs: 12.00px; /* 12px */ - --font-size-sm: 13.00px; /* 13px */ - --font-size-md: 14.00px; /* 14px */ - --font-size-base: 16.00px; /* 16px */ - --font-size-lg: 18.00px; /* 18px */ - --font-size-xl: 20.00px; /* 20px */ - --font-size-2xl: 24.00px; /* 24px */ - --font-size-3xl: 28.00px; /* 28px */ + /* 字号阶梯 —— 正文 16.00px(16px) 起,元信息下限 12.00px(12px) */ + --font-size-micro: 11.00px; /* 11px 仅角标/装饰,禁用于正文 */ + --font-size-xs: 12.00px; /* 12px 元信息下限 */ + --font-size-sm: 13.00px; /* 13px 次要说明 */ + --font-size-md: 14.00px; /* 14px 次要正文 */ + --font-size-base: 16.00px; /* 16px 正文 */ + --font-size-lg: 18.00px; /* 18px 小标题 */ + --font-size-xl: 20.00px; /* 20px 区块标题 */ + --font-size-2xl: 24.00px; /* 24px 页面标题 */ + --font-size-3xl: 28.00px; /* 28px 大标题 */ + --font-size-display: 32.00px; /* 32px Hero */ + /* 字重:只用 4 档。禁止 550/650/750 等非百位值 —— Android 无对应字重会回退, + 导致同一设计在不同机型上粗细不一致(审计发现 30 处)。 */ --font-weight-regular: 400; --font-weight-medium: 500; --font-weight-semibold: 600; @@ -99,51 +214,68 @@ --line-height-tight: 1.25; --line-height-normal: 1.5; - --line-height-relaxed: 1.7; + --line-height-relaxed: 1.65; - /* ============ 间距(规范 §12,4px 栅格) ============ */ - --spacing-1: 4.00px; /* 4px */ - --spacing-2: 8.00px; /* 8px */ - --spacing-3: 12.00px; /* 12px */ - --spacing-4: 16.00px; /* 16px */ - --spacing-5: 20.00px; /* 20px */ - --spacing-6: 24.00px; /* 24px */ - --spacing-8: 32.00px; /* 32px */ - --spacing-10: 40.00px; /* 40px */ - --spacing-12: 48.00px; /* 48px */ + --letter-spacing-tight: 0; + --letter-spacing-wide: 0.50px; + --letter-spacing-wider: 1.00px; - --spacing-page-x: 16.00px; /* 页面左右 16px */ - --spacing-section: 24.00px; /* 区块间 24px */ - --spacing-card-inner: 16.00px; /* 卡片内部 16px */ - --spacing-tight: 8.00px; /* 紧密 8px */ + /* ============ 间距(4px 栅格) ============ */ + --spacing-1: 4.00px; + --spacing-2: 8.00px; + --spacing-3: 12.00px; + --spacing-4: 16.00px; + --spacing-5: 20.00px; + --spacing-6: 24.00px; + --spacing-8: 32.00px; + --spacing-10: 40.00px; + --spacing-12: 48.00px; - /* ============ 圆角(规范 §14) ============ */ - --radius-sm: 8.00px; /* 8px */ - --radius-md: 12.00px; /* 12px */ - --radius-lg: 16.00px; /* 16px */ - --radius-xl: 20.00px; /* 20px */ + --spacing-page-x: 16.00px; + --spacing-section: 24.00px; + --spacing-card-inner: 16.00px; + --spacing-tight: 8.00px; + + /* ============ 圆角 ============ */ + --radius-sm: 8.00px; + --radius-md: 12.00px; + --radius-lg: 16.00px; + --radius-xl: 20.00px; + --radius-2xl: 24.00px; --radius-full: 4999.50px; - /* ============ 阴影(规范 §15,极轻) ============ */ - --shadow-card: 0 4.00px 16.00px rgba(0, 0, 0, 0.04); + /* ============ 阴影(统一为一套,此前 30+ 种近似值) ============ */ + --shadow-card: 0 4.00px 14.00px rgba(35, 35, 95, 0.07); + --shadow-raised: 0 6.00px 18.00px rgba(35, 35, 95, 0.10); --shadow-popup: 0 8.00px 32.00px rgba(0, 0, 0, 0.10); + --shadow-night: 0 8.00px 20.00px rgba(28, 30, 88, 0.18); - /* ============ 边框(规范 §16) ============ */ + /* ============ 边框宽度 ============ */ --border-width: 0.50px; + --border-width-strong: 1.00px; - /* ============ 动效(规范 §17) ============ */ + /* ============ 触摸目标(无障碍下限 44×44px) ============ */ + --tap-min: 44.00px; /* 44px 最小可点区域 */ + --tap-comfortable: 48.00px; /* 48px 舒适尺寸:主操作 */ + --tap-gap: 8.00px; /* 8px 相邻目标最小间距 */ + + /* ============ 动效 ============ */ --motion-fast: 120ms; --motion-normal: 200ms; --motion-slow: 300ms; - --ease-standard: ease-out; + --ease-standard: cubic-bezier(0.32, 0.72, 0, 1); + --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1); + --press-scale: 0.97; + --press-opacity: 0.88; - /* ============ 层级 z-index(规范 §90) ============ */ + /* ============ 层级 z-index ============ */ --z-base: 1; --z-sticky: 100; --z-tabbar: 200; --z-dropdown: 500; --z-modal: 1000; --z-toast: 2000; + --z-ambient: 0; /* ============ 页面基础样式 ============ */ background-color: var(--color-bg-page); @@ -153,7 +285,10 @@ line-height: var(--line-height-normal); } -/* ============ 通用工具类 ============ */ +/* ========================================================================== + 通用工具类 + ========================================================================== */ + .container { padding: var(--spacing-page-x); } @@ -167,17 +302,34 @@ .flex-shrink-0 { flex-shrink: 0; } .wrap { flex-wrap: wrap; } +/* 4 列宫格:用 flex + 百分比宽度实现。 + 注:display:grid 在 WebView 渲染下可用,但 Skyline 不支持,故统一改为 flex 以免疫渲染引擎迁移。*/ +.grid-4 { + display: flex; + flex-wrap: wrap; +} +.grid-4 > .grid-item { + width: 25%; + box-sizing: border-box; +} + +.text-strong { color: var(--color-text-strong); } .text-primary { color: var(--color-text-primary); } .text-secondary { color: var(--color-text-secondary); } .text-tertiary { color: var(--color-text-tertiary); } .text-placeholder { color: var(--color-text-placeholder); } .text-white { color: var(--color-text-inverse); } -.text-brand { color: var(--color-primary); } -.text-success { color: var(--color-success); } -.text-warning { color: var(--color-warning); } -.text-danger { color: var(--color-danger); } -.text-info { color: var(--color-info); } +.text-brand { color: var(--color-primary-strong); } +/* 品牌色作文字只能用 -strong 变体:基础色 #E96B6B 在白底仅 3.10:1。 + 保留 .text-brand-soft 这个类名是为了不破坏既有引用,取值已统一到 -strong, + 如需「更亮的品牌色」请用于背景/图形而非文字。 */ +.text-brand-soft { color: var(--color-primary-strong); } +.text-success { color: var(--color-success-strong); } +.text-warning { color: var(--color-warning-strong); } +.text-danger { color: var(--color-danger-strong); } +.text-info { color: var(--color-info-strong); } +.font-micro { font-size: var(--font-size-micro); } .font-xs { font-size: var(--font-size-xs); } .font-sm { font-size: var(--font-size-sm); } .font-md { font-size: var(--font-size-md); } @@ -186,6 +338,7 @@ .font-xl { font-size: var(--font-size-xl); } .font-2xl { font-size: var(--font-size-2xl); } .font-3xl { font-size: var(--font-size-3xl); } +.font-display { font-size: var(--font-size-display); } .font-regular { font-weight: var(--font-weight-regular); } .font-medium { font-weight: var(--font-weight-medium); } @@ -223,7 +376,7 @@ padding-bottom: 0px; } -/* 页面卡片基础样式(中低密度留白) */ +/* 页面卡片基础样式 */ .card-base { background: var(--color-bg-card); border-radius: var(--radius-lg); @@ -237,371 +390,1244 @@ background: var(--color-divider); } -.wx-page{background:var(--color-bg-page)}.service-page{min-height:100vh;padding-bottom:calc(70.00px + 0px)}.hero{padding:22.00px 16.00px 27.00px;background:linear-gradient(140deg,var(--color-primary-lighter),#FFF8EE);position:relative;overflow:hidden}.eyebrow{display:inline-flex;padding:3.50px 7.00px;border-radius:499.50px;background:rgba(255,255,255,.72);color:var(--color-primary);font-size:10.50px}.hero-title{display:block;margin-top:9.00px;font-size:20.00px;font-weight:700;line-height:1.35}.hero-desc{display:block;width:82%;margin-top:7.00px;font-size:12.50px;color:var(--color-text-secondary);line-height:1.7}.content{padding:0 var(--spacing-page-x)}.block{margin-top:var(--spacing-section)}.block-title{display:block;font-size:15.50px;font-weight:650}.block-subtitle{display:block;margin-top:4.00px;font-size:11.50px;color:var(--color-text-tertiary)}.card{margin-top:9.00px;padding:14.00px;background:var(--color-bg-card);border:0.50px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.feature-row,.menu-row,.record-row{display:flex;align-items:center;gap:10.00px;min-height:56.00px;padding:9.00px 0;border-bottom:0.50px solid var(--color-divider)}.feature-row:last-child,.menu-row:last-child,.record-row:last-child{border-bottom:0}.feature-icon{width:36.00px;height:36.00px;display:flex;align-items:center;justify-content:center;flex:none;border-radius:11.00px;background:var(--color-primary-light);color:var(--color-primary);font-weight:700}.feature-copy{flex:1;min-width:0}.feature-title{display:block;font-size:14.00px;font-weight:600}.feature-desc,.meta{display:block;margin-top:3.50px;font-size:11.50px;color:var(--color-text-tertiary);line-height:1.55}.arrow{font-size:20.00px;color:var(--color-text-disabled)}.tag{display:inline-flex;margin-right:5.00px;margin-top:5.00px;padding:3.00px 6.50px;border-radius:499.50px;background:var(--color-success-light);color:var(--color-success);font-size:10.00px}.tag.warning{background:var(--color-warning-light);color:var(--color-warning)}.primary-btn,.secondary-btn{height:44.00px;display:flex;align-items:center;justify-content:center;border-radius:22.00px;font-size:14.00px;font-weight:600}.primary-btn{background:linear-gradient(135deg,var(--mini-accent-coral),var(--mini-accent-pink));color:var(--color-text-inverse);box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)}.primary-btn.disabled{background:#E6E8EF;color:#989DAF;box-shadow:none}.secondary-btn{background:var(--color-primary-light);color:var(--color-primary)}.fixed-action{position:fixed;left:0;right:0;bottom:0;padding:9.00px var(--spacing-page-x) calc(9.00px + 0px);background:rgba(255,255,255,.96);border-top:0.50px solid var(--color-divider);z-index:100}.field{margin-top:13.00px}.label{display:block;margin-bottom:6.00px;font-size:12.50px;font-weight:600}.input,.select-box,.textarea{width:100%;box-sizing:border-box;background:#FCFAF8;border:0.50px solid var(--color-border);border-radius:var(--radius-md);font-size:13.00px}.input,.select-box{height:44.00px;padding:0 12.00px;display:flex;align-items:center}.textarea{min-height:90.00px;padding:11.00px}.notice{margin-top:10.00px;padding:11.00px;border-radius:var(--radius-md);background:#F3F7FC;color:var(--color-text-secondary);font-size:11.50px;line-height:1.65}.empty-panel{text-align:center;padding:35.00px 15.00px}.empty-symbol{width:48.00px;height:48.00px;margin:auto;display:flex;align-items:center;justify-content:center;border-radius:15.00px;background:var(--color-primary-light);color:var(--color-primary);font-size:18.00px;font-weight:700}.empty-title{display:block;margin-top:11.00px;font-size:15.00px;font-weight:600}.article-card{margin-top:9.00px;background:var(--color-bg-card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.article-cover{height:110.00px;padding:12.00px;background:linear-gradient(135deg,#F5E5DE,#F9F1E8);display:flex;align-items:flex-end}.article-cover text{font-size:21.00px;color:rgba(125,76,63,.52);font-weight:700}.article-body{padding:12.00px}.article-title{display:block;font-size:14.50px;font-weight:650;line-height:1.45}.article-meta{display:block;margin-top:5.00px;font-size:11.00px;color:var(--color-text-tertiary)}.article-content{padding:16.00px;background:var(--color-bg-card);font-size:14.00px;line-height:1.9;color:var(--color-text-secondary)}.article-content .lead{display:block;font-size:15.50px;color:var(--color-text-primary);font-weight:600;margin-bottom:12.00px}.danger-card{background:#FFF8F4;border-color:#F5DED2}.danger-card .feature-icon{background:#FFF0EA;color:#C85D43}@media(max-width:340px){.hero-title{font-size:18.00px}.hero-desc{width:92%}} +/* ========================================================================== + 可访问性:只用 token,不用工具类(2026-09-23 修订) + -------------------------------------------------------------------------- + v2 曾在此处新增 .tap-min / .tap-gap / .focusable / .pressable 四个工具类。 + 复检发现全部零引用(等价能力已各自写在组件样式内,例如 button/index.wxss + 直接使用 min-height:var(--tap-min)),且存在两个硬问题: -.service-shell{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:#F4F5FA}.service-content{padding:4.00px 12.00px 18.00px}.service-status{display:flex;align-items:center;justify-content:space-between;margin-top:12.00px;padding:10.00px 12.00px;border-radius:11.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-status__label{color:#7B8198;font-size:10.50px}.service-status__value{padding:3.00px 7.00px;border-radius:9.00px;background:#EAF8F2;color:#329472;font-size:9.50px;font-weight:650}.service-status__value.disabled{background:#FFF0F0;color:#D45A60}.service-topics{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.service-topic{min-height:74.00px;padding:10.00px;border-radius:12.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-topic__icon{display:flex;align-items:center;justify-content:center;width:27.00px;height:27.00px;border-radius:8.50px;background:#FFF0F5}.service-topic__icon image{width:17.00px;height:17.00px}.service-topic__title{display:block;margin-top:6.50px;color:#283056;font-size:12.00px;font-weight:650}.service-topic__desc{display:block;margin-top:3.00px;color:#858A9E;font-size:9.50px;line-height:1.45}.service-actions{display:flex;gap:7.00px}.service-actions .secondary-btn{width:95.00px;flex:none}.service-actions .primary-btn{flex:1}.privacy-note{display:flex;align-items:flex-start;gap:7.00px;margin-top:11.00px;padding:10.00px;border-radius:11.00px;background:#F1F4FF;color:#69718E;font-size:10.00px;line-height:1.55}.privacy-note image{width:17.00px;height:17.00px;flex:none} + 1) `.tap-gap > * + *` 用了通配符与兄弟选择器 —— WXSS 不支持, + wcc 编译期直接报 `error at token '*'`,导致整个小程序编译失败。 + (这是编译错误,不是静默失效,代价最高。) + 2) `.pressable:active` / `.focusable:focus-visible` 的伪类在 view 上 + 不生效(小程序须用 hover-class),属于"写了等于没写"。 + + 故整块移除,保留 token。需要热区/间距时直接引用 token: + min-height: var(--tap-min); → 44.00px = 44px,最小可点区域 + gap: var(--tap-gap); → 8.00px = 8px,相邻目标间距(flex gap) + 【WXSS 禁用清单】星号通配符、兄弟选择器、属性选择器。 + 【注释约束】WXSS 注释**不可嵌套**:内层注释的结束标记会提前终止外层注释, + 其后的文字会被当成真实样式解析,导致编译失败或样式被污染。 + (2026-09-23 实证:本块注释初版即踩此坑。) + ========================================================================== */ + +.wx-page{background:var(--color-bg-page)}.service-page{min-height:100vh;padding-bottom:calc(70.00px + 0px)}.hero{padding:22.00px 16.00px 27.00px;background:linear-gradient(140deg,var(--color-primary-lighter),var(--color-warning-light));position:relative;overflow:hidden}.eyebrow{display:inline-flex;padding:3.50px 7.00px;border-radius:499.50px;background:rgba(255,255,255,.72);color:var(--color-primary-strong);font-size:12.00px}.hero-title{display:block;margin-top:9.00px;font-size:20.00px;font-weight:700;line-height:1.35}.hero-desc{display:block;width:82%;margin-top:7.00px;font-size:12.50px;color:var(--color-text-secondary);line-height:1.7}.content{padding:0 var(--spacing-page-x)}.block{margin-top:var(--spacing-section)}.block-title{display:block;font-size:15.50px;font-weight:600}.block-subtitle{display:block;margin-top:4.00px;font-size:12.00px;color:var(--color-text-tertiary)}.card{margin-top:9.00px;padding:14.00px;background:var(--color-bg-card);border:0.50px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.feature-row,.menu-row,.record-row{display:flex;align-items:center;gap:10.00px;min-height:56.00px;padding:9.00px 0;border-bottom:0.50px solid var(--color-divider)}.feature-row:last-child,.menu-row:last-child,.record-row:last-child{border-bottom:0}.feature-icon{width:36.00px;height:36.00px;display:flex;align-items:center;justify-content:center;flex:none;border-radius:11.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-weight:700}.feature-copy{flex:1;min-width:0}.feature-title{display:block;font-size:14.00px;font-weight:600}.feature-desc,.meta{display:block;margin-top:3.50px;font-size:12.00px;color:var(--color-text-tertiary);line-height:1.55}.arrow{font-size:20.00px;color:var(--color-text-disabled)}.tag{display:inline-flex;margin-right:5.00px;margin-top:5.00px;padding:3.00px 6.50px;border-radius:499.50px;background:var(--color-success-light);color:var(--color-success-strong);font-size:12.00px}.tag.warning{background:var(--color-warning-light);color:var(--color-warning-strong)}.primary-btn,.secondary-btn{height:44.00px;display:flex;align-items:center;justify-content:center;border-radius:22.00px;font-size:14.00px;font-weight:600}.primary-btn{background:var(--gradient-brand-solid);color:var(--color-text-inverse);box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)}.primary-btn.disabled{background:var(--color-bg-muted);color:var(--color-text-tertiary);box-shadow:none}.secondary-btn{background:var(--color-primary-light);color:var(--color-primary-strong)}.fixed-action{position:fixed;left:0;right:0;bottom:0;padding:9.00px var(--spacing-page-x) calc(9.00px + 0px);background:rgba(255,255,255,.96);border-top:0.50px solid var(--color-divider);z-index:100}.field{margin-top:13.00px}.label{display:block;margin-bottom:6.00px;font-size:12.50px;font-weight:600}.input,.select-box,.textarea{width:100%;box-sizing:border-box;background:var(--color-bg-page);border:0.50px solid var(--color-border);border-radius:var(--radius-md);font-size:13.00px}.input,.select-box{height:44.00px;padding:0 12.00px;display:flex;align-items:center}.textarea{min-height:90.00px;padding:11.00px}.notice{margin-top:10.00px;padding:11.00px;border-radius:var(--radius-md);background:var(--color-info-light);color:var(--color-text-secondary);font-size:12.00px;line-height:1.65}.select-box.is-readonly{background:var(--color-bg-subtle);color:var(--color-text-secondary)}.empty-panel{text-align:center;padding:35.00px 15.00px}.empty-symbol{width:48.00px;height:48.00px;margin:auto;display:flex;align-items:center;justify-content:center;border-radius:15.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-size:18.00px;font-weight:700}.empty-title{display:block;margin-top:11.00px;font-size:15.00px;font-weight:600}.article-card{margin-top:9.00px;background:var(--color-bg-card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.article-cover{height:110.00px;padding:12.00px;background:linear-gradient(135deg,var(--color-warning-light),var(--color-warning-light));display:flex;align-items:flex-end}.article-cover text{font-size:21.00px;color:rgba(125,76,63,.52);font-weight:700}.article-body{padding:12.00px}.article-title{display:block;font-size:14.50px;font-weight:600;line-height:1.45}.article-meta{display:block;margin-top:5.00px;font-size:12.00px;color:var(--color-text-tertiary)}.article-content{padding:16.00px;background:var(--color-bg-card);font-size:14.00px;line-height:1.9;color:var(--color-text-secondary)}.article-content .lead{display:block;font-size:15.50px;color:var(--color-text-primary);font-weight:600;margin-bottom:12.00px}.danger-card{background:var(--color-primary-lighter);border-color:var(--color-primary-light)}.danger-card .feature-icon{background:var(--color-warning-light);color:var(--color-warning-strong)}@media(max-width:340px){.hero-title{font-size:18.00px}.hero-desc{width:92%}} + +.service-shell{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:var(--color-bg-page)}.service-content{padding:4.00px 12.00px 18.00px}.service-status{display:flex;align-items:center;justify-content:space-between;margin-top:12.00px;padding:10.00px 12.00px;border-radius:11.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-status__label{color:var(--color-text-tertiary);font-size:12.00px}.service-status__value{padding:3.00px 7.00px;border-radius:9.00px;background:var(--color-success-light);color:var(--color-success-strong);font-size:12.00px;font-weight:600}.service-status__value.disabled{background:var(--color-danger-light);color:var(--color-danger-strong)}.service-topics{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.service-topic{min-height:74.00px;padding:10.00px;border-radius:12.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-topic__icon{display:flex;align-items:center;justify-content:center;width:27.00px;height:27.00px;border-radius:8.50px;background:var(--color-primary-light)}.service-topic__icon image{width:17.00px;height:17.00px}.service-topic__title{display:block;margin-top:6.50px;color:var(--color-text-strong);font-size:12.00px;font-weight:600}.service-topic__desc{display:block;margin-top:3.00px;color:var(--color-text-tertiary);font-size:12.00px;line-height:1.45}.service-actions{display:flex;gap:7.00px}.service-actions .secondary-btn{width:95.00px;flex:none}.service-actions .primary-btn{flex:1}.privacy-note{display:flex;align-items:flex-start;gap:7.00px;margin-top:11.00px;padding:10.00px;border-radius:11.00px;background:var(--color-info-light);color:var(--color-text-tertiary);font-size:12.00px;line-height:1.55}.privacy-note image{width:17.00px;height:17.00px;flex:none} /* ==== miniapp/components/section-header ==== */ +/** + * 区块标题(全站所有页面共用,是排版层级的关键一环) + * + * 2026-09-22 修订: + * 1) 层级拉开:标题 18.00px→20.00px(--font-size-xl),与正文 16.00px / 卡片标题 14.00px + * 形成「区块标题 > 卡片标题 > 正文 > 元信息」四级阶梯。 + * 旧值 18.00px 与卡片标题仅差 5.00px,层级读不出来。 + * 2) 右侧 action 是全站最容易被忽略的触摸目标:只有 13.00px 文字高(约 13px), + * 远低于 44px 下限。改为 min-height:--tap-min,热区向上补白。 + * 3) action 文字色原为 --color-primary(#E96B6B)=3.10:1,不达标,改 -strong。 + */ .ui-section { - display: flex; - align-items: center; - justify-content: space-between; - padding: var(--spacing-3) var(--spacing-page-x); + display:flex; + align-items:center; + justify-content:space-between; + padding:var(--spacing-2) var(--spacing-page-x); } .ui-section__left { - display: flex; - align-items: baseline; + display:flex; + align-items:baseline; + min-width:0; } .ui-section__title { - font-size: var(--font-size-lg); - font-weight: var(--font-weight-semibold); - color: var(--color-text-primary); + font-size:var(--font-size-xl); + font-weight:var(--font-weight-semibold); + color:var(--color-text-strong); + letter-spacing:var(--letter-spacing-tight); } .ui-section__subtitle { - margin-left: var(--spacing-2); - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); + margin-left:var(--spacing-2); + font-size:var(--font-size-xs); + color:var(--color-text-tertiary); } .ui-section__action { - display: flex; - align-items: center; - font-size: var(--font-size-sm); - color: var(--color-primary); + display:flex; + align-items:center; + flex:none; + min-height:var(--tap-min); + padding-left:var(--spacing-3); + font-size:var(--font-size-sm); + font-weight:var(--font-weight-medium); + color:var(--color-primary-strong); + transition:opacity var(--motion-fast) var(--ease-standard); +} +.ui-section__action:active { + opacity:var(--press-opacity); } .ui-section__arrow { - margin-left: 2.00px; - width: 12.00px; - height: 12.00px; + margin-left:2.00px; + width:12.00px; + height:12.00px; } /* ==== miniapp/components/recommend-card ==== */ -.ui-rec{display:flex;align-items:center;gap:8.00px;min-height:66.00px;padding:7.00px 8.00px;background:#fff;border-bottom:0.50px solid #F0F1F6}.ui-rec:last-child{border-bottom:0}.ui-rec__info{flex:1;min-width:0}.ui-rec__name-row{display:flex;align-items:center;gap:5.00px}.ui-rec__name{font-size:13.00px;font-weight:700;color:#222746}.ui-rec__age{font-size:10.50px;color:#545B76}.ui-rec__online{margin-left:auto;font-size:9.00px;color:#39A987}.ui-rec__online::before{content:'·';margin-right:2.00px}.ui-rec__meta{margin-top:2.50px;font-size:10.00px;color:#767C94;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ui-rec__reasons{display:flex;gap:3.50px;margin-top:4.00px;overflow:hidden}.ui-rec__reason{flex:none;padding:2.00px 4.50px;border-radius:6.00px;background:#F3EEFF;color:#7860AE;font-size:8.50px;white-space:nowrap}.ui-rec__actions{width:41.00px;display:flex;flex-direction:column;align-items:center;gap:3.50px}.compact-like{width:32.00px;height:32.00px;display:flex;align-items:center;justify-content:center;border-radius:16.00px;background:#FFF0F5;box-shadow:0 3.50px 9.00px rgba(255,79,145,.18)}.compact-like image{width:22.00px;height:22.00px}.compact-pass{font-size:8.50px;color:#A0A4B4;white-space:nowrap} +.ui-rec{display:flex;align-items:center;gap:8.00px;min-height:66.00px;padding:7.00px 8.00px;background:var(--color-bg-card);border-bottom:0.50px solid var(--color-divider)}.ui-rec:last-child{border-bottom:0}.ui-rec__info{flex:1;min-width:0}.ui-rec__name-row{display:flex;align-items:center;gap:5.00px}.ui-rec__name{font-size:13.00px;font-weight:700;color:var(--color-text-strong)}.ui-rec__age{font-size:12.00px;color:var(--color-text-secondary)}.ui-rec__online{margin-left:auto;font-size:12.00px;color:var(--color-success-strong)}.ui-rec__online::before{content:'·';margin-right:2.00px}.ui-rec__meta{margin-top:2.50px;font-size:12.00px;color:var(--color-text-tertiary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ui-rec__reasons{display:flex;gap:3.50px;margin-top:4.00px;overflow:hidden}.ui-rec__reason{flex:none;padding:2.00px 4.50px;border-radius:6.00px;background:var(--color-accent-purple-light);color:var(--color-accent-purple-strong);font-size:12.00px;white-space:nowrap}.ui-rec__actions{width:var(--tap-min);display:flex;flex-direction:column;align-items:center;gap:3.50px}.compact-like{width:var(--tap-min);min-height:var(--tap-min);display:flex;align-items:center;justify-content:center;border-radius:var(--radius-full);background:var(--color-primary-light);box-shadow:0 3.50px 9.00px rgba(255,79,145,.18);}.compact-like__icon{width:22.00px;height:22.00px}.compact-pass{font-size:12.00px;color:var(--color-text-tertiary);white-space:nowrap} /* ==== miniapp/components/empty ==== */ .ui-empty { - display: flex; - flex-direction: column; - align-items: center; - padding: var(--spacing-10) var(--spacing-page-x); - text-align: center; + display:flex; + flex-direction:column; + align-items:center; + padding:var(--spacing-10) var(--spacing-page-x); + text-align:center; } .ui-empty__illustration { - width: 80.00px; - height: 80.00px; - border-radius: 50%; - background: var(--color-bg-disabled); - display: flex; - align-items: center; - justify-content: center; - margin-bottom: var(--spacing-4); + width:80.00px; + height:80.00px; + border-radius:50%; + background:var(--color-bg-disabled); + display:flex; + align-items:center; + justify-content:center; + margin-bottom:var(--spacing-4); } .ui-empty__icon { - width: 36.00px; - height: 36.00px; - opacity: 0.72; + width:36.00px; + height:36.00px; + opacity:0.72; } .ui-empty__title { - font-size: var(--font-size-lg); - font-weight: var(--font-weight-medium); - color: var(--color-text-primary); - margin-bottom: var(--spacing-2); + font-size:var(--font-size-lg); + font-weight:var(--font-weight-medium); + color:var(--color-text-primary); + margin-bottom:var(--spacing-2); } .ui-empty__desc { - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); - line-height: var(--line-height-relaxed); - max-width: 240.00px; + font-size:var(--font-size-sm); + color:var(--color-text-tertiary); + line-height:var(--line-height-relaxed); + max-width:240.00px; } .ui-empty__actions { - display: flex; - flex-direction: column; - gap: var(--spacing-2); - margin-top: var(--spacing-6); - width: 100%; - max-width: 240.00px; + display:flex; + flex-direction:column; + gap:var(--spacing-2); + margin-top:var(--spacing-6); + width:100%; + max-width:240.00px; } .ui-empty__action { - display: flex; - align-items: center; - justify-content: center; - height: 40.00px; - border-radius: var(--radius-full); - font-size: var(--font-size-base); - font-weight: var(--font-weight-medium); -} + display:flex; + align-items:center; + justify-content:center; + min-height:var(--tap-min); + border-radius:var(--radius-full); + font-size:var(--font-size-base); + font-weight:var(--font-weight-medium); +min-width:var(--tap-min);} .ui-empty__action--primary { - background: var(--color-primary); - color: #FFFFFF; + background:var(--color-primary-solid); + color:var(--color-text-inverse); } .ui-empty__action--secondary { - background: var(--color-bg-card); - color: var(--color-primary); - border: 0.50px solid var(--color-primary); + background:var(--color-bg-card); + color:var(--color-primary-strong); + border:0.50px solid var(--color-primary); } /* ==== miniapp/components/loading ==== */ .ui-loading--block { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: var(--spacing-8) var(--spacing-page-x); + display:flex; + flex-direction:column; + align-items:center; + justify-content:center; + padding:var(--spacing-8) var(--spacing-page-x); } .ui-loading--inline { - display: inline-flex; - align-items: center; + display:inline-flex; + align-items:center; } .ui-loading__spinner { - width: 30.00px; - height: 30.00px; - display: flex; - align-items: center; - justify-content: center; + width:30.00px; + height:30.00px; + display:flex; + align-items:center; + justify-content:center; } .ui-loading__spinner-icon { - width: 24.00px; - height: 24.00px; - animation: ui-loading-spin 0.8s linear infinite; + width:24.00px; + height:24.00px; + animation:ui-loading-spin 0.8s linear infinite; } @keyframes ui-loading-spin { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } + from { transform:rotate(0deg); } + to { transform:rotate(360deg); } } .ui-loading__text { - margin-top: var(--spacing-3); - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); + margin-top:var(--spacing-3); + font-size:var(--font-size-sm); + color:var(--color-text-tertiary); } /* Skeleton */ .ui-loading__skeleton { - width: 100%; + width:100%; } .ui-loading__skeleton-row { - display: flex; - align-items: center; - padding: var(--spacing-3) var(--spacing-page-x); - background: var(--color-bg-card); - border-bottom: 0.50px solid var(--color-divider); + display:flex; + align-items:center; + padding:var(--spacing-3) var(--spacing-page-x); + background:var(--color-bg-card); + border-bottom:0.50px solid var(--color-divider); } .ui-loading__skeleton-avatar { - width: 44.00px; - height: 44.00px; - border-radius: 50%; - background: var(--color-bg-disabled); - margin-right: var(--spacing-3); - flex-shrink: 0; + width:44.00px; + height:44.00px; + border-radius:50%; + background:var(--color-bg-disabled); + margin-right:var(--spacing-3); + flex-shrink:0; } .ui-loading__skeleton-content { - flex: 1; - min-width: 0; + flex:1; + min-width:0; } .ui-loading__skeleton-line { - height: 12.00px; - background: var(--color-bg-disabled); - border-radius: var(--radius-sm); - position: relative; - overflow: hidden; + height:12.00px; + background:var(--color-bg-disabled); + border-radius:var(--radius-sm); + position:relative; + overflow:hidden; } .ui-loading__skeleton-line--title { - width: 40%; - margin-bottom: var(--spacing-2); + width:40%; + margin-bottom:var(--spacing-2); } .ui-loading__skeleton-line--meta { - width: 70%; + width:70%; } /* shimmer */ .ui-loading__skeleton-line::after, .ui-loading__skeleton-avatar::after { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: linear-gradient( + content:''; + position:absolute; + top:0; + left:0; + width:100%; + height:100%; + background:linear-gradient( 90deg, transparent 0%, rgba(255, 255, 255, 0.55) 50%, transparent 100% ); - animation: ui-loading-shimmer 1.4s ease-in-out infinite; + animation:ui-loading-shimmer 1.4s ease-in-out infinite; } @keyframes ui-loading-shimmer { - 0% { transform: translateX(-100%); } - 100% { transform: translateX(100%); } + 0% { transform:translateX(-100%); } + 100% { transform:translateX(100%); } } /* ==== miniapp/components/status-badge ==== */ .ui-badge { - display: inline-flex; - align-items: center; - padding: 2.00px 7.00px; - border-radius: var(--radius-full); - font-size: var(--font-size-xs); - font-weight: var(--font-weight-medium); - line-height: 1.4; - white-space: nowrap; + display:inline-flex; + align-items:center; + padding:2.00px 7.00px; + border-radius:var(--radius-full); + font-size:var(--font-size-xs); + font-weight:var(--font-weight-medium); + line-height:1.4; + white-space:nowrap; } .ui-badge__dot { - width: 4.00px; - height: 4.00px; - border-radius: 50%; - background: currentColor; - margin-right: 4.00px; + width:4.00px; + height:4.00px; + border-radius:50%; + background:currentColor; + margin-right:4.00px; } .ui-badge__label { - font-size: inherit; + font-size:inherit; } .ui-badge--success { - background: var(--color-success-light); - color: var(--color-success); + background:var(--color-success-light); + color:var(--color-success-strong); } .ui-badge--warning { - background: var(--color-warning-light); - color: var(--color-warning); + background:var(--color-warning-light); + color:var(--color-warning-strong); } .ui-badge--danger { - background: var(--color-danger-light); - color: var(--color-danger); + background:var(--color-danger-light); + color:var(--color-danger-strong); } .ui-badge--info { - background: var(--color-info-light); - color: var(--color-info); + background:var(--color-info-light); + color:var(--color-info-strong); } .ui-badge--disabled { - background: var(--color-bg-disabled); - color: var(--color-text-disabled); + background:var(--color-bg-disabled); + color:var(--color-text-disabled); } /* ==== miniapp/components/error-state ==== */ .error-state { - padding: 32.00px 16.00px; - text-align: center; - background: var(--color-bg-card); - border-radius: var(--radius-lg); + padding:32.00px 16.00px; + text-align:center; + background:var(--color-bg-card); + border-radius:var(--radius-lg); } .error-icon { - display: block; - width: 36.00px; - height: 36.00px; - margin: 0 auto 10.00px; + display:block; + width:36.00px; + height:36.00px; + margin:0 auto 10.00px; } .error-title, .error-desc { - display: block; + display:block; } .error-title { - font-size: 15.00px; - font-weight: 600; + font-size:15.00px; + font-weight:600; } .error-desc { - margin-top: 4.00px; - color: var(--color-text-tertiary); - font-size: 12.00px; + margin-top:4.00px; + color:var(--color-text-tertiary); + font-size:12.00px; } .retry-btn { - width: 110.00px; - height: 40.00px; - margin-top: 12.00px; - border: 0; - border-radius: var(--radius-full); - background: var(--color-primary); - color: var(--color-text-inverse); - font-size: 13.00px; - line-height: 40.00px; -} + width:110.00px; + min-height:var(--tap-min); + margin-top:12.00px; + border:0; + border-radius:var(--radius-full); + background:var(--color-primary-solid); + color:var(--color-text-inverse); + font-size:13.00px; + line-height:var(--tap-min); +min-width:var(--tap-min);} .retry-btn::after { - border: 0; + border:0; } -.page{min-height:100vh;background:#F4F5FA;padding-bottom:20.00px}.night-shell{padding:0 12.00px 14.00px;background:linear-gradient(160deg,var(--mini-night-start),var(--mini-night-end));border-radius:0 0 21.00px 21.00px;box-shadow:var(--mini-shadow)} -.brand-bar{height:56.00px;padding-top:20px;display:flex;align-items:center;justify-content:space-between;color:var(--mini-text-on-night)}.brand-lockup{display:flex;align-items:center}.brand-logo{width:33.00px;height:33.00px}.brand-copy{display:flex;flex-direction:column;margin-left:6.00px}.brand-name{font-size:17.00px;font-weight:700;letter-spacing:1.00px}.brand-slogan{font-size:9.00px;letter-spacing:2.00px;color:var(--mini-text-on-night-muted)}.brand-actions{position:relative;min-width:38.00px;height:36.00px;display:flex;align-items:center;justify-content:center}.message-label{font-size:11.50px}.badge{position:absolute;right:0;top:2.00px;min-width:14.00px;height:14.00px;padding:0 2.00px;line-height:14.00px;text-align:center;font-size:9.00px;color:#fff;background:var(--mini-accent-pink);border-radius:10.00px} -.status-strip{margin:2.00px 0 8.00px;padding:9.00px 10.00px;border:0.50px solid rgba(255,255,255,.16);background:rgba(255,255,255,.09);border-radius:10.00px;color:#fff}.status-main{display:flex;align-items:center;gap:8.00px}.status-copy{flex:1;min-width:0;display:flex;flex-direction:column}.status-title{font-size:12.50px;font-weight:650}.status-desc{margin-top:2.50px;font-size:10.00px;color:var(--mini-text-on-night-muted);line-height:1.4}.status-action{flex:none;min-width:54.00px;min-height:28.00px;padding:0 9.00px;display:flex;align-items:center;justify-content:center;border-radius:14.00px;background:linear-gradient(135deg,var(--mini-accent-coral),var(--mini-accent-pink));font-size:11.00px;font-weight:650}.status-checks{display:flex;gap:5.00px;overflow:hidden}.status-check{padding:4.00px 6.00px;border-radius:10.00px;background:rgba(255,255,255,.08);font-size:9.50px;color:var(--mini-text-on-night-muted);white-space:nowrap}.status-check.done{background:rgba(90,226,184,.16);color:#A6F5D7} -.banner-section{width:100%}.banner-swiper,.banner-card{height:136.00px;border-radius:13.00px;overflow:hidden}.banner-card{position:relative}.banner-img{width:100%;height:100%;display:block}.banner-overlay{position:absolute;inset:0;background:linear-gradient(90deg,rgba(25,22,86,.78) 0%,rgba(43,22,101,.25) 58%,rgba(255,79,145,.08) 100%)}.banner-copy{position:absolute;left:13.00px;bottom:13.00px;width:68%;display:flex;flex-direction:column;color:#fff}.banner-kicker{font-size:9.00px;letter-spacing:1.50px;color:rgba(255,255,255,.78)}.banner-title{margin-top:4.50px;font-size:17.50px;line-height:1.2;font-weight:750;text-shadow:0 1.50px 5.00px rgba(0,0,0,.2)}.banner-subtitle{margin-top:4.00px;font-size:11.00px;color:rgba(255,255,255,.84)} -.entries-card{position:relative;z-index:2;margin:-7.00px 12.00px 0;padding:11.00px 5.00px 9.00px;background:var(--mini-card-bg);border-radius:15.00px;box-shadow:var(--mini-shadow)}.entries-grid{display:grid;grid-template-columns:repeat(4,1fr);row-gap:9.00px}.entry-item{min-height:52.00px;display:flex;flex-direction:column;align-items:center;justify-content:center}.entry-item.disabled{opacity:.4}.entry-icon{width:33.00px;height:33.00px;display:flex;align-items:center;justify-content:center;border-radius:10.00px;overflow:hidden}.entry-icon-image{width:22.50px;height:22.50px}.entry-label{margin-top:4.00px;font-size:10.50px;color:#283056;font-weight:550}.tone-rose{background:#FFF0F5}.tone-purple{background:#F0EAFE}.tone-blue{background:#EAF3FF}.tone-pink{background:#FFF0F7}.tone-amber{background:#FFF3E5}.tone-indigo{background:#ECEEFF}.tone-red{background:#FFEDEF}.tone-green{background:#EAF8F2} -.preview-note{margin:8.00px 12.00px 0;text-align:center;color:#8B63BC;font-size:10.00px}.section{margin-top:17.00px;padding:0 12.00px}.recommendation-section{margin-top:15.00px}.recommend-list{margin-top:8.00px;border-radius:13.00px;overflow:hidden;box-shadow:0 4.00px 14.00px rgba(35,35,95,.07)}.recommend-empty{margin-top:8.00px;padding:11.00px;display:flex;align-items:center;gap:9.00px;background:#fff;border-radius:13.00px;box-shadow:0 4.00px 14.00px rgba(35,35,95,.07)}.empty-logo{width:38.00px;height:38.00px;flex:none}.empty-copy{flex:1;min-width:0;display:flex;flex-direction:column}.empty-title{font-size:12.50px;font-weight:650;color:#222746}.empty-desc{margin-top:3.00px;font-size:10.00px;line-height:1.4;color:#7A7F98}.empty-actions{display:flex;flex-direction:column;gap:4.00px}.empty-btn{min-width:56.00px;height:24.00px;padding:0 6.00px;display:flex;align-items:center;justify-content:center;border-radius:12.00px;font-size:10.00px}.empty-btn.secondary{color:#7C60BC;background:#F1EEFB}.empty-btn.primary{color:#fff;background:linear-gradient(135deg,var(--mini-accent-coral),var(--mini-accent-pink))} -.service-card{display:flex;align-items:stretch;margin-top:8.00px;background:#fff;border-radius:13.00px;overflow:hidden;box-shadow:0 4.00px 14.00px rgba(35,35,95,.07)}.service-cover{width:105.00px;min-height:78.00px}.service-copy{flex:1;padding:10.00px;display:flex;flex-direction:column}.service-title{font-size:12.50px;font-weight:650;color:#222746}.service-desc{margin-top:3.50px;font-size:10.50px;color:#757B91;line-height:1.45}.text-link{margin-top:auto;padding-top:5.00px;font-size:10.50px;color:var(--mini-accent-pink);font-weight:650} -.activity-scroll{white-space:nowrap;margin-top:8.00px}.activity-card{display:inline-flex;width:275.00px;margin-right:9.00px;background:#fff;border-radius:12.00px;overflow:hidden;box-shadow:0 4.00px 14.00px rgba(35,35,95,.07);white-space:normal}.activity-cover{width:105.00px;height:84.00px}.activity-info{flex:1;padding:9.00px;display:flex;flex-direction:column}.activity-tag{align-self:flex-start;padding:2.50px 6.00px;border-radius:9.00px;background:#FFF0F5;color:var(--mini-accent-pink);font-size:9.00px}.activity-title{margin-top:5.00px;font-size:12.50px;font-weight:650;color:#222746;line-height:1.35}.activity-meta{margin-top:auto;font-size:10.00px;color:#81869B} -.station-card,.article-row,.safety-card{display:flex;align-items:center;background:#fff;border-radius:13.00px;overflow:hidden;box-shadow:0 4.00px 14.00px rgba(35,35,95,.07)}.station-cover{width:95.00px;height:85.00px}.station-info{flex:1;min-width:0;padding:9.00px}.station-name{display:block;font-size:13.00px;font-weight:650;color:#222746}.station-desc{display:block;margin:3.50px 0 6.00px;font-size:10.00px;color:#7A7F98}.mini-tag{display:inline-block;margin:2.00px 3.50px 0 0;padding:2.00px 4.50px;border-radius:7.00px;background:#F0EEFB;color:#6857A2;font-size:8.50px}.arrow-icon{width:14.00px;height:14.00px;margin:8.00px;flex:none}.article-list{margin-top:8.00px;display:flex;flex-direction:column;gap:6.00px}.article-row{min-height:56.00px}.article-cover{width:73.00px;height:56.00px}.article-info,.safety-info{flex:1;min-width:0;padding:8.00px}.article-title{display:block;font-size:12.00px;font-weight:600;color:#222746;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.article-meta{display:block;margin-top:3.00px;font-size:9.50px;color:#85899C}.section-empty{margin-top:8.00px;padding:15.00px 12.00px;text-align:center;color:#8A90A6;font-size:11.00px;background:#fff;border-radius:12.00px;box-shadow:0 4.00px 14.00px rgba(35,35,95,.05)}.safety-card{padding:0}.safety-cover{width:90.00px;align-self:stretch}.safety-title{display:block;font-size:12.50px;font-weight:650;color:#222746}.safety-body{display:block;margin-top:3.50px;font-size:10.00px;line-height:1.45;color:#74798E}.safety-link{display:block;margin-top:4.50px;font-size:10.00px;color:var(--mini-accent-pink);font-weight:650} -@media (max-width:340px){.entry-label{font-size:9.50px}.entry-icon{width:30.00px;height:30.00px}.banner-title{font-size:15.50px}.status-checks{overflow-x:auto}.empty-actions{display:none}} +/** + * 首页 —— 全站设计系统样板页 + * + * 2026-09-22 重做。这一版要证明 app.wxss v2 的底座是"能用"的: + * + * 1) 氛围层(参考图的关键差异项) + * 旧版只有一条线性渐变,参考图里有明显的暖粉光晕、星点与玻璃质感。 + * 现用三层叠加:--mini-starfield(星点)+ --gradient-night(夜空) + * + 两个定位光晕伪元素(左上粉 / 左下靛蓝),零图片、零额外请求。 + * + * 2) 排版层级 + * 旧版 hero 标题 17.50px、区块标题 18.00px、卡片标题 12.50px、正文 12.00px —— + * hero 与区块标题几乎同号,层级读不出来。现为: + * hero 24.00px/700 > 区块标题 20.00px/600 > 卡片标题 14.00px/600 > + * 正文 13.00px > 元信息 12.00px + * + * 3) 触摸目标 + * 所有可点元素以 --tap-min(44.00px=44px) 为下限;旧版 .empty-btn 只有 24px。 + * 并且删掉了 @media(max-width:340px) 里的 .empty-actions{display:none} —— + * 那等于在小屏上把「调整条件 / 公益红娘」两个入口整块砍掉。 + * + * 4) 交互反馈 + * 旧版全站 --motion-* 只被引用 5 次,点了没反应。现统一走 --ease-spring + * + --press-scale,并给区块卡片加上按压缩放。 + * + * 5) 对比度 + * 旧版 .text-link/.activity-tag/.safety-link 用 --mini-accent-pink(#FF4F91) + * 作文字 = 3.10:1,不达标;CTA 白字压在珊瑚粉渐变上也只有 2.77:1。 + * 现分别改用 --color-primary-strong(5.33:1) 与 --gradient-brand-solid(≥4.7:1)。 + * + * 单位:rpx(375.00px = 屏幕宽度,0.50px ≈ 0.5px) + */ + +/* ============================== 页面骨架 ============================== */ + +.page { + min-height: 100vh; + background: var(--color-bg-page); + padding-bottom: var(--spacing-5); +} + +/* ============================== 夜空头部 ============================== */ + +.night-shell { + position: relative; + overflow: hidden; + /* --nav-status / --nav-h / --nav-right 由 index.ts 经 utils/nav-metrics 实测胶囊按钮后注入。 + 顶到胶囊所在横带,而不是用 20px:后者只反映设备物理安全区, + 安卓上常为 0,也完全不反映右上角胶囊的位置(2026-09-23 重合缺陷的根因)。 */ + padding: var(--nav-status, 44px) var(--spacing-3) var(--spacing-4); + background: var(--mini-starfield), var(--gradient-night); + border-radius: 0 0 var(--radius-2xl) var(--radius-2xl); + box-shadow: var(--shadow-night); +} + +/* 两个光晕:伪元素承担,避免为了装饰再嵌一层 view */ +.night-shell::before, +.night-shell::after { + content: ''; + position: absolute; + border-radius: 50%; + pointer-events: none; + z-index: var(--z-ambient); +} +.night-shell::before { + top: -100.00px; + right: -70.00px; + width: 280.00px; + height: 280.00px; + background: radial-gradient(circle, var(--mini-glow-coral) 0%, transparent 68%); +} +.night-shell::after { + bottom: -110.00px; + left: -80.00px; + width: 310.00px; + height: 310.00px; + background: radial-gradient(circle, var(--mini-glow-indigo) 0%, transparent 70%); +} + +/* 伪元素是定位元素,会盖住静态流内容;正文需要显式抬一层 */ +.night-shell > view { + position: relative; + z-index: var(--z-base); +} + +/* ============================== 品牌栏 ============================== */ + +.brand-bar { + /* 高度与胶囊按钮对齐;右侧留出胶囊安全区,否则「消息」入口会被胶囊压住点不到 */ + height: var(--nav-h, 40.00px); + box-sizing: border-box; + padding-right: var(--nav-right, 102px); + display: flex; + align-items: center; + justify-content: space-between; + color: var(--mini-text-on-night); +} +.brand-lockup { + display: flex; + align-items: center; + min-width: 0; +} +.brand-logo { + width: 34.00px; + height: 34.00px; + flex: none; +} +.brand-copy { + display: flex; + flex-direction: column; + margin-left: var(--spacing-2); +} +.brand-name { + font-size: var(--font-size-lg); + font-weight: var(--font-weight-bold); + letter-spacing: var(--letter-spacing-wider); + line-height: var(--line-height-tight); +} +.brand-slogan { + margin-top: 1.00px; + font-size: var(--font-size-xs); + letter-spacing: 1.50px; + color: var(--mini-text-on-night-muted); +} +.brand-actions { + position: relative; + flex: none; + min-width: var(--tap-min); + min-height: var(--tap-min); + display: flex; + align-items: center; + justify-content: center; +} +.message-label { + font-size: var(--font-size-sm); +} +.badge { + position: absolute; + right: 0; + top: 2.00px; + min-width: 15.00px; + height: 15.00px; + padding: 0 2.50px; + line-height: 15.00px; + text-align: center; + font-size: var(--font-size-micro); + color: var(--color-text-inverse); + /* 白字需 4.5:1:--mini-accent-pink 仅 3.10,改用 solid 变体 */ + background: var(--color-primary-solid); + border-radius: var(--radius-full); + /* 描一圈夜空底色,避免角标压在光晕上时边缘糊掉 */ + box-shadow: 0 0 0 1.50px var(--mini-night-start); +} + +/* ============================== 状态条 ============================== */ + +.status-strip { + margin: var(--spacing-1) 0 var(--spacing-2); + padding: var(--spacing-3); + border: var(--border-width) solid var(--mini-hairline); + background: var(--mini-glass); + border-radius: var(--radius-md); + color: var(--color-text-inverse); +} +.status-main { + display: flex; + align-items: center; + gap: var(--spacing-2); +} +.status-copy { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; +} +.status-title { + font-size: var(--font-size-md); + font-weight: var(--font-weight-semibold); + line-height: var(--line-height-tight); +} +.status-desc { + margin-top: 3.00px; + font-size: var(--font-size-xs); + line-height: var(--line-height-normal); + color: var(--mini-text-on-night-muted); +} +.status-action { + flex: none; + min-width: 58.00px; + min-height: var(--tap-min); + padding: 0 var(--spacing-3); + display: flex; + align-items: center; + justify-content: center; + border-radius: var(--radius-full); + background: var(--gradient-brand-solid); + font-size: var(--font-size-sm); + font-weight: var(--font-weight-semibold); +} +.status-checks { + display: flex; + gap: 5.00px; + overflow: hidden; +} +.status-check { + padding: 4.00px 7.00px; + border-radius: var(--radius-full); + background: var(--mini-glass); + font-size: var(--font-size-xs); + color: var(--mini-text-on-night-muted); + white-space: nowrap; +} +.status-check.done { + background: var(--mini-glass-success); + color: var(--color-success-on-night); + font-weight: var(--font-weight-semibold); +} + +/* ============================== 主视觉横幅 ============================== */ + +.banner-section { + width: 100%; +} +.banner-swiper, +.banner-card { + height: 150.00px; + border-radius: var(--radius-lg); + overflow: hidden; +} +.banner-card { + position: relative; +} +.banner-img { + width: 100%; + height: 100%; + display: block; +} +.banner-overlay { + position: absolute; + inset: 0; + background: var(--mini-banner-scrim); +} +.banner-copy { + position: absolute; + left: var(--spacing-3); + bottom: var(--spacing-5); + width: 68%; + display: flex; + flex-direction: column; + color: var(--color-text-inverse); +} +.banner-kicker { + font-size: var(--font-size-xs); + letter-spacing: 1.50px; + color: var(--mini-text-on-night-muted); +} +.banner-title { + margin-top: 5.00px; + font-size: var(--font-size-2xl); + line-height: var(--line-height-tight); + font-weight: var(--font-weight-bold); + letter-spacing: var(--letter-spacing-wide); + text-shadow: 0 2.00px 7.00px rgba(0, 0, 0, 0.22); +} +.banner-subtitle { + margin-top: 5.00px; + font-size: var(--font-size-sm); + color: var(--mini-text-on-night-muted); +} + +/* ============================== 快捷入口 ============================== */ + +.entries-card { + position: relative; + z-index: 2; + margin: -9.00px var(--spacing-3) 0; + padding: var(--spacing-3) var(--spacing-1) var(--spacing-2); + background: var(--mini-card-bg); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-raised); +} +/* 4 列宫格用 flex + 25% 宽实现。display:grid 在 Skyline 渲染引擎下不支持, + 统一避开以免将来切渲染引擎时整体错版。 */ +.entries-grid { + display: flex; + flex-wrap: wrap; + row-gap: var(--spacing-2); +} +.entry-item { + width: 25%; + box-sizing: border-box; + min-height: 88.00px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} +.entry-item.disabled { + opacity: 0.4; +} +/* 图标砖(参考图 2):48.00px 圆角方 + 高饱和渐变面 + 白色描画图形。 + 两层背景:上层 26.00px = 白色图形(data-uri SVG),下层 100% = 渐变砖面。 + background-color 是**兜底**:万一 SVG 背景层被解析器丢弃,砖面仍在(只是没有图形), + 不会退化成「白底白图标」这种彻底不可见的形态。 */ +.entry-icon { + width: 48.00px; + height: 48.00px; + border-radius: 14.00px; + background-repeat: no-repeat, no-repeat; + background-position: center, center; + background-size: 26.00px 26.00px, 100% 100%; + box-shadow: var(--mini-entry-shadow); +} +.entry-label { + margin-top: var(--spacing-1); + font-size: var(--font-size-md); + font-weight: var(--font-weight-semibold); + color: var(--color-text-strong); + letter-spacing: var(--letter-spacing-tight); +} +/* 副标题:承接参考图「主标题 + 一行说明」的双层信息结构。 + 字号用 --font-size-xs(12px,本项目的元信息下限),不再往下探 micro —— + micro 是「仅角标/装饰、禁用于正文」的档位,这行字承载语义,不属于装饰。 */ +.entry-sub { + margin-top: 1.00px; + font-size: var(--font-size-xs); + font-weight: var(--font-weight-regular); + color: var(--mini-muted); + line-height: 1.3; +} + +/* ---- tone → 渐变砖面 + 白色图形 ---------------------------------------- + 色相语义与实算对比度见 app.wxss 的 --gradient-entry-* 注释块; + 本处只负责「把哪个图形放到哪种砖上」,颜色事实源仍在 app.wxss。 + 图形均为 24×24 viewBox 白色矢量,随 background-size 等比缩放到 26.00px。 */ +.tone-rose { + background-color: #F34671; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' d='M12 21.2l-1.4-1.3C5.5 15.3 2.2 12.3 2.2 8.6 2.2 5.6 4.6 3.2 7.6 3.2c1.7 0 3.3.8 4.4 2 1.1-1.2 2.7-2 4.4-2 3 0 5.4 2.4 5.4 5.4 0 3.7-3.3 6.7-8.4 11.3z'/%3E%3C/svg%3E"), var(--gradient-entry-rose); +} +.tone-orange { + background-color: #D95E06; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='%23fff'%3E%3Ccircle cx='9' cy='7.6' r='3.4'/%3E%3Ccircle cx='17.2' cy='9.8' r='2.7'/%3E%3Crect x='2.4' y='15.2' width='13.2' height='6.4' rx='3.2'/%3E%3Crect x='13.8' y='16.4' width='8.6' height='5.2' rx='2.6'/%3E%3C/g%3E%3C/svg%3E"), var(--gradient-entry-orange); +} +.tone-violet { + background-color: #8F64F2; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='%23fff' stroke-width='1.8'%3E%3Crect x='3.2' y='5.4' width='17.6' height='15.4' rx='3.2'/%3E%3C/g%3E%3Cg fill='%23fff'%3E%3Crect x='7.6' y='2.6' width='2.1' height='4.3' rx='1.05'/%3E%3Crect x='14.3' y='2.6' width='2.1' height='4.3' rx='1.05'/%3E%3Cpath d='M12.00 10.65L12.74 12.58L14.81 12.69L13.20 13.99L13.73 15.99L12.00 14.86L10.27 15.99L10.80 13.99L9.19 12.69L11.26 12.58Z'/%3E%3C/g%3E%3C/svg%3E"), var(--gradient-entry-violet); +} +.tone-blue { + background-color: #3484F4; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='%23fff' stroke-width='1.7' stroke-linejoin='round'%3E%3Cpath d='M3.7 7.1a3.4 3.4 0 0 1 3.4-3.4h6.6a3.4 3.4 0 0 1 3.4 3.4v3.6a3.4 3.4 0 0 1-3.4 3.4H9.3l-4 3.4a.8.8 0 0 1-1.6-.5z'/%3E%3C/g%3E%3Cg fill='none' stroke='%23fff' stroke-width='1.6'%3E%3Cpath d='M18.1 9.4h.4a2.5 2.5 0 0 1 2.5 2.5v2.3a2.5 2.5 0 0 1-2.5 2.5h-.4v2.1l-2.5-2.1h-2a2.5 2.5 0 0 1-2.5-2.5'/%3E%3C/g%3E%3C/svg%3E"), var(--gradient-entry-blue); +} +.tone-purple { + background-color: #A260ED; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='%23fff'%3E%3Cpath d='M11.3 7.4C9.6 5.9 7.2 5.2 4.6 5.2H2.8v12.9h1.8c2.6 0 5 .7 6.7 2.2z'/%3E%3Cpath d='M12.7 7.4c1.7-1.5 4.1-2.2 6.7-2.2h1.8v12.9h-1.8c-2.6 0-5 .7-6.7 2.2z'/%3E%3C/g%3E%3C/svg%3E"), var(--gradient-entry-purple); +} +.tone-pink { + background-color: #F0458C; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='%23fff'%3E%3Cpath d='M12 13.6l-1.05-1C7.2 9.3 5 7.2 5 5 5 3.2 6.5 1.8 8.3 1.8c1.1 0 2.1.5 2.7 1.4.6-.9 1.6-1.4 2.7-1.4 1.8 0 3.3 1.4 3.3 3.2 0 2.2-2.2 4.3-5.8 7.7z'/%3E%3Crect x='3.4' y='15.6' width='10' height='3.6' rx='1.8' transform='rotate(18 8.4 17.4)'/%3E%3Crect x='10.6' y='15.6' width='10' height='3.6' rx='1.8' transform='rotate(-18 15.6 17.4)'/%3E%3C/g%3E%3C/svg%3E"), var(--gradient-entry-pink); +} +.tone-green { + background-color: #148F66; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='%23fff' stroke-width='1.8' stroke-linejoin='round'%3E%3Cpath d='M12 2.6l7.4 2.8v6.2c0 4.6-3.1 8.7-7.4 9.8-4.3-1.1-7.4-5.2-7.4-9.8V5.4z'/%3E%3C/g%3E%3Cpath d='M8.4 12.2l2.5 2.5 4.7-5' fill='none' stroke='%23fff' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"), var(--gradient-entry-green); +} +.tone-amber { + background-color: #CC650B; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' d='M12 3.1l9.2 7.5h-2.3v9.4h-4.3v-5.7H9.4v5.7H5.1v-9.4H2.8z'/%3E%3C/svg%3E"), var(--gradient-entry-amber); +} + +/* ============================== 区块容器 ============================== */ + +.preview-note { + margin: var(--spacing-2) var(--spacing-3) 0; + text-align: center; + font-size: var(--font-size-xs); + color: var(--color-accent-purple-strong); +} +.section { + margin-top: var(--spacing-5); + padding: 0 var(--spacing-3); +} +.recommendation-section { + margin-top: var(--spacing-5); +} +/* 标题与卡片左边缘必须对齐:.section 已提供 12.00px 内边距, + 而 ui-section 自带 --spacing-page-x(16.00px),叠加会让标题比卡片多缩进 16.00px。 */ +.section .ui-section { + padding-left: 0; + padding-right: 0; +} + +/* ============================== 今日推荐 ============================== */ + +.recommend-list { + margin-top: var(--spacing-2); + border-radius: var(--radius-lg); + overflow: hidden; + box-shadow: var(--shadow-card); +} +.recommend-empty { + margin-top: var(--spacing-2); + padding: var(--spacing-3); + display: flex; + align-items: center; + gap: var(--spacing-2); + background: var(--color-bg-card); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-card); +} +.empty-logo { + width: 38.00px; + height: 38.00px; + flex: none; +} +.empty-copy { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; +} +.empty-title { + font-size: var(--font-size-md); + font-weight: var(--font-weight-semibold); + color: var(--color-text-strong); +} +.empty-desc { + margin-top: 3.00px; + font-size: var(--font-size-sm); + line-height: var(--line-height-normal); + color: var(--color-text-tertiary); +} +.empty-actions { + display: flex; + flex-direction: column; + gap: var(--spacing-1); +} +.empty-btn { + min-width: 60.00px; + min-height: var(--tap-min); + padding: 0 var(--spacing-2); + display: flex; + align-items: center; + justify-content: center; + border-radius: var(--radius-full); + font-size: var(--font-size-sm); + font-weight: var(--font-weight-medium); +} +.empty-btn.secondary { + color: var(--color-accent-purple-strong); + background: var(--color-accent-purple-light); +} +.empty-btn.primary { + color: var(--color-text-inverse); + background: var(--gradient-brand-solid); +} + +/* ============================== 公益服务(1/3 小卡) ============================== + 2026-09-23 重做。此前的卡片是「整行宽 + 封面写 width 不写 height」: + 小程序 在未指定高度时会取默认 240px(=240.00px),卡片被硬生生撑到约 240.00px 高, + 首页上极占地方(用户反馈的「占用过大」即此)。现在: + - 宽度:一行 3 张,每张约 112.00px(≈ 原 351.00px 的 1/3) + - 高度:固定 84.00px(≈ 原 240.00px 的 1/3) + - 内容:只留配图 + 标题,整块可点,长文案与入口交给详情页 + ⇒ 想改回整行宽:把 .mini-card 的 width 换成 100%、height 改成 80.00px 即可(一处改动)。 */ + +.mini-rail { + display: flex; + flex-wrap: wrap; + align-items: flex-start; + gap: var(--spacing-2); + margin-top: var(--spacing-2); +} +.mini-card { + position: relative; + width: calc((100% - var(--spacing-2) * 2) / 3); + height: 84.00px; + border-radius: var(--radius-md); + overflow: hidden; + box-shadow: var(--shadow-card); +} +.mini-card-cover { + width: 100%; + height: 100%; + display: block; +} +.mini-card-scrim { + position: absolute; + left: 0; + right: 0; + bottom: 0; + height: 56.00px; + background: linear-gradient(180deg, rgba(23, 42, 114, 0) 0%, rgba(23, 42, 114, 0.88) 100%); +} +.mini-card-title { + position: absolute; + left: var(--spacing-2); + right: var(--spacing-1); + bottom: 6.00px; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; + font-size: var(--font-size-sm); + font-weight: var(--font-weight-semibold); + line-height: var(--line-height-tight); + color: var(--color-text-inverse); +} +/* 安全提醒右半区:文案是公益属性的一部分,缩卡后不能整块丢掉 */ +.mini-note { + flex: 1; + min-width: 0; + padding-top: var(--spacing-1); + display: flex; + flex-direction: column; +} +.mini-note-text { + font-size: var(--font-size-sm); + line-height: var(--line-height-normal); + color: var(--color-text-tertiary); +} +.mini-note-link { + margin-top: var(--spacing-1); + font-size: var(--font-size-sm); + font-weight: var(--font-weight-semibold); + color: var(--color-primary-strong); +} + +/* ============================== 近期活动 ============================== */ + +.activity-scroll { + white-space: nowrap; + margin-top: var(--spacing-2); +} +.activity-card { + display: inline-flex; + width: 275.00px; + margin-right: var(--spacing-2); + background: var(--color-bg-card); + border-radius: var(--radius-md); + overflow: hidden; + box-shadow: var(--shadow-card); + white-space: normal; +} +.activity-cover { + width: 105.00px; + height: 86.00px; + flex: none; +} +.activity-info { + flex: 1; + min-width: 0; + padding: var(--spacing-2); + display: flex; + flex-direction: column; +} +.activity-tag { + align-self: flex-start; + padding: 2.50px 7.00px; + border-radius: var(--radius-full); + background: var(--color-primary-light); + color: var(--color-primary-strong); + font-size: var(--font-size-xs); + font-weight: var(--font-weight-medium); +} +.activity-title { + margin-top: 5.00px; + font-size: var(--font-size-md); + font-weight: var(--font-weight-semibold); + line-height: var(--line-height-tight); + color: var(--color-text-strong); +} +.activity-meta { + margin-top: auto; + font-size: var(--font-size-xs); + color: var(--color-text-tertiary); +} + +/* ============================== 服务站 / 婚恋课堂 ============================== */ + +.station-card, +.article-row { + display: flex; + align-items: center; + background: var(--color-bg-card); + border-radius: var(--radius-lg); + overflow: hidden; + box-shadow: var(--shadow-card); +} +.station-cover { + width: 95.00px; + height: 86.00px; + flex: none; +} +.station-info { + flex: 1; + min-width: 0; + padding: var(--spacing-2); +} +.station-name { + display: block; + font-size: var(--font-size-md); + font-weight: var(--font-weight-semibold); + color: var(--color-text-strong); +} +.station-desc { + display: block; + margin: 4.00px 0 6.00px; + font-size: var(--font-size-sm); + color: var(--color-text-tertiary); +} +.mini-tag { + display: inline-block; + margin: 2.00px 4.00px 0 0; + padding: 2.00px 6.00px; + border-radius: var(--radius-sm); + background: var(--color-accent-purple-light); + color: var(--color-accent-purple-strong); + font-size: var(--font-size-xs); +} +.arrow-icon { + width: 14.00px; + height: 14.00px; + margin: var(--spacing-2); + flex: none; +} +.article-list { + margin-top: var(--spacing-2); + display: flex; + flex-direction: column; + gap: 6.00px; +} +.article-row { + min-height: 58.00px; +} +.article-cover { + width: 73.00px; + height: 58.00px; + flex: none; +} +.article-info { + flex: 1; + min-width: 0; + padding: var(--spacing-2); +} +.article-title { + display: block; + font-size: var(--font-size-md); + font-weight: var(--font-weight-semibold); + color: var(--color-text-strong); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.article-meta { + display: block; + margin-top: 3.00px; + font-size: var(--font-size-xs); + color: var(--color-text-tertiary); +} +.section-empty { + margin-top: var(--spacing-2); + padding: var(--spacing-4) var(--spacing-3); + text-align: center; + font-size: var(--font-size-sm); + color: var(--color-text-tertiary); + background: var(--color-bg-card); + border-radius: var(--radius-md); + box-shadow: var(--shadow-card); +} + +/* ============================== 安全提醒 ============================== + 2026-09-23:由「整行宽的大卡」改为 mini-rail(左 1/3 小卡 + 右文案),样式复用 + .mini-card / .mini-note,不再单独维护一套。历史记录: + 旧版这里写了 padding:0,把 .section 的左右内边距覆盖掉,于是这张卡比其它区块宽出 24.00px、 + 直接贴到屏幕边缘(已在本轮随整块重做一并移除)。 */ + +/* ============================== 按压反馈 ============================== + 全站约定:可点元素必须有即时反馈(旧版 --motion-* 全站只被引用 5 次)。 + 统一走 --ease-spring 的轻微回弹 + --press-scale,避免"点了没反应"。 */ + +.entry-item, +.status-action, +.empty-btn, +.brand-actions, +.mini-card, +.activity-card, +.station-card, +.article-row, +.mini-note-link, +.section-empty, +.banner-card { + transition: transform var(--motion-fast) var(--ease-spring), + opacity var(--motion-fast) var(--ease-standard); +} +.entry-item:active, +.status-action:active, +.empty-btn:active, +.brand-actions:active, +.mini-card:active, +.activity-card:active, +.station-card:active, +.article-row:active, +.mini-note-link:active, +.section-empty:active, +.banner-card:active { + transform: scale(var(--press-scale)); + opacity: var(--press-opacity); +} + +/* ============================== 小屏适配 ============================== + 旧版在这里写了 .empty-actions{display:none}:小于 340px 的机型上 + 「调整条件 / 公益红娘」两个入口会整块消失,属于功能级缺陷,已删除。 + 收紧的是尺寸,不是功能。 */ + +@media (max-width: 340px) { + .entry-label { + font-size: var(--font-size-xs); + } + /* 图标砖与副标题按同一比例收紧。副标题不再往下缩到 micro: + 340px 机型下单元格约 72px 宽,4 字副标题 12px 仍放得下,没必要牺牲可读性。 */ + .entry-icon { + width: 40.00px; + height: 40.00px; + background-size: 22.00px 22.00px, 100% 100%; + } + .banner-title { + font-size: var(--font-size-xl); + } + .status-checks { + overflow-x: auto; + } + .empty-btn { + min-width: 54.00px; + padding: 0 var(--spacing-1); + } +} /** * 丹阳公益婚恋服务平台 - 全局 Design Token * - * 依据《前端组件库与 Design Token 规范 V1.0》 - * 单位说明:rpx(375.00px = 屏幕宽度),规范 px 值按 2x 映射为 rpx - * 禁止页面层写死颜色/间距/圆角,必须引用 var(--token) + * v2(2026-09-22 设计系统夯实) + * --------------------------------------------------------------- + * 本次修订针对审计发现的系统性问题,逐条给出依据: + * + * 1) 品牌色不能承载文字 → 引入「基础色 / -strong」分级 + * #E96B6B on 白 = 3.10:1,白字 on #E96B6B = 3.10:1,on #FFF3F2 = 2.85:1, + * 三条路径都不满足正文 4.5:1。故: + * --color-primary 仅用于大色块、渐变、光晕、装饰(非文字) + * --color-primary-strong 用于文字、小图标、纯文字链接(5.33:1 ✓) + * --color-primary-solid 实心按钮底(白字 ≥4.5:1 ✓) + * 功能色(success/warning/danger/info)同此分级。 + * + * 2) 次要文字对比度过低 + * 旧 --color-text-tertiary(#777) = 4.48(on 白,勉强)/ #999 实测 2.85 却被用了 71 次。 + * 现将三级文字压到 #646C85 = 5.22:1,占位符保留浅色(占位符非正文)。 + * + * 3) 颜色碎片化 + * 审计前全站 182 种 hex、770 次硬编码(54 种灰、60 种蓝紫、40 种红橙)。 + * 本文件是唯一的颜色事实源;页面层禁止再写 hex,一律 var(--token)。 + * + * 4) 触摸目标 + * 组件库默认按钮只有 40px、小号 28px、"喜欢"按钮 31px。 + * 统一以 --tap-min(44.00px=44px) 为下限,--tap-gap 为最小间距。 + * + * 5) 动效几乎未落地(--motion-* 全站仅 5 次引用) + * 补充 --ease-spring 与 --press-scale,让点击有即时反馈。 + * + * 6) 夜间氛围层缺失(参考图有明显的光晕/星点,代码只有纯渐变) + * 新增 --mini-glow-* / --mini-star / --mini-glass / --mini-hairline。 + * + * 单位说明:rpx(375.00px = 屏幕宽度,0.50px ≈ 0.5px @375pt) + * 旧 token 名全部保留(88 个 wxss 共 909 处引用),只更新取值,避免大范围失效。 */ .wx-page { - /* ============ 品牌主色(规范 §3) ============ */ - --color-primary: #E96B6B; - --color-primary-active: #D95F5F; + /* ============ 品牌主色(分级:色块 / 文字 / 实心按钮) ============ */ + --color-primary: #E96B6B; /* 基础色:渐变、光晕、装饰、非文字图形 */ + --color-primary-strong: #B8434A; /* 文字与小图标(5.33:1 on 白,4.91:1 on 浅粉底) */ + --color-primary-solid: #C24C50; /* 实心按钮底(白字 4.62:1) */ + --color-primary-active: #D95F5F; /* 按压态(配合 --color-primary 使用) */ --color-primary-light: #FFF3F2; --color-primary-lighter: #FFF8F7; - /* ============ 小程序参考图品牌主题 ============ */ + /* ============ 小程序参考图品牌主题(夜间紫蓝) ============ */ --mini-night-start: #172A72; --mini-night-end: #25104F; --mini-night-soft: #3445A1; - --mini-accent-pink: #FF4F91; + --mini-accent-pink: #FF4F91; /* 点缀色:仅用于色块/装饰,不作正文 */ --mini-accent-coral: #FF6A78; --mini-card-bg: rgba(255, 255, 255, 0.98); --mini-text: #1F2744; --mini-muted: #7D839B; --mini-card-radius: 12.00px; - --mini-text-on-night: #FFFFFF; - --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); + --mini-text-on-night: #FFFFFF; /* on 深底 13.04:1 ✓ */ + --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); /* on 深底 ≈8:1 ✓ */ --mini-shadow: 0 8.00px 20.00px rgba(28, 30, 88, 0.14); - /* ============ 功能色(规范 §4) ============ */ - --color-success: #2E9B68; + /* ---- 渐变(集中定义:此前 4 个页面各写了一份「橙红渐变」按钮) ---- */ + /* --gradient-brand 明亮活泼,但白字仅 2.77:1 —— 只能用于无文字的装饰填充。 */ + --gradient-brand: linear-gradient(135deg, #FF6A78 0%, #E96B6B 100%); + /* 承载白字的 CTA 渐变:两端 #C24C50(4.73:1) / #B8434A(5.33:1) 均达标。 */ + --gradient-brand-solid: linear-gradient(135deg, #C24C50 0%, #B8434A 100%); + --gradient-night: linear-gradient(160deg, #172A72 0%, #25104F 100%); + --gradient-night-soft: linear-gradient(160deg, #3445A1 0%, #172A72 100%); + + /* ---- 首页 4×2 入口宫格图标渐变(参考图 2:高饱和圆角砖 + 白色描画图标) ---- + 白图标的对比度判据是**非文本图形 3:1**(WCAG 1.4.11)。渐变是斜向的、图标又跨在 + 两色之间,所以**较亮的一端也必须达标** —— 下表注释给的是 0% 处实算值,100% 更暗只会更高。 + 色相按业务语义固定(不随 tone 名漂移):找对象/婚前辅导=玫瑰粉系、公益红娘/服务站=暖橙系、 + 公益活动=紫罗兰、婚恋咨询=蓝、婚恋课堂=紫、婚恋反诈=绿。 */ + --gradient-entry-rose: linear-gradient(135deg, #F56287 0%, #F34671 100%); /* 3.01:1 / 3.54:1 */ + --gradient-entry-orange: linear-gradient(135deg, #F66A06 0%, #D95E06 100%); /* 3.01:1 / 3.78:1 */ + --gradient-entry-violet: linear-gradient(135deg, #A380F5 0%, #8F64F2 100%); /* 3.02:1 / 3.98:1 */ + --gradient-entry-blue: linear-gradient(135deg, #5195F6 0%, #3484F4 100%); /* 3.01:1 / 3.65:1 */ + --gradient-entry-purple: linear-gradient(135deg, #B27BF0 0%, #A260ED 100%); /* 3.01:1 / 3.87:1 */ + --gradient-entry-pink: linear-gradient(135deg, #F2619E 0%, #F0458C 100%); /* 3.01:1 / 3.54:1 */ + --gradient-entry-green: linear-gradient(135deg, #18A979 0%, #148F66 100%); /* 3.00:1 / 4.08:1 */ + --gradient-entry-amber: linear-gradient(135deg, #E9740C 0%, #CC650B 100%); /* 3.01:1 / 3.86:1 */ + /* 图标砖落影:比 --mini-shadow 更小,避免 4 列宫格里相邻砖块的投影互相压边 */ + --mini-entry-shadow: 0 4.00px 9.00px rgba(28, 30, 88, 0.18); + + /* ---- 夜间氛围层(v2 新增;参考图有光晕与星点,此前完全没有) ---- */ + --mini-glow-coral: rgba(255, 79, 145, 0.40); + --mini-glow-indigo: rgba(94, 124, 255, 0.32); + --mini-glow-soft: rgba(255, 255, 255, 0.10); + --mini-star: rgba(255, 255, 255, 0.70); + --mini-glass: rgba(255, 255, 255, 0.10); /* 深底玻璃面 */ + --mini-glass-strong: rgba(255, 255, 255, 0.16); + --mini-hairline: rgba(255, 255, 255, 0.16); /* 深底分隔线 */ + --mini-glass-success: rgba(90, 226, 184, 0.16); /* 深底上的成功态玻璃面 */ + + /* 星点层:多个小径向渐变叠在夜空渐变之上。用 radial-gradient 而非图片, + 避免额外请求,也便于随主题换色(index 页脚注:装饰层不承载信息)。 */ + --mini-starfield: + radial-gradient(circle at 12% 18%, var(--mini-star) 0, transparent 1.25px), + radial-gradient(circle at 31% 66%, var(--mini-star) 0, transparent 1.00px), + radial-gradient(circle at 57% 12%, var(--mini-star) 0, transparent 1.00px), + radial-gradient(circle at 79% 52%, var(--mini-star) 0, transparent 1.50px), + radial-gradient(circle at 93% 84%, var(--mini-star) 0, transparent 1.00px); + + /* 横幅压暗层:保证任何底图上的白色标题都有足够对比度 */ + --mini-banner-scrim: linear-gradient(90deg, rgba(23, 42, 114, 0.84) 0%, rgba(37, 16, 79, 0.40) 56%, rgba(255, 79, 145, 0.12) 100%); + + /* ============ 功能色(同样分级) ============ */ + --color-success: #2E9B68; /* 色块/图标 */ + --color-success-strong: #17805A; /* 文字(4.92:1 ✓) */ --color-success-light: #ECF8F2; - --color-warning: #E59A32; + --color-warning: #E59A32; /* 色块/图标(作文字仅 2.33:1) */ + --color-warning-strong: #9C5F14; /* 文字(5.17:1 ✓) */ --color-warning-light: #FFF7E9; - --color-danger: #D94A4A; + --color-danger: #D94A4A; /* 色块/图标 */ + --color-danger-strong: #C62828; /* 文字(5.62:1 ✓) */ --color-danger-light: #FFF0F0; - --color-info: #4A7CD4; + --color-info: #4A7CD4; /* 色块/图标 */ + --color-info-strong: #2A5DB0; /* 文字(6.38:1 ✓) */ --color-info-light: #EEF4FF; - /* ============ 中性色(规范 §5-6) ============ */ - --color-text-primary: #222222; - --color-text-secondary: #444444; - --color-text-tertiary: #777777; - --color-text-placeholder: #999999; - --color-text-disabled: #B5B5B5; - --color-text-inverse: #FFFFFF; /* 用于 primary/success 等深色背景上的文字 */ + /* ============ 强调紫(参考图的标签语言;此前散落成 6 种写法) ============ */ + --color-accent-purple: #8B63BC; /* 色块/装饰 */ + --color-accent-purple-strong: #7C60BC; /* 文字(5.03:1 ✓) */ + --color-accent-purple-light: #F3EEFF; - --color-border: #EEEEEE; - --color-divider: #F0F0F0; - --color-border-focus: #E96B6B; - --color-border-error: #D94A4A; + /* 深色夜空底上的强调色(不可用于浅色底) */ + --color-success-on-night: #A6F5D7; /* on #172A72 = 10.35:1 ✓ */ - --color-bg-page: #FAFAF8; + /* ============ 文字色(实测对比度 on 白 / on 页面底) ============ */ + --color-text-strong: #1A1F36; /* 标题 16.24 / 14.90 ✓ */ + --color-text-primary: #2A3050; /* 正文 12.83 / 11.77 ✓ */ + --color-text-secondary: #4A5169; /* 次要正文 7.86 / 7.21 ✓ */ + --color-text-tertiary: #646C85; /* 说明文字 5.22 / 4.79 ✓(旧 #777 为 4.48) */ + --color-text-placeholder: #9AA1B4; /* 占位符(非正文,可浅) */ + --color-text-disabled: #B8BDC9; + --color-text-inverse: #FFFFFF; /* 深色背景上的文字 */ + + /* ============ 边框与分割线 ============ */ + --color-border: #E6E8EF; + --color-border-strong: #D8DBE5; + --color-divider: #EFF0F5; + --color-border-focus: #B8434A; /* 焦点环用 strong,保证 3:1 可见度 */ + --color-border-error: #C62828; + + /* ============ 背景(避免纯白/纯灰平铺,页面底为暖白) ============ */ + --color-bg-page: #F6F5F3; --color-bg-card: #FFFFFF; - --color-bg-disabled: #F3F3F3; + --color-bg-subtle: #F5F6FA; /* 次级区块、内嵌列表 */ + --color-bg-muted: #EEF0F6; /* 更弱的填充 */ + --color-bg-input: #F7F8FB; /* 表单输入框底(此前被引用但从未定义,导致背景失效) */ + --color-bg-disabled: #F3F4F7; --color-bg-overlay: rgba(0, 0, 0, 0.45); - /* ============ 字体(规范 §7-11) ============ */ + /* ============ 字体 ============ */ + /* 小程序无法可靠加载 Web Font(wx.loadFontFace 依赖 HTTPS 白名单且有闪动风险), + 故使用中文系统字栈:iOS 走苹方、Android 走思源/系统黑体。 + 排版辨识度靠字号阶梯与字重建立,而非依赖字体本身。 */ --font-family-cn: -apple-system, "PingFang SC", "Noto Sans SC", "Hiragino Sans GB", "Microsoft YaHei", system-ui, sans-serif; + --font-family-number: "SF Pro Display", -apple-system, "DIN Alternate", "PingFang SC", sans-serif; - --font-size-xs: 12.00px; /* 12px */ - --font-size-sm: 13.00px; /* 13px */ - --font-size-md: 14.00px; /* 14px */ - --font-size-base: 16.00px; /* 16px */ - --font-size-lg: 18.00px; /* 18px */ - --font-size-xl: 20.00px; /* 20px */ - --font-size-2xl: 24.00px; /* 24px */ - --font-size-3xl: 28.00px; /* 28px */ + /* 字号阶梯 —— 正文 16.00px(16px) 起,元信息下限 12.00px(12px) */ + --font-size-micro: 11.00px; /* 11px 仅角标/装饰,禁用于正文 */ + --font-size-xs: 12.00px; /* 12px 元信息下限 */ + --font-size-sm: 13.00px; /* 13px 次要说明 */ + --font-size-md: 14.00px; /* 14px 次要正文 */ + --font-size-base: 16.00px; /* 16px 正文 */ + --font-size-lg: 18.00px; /* 18px 小标题 */ + --font-size-xl: 20.00px; /* 20px 区块标题 */ + --font-size-2xl: 24.00px; /* 24px 页面标题 */ + --font-size-3xl: 28.00px; /* 28px 大标题 */ + --font-size-display: 32.00px; /* 32px Hero */ + /* 字重:只用 4 档。禁止 550/650/750 等非百位值 —— Android 无对应字重会回退, + 导致同一设计在不同机型上粗细不一致(审计发现 30 处)。 */ --font-weight-regular: 400; --font-weight-medium: 500; --font-weight-semibold: 600; @@ -609,51 +1635,68 @@ --line-height-tight: 1.25; --line-height-normal: 1.5; - --line-height-relaxed: 1.7; + --line-height-relaxed: 1.65; - /* ============ 间距(规范 §12,4px 栅格) ============ */ - --spacing-1: 4.00px; /* 4px */ - --spacing-2: 8.00px; /* 8px */ - --spacing-3: 12.00px; /* 12px */ - --spacing-4: 16.00px; /* 16px */ - --spacing-5: 20.00px; /* 20px */ - --spacing-6: 24.00px; /* 24px */ - --spacing-8: 32.00px; /* 32px */ - --spacing-10: 40.00px; /* 40px */ - --spacing-12: 48.00px; /* 48px */ + --letter-spacing-tight: 0; + --letter-spacing-wide: 0.50px; + --letter-spacing-wider: 1.00px; - --spacing-page-x: 16.00px; /* 页面左右 16px */ - --spacing-section: 24.00px; /* 区块间 24px */ - --spacing-card-inner: 16.00px; /* 卡片内部 16px */ - --spacing-tight: 8.00px; /* 紧密 8px */ + /* ============ 间距(4px 栅格) ============ */ + --spacing-1: 4.00px; + --spacing-2: 8.00px; + --spacing-3: 12.00px; + --spacing-4: 16.00px; + --spacing-5: 20.00px; + --spacing-6: 24.00px; + --spacing-8: 32.00px; + --spacing-10: 40.00px; + --spacing-12: 48.00px; - /* ============ 圆角(规范 §14) ============ */ - --radius-sm: 8.00px; /* 8px */ - --radius-md: 12.00px; /* 12px */ - --radius-lg: 16.00px; /* 16px */ - --radius-xl: 20.00px; /* 20px */ + --spacing-page-x: 16.00px; + --spacing-section: 24.00px; + --spacing-card-inner: 16.00px; + --spacing-tight: 8.00px; + + /* ============ 圆角 ============ */ + --radius-sm: 8.00px; + --radius-md: 12.00px; + --radius-lg: 16.00px; + --radius-xl: 20.00px; + --radius-2xl: 24.00px; --radius-full: 4999.50px; - /* ============ 阴影(规范 §15,极轻) ============ */ - --shadow-card: 0 4.00px 16.00px rgba(0, 0, 0, 0.04); + /* ============ 阴影(统一为一套,此前 30+ 种近似值) ============ */ + --shadow-card: 0 4.00px 14.00px rgba(35, 35, 95, 0.07); + --shadow-raised: 0 6.00px 18.00px rgba(35, 35, 95, 0.10); --shadow-popup: 0 8.00px 32.00px rgba(0, 0, 0, 0.10); + --shadow-night: 0 8.00px 20.00px rgba(28, 30, 88, 0.18); - /* ============ 边框(规范 §16) ============ */ + /* ============ 边框宽度 ============ */ --border-width: 0.50px; + --border-width-strong: 1.00px; - /* ============ 动效(规范 §17) ============ */ + /* ============ 触摸目标(无障碍下限 44×44px) ============ */ + --tap-min: 44.00px; /* 44px 最小可点区域 */ + --tap-comfortable: 48.00px; /* 48px 舒适尺寸:主操作 */ + --tap-gap: 8.00px; /* 8px 相邻目标最小间距 */ + + /* ============ 动效 ============ */ --motion-fast: 120ms; --motion-normal: 200ms; --motion-slow: 300ms; - --ease-standard: ease-out; + --ease-standard: cubic-bezier(0.32, 0.72, 0, 1); + --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1); + --press-scale: 0.97; + --press-opacity: 0.88; - /* ============ 层级 z-index(规范 §90) ============ */ + /* ============ 层级 z-index ============ */ --z-base: 1; --z-sticky: 100; --z-tabbar: 200; --z-dropdown: 500; --z-modal: 1000; --z-toast: 2000; + --z-ambient: 0; /* ============ 页面基础样式 ============ */ background-color: var(--color-bg-page); @@ -663,7 +1706,10 @@ line-height: var(--line-height-normal); } -/* ============ 通用工具类 ============ */ +/* ========================================================================== + 通用工具类 + ========================================================================== */ + .container { padding: var(--spacing-page-x); } @@ -677,17 +1723,34 @@ .flex-shrink-0 { flex-shrink: 0; } .wrap { flex-wrap: wrap; } +/* 4 列宫格:用 flex + 百分比宽度实现。 + 注:display:grid 在 WebView 渲染下可用,但 Skyline 不支持,故统一改为 flex 以免疫渲染引擎迁移。*/ +.grid-4 { + display: flex; + flex-wrap: wrap; +} +.grid-4 > .grid-item { + width: 25%; + box-sizing: border-box; +} + +.text-strong { color: var(--color-text-strong); } .text-primary { color: var(--color-text-primary); } .text-secondary { color: var(--color-text-secondary); } .text-tertiary { color: var(--color-text-tertiary); } .text-placeholder { color: var(--color-text-placeholder); } .text-white { color: var(--color-text-inverse); } -.text-brand { color: var(--color-primary); } -.text-success { color: var(--color-success); } -.text-warning { color: var(--color-warning); } -.text-danger { color: var(--color-danger); } -.text-info { color: var(--color-info); } +.text-brand { color: var(--color-primary-strong); } +/* 品牌色作文字只能用 -strong 变体:基础色 #E96B6B 在白底仅 3.10:1。 + 保留 .text-brand-soft 这个类名是为了不破坏既有引用,取值已统一到 -strong, + 如需「更亮的品牌色」请用于背景/图形而非文字。 */ +.text-brand-soft { color: var(--color-primary-strong); } +.text-success { color: var(--color-success-strong); } +.text-warning { color: var(--color-warning-strong); } +.text-danger { color: var(--color-danger-strong); } +.text-info { color: var(--color-info-strong); } +.font-micro { font-size: var(--font-size-micro); } .font-xs { font-size: var(--font-size-xs); } .font-sm { font-size: var(--font-size-sm); } .font-md { font-size: var(--font-size-md); } @@ -696,6 +1759,7 @@ .font-xl { font-size: var(--font-size-xl); } .font-2xl { font-size: var(--font-size-2xl); } .font-3xl { font-size: var(--font-size-3xl); } +.font-display { font-size: var(--font-size-display); } .font-regular { font-weight: var(--font-weight-regular); } .font-medium { font-weight: var(--font-weight-medium); } @@ -733,7 +1797,7 @@ padding-bottom: 0px; } -/* 页面卡片基础样式(中低密度留白) */ +/* 页面卡片基础样式 */ .card-base { background: var(--color-bg-card); border-radius: var(--radius-lg); @@ -747,481 +1811,643 @@ background: var(--color-divider); } -.wx-page{background:var(--color-bg-page)}.service-page{min-height:100vh;padding-bottom:calc(70.00px + 0px)}.hero{padding:22.00px 16.00px 27.00px;background:linear-gradient(140deg,var(--color-primary-lighter),#FFF8EE);position:relative;overflow:hidden}.eyebrow{display:inline-flex;padding:3.50px 7.00px;border-radius:499.50px;background:rgba(255,255,255,.72);color:var(--color-primary);font-size:10.50px}.hero-title{display:block;margin-top:9.00px;font-size:20.00px;font-weight:700;line-height:1.35}.hero-desc{display:block;width:82%;margin-top:7.00px;font-size:12.50px;color:var(--color-text-secondary);line-height:1.7}.content{padding:0 var(--spacing-page-x)}.block{margin-top:var(--spacing-section)}.block-title{display:block;font-size:15.50px;font-weight:650}.block-subtitle{display:block;margin-top:4.00px;font-size:11.50px;color:var(--color-text-tertiary)}.card{margin-top:9.00px;padding:14.00px;background:var(--color-bg-card);border:0.50px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.feature-row,.menu-row,.record-row{display:flex;align-items:center;gap:10.00px;min-height:56.00px;padding:9.00px 0;border-bottom:0.50px solid var(--color-divider)}.feature-row:last-child,.menu-row:last-child,.record-row:last-child{border-bottom:0}.feature-icon{width:36.00px;height:36.00px;display:flex;align-items:center;justify-content:center;flex:none;border-radius:11.00px;background:var(--color-primary-light);color:var(--color-primary);font-weight:700}.feature-copy{flex:1;min-width:0}.feature-title{display:block;font-size:14.00px;font-weight:600}.feature-desc,.meta{display:block;margin-top:3.50px;font-size:11.50px;color:var(--color-text-tertiary);line-height:1.55}.arrow{font-size:20.00px;color:var(--color-text-disabled)}.tag{display:inline-flex;margin-right:5.00px;margin-top:5.00px;padding:3.00px 6.50px;border-radius:499.50px;background:var(--color-success-light);color:var(--color-success);font-size:10.00px}.tag.warning{background:var(--color-warning-light);color:var(--color-warning)}.primary-btn,.secondary-btn{height:44.00px;display:flex;align-items:center;justify-content:center;border-radius:22.00px;font-size:14.00px;font-weight:600}.primary-btn{background:linear-gradient(135deg,var(--mini-accent-coral),var(--mini-accent-pink));color:var(--color-text-inverse);box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)}.primary-btn.disabled{background:#E6E8EF;color:#989DAF;box-shadow:none}.secondary-btn{background:var(--color-primary-light);color:var(--color-primary)}.fixed-action{position:fixed;left:0;right:0;bottom:0;padding:9.00px var(--spacing-page-x) calc(9.00px + 0px);background:rgba(255,255,255,.96);border-top:0.50px solid var(--color-divider);z-index:100}.field{margin-top:13.00px}.label{display:block;margin-bottom:6.00px;font-size:12.50px;font-weight:600}.input,.select-box,.textarea{width:100%;box-sizing:border-box;background:#FCFAF8;border:0.50px solid var(--color-border);border-radius:var(--radius-md);font-size:13.00px}.input,.select-box{height:44.00px;padding:0 12.00px;display:flex;align-items:center}.textarea{min-height:90.00px;padding:11.00px}.notice{margin-top:10.00px;padding:11.00px;border-radius:var(--radius-md);background:#F3F7FC;color:var(--color-text-secondary);font-size:11.50px;line-height:1.65}.empty-panel{text-align:center;padding:35.00px 15.00px}.empty-symbol{width:48.00px;height:48.00px;margin:auto;display:flex;align-items:center;justify-content:center;border-radius:15.00px;background:var(--color-primary-light);color:var(--color-primary);font-size:18.00px;font-weight:700}.empty-title{display:block;margin-top:11.00px;font-size:15.00px;font-weight:600}.article-card{margin-top:9.00px;background:var(--color-bg-card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.article-cover{height:110.00px;padding:12.00px;background:linear-gradient(135deg,#F5E5DE,#F9F1E8);display:flex;align-items:flex-end}.article-cover text{font-size:21.00px;color:rgba(125,76,63,.52);font-weight:700}.article-body{padding:12.00px}.article-title{display:block;font-size:14.50px;font-weight:650;line-height:1.45}.article-meta{display:block;margin-top:5.00px;font-size:11.00px;color:var(--color-text-tertiary)}.article-content{padding:16.00px;background:var(--color-bg-card);font-size:14.00px;line-height:1.9;color:var(--color-text-secondary)}.article-content .lead{display:block;font-size:15.50px;color:var(--color-text-primary);font-weight:600;margin-bottom:12.00px}.danger-card{background:#FFF8F4;border-color:#F5DED2}.danger-card .feature-icon{background:#FFF0EA;color:#C85D43}@media(max-width:340px){.hero-title{font-size:18.00px}.hero-desc{width:92%}} +/* ========================================================================== + 可访问性:只用 token,不用工具类(2026-09-23 修订) + -------------------------------------------------------------------------- + v2 曾在此处新增 .tap-min / .tap-gap / .focusable / .pressable 四个工具类。 + 复检发现全部零引用(等价能力已各自写在组件样式内,例如 button/index.wxss + 直接使用 min-height:var(--tap-min)),且存在两个硬问题: -.service-shell{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:#F4F5FA}.service-content{padding:4.00px 12.00px 18.00px}.service-status{display:flex;align-items:center;justify-content:space-between;margin-top:12.00px;padding:10.00px 12.00px;border-radius:11.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-status__label{color:#7B8198;font-size:10.50px}.service-status__value{padding:3.00px 7.00px;border-radius:9.00px;background:#EAF8F2;color:#329472;font-size:9.50px;font-weight:650}.service-status__value.disabled{background:#FFF0F0;color:#D45A60}.service-topics{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.service-topic{min-height:74.00px;padding:10.00px;border-radius:12.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-topic__icon{display:flex;align-items:center;justify-content:center;width:27.00px;height:27.00px;border-radius:8.50px;background:#FFF0F5}.service-topic__icon image{width:17.00px;height:17.00px}.service-topic__title{display:block;margin-top:6.50px;color:#283056;font-size:12.00px;font-weight:650}.service-topic__desc{display:block;margin-top:3.00px;color:#858A9E;font-size:9.50px;line-height:1.45}.service-actions{display:flex;gap:7.00px}.service-actions .secondary-btn{width:95.00px;flex:none}.service-actions .primary-btn{flex:1}.privacy-note{display:flex;align-items:flex-start;gap:7.00px;margin-top:11.00px;padding:10.00px;border-radius:11.00px;background:#F1F4FF;color:#69718E;font-size:10.00px;line-height:1.55}.privacy-note image{width:17.00px;height:17.00px;flex:none} + 1) `.tap-gap > * + *` 用了通配符与兄弟选择器 —— WXSS 不支持, + wcc 编译期直接报 `error at token '*'`,导致整个小程序编译失败。 + (这是编译错误,不是静默失效,代价最高。) + 2) `.pressable:active` / `.focusable:focus-visible` 的伪类在 view 上 + 不生效(小程序须用 hover-class),属于"写了等于没写"。 + + 故整块移除,保留 token。需要热区/间距时直接引用 token: + min-height: var(--tap-min); → 44.00px = 44px,最小可点区域 + gap: var(--tap-gap); → 8.00px = 8px,相邻目标间距(flex gap) + 【WXSS 禁用清单】星号通配符、兄弟选择器、属性选择器。 + 【注释约束】WXSS 注释**不可嵌套**:内层注释的结束标记会提前终止外层注释, + 其后的文字会被当成真实样式解析,导致编译失败或样式被污染。 + (2026-09-23 实证:本块注释初版即踩此坑。) + ========================================================================== */ + +.wx-page{background:var(--color-bg-page)}.service-page{min-height:100vh;padding-bottom:calc(70.00px + 0px)}.hero{padding:22.00px 16.00px 27.00px;background:linear-gradient(140deg,var(--color-primary-lighter),var(--color-warning-light));position:relative;overflow:hidden}.eyebrow{display:inline-flex;padding:3.50px 7.00px;border-radius:499.50px;background:rgba(255,255,255,.72);color:var(--color-primary-strong);font-size:12.00px}.hero-title{display:block;margin-top:9.00px;font-size:20.00px;font-weight:700;line-height:1.35}.hero-desc{display:block;width:82%;margin-top:7.00px;font-size:12.50px;color:var(--color-text-secondary);line-height:1.7}.content{padding:0 var(--spacing-page-x)}.block{margin-top:var(--spacing-section)}.block-title{display:block;font-size:15.50px;font-weight:600}.block-subtitle{display:block;margin-top:4.00px;font-size:12.00px;color:var(--color-text-tertiary)}.card{margin-top:9.00px;padding:14.00px;background:var(--color-bg-card);border:0.50px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.feature-row,.menu-row,.record-row{display:flex;align-items:center;gap:10.00px;min-height:56.00px;padding:9.00px 0;border-bottom:0.50px solid var(--color-divider)}.feature-row:last-child,.menu-row:last-child,.record-row:last-child{border-bottom:0}.feature-icon{width:36.00px;height:36.00px;display:flex;align-items:center;justify-content:center;flex:none;border-radius:11.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-weight:700}.feature-copy{flex:1;min-width:0}.feature-title{display:block;font-size:14.00px;font-weight:600}.feature-desc,.meta{display:block;margin-top:3.50px;font-size:12.00px;color:var(--color-text-tertiary);line-height:1.55}.arrow{font-size:20.00px;color:var(--color-text-disabled)}.tag{display:inline-flex;margin-right:5.00px;margin-top:5.00px;padding:3.00px 6.50px;border-radius:499.50px;background:var(--color-success-light);color:var(--color-success-strong);font-size:12.00px}.tag.warning{background:var(--color-warning-light);color:var(--color-warning-strong)}.primary-btn,.secondary-btn{height:44.00px;display:flex;align-items:center;justify-content:center;border-radius:22.00px;font-size:14.00px;font-weight:600}.primary-btn{background:var(--gradient-brand-solid);color:var(--color-text-inverse);box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)}.primary-btn.disabled{background:var(--color-bg-muted);color:var(--color-text-tertiary);box-shadow:none}.secondary-btn{background:var(--color-primary-light);color:var(--color-primary-strong)}.fixed-action{position:fixed;left:0;right:0;bottom:0;padding:9.00px var(--spacing-page-x) calc(9.00px + 0px);background:rgba(255,255,255,.96);border-top:0.50px solid var(--color-divider);z-index:100}.field{margin-top:13.00px}.label{display:block;margin-bottom:6.00px;font-size:12.50px;font-weight:600}.input,.select-box,.textarea{width:100%;box-sizing:border-box;background:var(--color-bg-page);border:0.50px solid var(--color-border);border-radius:var(--radius-md);font-size:13.00px}.input,.select-box{height:44.00px;padding:0 12.00px;display:flex;align-items:center}.textarea{min-height:90.00px;padding:11.00px}.notice{margin-top:10.00px;padding:11.00px;border-radius:var(--radius-md);background:var(--color-info-light);color:var(--color-text-secondary);font-size:12.00px;line-height:1.65}.select-box.is-readonly{background:var(--color-bg-subtle);color:var(--color-text-secondary)}.empty-panel{text-align:center;padding:35.00px 15.00px}.empty-symbol{width:48.00px;height:48.00px;margin:auto;display:flex;align-items:center;justify-content:center;border-radius:15.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-size:18.00px;font-weight:700}.empty-title{display:block;margin-top:11.00px;font-size:15.00px;font-weight:600}.article-card{margin-top:9.00px;background:var(--color-bg-card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.article-cover{height:110.00px;padding:12.00px;background:linear-gradient(135deg,var(--color-warning-light),var(--color-warning-light));display:flex;align-items:flex-end}.article-cover text{font-size:21.00px;color:rgba(125,76,63,.52);font-weight:700}.article-body{padding:12.00px}.article-title{display:block;font-size:14.50px;font-weight:600;line-height:1.45}.article-meta{display:block;margin-top:5.00px;font-size:12.00px;color:var(--color-text-tertiary)}.article-content{padding:16.00px;background:var(--color-bg-card);font-size:14.00px;line-height:1.9;color:var(--color-text-secondary)}.article-content .lead{display:block;font-size:15.50px;color:var(--color-text-primary);font-weight:600;margin-bottom:12.00px}.danger-card{background:var(--color-primary-lighter);border-color:var(--color-primary-light)}.danger-card .feature-icon{background:var(--color-warning-light);color:var(--color-warning-strong)}@media(max-width:340px){.hero-title{font-size:18.00px}.hero-desc{width:92%}} + +.service-shell{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:var(--color-bg-page)}.service-content{padding:4.00px 12.00px 18.00px}.service-status{display:flex;align-items:center;justify-content:space-between;margin-top:12.00px;padding:10.00px 12.00px;border-radius:11.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-status__label{color:var(--color-text-tertiary);font-size:12.00px}.service-status__value{padding:3.00px 7.00px;border-radius:9.00px;background:var(--color-success-light);color:var(--color-success-strong);font-size:12.00px;font-weight:600}.service-status__value.disabled{background:var(--color-danger-light);color:var(--color-danger-strong)}.service-topics{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.service-topic{min-height:74.00px;padding:10.00px;border-radius:12.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-topic__icon{display:flex;align-items:center;justify-content:center;width:27.00px;height:27.00px;border-radius:8.50px;background:var(--color-primary-light)}.service-topic__icon image{width:17.00px;height:17.00px}.service-topic__title{display:block;margin-top:6.50px;color:var(--color-text-strong);font-size:12.00px;font-weight:600}.service-topic__desc{display:block;margin-top:3.00px;color:var(--color-text-tertiary);font-size:12.00px;line-height:1.45}.service-actions{display:flex;gap:7.00px}.service-actions .secondary-btn{width:95.00px;flex:none}.service-actions .primary-btn{flex:1}.privacy-note{display:flex;align-items:flex-start;gap:7.00px;margin-top:11.00px;padding:10.00px;border-radius:11.00px;background:var(--color-info-light);color:var(--color-text-tertiary);font-size:12.00px;line-height:1.55}.privacy-note image{width:17.00px;height:17.00px;flex:none} /* ==== miniapp/components/user-card ==== */ .ui-user-card { - display: flex; - align-items: center; - background: var(--color-bg-card); - min-height: 74.00px; - padding: 7.00px 9.00px; - border-bottom: 0.50px solid #F0F1F6; + display:flex; + align-items:center; + background:var(--color-bg-card); + min-height:74.00px; + padding:7.00px 9.00px; + border-bottom:0.50px solid var(--color-divider); } .ui-user-card__select { - margin-right: var(--spacing-3); + margin-right:var(--spacing-3); } .ui-user-card__checkbox { - transform: scale(.82); + transform:scale(.82); } .ui-user-card__body { - flex: 1; - min-width: 0; - margin-left: 8.00px; + flex:1; + min-width:0; + margin-left:8.00px; } .ui-user-card__name-row { - display: flex; - align-items: baseline; - margin-bottom: var(--spacing-1); + display:flex; + align-items:baseline; + margin-bottom:var(--spacing-1); } .ui-user-card__name { - font-size: 13.00px; - font-weight: 700; - color: #222746; - margin-right: var(--spacing-2); + font-size:13.00px; + font-weight:700; + color:var(--color-text-strong); + margin-right:var(--spacing-2); } .ui-user-card__age { - font-size: 10.50px; - color: #596079; + font-size:12.00px; + color:var(--color-text-secondary); } .ui-user-card__online { - margin-left: auto; - color: #39A987; - font-size: 9.00px; + margin-left:auto; + color:var(--color-success-strong); + font-size:12.00px; } .ui-user-card__meta { - font-size: 10.00px; - color: #767C94; - line-height: 1.4; - margin-top: 2.00px; + font-size:12.00px; + color:var(--color-text-tertiary); + line-height:1.4; + margin-top:2.00px; } .ui-user-card__actions { - flex-shrink: 0; - margin-left: var(--spacing-2); + flex-shrink:0; + margin-left:var(--spacing-2); } -.ui-user-card__tags{display:flex;gap:3.50px;margin-top:4.00px;overflow:hidden}.ui-user-card__tag{flex:none;padding:2.00px 4.50px;border-radius:6.00px;background:#F3EEFF;color:#7860AE;font-size:8.50px;white-space:nowrap} +.ui-user-card__tags{display:flex;gap:3.50px;margin-top:4.00px;overflow:hidden}.ui-user-card__tag{flex:none;padding:2.00px 4.50px;border-radius:6.00px;background:var(--color-accent-purple-light);color:var(--color-accent-purple-strong);font-size:12.00px;white-space:nowrap} /* ==== miniapp/components/button ==== */ /** * Button 组件样式 - * 引用全局 Design Token(addGlobalClass: true) + * 引用全局 Design Token(addGlobalClass:true) + * + * 2026-09-22 修复: + * 1) 触摸目标:md 只有 40.00px(40px)、sm 只有 28.00px(28px),低于 44px 下限; + * text 变体更是 min-height:auto,几乎点不中。现统一以 --tap-min 兜底。 + * 2) 对比度:主按钮背景原为 --color-primary(#E96B6B),白字仅 3.10:1。 + * 改用 --color-primary-solid(#C24C50) = 4.73:1,视觉上仍是暖红。 + * secondary/text 的红色文字同理从 3.10 提到 --color-primary-strong 的 5.33。 + * 3) 危险按钮 --color-danger(#D94A4A) 白字 4.18:1 不达标,改用 -strong 变体。 + * 4) 按压反馈统一走 --press-scale / --press-opacity,替代硬编码 0.98 / 0.85。 */ .ui-btn { - display: inline-flex; - align-items: center; - justify-content: center; - box-sizing: border-box; - border-radius: var(--radius-full); - font-family: var(--font-family-cn); - font-weight: var(--font-weight-medium); - text-align: center; - transition: opacity var(--motion-fast) var(--ease-standard), - transform var(--motion-fast) var(--ease-standard); - user-select: none; - line-height: 1; - white-space: nowrap; + display:inline-flex; + align-items:center; + justify-content:center; + box-sizing:border-box; + border-radius:var(--radius-full); + font-family:var(--font-family-cn); + font-weight:var(--font-weight-semibold); + text-align:center; + transition:transform var(--motion-fast) var(--ease-spring), + opacity var(--motion-fast) var(--ease-standard), + background-color var(--motion-fast) var(--ease-standard); + user-select:none; + line-height:1.2; + white-space:nowrap; } -/* 尺寸 */ +/* 尺寸:全部以 44×44px 为热区下限 */ .ui-btn--sm { - padding: 7.00px 12.00px; - font-size: var(--font-size-sm); - min-height: 28.00px; + padding:7.00px 14.00px; + font-size:var(--font-size-sm); + min-height:var(--tap-min); } .ui-btn--md { - padding: 10.00px 18.00px; - font-size: var(--font-size-base); - min-height: 40.00px; + padding:10.00px 18.00px; + font-size:var(--font-size-base); + min-height:var(--tap-min); } .ui-btn--lg { - padding: 13.00px 24.00px; - font-size: var(--font-size-lg); - min-height: 48.00px; + padding:13.00px 24.00px; + font-size:var(--font-size-lg); + min-height:var(--tap-comfortable); } /* 撑满 */ .ui-btn--block { - display: flex; - width: 100%; + display:flex; + width:100%; } /* 变体 */ .ui-btn--primary { - background: var(--color-primary); - color: #FFFFFF; + background:var(--color-primary-solid); + color:var(--color-text-inverse); } .ui-btn--secondary { - background: var(--color-bg-card); - color: var(--color-primary); - border: 0.50px solid var(--color-primary); + background:var(--color-bg-card); + color:var(--color-primary-strong); + border:var(--border-width) solid var(--color-primary-strong); } .ui-btn--ghost { - background: transparent; - color: var(--color-text-primary); - border: 0.50px solid var(--color-border); + background:transparent; + color:var(--color-text-primary); + border:var(--border-width) solid var(--color-border-strong); } .ui-btn--danger { - background: var(--color-danger); - color: #FFFFFF; + background:var(--color-danger-strong); + color:var(--color-text-inverse); } .ui-btn--text { - background: transparent; - color: var(--color-primary); - padding-left: 0; - padding-right: 0; - min-height: auto; + background:transparent; + color:var(--color-primary-strong); + padding-left:var(--spacing-2); + padding-right:var(--spacing-2); + /* 视觉是纯文字,但热区仍需 44px:多出的部分由 align-items:center 居中留白 */ + min-height:var(--tap-min); } /* 状态 */ .ui-btn--disabled, .ui-btn--loading { - opacity: 0.55; + opacity:0.55; } .ui-btn--disabled.ui-btn--primary, .ui-btn--disabled.ui-btn--danger { - background: var(--color-text-disabled); + background:var(--color-text-disabled); } .ui-btn--disabled.ui-btn--secondary, .ui-btn--disabled.ui-btn--ghost { - color: var(--color-text-disabled); - border-color: var(--color-text-disabled); + color:var(--color-text-disabled); + border-color:var(--color-text-disabled); } -.ui-btn--hover { - opacity: 0.85; - transform: scale(0.98); +/* 按压反馈(hover-class 与 CSS :active 双保险) */ +.ui-btn--hover, +.ui-btn:active { + opacity:var(--press-opacity); + transform:scale(var(--press-scale)); } /* Loading spinner */ .ui-btn__spinner { - width: 14.00px; - height: 14.00px; - margin-right: 6.00px; - display: flex; - align-items: center; - justify-content: center; + width:14.00px; + height:14.00px; + margin-right:6.00px; + display:flex; + align-items:center; + justify-content:center; } .ui-btn__spinner-dot { - width: 9.00px; - height: 9.00px; - border-radius: 50%; - border: 1.50px solid currentColor; - border-top-color: transparent; - animation: ui-btn-spin 0.7s linear infinite; + width:9.00px; + height:9.00px; + border-radius:50%; + border:1.50px solid currentColor; + border-top-color:transparent; + animation:ui-btn-spin 0.7s linear infinite; } @keyframes ui-btn-spin { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } + from { transform:rotate(0deg); } + to { transform:rotate(360deg); } } /* ==== miniapp/components/loading ==== */ .ui-loading--block { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: var(--spacing-8) var(--spacing-page-x); + display:flex; + flex-direction:column; + align-items:center; + justify-content:center; + padding:var(--spacing-8) var(--spacing-page-x); } .ui-loading--inline { - display: inline-flex; - align-items: center; + display:inline-flex; + align-items:center; } .ui-loading__spinner { - width: 30.00px; - height: 30.00px; - display: flex; - align-items: center; - justify-content: center; + width:30.00px; + height:30.00px; + display:flex; + align-items:center; + justify-content:center; } .ui-loading__spinner-icon { - width: 24.00px; - height: 24.00px; - animation: ui-loading-spin 0.8s linear infinite; + width:24.00px; + height:24.00px; + animation:ui-loading-spin 0.8s linear infinite; } @keyframes ui-loading-spin { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } + from { transform:rotate(0deg); } + to { transform:rotate(360deg); } } .ui-loading__text { - margin-top: var(--spacing-3); - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); + margin-top:var(--spacing-3); + font-size:var(--font-size-sm); + color:var(--color-text-tertiary); } /* Skeleton */ .ui-loading__skeleton { - width: 100%; + width:100%; } .ui-loading__skeleton-row { - display: flex; - align-items: center; - padding: var(--spacing-3) var(--spacing-page-x); - background: var(--color-bg-card); - border-bottom: 0.50px solid var(--color-divider); + display:flex; + align-items:center; + padding:var(--spacing-3) var(--spacing-page-x); + background:var(--color-bg-card); + border-bottom:0.50px solid var(--color-divider); } .ui-loading__skeleton-avatar { - width: 44.00px; - height: 44.00px; - border-radius: 50%; - background: var(--color-bg-disabled); - margin-right: var(--spacing-3); - flex-shrink: 0; + width:44.00px; + height:44.00px; + border-radius:50%; + background:var(--color-bg-disabled); + margin-right:var(--spacing-3); + flex-shrink:0; } .ui-loading__skeleton-content { - flex: 1; - min-width: 0; + flex:1; + min-width:0; } .ui-loading__skeleton-line { - height: 12.00px; - background: var(--color-bg-disabled); - border-radius: var(--radius-sm); - position: relative; - overflow: hidden; + height:12.00px; + background:var(--color-bg-disabled); + border-radius:var(--radius-sm); + position:relative; + overflow:hidden; } .ui-loading__skeleton-line--title { - width: 40%; - margin-bottom: var(--spacing-2); + width:40%; + margin-bottom:var(--spacing-2); } .ui-loading__skeleton-line--meta { - width: 70%; + width:70%; } /* shimmer */ .ui-loading__skeleton-line::after, .ui-loading__skeleton-avatar::after { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: linear-gradient( + content:''; + position:absolute; + top:0; + left:0; + width:100%; + height:100%; + background:linear-gradient( 90deg, transparent 0%, rgba(255, 255, 255, 0.55) 50%, transparent 100% ); - animation: ui-loading-shimmer 1.4s ease-in-out infinite; + animation:ui-loading-shimmer 1.4s ease-in-out infinite; } @keyframes ui-loading-shimmer { - 0% { transform: translateX(-100%); } - 100% { transform: translateX(100%); } + 0% { transform:translateX(-100%); } + 100% { transform:translateX(100%); } } /* ==== miniapp/components/empty ==== */ .ui-empty { - display: flex; - flex-direction: column; - align-items: center; - padding: var(--spacing-10) var(--spacing-page-x); - text-align: center; + display:flex; + flex-direction:column; + align-items:center; + padding:var(--spacing-10) var(--spacing-page-x); + text-align:center; } .ui-empty__illustration { - width: 80.00px; - height: 80.00px; - border-radius: 50%; - background: var(--color-bg-disabled); - display: flex; - align-items: center; - justify-content: center; - margin-bottom: var(--spacing-4); + width:80.00px; + height:80.00px; + border-radius:50%; + background:var(--color-bg-disabled); + display:flex; + align-items:center; + justify-content:center; + margin-bottom:var(--spacing-4); } .ui-empty__icon { - width: 36.00px; - height: 36.00px; - opacity: 0.72; + width:36.00px; + height:36.00px; + opacity:0.72; } .ui-empty__title { - font-size: var(--font-size-lg); - font-weight: var(--font-weight-medium); - color: var(--color-text-primary); - margin-bottom: var(--spacing-2); + font-size:var(--font-size-lg); + font-weight:var(--font-weight-medium); + color:var(--color-text-primary); + margin-bottom:var(--spacing-2); } .ui-empty__desc { - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); - line-height: var(--line-height-relaxed); - max-width: 240.00px; + font-size:var(--font-size-sm); + color:var(--color-text-tertiary); + line-height:var(--line-height-relaxed); + max-width:240.00px; } .ui-empty__actions { - display: flex; - flex-direction: column; - gap: var(--spacing-2); - margin-top: var(--spacing-6); - width: 100%; - max-width: 240.00px; + display:flex; + flex-direction:column; + gap:var(--spacing-2); + margin-top:var(--spacing-6); + width:100%; + max-width:240.00px; } .ui-empty__action { - display: flex; - align-items: center; - justify-content: center; - height: 40.00px; - border-radius: var(--radius-full); - font-size: var(--font-size-base); - font-weight: var(--font-weight-medium); -} + display:flex; + align-items:center; + justify-content:center; + min-height:var(--tap-min); + border-radius:var(--radius-full); + font-size:var(--font-size-base); + font-weight:var(--font-weight-medium); +min-width:var(--tap-min);} .ui-empty__action--primary { - background: var(--color-primary); - color: #FFFFFF; + background:var(--color-primary-solid); + color:var(--color-text-inverse); } .ui-empty__action--secondary { - background: var(--color-bg-card); - color: var(--color-primary); - border: 0.50px solid var(--color-primary); + background:var(--color-bg-card); + color:var(--color-primary-strong); + border:0.50px solid var(--color-primary); } /* ==== miniapp/components/section-header ==== */ +/** + * 区块标题(全站所有页面共用,是排版层级的关键一环) + * + * 2026-09-22 修订: + * 1) 层级拉开:标题 18.00px→20.00px(--font-size-xl),与正文 16.00px / 卡片标题 14.00px + * 形成「区块标题 > 卡片标题 > 正文 > 元信息」四级阶梯。 + * 旧值 18.00px 与卡片标题仅差 5.00px,层级读不出来。 + * 2) 右侧 action 是全站最容易被忽略的触摸目标:只有 13.00px 文字高(约 13px), + * 远低于 44px 下限。改为 min-height:--tap-min,热区向上补白。 + * 3) action 文字色原为 --color-primary(#E96B6B)=3.10:1,不达标,改 -strong。 + */ .ui-section { - display: flex; - align-items: center; - justify-content: space-between; - padding: var(--spacing-3) var(--spacing-page-x); + display:flex; + align-items:center; + justify-content:space-between; + padding:var(--spacing-2) var(--spacing-page-x); } .ui-section__left { - display: flex; - align-items: baseline; + display:flex; + align-items:baseline; + min-width:0; } .ui-section__title { - font-size: var(--font-size-lg); - font-weight: var(--font-weight-semibold); - color: var(--color-text-primary); + font-size:var(--font-size-xl); + font-weight:var(--font-weight-semibold); + color:var(--color-text-strong); + letter-spacing:var(--letter-spacing-tight); } .ui-section__subtitle { - margin-left: var(--spacing-2); - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); + margin-left:var(--spacing-2); + font-size:var(--font-size-xs); + color:var(--color-text-tertiary); } .ui-section__action { - display: flex; - align-items: center; - font-size: var(--font-size-sm); - color: var(--color-primary); + display:flex; + align-items:center; + flex:none; + min-height:var(--tap-min); + padding-left:var(--spacing-3); + font-size:var(--font-size-sm); + font-weight:var(--font-weight-medium); + color:var(--color-primary-strong); + transition:opacity var(--motion-fast) var(--ease-standard); +} +.ui-section__action:active { + opacity:var(--press-opacity); } .ui-section__arrow { - margin-left: 2.00px; - width: 12.00px; - height: 12.00px; + margin-left:2.00px; + width:12.00px; + height:12.00px; } -.page{min-height:100vh;background:#F4F5FA} -.discover-hero{padding:20px 12.00px 12.00px;background:linear-gradient(160deg,var(--mini-night-start),var(--mini-night-end));border-radius:0 0 17.00px 17.00px;box-shadow:var(--mini-shadow);position:relative;z-index:1} -.discover-nav{height:44.00px;display:flex;align-items:center;justify-content:center;position:relative;color:#fff} +.page{min-height:100vh;background:var(--color-bg-page)} +/* --nav-status / --nav-h / --nav-right 由 discover.ts 经 utils/nav-metrics 实测胶囊按钮后注入 */ +.discover-hero{padding:var(--nav-status, 44px) 12.00px 12.00px;background:linear-gradient(160deg,var(--mini-night-start),var(--mini-night-end));border-radius:0 0 17.00px 17.00px;box-shadow:var(--mini-shadow);position:relative;z-index:1} +.discover-nav{height:var(--nav-h, 40.00px);display:flex;align-items:center;justify-content:center;position:relative;color:var(--color-text-inverse)} .nav-title{font-size:15.50px;font-weight:700} -.nav-search{position:absolute;right:0;width:32.00px;height:32.00px;display:flex;align-items:center;justify-content:center;border:0.50px solid rgba(255,255,255,.18);border-radius:16.00px;background:rgba(255,255,255,.08)} +.nav-search{position:absolute;right:var(--nav-right, 102px);width:32.00px;height:32.00px;display:flex;align-items:center;justify-content:center;border:0.50px solid rgba(255,255,255,.18);border-radius:16.00px;background:rgba(255,255,255,.08)} .nav-search image{width:19.00px;height:19.00px;filter:brightness(0) invert(1)} .search-bar{display:flex;align-items:center} .search-input{height:35.00px;flex:1;display:flex;align-items:center;padding:0 10.00px;border-radius:17.50px;background:rgba(255,255,255,.12);border:0.50px solid rgba(255,255,255,.14)} -.search-label{margin-right:7.00px;padding-right:7.00px;border-right:0.50px solid rgba(255,255,255,.2);font-size:10.00px;color:#fff} -.search-field{flex:1;font-size:11.50px;color:#fff} -.search-placeholder{font-size:11.50px;color:rgba(255,255,255,.52)} +.search-label{margin-right:7.00px;padding-right:7.00px;border-right:0.50px solid rgba(255,255,255,.2);font-size:12.00px;color:var(--color-text-inverse)} +.search-field{flex:1;font-size:12.00px;color:var(--color-text-inverse)} +.search-placeholder{font-size:12.00px;color:rgba(255,255,255,.52)} .filter-scroll{margin-top:8.00px;white-space:nowrap} .filter-chips{display:inline-flex;gap:6.00px} -.filter-chip{padding:5.50px 10.00px;border-radius:12.50px;background:rgba(255,255,255,.1);color:rgba(255,255,255,.72);font-size:10.00px} -.filter-chip.active{background:#fff;color:var(--mini-accent-pink);font-weight:650} +.filter-chip{padding:5.50px 10.00px;border-radius:12.50px;background:rgba(255,255,255,.1);color:rgba(255,255,255,.72);font-size:12.00px} +.filter-chip.active{background:var(--color-bg-card);color:var(--color-primary-strong);font-weight:600} /* 遮罩层 + 底部抽屉样式 */ .filter-mask{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.35);z-index:10} -.filter-panel-wrap{position:fixed;left:0;right:0;bottom:0;z-index:11;background:#fff;border-radius:14.00px 14.00px 0 0;max-height:78vh;box-shadow:0 -5.00px 20.00px rgba(31,32,89,.15);display:flex;flex-direction:column;padding:12.00px 14.00px 14.00px} +.filter-panel-wrap{position:fixed;left:0;right:0;bottom:0;z-index:11;background:var(--color-bg-card);border-radius:14.00px 14.00px 0 0;max-height:78vh;box-shadow:0 -5.00px 20.00px rgba(31,32,89,.15);display:flex;flex-direction:column;padding:12.00px 14.00px 14.00px} .filter-scroll-wrap{flex:1;max-height:calc(78vh - 70.00px);padding:4.00px 0 0} .filter-section{margin-bottom:14.00px;padding:8.00px 10.00px;border-radius:8.00px;transition:background .2s,box-shadow .2s} -.filter-section.hl{background:#FFF5F8;box-shadow:inset 0 0 0 1.00px var(--mini-accent-pink)} +.filter-section.hl{background:var(--color-primary-light);box-shadow:inset 0 0 0 1.00px var(--mini-accent-pink)} .filter-heading{display:flex;justify-content:space-between} -.filter-label{display:block;font-size:12.00px;font-weight:650;color:#282D4E} -.filter-value{font-size:10.50px;color:#777E99} +.filter-label{display:block;font-size:12.00px;font-weight:600;color:var(--color-text-strong)} +.filter-value{font-size:12.00px;color:var(--color-text-tertiary)} .range-slider{margin:4.00px 0} .tag-group{display:flex;flex-wrap:wrap;gap:7.00px;margin-top:8.00px} -.tag{padding:5.00px 11.00px;border-radius:11.00px;background:#F1F2F7;color:#626981;font-size:10.50px} -.tag.selected{background:#FCEBF3;color:var(--mini-accent-pink)} +.tag{padding:5.00px 11.00px;border-radius:11.00px;background:var(--color-bg-subtle);color:var(--color-text-secondary);font-size:12.00px} +.tag.selected{background:var(--color-primary-light);color:var(--color-primary-strong)} .filter-actions{display:flex;gap:9.00px;margin-top:4.00px} .result-head{padding:15.00px 13.00px 8.00px;display:flex;align-items:flex-end;justify-content:space-between} .result-head>view{display:flex;flex-direction:column} -.result-title{font-size:15.00px;font-weight:700;color:#252A49} -.result-subtitle{margin-top:2.50px;font-size:10.00px;color:#8A8FA4} -.result-count{font-size:10.00px;color:#8A8FA4} -.user-list{margin:0 12.00px;padding:2.00px 0;background:#fff;border-radius:14.00px;overflow:hidden;box-shadow:0 5.00px 16.00px rgba(34,35,91,.08)} +.result-title{font-size:15.00px;font-weight:700;color:var(--color-text-strong)} +.result-subtitle{margin-top:2.50px;font-size:12.00px;color:var(--color-text-tertiary)} +.result-count{font-size:10.00px;color:var(--color-text-tertiary)} +.user-list{margin:0 12.00px;padding:2.00px 0;background:var(--color-bg-card);border-radius:14.00px;overflow:hidden;box-shadow:0 5.00px 16.00px rgba(34,35,91,.08)} .card-action{display:flex;align-items:center} -.like-button{width:31.00px;height:31.00px;display:flex;align-items:center;justify-content:center;border-radius:15.50px;background:#FFF0F5;box-shadow:0 3.00px 9.00px rgba(255,79,145,.16)} +.like-button{width:var(--tap-min);min-height:var(--tap-min);display:flex;align-items:center;justify-content:center;border-radius:var(--radius-full);background:var(--color-primary-light);box-shadow:0 3.00px 9.00px rgba(255,79,145,.16);} .like-button image{width:21.00px;height:21.00px} .like-button.loading{opacity:.45} -.list-end-hint{text-align:center;padding:12.00px;font-size:10.00px;color:#9A9EB0} -.discover-empty{margin:35.00px 20.00px 0;padding:17.00px;display:flex;flex-direction:column;align-items:center;background:#fff;border-radius:14.00px;box-shadow:0 5.00px 16.00px rgba(34,35,91,.08)} +.list-end-hint{text-align:center;padding:12.00px;font-size:12.00px;color:var(--color-text-tertiary)} +.discover-empty{margin:35.00px 20.00px 0;padding:17.00px;display:flex;flex-direction:column;align-items:center;background:var(--color-bg-card);border-radius:14.00px;box-shadow:0 5.00px 16.00px rgba(34,35,91,.08)} .discover-empty image{width:56.00px;height:56.00px} -.empty-title{margin-top:6.00px;font-size:14.00px;font-weight:650;color:#252A49} -.empty-desc{margin-top:5.00px;text-align:center;font-size:10.50px;line-height:1.55;color:#858A9E} -.empty-action{margin-top:12.00px;min-width:90.00px;height:32.00px;display:flex;align-items:center;justify-content:center;border-radius:16.00px;background:linear-gradient(135deg,var(--mini-accent-coral),var(--mini-accent-pink));color:#fff;font-size:11.50px;font-weight:650} +.empty-title{margin-top:6.00px;font-size:14.00px;font-weight:600;color:var(--color-text-strong)} +.empty-desc{margin-top:5.00px;text-align:center;font-size:12.00px;line-height:1.55;color:var(--color-text-tertiary)} +.empty-action{margin-top:12.00px;min-width:90.00px;min-height:var(--tap-min);display:flex;align-items:center;justify-content:center;border-radius:16.00px;background:var(--gradient-brand-solid);color:var(--color-text-inverse);font-size:12.00px;font-weight:600} /** * 丹阳公益婚恋服务平台 - 全局 Design Token * - * 依据《前端组件库与 Design Token 规范 V1.0》 - * 单位说明:rpx(375.00px = 屏幕宽度),规范 px 值按 2x 映射为 rpx - * 禁止页面层写死颜色/间距/圆角,必须引用 var(--token) + * v2(2026-09-22 设计系统夯实) + * --------------------------------------------------------------- + * 本次修订针对审计发现的系统性问题,逐条给出依据: + * + * 1) 品牌色不能承载文字 → 引入「基础色 / -strong」分级 + * #E96B6B on 白 = 3.10:1,白字 on #E96B6B = 3.10:1,on #FFF3F2 = 2.85:1, + * 三条路径都不满足正文 4.5:1。故: + * --color-primary 仅用于大色块、渐变、光晕、装饰(非文字) + * --color-primary-strong 用于文字、小图标、纯文字链接(5.33:1 ✓) + * --color-primary-solid 实心按钮底(白字 ≥4.5:1 ✓) + * 功能色(success/warning/danger/info)同此分级。 + * + * 2) 次要文字对比度过低 + * 旧 --color-text-tertiary(#777) = 4.48(on 白,勉强)/ #999 实测 2.85 却被用了 71 次。 + * 现将三级文字压到 #646C85 = 5.22:1,占位符保留浅色(占位符非正文)。 + * + * 3) 颜色碎片化 + * 审计前全站 182 种 hex、770 次硬编码(54 种灰、60 种蓝紫、40 种红橙)。 + * 本文件是唯一的颜色事实源;页面层禁止再写 hex,一律 var(--token)。 + * + * 4) 触摸目标 + * 组件库默认按钮只有 40px、小号 28px、"喜欢"按钮 31px。 + * 统一以 --tap-min(44.00px=44px) 为下限,--tap-gap 为最小间距。 + * + * 5) 动效几乎未落地(--motion-* 全站仅 5 次引用) + * 补充 --ease-spring 与 --press-scale,让点击有即时反馈。 + * + * 6) 夜间氛围层缺失(参考图有明显的光晕/星点,代码只有纯渐变) + * 新增 --mini-glow-* / --mini-star / --mini-glass / --mini-hairline。 + * + * 单位说明:rpx(375.00px = 屏幕宽度,0.50px ≈ 0.5px @375pt) + * 旧 token 名全部保留(88 个 wxss 共 909 处引用),只更新取值,避免大范围失效。 */ .wx-page { - /* ============ 品牌主色(规范 §3) ============ */ - --color-primary: #E96B6B; - --color-primary-active: #D95F5F; + /* ============ 品牌主色(分级:色块 / 文字 / 实心按钮) ============ */ + --color-primary: #E96B6B; /* 基础色:渐变、光晕、装饰、非文字图形 */ + --color-primary-strong: #B8434A; /* 文字与小图标(5.33:1 on 白,4.91:1 on 浅粉底) */ + --color-primary-solid: #C24C50; /* 实心按钮底(白字 4.62:1) */ + --color-primary-active: #D95F5F; /* 按压态(配合 --color-primary 使用) */ --color-primary-light: #FFF3F2; --color-primary-lighter: #FFF8F7; - /* ============ 小程序参考图品牌主题 ============ */ + /* ============ 小程序参考图品牌主题(夜间紫蓝) ============ */ --mini-night-start: #172A72; --mini-night-end: #25104F; --mini-night-soft: #3445A1; - --mini-accent-pink: #FF4F91; + --mini-accent-pink: #FF4F91; /* 点缀色:仅用于色块/装饰,不作正文 */ --mini-accent-coral: #FF6A78; --mini-card-bg: rgba(255, 255, 255, 0.98); --mini-text: #1F2744; --mini-muted: #7D839B; --mini-card-radius: 12.00px; - --mini-text-on-night: #FFFFFF; - --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); + --mini-text-on-night: #FFFFFF; /* on 深底 13.04:1 ✓ */ + --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); /* on 深底 ≈8:1 ✓ */ --mini-shadow: 0 8.00px 20.00px rgba(28, 30, 88, 0.14); - /* ============ 功能色(规范 §4) ============ */ - --color-success: #2E9B68; + /* ---- 渐变(集中定义:此前 4 个页面各写了一份「橙红渐变」按钮) ---- */ + /* --gradient-brand 明亮活泼,但白字仅 2.77:1 —— 只能用于无文字的装饰填充。 */ + --gradient-brand: linear-gradient(135deg, #FF6A78 0%, #E96B6B 100%); + /* 承载白字的 CTA 渐变:两端 #C24C50(4.73:1) / #B8434A(5.33:1) 均达标。 */ + --gradient-brand-solid: linear-gradient(135deg, #C24C50 0%, #B8434A 100%); + --gradient-night: linear-gradient(160deg, #172A72 0%, #25104F 100%); + --gradient-night-soft: linear-gradient(160deg, #3445A1 0%, #172A72 100%); + + /* ---- 首页 4×2 入口宫格图标渐变(参考图 2:高饱和圆角砖 + 白色描画图标) ---- + 白图标的对比度判据是**非文本图形 3:1**(WCAG 1.4.11)。渐变是斜向的、图标又跨在 + 两色之间,所以**较亮的一端也必须达标** —— 下表注释给的是 0% 处实算值,100% 更暗只会更高。 + 色相按业务语义固定(不随 tone 名漂移):找对象/婚前辅导=玫瑰粉系、公益红娘/服务站=暖橙系、 + 公益活动=紫罗兰、婚恋咨询=蓝、婚恋课堂=紫、婚恋反诈=绿。 */ + --gradient-entry-rose: linear-gradient(135deg, #F56287 0%, #F34671 100%); /* 3.01:1 / 3.54:1 */ + --gradient-entry-orange: linear-gradient(135deg, #F66A06 0%, #D95E06 100%); /* 3.01:1 / 3.78:1 */ + --gradient-entry-violet: linear-gradient(135deg, #A380F5 0%, #8F64F2 100%); /* 3.02:1 / 3.98:1 */ + --gradient-entry-blue: linear-gradient(135deg, #5195F6 0%, #3484F4 100%); /* 3.01:1 / 3.65:1 */ + --gradient-entry-purple: linear-gradient(135deg, #B27BF0 0%, #A260ED 100%); /* 3.01:1 / 3.87:1 */ + --gradient-entry-pink: linear-gradient(135deg, #F2619E 0%, #F0458C 100%); /* 3.01:1 / 3.54:1 */ + --gradient-entry-green: linear-gradient(135deg, #18A979 0%, #148F66 100%); /* 3.00:1 / 4.08:1 */ + --gradient-entry-amber: linear-gradient(135deg, #E9740C 0%, #CC650B 100%); /* 3.01:1 / 3.86:1 */ + /* 图标砖落影:比 --mini-shadow 更小,避免 4 列宫格里相邻砖块的投影互相压边 */ + --mini-entry-shadow: 0 4.00px 9.00px rgba(28, 30, 88, 0.18); + + /* ---- 夜间氛围层(v2 新增;参考图有光晕与星点,此前完全没有) ---- */ + --mini-glow-coral: rgba(255, 79, 145, 0.40); + --mini-glow-indigo: rgba(94, 124, 255, 0.32); + --mini-glow-soft: rgba(255, 255, 255, 0.10); + --mini-star: rgba(255, 255, 255, 0.70); + --mini-glass: rgba(255, 255, 255, 0.10); /* 深底玻璃面 */ + --mini-glass-strong: rgba(255, 255, 255, 0.16); + --mini-hairline: rgba(255, 255, 255, 0.16); /* 深底分隔线 */ + --mini-glass-success: rgba(90, 226, 184, 0.16); /* 深底上的成功态玻璃面 */ + + /* 星点层:多个小径向渐变叠在夜空渐变之上。用 radial-gradient 而非图片, + 避免额外请求,也便于随主题换色(index 页脚注:装饰层不承载信息)。 */ + --mini-starfield: + radial-gradient(circle at 12% 18%, var(--mini-star) 0, transparent 1.25px), + radial-gradient(circle at 31% 66%, var(--mini-star) 0, transparent 1.00px), + radial-gradient(circle at 57% 12%, var(--mini-star) 0, transparent 1.00px), + radial-gradient(circle at 79% 52%, var(--mini-star) 0, transparent 1.50px), + radial-gradient(circle at 93% 84%, var(--mini-star) 0, transparent 1.00px); + + /* 横幅压暗层:保证任何底图上的白色标题都有足够对比度 */ + --mini-banner-scrim: linear-gradient(90deg, rgba(23, 42, 114, 0.84) 0%, rgba(37, 16, 79, 0.40) 56%, rgba(255, 79, 145, 0.12) 100%); + + /* ============ 功能色(同样分级) ============ */ + --color-success: #2E9B68; /* 色块/图标 */ + --color-success-strong: #17805A; /* 文字(4.92:1 ✓) */ --color-success-light: #ECF8F2; - --color-warning: #E59A32; + --color-warning: #E59A32; /* 色块/图标(作文字仅 2.33:1) */ + --color-warning-strong: #9C5F14; /* 文字(5.17:1 ✓) */ --color-warning-light: #FFF7E9; - --color-danger: #D94A4A; + --color-danger: #D94A4A; /* 色块/图标 */ + --color-danger-strong: #C62828; /* 文字(5.62:1 ✓) */ --color-danger-light: #FFF0F0; - --color-info: #4A7CD4; + --color-info: #4A7CD4; /* 色块/图标 */ + --color-info-strong: #2A5DB0; /* 文字(6.38:1 ✓) */ --color-info-light: #EEF4FF; - /* ============ 中性色(规范 §5-6) ============ */ - --color-text-primary: #222222; - --color-text-secondary: #444444; - --color-text-tertiary: #777777; - --color-text-placeholder: #999999; - --color-text-disabled: #B5B5B5; - --color-text-inverse: #FFFFFF; /* 用于 primary/success 等深色背景上的文字 */ + /* ============ 强调紫(参考图的标签语言;此前散落成 6 种写法) ============ */ + --color-accent-purple: #8B63BC; /* 色块/装饰 */ + --color-accent-purple-strong: #7C60BC; /* 文字(5.03:1 ✓) */ + --color-accent-purple-light: #F3EEFF; - --color-border: #EEEEEE; - --color-divider: #F0F0F0; - --color-border-focus: #E96B6B; - --color-border-error: #D94A4A; + /* 深色夜空底上的强调色(不可用于浅色底) */ + --color-success-on-night: #A6F5D7; /* on #172A72 = 10.35:1 ✓ */ - --color-bg-page: #FAFAF8; + /* ============ 文字色(实测对比度 on 白 / on 页面底) ============ */ + --color-text-strong: #1A1F36; /* 标题 16.24 / 14.90 ✓ */ + --color-text-primary: #2A3050; /* 正文 12.83 / 11.77 ✓ */ + --color-text-secondary: #4A5169; /* 次要正文 7.86 / 7.21 ✓ */ + --color-text-tertiary: #646C85; /* 说明文字 5.22 / 4.79 ✓(旧 #777 为 4.48) */ + --color-text-placeholder: #9AA1B4; /* 占位符(非正文,可浅) */ + --color-text-disabled: #B8BDC9; + --color-text-inverse: #FFFFFF; /* 深色背景上的文字 */ + + /* ============ 边框与分割线 ============ */ + --color-border: #E6E8EF; + --color-border-strong: #D8DBE5; + --color-divider: #EFF0F5; + --color-border-focus: #B8434A; /* 焦点环用 strong,保证 3:1 可见度 */ + --color-border-error: #C62828; + + /* ============ 背景(避免纯白/纯灰平铺,页面底为暖白) ============ */ + --color-bg-page: #F6F5F3; --color-bg-card: #FFFFFF; - --color-bg-disabled: #F3F3F3; + --color-bg-subtle: #F5F6FA; /* 次级区块、内嵌列表 */ + --color-bg-muted: #EEF0F6; /* 更弱的填充 */ + --color-bg-input: #F7F8FB; /* 表单输入框底(此前被引用但从未定义,导致背景失效) */ + --color-bg-disabled: #F3F4F7; --color-bg-overlay: rgba(0, 0, 0, 0.45); - /* ============ 字体(规范 §7-11) ============ */ + /* ============ 字体 ============ */ + /* 小程序无法可靠加载 Web Font(wx.loadFontFace 依赖 HTTPS 白名单且有闪动风险), + 故使用中文系统字栈:iOS 走苹方、Android 走思源/系统黑体。 + 排版辨识度靠字号阶梯与字重建立,而非依赖字体本身。 */ --font-family-cn: -apple-system, "PingFang SC", "Noto Sans SC", "Hiragino Sans GB", "Microsoft YaHei", system-ui, sans-serif; + --font-family-number: "SF Pro Display", -apple-system, "DIN Alternate", "PingFang SC", sans-serif; - --font-size-xs: 12.00px; /* 12px */ - --font-size-sm: 13.00px; /* 13px */ - --font-size-md: 14.00px; /* 14px */ - --font-size-base: 16.00px; /* 16px */ - --font-size-lg: 18.00px; /* 18px */ - --font-size-xl: 20.00px; /* 20px */ - --font-size-2xl: 24.00px; /* 24px */ - --font-size-3xl: 28.00px; /* 28px */ + /* 字号阶梯 —— 正文 16.00px(16px) 起,元信息下限 12.00px(12px) */ + --font-size-micro: 11.00px; /* 11px 仅角标/装饰,禁用于正文 */ + --font-size-xs: 12.00px; /* 12px 元信息下限 */ + --font-size-sm: 13.00px; /* 13px 次要说明 */ + --font-size-md: 14.00px; /* 14px 次要正文 */ + --font-size-base: 16.00px; /* 16px 正文 */ + --font-size-lg: 18.00px; /* 18px 小标题 */ + --font-size-xl: 20.00px; /* 20px 区块标题 */ + --font-size-2xl: 24.00px; /* 24px 页面标题 */ + --font-size-3xl: 28.00px; /* 28px 大标题 */ + --font-size-display: 32.00px; /* 32px Hero */ + /* 字重:只用 4 档。禁止 550/650/750 等非百位值 —— Android 无对应字重会回退, + 导致同一设计在不同机型上粗细不一致(审计发现 30 处)。 */ --font-weight-regular: 400; --font-weight-medium: 500; --font-weight-semibold: 600; @@ -1229,51 +2455,68 @@ --line-height-tight: 1.25; --line-height-normal: 1.5; - --line-height-relaxed: 1.7; + --line-height-relaxed: 1.65; - /* ============ 间距(规范 §12,4px 栅格) ============ */ - --spacing-1: 4.00px; /* 4px */ - --spacing-2: 8.00px; /* 8px */ - --spacing-3: 12.00px; /* 12px */ - --spacing-4: 16.00px; /* 16px */ - --spacing-5: 20.00px; /* 20px */ - --spacing-6: 24.00px; /* 24px */ - --spacing-8: 32.00px; /* 32px */ - --spacing-10: 40.00px; /* 40px */ - --spacing-12: 48.00px; /* 48px */ + --letter-spacing-tight: 0; + --letter-spacing-wide: 0.50px; + --letter-spacing-wider: 1.00px; - --spacing-page-x: 16.00px; /* 页面左右 16px */ - --spacing-section: 24.00px; /* 区块间 24px */ - --spacing-card-inner: 16.00px; /* 卡片内部 16px */ - --spacing-tight: 8.00px; /* 紧密 8px */ + /* ============ 间距(4px 栅格) ============ */ + --spacing-1: 4.00px; + --spacing-2: 8.00px; + --spacing-3: 12.00px; + --spacing-4: 16.00px; + --spacing-5: 20.00px; + --spacing-6: 24.00px; + --spacing-8: 32.00px; + --spacing-10: 40.00px; + --spacing-12: 48.00px; - /* ============ 圆角(规范 §14) ============ */ - --radius-sm: 8.00px; /* 8px */ - --radius-md: 12.00px; /* 12px */ - --radius-lg: 16.00px; /* 16px */ - --radius-xl: 20.00px; /* 20px */ + --spacing-page-x: 16.00px; + --spacing-section: 24.00px; + --spacing-card-inner: 16.00px; + --spacing-tight: 8.00px; + + /* ============ 圆角 ============ */ + --radius-sm: 8.00px; + --radius-md: 12.00px; + --radius-lg: 16.00px; + --radius-xl: 20.00px; + --radius-2xl: 24.00px; --radius-full: 4999.50px; - /* ============ 阴影(规范 §15,极轻) ============ */ - --shadow-card: 0 4.00px 16.00px rgba(0, 0, 0, 0.04); + /* ============ 阴影(统一为一套,此前 30+ 种近似值) ============ */ + --shadow-card: 0 4.00px 14.00px rgba(35, 35, 95, 0.07); + --shadow-raised: 0 6.00px 18.00px rgba(35, 35, 95, 0.10); --shadow-popup: 0 8.00px 32.00px rgba(0, 0, 0, 0.10); + --shadow-night: 0 8.00px 20.00px rgba(28, 30, 88, 0.18); - /* ============ 边框(规范 §16) ============ */ + /* ============ 边框宽度 ============ */ --border-width: 0.50px; + --border-width-strong: 1.00px; - /* ============ 动效(规范 §17) ============ */ + /* ============ 触摸目标(无障碍下限 44×44px) ============ */ + --tap-min: 44.00px; /* 44px 最小可点区域 */ + --tap-comfortable: 48.00px; /* 48px 舒适尺寸:主操作 */ + --tap-gap: 8.00px; /* 8px 相邻目标最小间距 */ + + /* ============ 动效 ============ */ --motion-fast: 120ms; --motion-normal: 200ms; --motion-slow: 300ms; - --ease-standard: ease-out; + --ease-standard: cubic-bezier(0.32, 0.72, 0, 1); + --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1); + --press-scale: 0.97; + --press-opacity: 0.88; - /* ============ 层级 z-index(规范 §90) ============ */ + /* ============ 层级 z-index ============ */ --z-base: 1; --z-sticky: 100; --z-tabbar: 200; --z-dropdown: 500; --z-modal: 1000; --z-toast: 2000; + --z-ambient: 0; /* ============ 页面基础样式 ============ */ background-color: var(--color-bg-page); @@ -1283,7 +2526,10 @@ line-height: var(--line-height-normal); } -/* ============ 通用工具类 ============ */ +/* ========================================================================== + 通用工具类 + ========================================================================== */ + .container { padding: var(--spacing-page-x); } @@ -1297,17 +2543,34 @@ .flex-shrink-0 { flex-shrink: 0; } .wrap { flex-wrap: wrap; } +/* 4 列宫格:用 flex + 百分比宽度实现。 + 注:display:grid 在 WebView 渲染下可用,但 Skyline 不支持,故统一改为 flex 以免疫渲染引擎迁移。*/ +.grid-4 { + display: flex; + flex-wrap: wrap; +} +.grid-4 > .grid-item { + width: 25%; + box-sizing: border-box; +} + +.text-strong { color: var(--color-text-strong); } .text-primary { color: var(--color-text-primary); } .text-secondary { color: var(--color-text-secondary); } .text-tertiary { color: var(--color-text-tertiary); } .text-placeholder { color: var(--color-text-placeholder); } .text-white { color: var(--color-text-inverse); } -.text-brand { color: var(--color-primary); } -.text-success { color: var(--color-success); } -.text-warning { color: var(--color-warning); } -.text-danger { color: var(--color-danger); } -.text-info { color: var(--color-info); } +.text-brand { color: var(--color-primary-strong); } +/* 品牌色作文字只能用 -strong 变体:基础色 #E96B6B 在白底仅 3.10:1。 + 保留 .text-brand-soft 这个类名是为了不破坏既有引用,取值已统一到 -strong, + 如需「更亮的品牌色」请用于背景/图形而非文字。 */ +.text-brand-soft { color: var(--color-primary-strong); } +.text-success { color: var(--color-success-strong); } +.text-warning { color: var(--color-warning-strong); } +.text-danger { color: var(--color-danger-strong); } +.text-info { color: var(--color-info-strong); } +.font-micro { font-size: var(--font-size-micro); } .font-xs { font-size: var(--font-size-xs); } .font-sm { font-size: var(--font-size-sm); } .font-md { font-size: var(--font-size-md); } @@ -1316,6 +2579,7 @@ .font-xl { font-size: var(--font-size-xl); } .font-2xl { font-size: var(--font-size-2xl); } .font-3xl { font-size: var(--font-size-3xl); } +.font-display { font-size: var(--font-size-display); } .font-regular { font-weight: var(--font-weight-regular); } .font-medium { font-weight: var(--font-weight-medium); } @@ -1353,7 +2617,7 @@ padding-bottom: 0px; } -/* 页面卡片基础样式(中低密度留白) */ +/* 页面卡片基础样式 */ .card-base { background: var(--color-bg-card); border-radius: var(--radius-lg); @@ -1367,416 +2631,566 @@ background: var(--color-divider); } -.wx-page{background:var(--color-bg-page)}.service-page{min-height:100vh;padding-bottom:calc(70.00px + 0px)}.hero{padding:22.00px 16.00px 27.00px;background:linear-gradient(140deg,var(--color-primary-lighter),#FFF8EE);position:relative;overflow:hidden}.eyebrow{display:inline-flex;padding:3.50px 7.00px;border-radius:499.50px;background:rgba(255,255,255,.72);color:var(--color-primary);font-size:10.50px}.hero-title{display:block;margin-top:9.00px;font-size:20.00px;font-weight:700;line-height:1.35}.hero-desc{display:block;width:82%;margin-top:7.00px;font-size:12.50px;color:var(--color-text-secondary);line-height:1.7}.content{padding:0 var(--spacing-page-x)}.block{margin-top:var(--spacing-section)}.block-title{display:block;font-size:15.50px;font-weight:650}.block-subtitle{display:block;margin-top:4.00px;font-size:11.50px;color:var(--color-text-tertiary)}.card{margin-top:9.00px;padding:14.00px;background:var(--color-bg-card);border:0.50px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.feature-row,.menu-row,.record-row{display:flex;align-items:center;gap:10.00px;min-height:56.00px;padding:9.00px 0;border-bottom:0.50px solid var(--color-divider)}.feature-row:last-child,.menu-row:last-child,.record-row:last-child{border-bottom:0}.feature-icon{width:36.00px;height:36.00px;display:flex;align-items:center;justify-content:center;flex:none;border-radius:11.00px;background:var(--color-primary-light);color:var(--color-primary);font-weight:700}.feature-copy{flex:1;min-width:0}.feature-title{display:block;font-size:14.00px;font-weight:600}.feature-desc,.meta{display:block;margin-top:3.50px;font-size:11.50px;color:var(--color-text-tertiary);line-height:1.55}.arrow{font-size:20.00px;color:var(--color-text-disabled)}.tag{display:inline-flex;margin-right:5.00px;margin-top:5.00px;padding:3.00px 6.50px;border-radius:499.50px;background:var(--color-success-light);color:var(--color-success);font-size:10.00px}.tag.warning{background:var(--color-warning-light);color:var(--color-warning)}.primary-btn,.secondary-btn{height:44.00px;display:flex;align-items:center;justify-content:center;border-radius:22.00px;font-size:14.00px;font-weight:600}.primary-btn{background:linear-gradient(135deg,var(--mini-accent-coral),var(--mini-accent-pink));color:var(--color-text-inverse);box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)}.primary-btn.disabled{background:#E6E8EF;color:#989DAF;box-shadow:none}.secondary-btn{background:var(--color-primary-light);color:var(--color-primary)}.fixed-action{position:fixed;left:0;right:0;bottom:0;padding:9.00px var(--spacing-page-x) calc(9.00px + 0px);background:rgba(255,255,255,.96);border-top:0.50px solid var(--color-divider);z-index:100}.field{margin-top:13.00px}.label{display:block;margin-bottom:6.00px;font-size:12.50px;font-weight:600}.input,.select-box,.textarea{width:100%;box-sizing:border-box;background:#FCFAF8;border:0.50px solid var(--color-border);border-radius:var(--radius-md);font-size:13.00px}.input,.select-box{height:44.00px;padding:0 12.00px;display:flex;align-items:center}.textarea{min-height:90.00px;padding:11.00px}.notice{margin-top:10.00px;padding:11.00px;border-radius:var(--radius-md);background:#F3F7FC;color:var(--color-text-secondary);font-size:11.50px;line-height:1.65}.empty-panel{text-align:center;padding:35.00px 15.00px}.empty-symbol{width:48.00px;height:48.00px;margin:auto;display:flex;align-items:center;justify-content:center;border-radius:15.00px;background:var(--color-primary-light);color:var(--color-primary);font-size:18.00px;font-weight:700}.empty-title{display:block;margin-top:11.00px;font-size:15.00px;font-weight:600}.article-card{margin-top:9.00px;background:var(--color-bg-card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.article-cover{height:110.00px;padding:12.00px;background:linear-gradient(135deg,#F5E5DE,#F9F1E8);display:flex;align-items:flex-end}.article-cover text{font-size:21.00px;color:rgba(125,76,63,.52);font-weight:700}.article-body{padding:12.00px}.article-title{display:block;font-size:14.50px;font-weight:650;line-height:1.45}.article-meta{display:block;margin-top:5.00px;font-size:11.00px;color:var(--color-text-tertiary)}.article-content{padding:16.00px;background:var(--color-bg-card);font-size:14.00px;line-height:1.9;color:var(--color-text-secondary)}.article-content .lead{display:block;font-size:15.50px;color:var(--color-text-primary);font-weight:600;margin-bottom:12.00px}.danger-card{background:#FFF8F4;border-color:#F5DED2}.danger-card .feature-icon{background:#FFF0EA;color:#C85D43}@media(max-width:340px){.hero-title{font-size:18.00px}.hero-desc{width:92%}} +/* ========================================================================== + 可访问性:只用 token,不用工具类(2026-09-23 修订) + -------------------------------------------------------------------------- + v2 曾在此处新增 .tap-min / .tap-gap / .focusable / .pressable 四个工具类。 + 复检发现全部零引用(等价能力已各自写在组件样式内,例如 button/index.wxss + 直接使用 min-height:var(--tap-min)),且存在两个硬问题: -.service-shell{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:#F4F5FA}.service-content{padding:4.00px 12.00px 18.00px}.service-status{display:flex;align-items:center;justify-content:space-between;margin-top:12.00px;padding:10.00px 12.00px;border-radius:11.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-status__label{color:#7B8198;font-size:10.50px}.service-status__value{padding:3.00px 7.00px;border-radius:9.00px;background:#EAF8F2;color:#329472;font-size:9.50px;font-weight:650}.service-status__value.disabled{background:#FFF0F0;color:#D45A60}.service-topics{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.service-topic{min-height:74.00px;padding:10.00px;border-radius:12.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-topic__icon{display:flex;align-items:center;justify-content:center;width:27.00px;height:27.00px;border-radius:8.50px;background:#FFF0F5}.service-topic__icon image{width:17.00px;height:17.00px}.service-topic__title{display:block;margin-top:6.50px;color:#283056;font-size:12.00px;font-weight:650}.service-topic__desc{display:block;margin-top:3.00px;color:#858A9E;font-size:9.50px;line-height:1.45}.service-actions{display:flex;gap:7.00px}.service-actions .secondary-btn{width:95.00px;flex:none}.service-actions .primary-btn{flex:1}.privacy-note{display:flex;align-items:flex-start;gap:7.00px;margin-top:11.00px;padding:10.00px;border-radius:11.00px;background:#F1F4FF;color:#69718E;font-size:10.00px;line-height:1.55}.privacy-note image{width:17.00px;height:17.00px;flex:none} + 1) `.tap-gap > * + *` 用了通配符与兄弟选择器 —— WXSS 不支持, + wcc 编译期直接报 `error at token '*'`,导致整个小程序编译失败。 + (这是编译错误,不是静默失效,代价最高。) + 2) `.pressable:active` / `.focusable:focus-visible` 的伪类在 view 上 + 不生效(小程序须用 hover-class),属于"写了等于没写"。 + + 故整块移除,保留 token。需要热区/间距时直接引用 token: + min-height: var(--tap-min); → 44.00px = 44px,最小可点区域 + gap: var(--tap-gap); → 8.00px = 8px,相邻目标间距(flex gap) + 【WXSS 禁用清单】星号通配符、兄弟选择器、属性选择器。 + 【注释约束】WXSS 注释**不可嵌套**:内层注释的结束标记会提前终止外层注释, + 其后的文字会被当成真实样式解析,导致编译失败或样式被污染。 + (2026-09-23 实证:本块注释初版即踩此坑。) + ========================================================================== */ + +.wx-page{background:var(--color-bg-page)}.service-page{min-height:100vh;padding-bottom:calc(70.00px + 0px)}.hero{padding:22.00px 16.00px 27.00px;background:linear-gradient(140deg,var(--color-primary-lighter),var(--color-warning-light));position:relative;overflow:hidden}.eyebrow{display:inline-flex;padding:3.50px 7.00px;border-radius:499.50px;background:rgba(255,255,255,.72);color:var(--color-primary-strong);font-size:12.00px}.hero-title{display:block;margin-top:9.00px;font-size:20.00px;font-weight:700;line-height:1.35}.hero-desc{display:block;width:82%;margin-top:7.00px;font-size:12.50px;color:var(--color-text-secondary);line-height:1.7}.content{padding:0 var(--spacing-page-x)}.block{margin-top:var(--spacing-section)}.block-title{display:block;font-size:15.50px;font-weight:600}.block-subtitle{display:block;margin-top:4.00px;font-size:12.00px;color:var(--color-text-tertiary)}.card{margin-top:9.00px;padding:14.00px;background:var(--color-bg-card);border:0.50px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.feature-row,.menu-row,.record-row{display:flex;align-items:center;gap:10.00px;min-height:56.00px;padding:9.00px 0;border-bottom:0.50px solid var(--color-divider)}.feature-row:last-child,.menu-row:last-child,.record-row:last-child{border-bottom:0}.feature-icon{width:36.00px;height:36.00px;display:flex;align-items:center;justify-content:center;flex:none;border-radius:11.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-weight:700}.feature-copy{flex:1;min-width:0}.feature-title{display:block;font-size:14.00px;font-weight:600}.feature-desc,.meta{display:block;margin-top:3.50px;font-size:12.00px;color:var(--color-text-tertiary);line-height:1.55}.arrow{font-size:20.00px;color:var(--color-text-disabled)}.tag{display:inline-flex;margin-right:5.00px;margin-top:5.00px;padding:3.00px 6.50px;border-radius:499.50px;background:var(--color-success-light);color:var(--color-success-strong);font-size:12.00px}.tag.warning{background:var(--color-warning-light);color:var(--color-warning-strong)}.primary-btn,.secondary-btn{height:44.00px;display:flex;align-items:center;justify-content:center;border-radius:22.00px;font-size:14.00px;font-weight:600}.primary-btn{background:var(--gradient-brand-solid);color:var(--color-text-inverse);box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)}.primary-btn.disabled{background:var(--color-bg-muted);color:var(--color-text-tertiary);box-shadow:none}.secondary-btn{background:var(--color-primary-light);color:var(--color-primary-strong)}.fixed-action{position:fixed;left:0;right:0;bottom:0;padding:9.00px var(--spacing-page-x) calc(9.00px + 0px);background:rgba(255,255,255,.96);border-top:0.50px solid var(--color-divider);z-index:100}.field{margin-top:13.00px}.label{display:block;margin-bottom:6.00px;font-size:12.50px;font-weight:600}.input,.select-box,.textarea{width:100%;box-sizing:border-box;background:var(--color-bg-page);border:0.50px solid var(--color-border);border-radius:var(--radius-md);font-size:13.00px}.input,.select-box{height:44.00px;padding:0 12.00px;display:flex;align-items:center}.textarea{min-height:90.00px;padding:11.00px}.notice{margin-top:10.00px;padding:11.00px;border-radius:var(--radius-md);background:var(--color-info-light);color:var(--color-text-secondary);font-size:12.00px;line-height:1.65}.select-box.is-readonly{background:var(--color-bg-subtle);color:var(--color-text-secondary)}.empty-panel{text-align:center;padding:35.00px 15.00px}.empty-symbol{width:48.00px;height:48.00px;margin:auto;display:flex;align-items:center;justify-content:center;border-radius:15.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-size:18.00px;font-weight:700}.empty-title{display:block;margin-top:11.00px;font-size:15.00px;font-weight:600}.article-card{margin-top:9.00px;background:var(--color-bg-card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.article-cover{height:110.00px;padding:12.00px;background:linear-gradient(135deg,var(--color-warning-light),var(--color-warning-light));display:flex;align-items:flex-end}.article-cover text{font-size:21.00px;color:rgba(125,76,63,.52);font-weight:700}.article-body{padding:12.00px}.article-title{display:block;font-size:14.50px;font-weight:600;line-height:1.45}.article-meta{display:block;margin-top:5.00px;font-size:12.00px;color:var(--color-text-tertiary)}.article-content{padding:16.00px;background:var(--color-bg-card);font-size:14.00px;line-height:1.9;color:var(--color-text-secondary)}.article-content .lead{display:block;font-size:15.50px;color:var(--color-text-primary);font-weight:600;margin-bottom:12.00px}.danger-card{background:var(--color-primary-lighter);border-color:var(--color-primary-light)}.danger-card .feature-icon{background:var(--color-warning-light);color:var(--color-warning-strong)}@media(max-width:340px){.hero-title{font-size:18.00px}.hero-desc{width:92%}} + +.service-shell{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:var(--color-bg-page)}.service-content{padding:4.00px 12.00px 18.00px}.service-status{display:flex;align-items:center;justify-content:space-between;margin-top:12.00px;padding:10.00px 12.00px;border-radius:11.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-status__label{color:var(--color-text-tertiary);font-size:12.00px}.service-status__value{padding:3.00px 7.00px;border-radius:9.00px;background:var(--color-success-light);color:var(--color-success-strong);font-size:12.00px;font-weight:600}.service-status__value.disabled{background:var(--color-danger-light);color:var(--color-danger-strong)}.service-topics{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.service-topic{min-height:74.00px;padding:10.00px;border-radius:12.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-topic__icon{display:flex;align-items:center;justify-content:center;width:27.00px;height:27.00px;border-radius:8.50px;background:var(--color-primary-light)}.service-topic__icon image{width:17.00px;height:17.00px}.service-topic__title{display:block;margin-top:6.50px;color:var(--color-text-strong);font-size:12.00px;font-weight:600}.service-topic__desc{display:block;margin-top:3.00px;color:var(--color-text-tertiary);font-size:12.00px;line-height:1.45}.service-actions{display:flex;gap:7.00px}.service-actions .secondary-btn{width:95.00px;flex:none}.service-actions .primary-btn{flex:1}.privacy-note{display:flex;align-items:flex-start;gap:7.00px;margin-top:11.00px;padding:10.00px;border-radius:11.00px;background:var(--color-info-light);color:var(--color-text-tertiary);font-size:12.00px;line-height:1.55}.privacy-note image{width:17.00px;height:17.00px;flex:none} /* ==== miniapp/components/conversation-item ==== */ .ui-conv { - display: flex; - align-items: center; - background: var(--color-bg-card); - padding: 9.00px 10.00px; - border-bottom: 0.50px solid var(--color-divider); + display:flex; + align-items:center; + background:var(--color-bg-card); + padding:9.00px 10.00px; + border-bottom:0.50px solid var(--color-divider); } .ui-conv--disabled { - opacity: 0.6; + opacity:0.6; } .ui-conv__body { - flex: 1; - min-width: 0; - margin-left: var(--spacing-3); + flex:1; + min-width:0; + margin-left:var(--spacing-3); } .ui-conv__top { - display: flex; - justify-content: space-between; - align-items: baseline; + display:flex; + justify-content:space-between; + align-items:baseline; } .ui-conv__name { - color: #222746; - font-size: 13.00px; - font-weight: 650; + color:var(--color-text-strong); + font-size:13.00px; + font-weight:600; } .ui-conv__time { - color: #8b90a5; - font-size: 9.50px; - flex-shrink: 0; - margin-left: var(--spacing-2); + color:var(--color-text-tertiary); + font-size:12.00px; + flex-shrink:0; + margin-left:var(--spacing-2); } .ui-conv__bottom { - display: flex; - justify-content: space-between; - align-items: center; - margin-top: var(--spacing-1); + display:flex; + justify-content:space-between; + align-items:center; + margin-top:var(--spacing-1); } .ui-conv__last { - flex: 1; - min-width: 0; - color: #7a8097; - font-size: 10.50px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - margin-right: var(--spacing-2); + flex:1; + min-width:0; + color:var(--color-text-tertiary); + font-size:12.00px; + overflow:hidden; + white-space:nowrap; + text-overflow:ellipsis; + margin-right:var(--spacing-2); } .ui-conv__badge { - min-width: 18.00px; - height: 18.00px; - padding: 0 5.00px; - border-radius: var(--radius-full); - background: var(--color-danger); - color: #FFFFFF; - font-size: var(--font-size-xs); - display: flex; - align-items: center; - justify-content: center; - line-height: 1; - flex-shrink: 0; + min-width:18.00px; + height:18.00px; + padding:0 5.00px; + border-radius:var(--radius-full); + background:var(--color-danger); + color:var(--color-text-inverse); + font-size:var(--font-size-xs); + display:flex; + align-items:center; + justify-content:center; + line-height:1; + flex-shrink:0; } .ui-conv__status-hint { - margin-top: var(--spacing-1); - font-size: var(--font-size-xs); - color: var(--color-text-tertiary); + margin-top:var(--spacing-1); + font-size:var(--font-size-xs); + color:var(--color-text-tertiary); } /* ==== miniapp/components/empty ==== */ .ui-empty { - display: flex; - flex-direction: column; - align-items: center; - padding: var(--spacing-10) var(--spacing-page-x); - text-align: center; + display:flex; + flex-direction:column; + align-items:center; + padding:var(--spacing-10) var(--spacing-page-x); + text-align:center; } .ui-empty__illustration { - width: 80.00px; - height: 80.00px; - border-radius: 50%; - background: var(--color-bg-disabled); - display: flex; - align-items: center; - justify-content: center; - margin-bottom: var(--spacing-4); + width:80.00px; + height:80.00px; + border-radius:50%; + background:var(--color-bg-disabled); + display:flex; + align-items:center; + justify-content:center; + margin-bottom:var(--spacing-4); } .ui-empty__icon { - width: 36.00px; - height: 36.00px; - opacity: 0.72; + width:36.00px; + height:36.00px; + opacity:0.72; } .ui-empty__title { - font-size: var(--font-size-lg); - font-weight: var(--font-weight-medium); - color: var(--color-text-primary); - margin-bottom: var(--spacing-2); + font-size:var(--font-size-lg); + font-weight:var(--font-weight-medium); + color:var(--color-text-primary); + margin-bottom:var(--spacing-2); } .ui-empty__desc { - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); - line-height: var(--line-height-relaxed); - max-width: 240.00px; + font-size:var(--font-size-sm); + color:var(--color-text-tertiary); + line-height:var(--line-height-relaxed); + max-width:240.00px; } .ui-empty__actions { - display: flex; - flex-direction: column; - gap: var(--spacing-2); - margin-top: var(--spacing-6); - width: 100%; - max-width: 240.00px; + display:flex; + flex-direction:column; + gap:var(--spacing-2); + margin-top:var(--spacing-6); + width:100%; + max-width:240.00px; } .ui-empty__action { - display: flex; - align-items: center; - justify-content: center; - height: 40.00px; - border-radius: var(--radius-full); - font-size: var(--font-size-base); - font-weight: var(--font-weight-medium); -} + display:flex; + align-items:center; + justify-content:center; + min-height:var(--tap-min); + border-radius:var(--radius-full); + font-size:var(--font-size-base); + font-weight:var(--font-weight-medium); +min-width:var(--tap-min);} .ui-empty__action--primary { - background: var(--color-primary); - color: #FFFFFF; + background:var(--color-primary-solid); + color:var(--color-text-inverse); } .ui-empty__action--secondary { - background: var(--color-bg-card); - color: var(--color-primary); - border: 0.50px solid var(--color-primary); + background:var(--color-bg-card); + color:var(--color-primary-strong); + border:0.50px solid var(--color-primary); } /* ==== miniapp/components/loading ==== */ .ui-loading--block { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: var(--spacing-8) var(--spacing-page-x); + display:flex; + flex-direction:column; + align-items:center; + justify-content:center; + padding:var(--spacing-8) var(--spacing-page-x); } .ui-loading--inline { - display: inline-flex; - align-items: center; + display:inline-flex; + align-items:center; } .ui-loading__spinner { - width: 30.00px; - height: 30.00px; - display: flex; - align-items: center; - justify-content: center; + width:30.00px; + height:30.00px; + display:flex; + align-items:center; + justify-content:center; } .ui-loading__spinner-icon { - width: 24.00px; - height: 24.00px; - animation: ui-loading-spin 0.8s linear infinite; + width:24.00px; + height:24.00px; + animation:ui-loading-spin 0.8s linear infinite; } @keyframes ui-loading-spin { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } + from { transform:rotate(0deg); } + to { transform:rotate(360deg); } } .ui-loading__text { - margin-top: var(--spacing-3); - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); + margin-top:var(--spacing-3); + font-size:var(--font-size-sm); + color:var(--color-text-tertiary); } /* Skeleton */ .ui-loading__skeleton { - width: 100%; + width:100%; } .ui-loading__skeleton-row { - display: flex; - align-items: center; - padding: var(--spacing-3) var(--spacing-page-x); - background: var(--color-bg-card); - border-bottom: 0.50px solid var(--color-divider); + display:flex; + align-items:center; + padding:var(--spacing-3) var(--spacing-page-x); + background:var(--color-bg-card); + border-bottom:0.50px solid var(--color-divider); } .ui-loading__skeleton-avatar { - width: 44.00px; - height: 44.00px; - border-radius: 50%; - background: var(--color-bg-disabled); - margin-right: var(--spacing-3); - flex-shrink: 0; + width:44.00px; + height:44.00px; + border-radius:50%; + background:var(--color-bg-disabled); + margin-right:var(--spacing-3); + flex-shrink:0; } .ui-loading__skeleton-content { - flex: 1; - min-width: 0; + flex:1; + min-width:0; } .ui-loading__skeleton-line { - height: 12.00px; - background: var(--color-bg-disabled); - border-radius: var(--radius-sm); - position: relative; - overflow: hidden; + height:12.00px; + background:var(--color-bg-disabled); + border-radius:var(--radius-sm); + position:relative; + overflow:hidden; } .ui-loading__skeleton-line--title { - width: 40%; - margin-bottom: var(--spacing-2); + width:40%; + margin-bottom:var(--spacing-2); } .ui-loading__skeleton-line--meta { - width: 70%; + width:70%; } /* shimmer */ .ui-loading__skeleton-line::after, .ui-loading__skeleton-avatar::after { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: linear-gradient( + content:''; + position:absolute; + top:0; + left:0; + width:100%; + height:100%; + background:linear-gradient( 90deg, transparent 0%, rgba(255, 255, 255, 0.55) 50%, transparent 100% ); - animation: ui-loading-shimmer 1.4s ease-in-out infinite; + animation:ui-loading-shimmer 1.4s ease-in-out infinite; } @keyframes ui-loading-shimmer { - 0% { transform: translateX(-100%); } - 100% { transform: translateX(100%); } + 0% { transform:translateX(-100%); } + 100% { transform:translateX(100%); } } /* ==== miniapp/components/section-header ==== */ +/** + * 区块标题(全站所有页面共用,是排版层级的关键一环) + * + * 2026-09-22 修订: + * 1) 层级拉开:标题 18.00px→20.00px(--font-size-xl),与正文 16.00px / 卡片标题 14.00px + * 形成「区块标题 > 卡片标题 > 正文 > 元信息」四级阶梯。 + * 旧值 18.00px 与卡片标题仅差 5.00px,层级读不出来。 + * 2) 右侧 action 是全站最容易被忽略的触摸目标:只有 13.00px 文字高(约 13px), + * 远低于 44px 下限。改为 min-height:--tap-min,热区向上补白。 + * 3) action 文字色原为 --color-primary(#E96B6B)=3.10:1,不达标,改 -strong。 + */ .ui-section { - display: flex; - align-items: center; - justify-content: space-between; - padding: var(--spacing-3) var(--spacing-page-x); + display:flex; + align-items:center; + justify-content:space-between; + padding:var(--spacing-2) var(--spacing-page-x); } .ui-section__left { - display: flex; - align-items: baseline; + display:flex; + align-items:baseline; + min-width:0; } .ui-section__title { - font-size: var(--font-size-lg); - font-weight: var(--font-weight-semibold); - color: var(--color-text-primary); + font-size:var(--font-size-xl); + font-weight:var(--font-weight-semibold); + color:var(--color-text-strong); + letter-spacing:var(--letter-spacing-tight); } .ui-section__subtitle { - margin-left: var(--spacing-2); - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); + margin-left:var(--spacing-2); + font-size:var(--font-size-xs); + color:var(--color-text-tertiary); } .ui-section__action { - display: flex; - align-items: center; - font-size: var(--font-size-sm); - color: var(--color-primary); + display:flex; + align-items:center; + flex:none; + min-height:var(--tap-min); + padding-left:var(--spacing-3); + font-size:var(--font-size-sm); + font-weight:var(--font-weight-medium); + color:var(--color-primary-strong); + transition:opacity var(--motion-fast) var(--ease-standard); +} +.ui-section__action:active { + opacity:var(--press-opacity); } .ui-section__arrow { - margin-left: 2.00px; - width: 12.00px; - height: 12.00px; + margin-left:2.00px; + width:12.00px; + height:12.00px; } .page { - min-height: 100vh; - background: #f4f5fa; + min-height:100vh; + background:var(--color-bg-page); } +/* --nav-status / --nav-h / --nav-right 由 messages.ts 经 utils/nav-metrics 实测胶囊按钮后注入 */ .messages-hero { - padding: 20px 12.00px 17.00px; - border-radius: 0 0 18.00px 18.00px; - background: linear-gradient(160deg, var(--mini-night-start), var(--mini-night-end)); - box-shadow: var(--mini-shadow); + padding:var(--nav-status, 44px) 12.00px 17.00px; + border-radius:0 0 18.00px 18.00px; + background:linear-gradient(160deg, var(--mini-night-start), var(--mini-night-end)); + box-shadow:var(--mini-shadow); } .messages-nav { - position: relative; - display: flex; - align-items: center; - justify-content: center; - height: 44.00px; + position:relative; + display:flex; + align-items:center; + justify-content:center; + height:var(--nav-h, 40.00px); } .messages-title { - color: #fff; - font-size: 15.50px; - font-weight: 700; + color:var(--color-text-inverse); + font-size:15.50px; + font-weight:700; } +/* 胶囊安全区:右对齐图标必须整体左移到胶囊左侧,否则被胶囊盖住点不到 */ .messages-search { - position: absolute; - right: 7.00px; - width: 17.00px; - height: 17.00px; + position:absolute; + right:var(--nav-right, 102px); + width:17.00px; + height:17.00px; } .message-shortcuts { - display: grid; - grid-template-columns: repeat(4, 1fr); - padding: 11.00px 4.00px 2.00px; + display:grid; + grid-template-columns:repeat(4, 1fr); + padding:11.00px 4.00px 2.00px; } .message-shortcut { - display: flex; - flex-direction: column; - align-items: center; - color: rgba(255, 255, 255, .88); - font-size: 10.00px; + display:flex; + flex-direction:column; + align-items:center; + color:rgba(255, 255, 255, .88); + font-size:12.00px; } .shortcut-icon { - display: flex; - align-items: center; - justify-content: center; - width: 36.00px; - height: 36.00px; - margin-bottom: 6.00px; - border: 0.50px solid rgba(255, 255, 255, .2); - border-radius: 13.00px; + display:flex; + align-items:center; + justify-content:center; + width:36.00px; + height:36.00px; + margin-bottom:6.00px; + border:0.50px solid rgba(255, 255, 255, .2); + border-radius:13.00px; } .shortcut-icon image { - width: 22.50px; - height: 22.50px; + width:22.50px; + height:22.50px; } -.shortcut-icon--blue { background: rgba(79, 139, 255, .28); } -.shortcut-icon--pink { background: rgba(255, 92, 130, .28); } -.shortcut-icon--purple { background: rgba(154, 107, 255, .28); } -.shortcut-icon--coral { background: rgba(240, 106, 100, .28); } +.shortcut-icon--blue { background:rgba(79, 139, 255, .28); } +.shortcut-icon--pink { background:rgba(255, 92, 130, .28); } +.shortcut-icon--purple { background:rgba(154, 107, 255, .28); } +.shortcut-icon--coral { background:rgba(240, 106, 100, .28); } .messages-content { - padding: 8.00px 12.00px 20.00px; + padding:8.00px 12.00px 20.00px; } .conversation-list { - overflow: hidden; - margin-top: 4.00px; - border-radius: 14.00px; - background: #fff; - box-shadow: 0 5.00px 16.00px rgba(34, 35, 91, .08); + overflow:hidden; + margin-top:4.00px; + border-radius:14.00px; + background:var(--color-bg-card); + box-shadow:0 5.00px 16.00px rgba(34, 35, 91, .08); } /** * 丹阳公益婚恋服务平台 - 全局 Design Token * - * 依据《前端组件库与 Design Token 规范 V1.0》 - * 单位说明:rpx(375.00px = 屏幕宽度),规范 px 值按 2x 映射为 rpx - * 禁止页面层写死颜色/间距/圆角,必须引用 var(--token) + * v2(2026-09-22 设计系统夯实) + * --------------------------------------------------------------- + * 本次修订针对审计发现的系统性问题,逐条给出依据: + * + * 1) 品牌色不能承载文字 → 引入「基础色 / -strong」分级 + * #E96B6B on 白 = 3.10:1,白字 on #E96B6B = 3.10:1,on #FFF3F2 = 2.85:1, + * 三条路径都不满足正文 4.5:1。故: + * --color-primary 仅用于大色块、渐变、光晕、装饰(非文字) + * --color-primary-strong 用于文字、小图标、纯文字链接(5.33:1 ✓) + * --color-primary-solid 实心按钮底(白字 ≥4.5:1 ✓) + * 功能色(success/warning/danger/info)同此分级。 + * + * 2) 次要文字对比度过低 + * 旧 --color-text-tertiary(#777) = 4.48(on 白,勉强)/ #999 实测 2.85 却被用了 71 次。 + * 现将三级文字压到 #646C85 = 5.22:1,占位符保留浅色(占位符非正文)。 + * + * 3) 颜色碎片化 + * 审计前全站 182 种 hex、770 次硬编码(54 种灰、60 种蓝紫、40 种红橙)。 + * 本文件是唯一的颜色事实源;页面层禁止再写 hex,一律 var(--token)。 + * + * 4) 触摸目标 + * 组件库默认按钮只有 40px、小号 28px、"喜欢"按钮 31px。 + * 统一以 --tap-min(44.00px=44px) 为下限,--tap-gap 为最小间距。 + * + * 5) 动效几乎未落地(--motion-* 全站仅 5 次引用) + * 补充 --ease-spring 与 --press-scale,让点击有即时反馈。 + * + * 6) 夜间氛围层缺失(参考图有明显的光晕/星点,代码只有纯渐变) + * 新增 --mini-glow-* / --mini-star / --mini-glass / --mini-hairline。 + * + * 单位说明:rpx(375.00px = 屏幕宽度,0.50px ≈ 0.5px @375pt) + * 旧 token 名全部保留(88 个 wxss 共 909 处引用),只更新取值,避免大范围失效。 */ .wx-page { - /* ============ 品牌主色(规范 §3) ============ */ - --color-primary: #E96B6B; - --color-primary-active: #D95F5F; + /* ============ 品牌主色(分级:色块 / 文字 / 实心按钮) ============ */ + --color-primary: #E96B6B; /* 基础色:渐变、光晕、装饰、非文字图形 */ + --color-primary-strong: #B8434A; /* 文字与小图标(5.33:1 on 白,4.91:1 on 浅粉底) */ + --color-primary-solid: #C24C50; /* 实心按钮底(白字 4.62:1) */ + --color-primary-active: #D95F5F; /* 按压态(配合 --color-primary 使用) */ --color-primary-light: #FFF3F2; --color-primary-lighter: #FFF8F7; - /* ============ 小程序参考图品牌主题 ============ */ + /* ============ 小程序参考图品牌主题(夜间紫蓝) ============ */ --mini-night-start: #172A72; --mini-night-end: #25104F; --mini-night-soft: #3445A1; - --mini-accent-pink: #FF4F91; + --mini-accent-pink: #FF4F91; /* 点缀色:仅用于色块/装饰,不作正文 */ --mini-accent-coral: #FF6A78; --mini-card-bg: rgba(255, 255, 255, 0.98); --mini-text: #1F2744; --mini-muted: #7D839B; --mini-card-radius: 12.00px; - --mini-text-on-night: #FFFFFF; - --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); + --mini-text-on-night: #FFFFFF; /* on 深底 13.04:1 ✓ */ + --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); /* on 深底 ≈8:1 ✓ */ --mini-shadow: 0 8.00px 20.00px rgba(28, 30, 88, 0.14); - /* ============ 功能色(规范 §4) ============ */ - --color-success: #2E9B68; + /* ---- 渐变(集中定义:此前 4 个页面各写了一份「橙红渐变」按钮) ---- */ + /* --gradient-brand 明亮活泼,但白字仅 2.77:1 —— 只能用于无文字的装饰填充。 */ + --gradient-brand: linear-gradient(135deg, #FF6A78 0%, #E96B6B 100%); + /* 承载白字的 CTA 渐变:两端 #C24C50(4.73:1) / #B8434A(5.33:1) 均达标。 */ + --gradient-brand-solid: linear-gradient(135deg, #C24C50 0%, #B8434A 100%); + --gradient-night: linear-gradient(160deg, #172A72 0%, #25104F 100%); + --gradient-night-soft: linear-gradient(160deg, #3445A1 0%, #172A72 100%); + + /* ---- 首页 4×2 入口宫格图标渐变(参考图 2:高饱和圆角砖 + 白色描画图标) ---- + 白图标的对比度判据是**非文本图形 3:1**(WCAG 1.4.11)。渐变是斜向的、图标又跨在 + 两色之间,所以**较亮的一端也必须达标** —— 下表注释给的是 0% 处实算值,100% 更暗只会更高。 + 色相按业务语义固定(不随 tone 名漂移):找对象/婚前辅导=玫瑰粉系、公益红娘/服务站=暖橙系、 + 公益活动=紫罗兰、婚恋咨询=蓝、婚恋课堂=紫、婚恋反诈=绿。 */ + --gradient-entry-rose: linear-gradient(135deg, #F56287 0%, #F34671 100%); /* 3.01:1 / 3.54:1 */ + --gradient-entry-orange: linear-gradient(135deg, #F66A06 0%, #D95E06 100%); /* 3.01:1 / 3.78:1 */ + --gradient-entry-violet: linear-gradient(135deg, #A380F5 0%, #8F64F2 100%); /* 3.02:1 / 3.98:1 */ + --gradient-entry-blue: linear-gradient(135deg, #5195F6 0%, #3484F4 100%); /* 3.01:1 / 3.65:1 */ + --gradient-entry-purple: linear-gradient(135deg, #B27BF0 0%, #A260ED 100%); /* 3.01:1 / 3.87:1 */ + --gradient-entry-pink: linear-gradient(135deg, #F2619E 0%, #F0458C 100%); /* 3.01:1 / 3.54:1 */ + --gradient-entry-green: linear-gradient(135deg, #18A979 0%, #148F66 100%); /* 3.00:1 / 4.08:1 */ + --gradient-entry-amber: linear-gradient(135deg, #E9740C 0%, #CC650B 100%); /* 3.01:1 / 3.86:1 */ + /* 图标砖落影:比 --mini-shadow 更小,避免 4 列宫格里相邻砖块的投影互相压边 */ + --mini-entry-shadow: 0 4.00px 9.00px rgba(28, 30, 88, 0.18); + + /* ---- 夜间氛围层(v2 新增;参考图有光晕与星点,此前完全没有) ---- */ + --mini-glow-coral: rgba(255, 79, 145, 0.40); + --mini-glow-indigo: rgba(94, 124, 255, 0.32); + --mini-glow-soft: rgba(255, 255, 255, 0.10); + --mini-star: rgba(255, 255, 255, 0.70); + --mini-glass: rgba(255, 255, 255, 0.10); /* 深底玻璃面 */ + --mini-glass-strong: rgba(255, 255, 255, 0.16); + --mini-hairline: rgba(255, 255, 255, 0.16); /* 深底分隔线 */ + --mini-glass-success: rgba(90, 226, 184, 0.16); /* 深底上的成功态玻璃面 */ + + /* 星点层:多个小径向渐变叠在夜空渐变之上。用 radial-gradient 而非图片, + 避免额外请求,也便于随主题换色(index 页脚注:装饰层不承载信息)。 */ + --mini-starfield: + radial-gradient(circle at 12% 18%, var(--mini-star) 0, transparent 1.25px), + radial-gradient(circle at 31% 66%, var(--mini-star) 0, transparent 1.00px), + radial-gradient(circle at 57% 12%, var(--mini-star) 0, transparent 1.00px), + radial-gradient(circle at 79% 52%, var(--mini-star) 0, transparent 1.50px), + radial-gradient(circle at 93% 84%, var(--mini-star) 0, transparent 1.00px); + + /* 横幅压暗层:保证任何底图上的白色标题都有足够对比度 */ + --mini-banner-scrim: linear-gradient(90deg, rgba(23, 42, 114, 0.84) 0%, rgba(37, 16, 79, 0.40) 56%, rgba(255, 79, 145, 0.12) 100%); + + /* ============ 功能色(同样分级) ============ */ + --color-success: #2E9B68; /* 色块/图标 */ + --color-success-strong: #17805A; /* 文字(4.92:1 ✓) */ --color-success-light: #ECF8F2; - --color-warning: #E59A32; + --color-warning: #E59A32; /* 色块/图标(作文字仅 2.33:1) */ + --color-warning-strong: #9C5F14; /* 文字(5.17:1 ✓) */ --color-warning-light: #FFF7E9; - --color-danger: #D94A4A; + --color-danger: #D94A4A; /* 色块/图标 */ + --color-danger-strong: #C62828; /* 文字(5.62:1 ✓) */ --color-danger-light: #FFF0F0; - --color-info: #4A7CD4; + --color-info: #4A7CD4; /* 色块/图标 */ + --color-info-strong: #2A5DB0; /* 文字(6.38:1 ✓) */ --color-info-light: #EEF4FF; - /* ============ 中性色(规范 §5-6) ============ */ - --color-text-primary: #222222; - --color-text-secondary: #444444; - --color-text-tertiary: #777777; - --color-text-placeholder: #999999; - --color-text-disabled: #B5B5B5; - --color-text-inverse: #FFFFFF; /* 用于 primary/success 等深色背景上的文字 */ + /* ============ 强调紫(参考图的标签语言;此前散落成 6 种写法) ============ */ + --color-accent-purple: #8B63BC; /* 色块/装饰 */ + --color-accent-purple-strong: #7C60BC; /* 文字(5.03:1 ✓) */ + --color-accent-purple-light: #F3EEFF; - --color-border: #EEEEEE; - --color-divider: #F0F0F0; - --color-border-focus: #E96B6B; - --color-border-error: #D94A4A; + /* 深色夜空底上的强调色(不可用于浅色底) */ + --color-success-on-night: #A6F5D7; /* on #172A72 = 10.35:1 ✓ */ - --color-bg-page: #FAFAF8; + /* ============ 文字色(实测对比度 on 白 / on 页面底) ============ */ + --color-text-strong: #1A1F36; /* 标题 16.24 / 14.90 ✓ */ + --color-text-primary: #2A3050; /* 正文 12.83 / 11.77 ✓ */ + --color-text-secondary: #4A5169; /* 次要正文 7.86 / 7.21 ✓ */ + --color-text-tertiary: #646C85; /* 说明文字 5.22 / 4.79 ✓(旧 #777 为 4.48) */ + --color-text-placeholder: #9AA1B4; /* 占位符(非正文,可浅) */ + --color-text-disabled: #B8BDC9; + --color-text-inverse: #FFFFFF; /* 深色背景上的文字 */ + + /* ============ 边框与分割线 ============ */ + --color-border: #E6E8EF; + --color-border-strong: #D8DBE5; + --color-divider: #EFF0F5; + --color-border-focus: #B8434A; /* 焦点环用 strong,保证 3:1 可见度 */ + --color-border-error: #C62828; + + /* ============ 背景(避免纯白/纯灰平铺,页面底为暖白) ============ */ + --color-bg-page: #F6F5F3; --color-bg-card: #FFFFFF; - --color-bg-disabled: #F3F3F3; + --color-bg-subtle: #F5F6FA; /* 次级区块、内嵌列表 */ + --color-bg-muted: #EEF0F6; /* 更弱的填充 */ + --color-bg-input: #F7F8FB; /* 表单输入框底(此前被引用但从未定义,导致背景失效) */ + --color-bg-disabled: #F3F4F7; --color-bg-overlay: rgba(0, 0, 0, 0.45); - /* ============ 字体(规范 §7-11) ============ */ + /* ============ 字体 ============ */ + /* 小程序无法可靠加载 Web Font(wx.loadFontFace 依赖 HTTPS 白名单且有闪动风险), + 故使用中文系统字栈:iOS 走苹方、Android 走思源/系统黑体。 + 排版辨识度靠字号阶梯与字重建立,而非依赖字体本身。 */ --font-family-cn: -apple-system, "PingFang SC", "Noto Sans SC", "Hiragino Sans GB", "Microsoft YaHei", system-ui, sans-serif; + --font-family-number: "SF Pro Display", -apple-system, "DIN Alternate", "PingFang SC", sans-serif; - --font-size-xs: 12.00px; /* 12px */ - --font-size-sm: 13.00px; /* 13px */ - --font-size-md: 14.00px; /* 14px */ - --font-size-base: 16.00px; /* 16px */ - --font-size-lg: 18.00px; /* 18px */ - --font-size-xl: 20.00px; /* 20px */ - --font-size-2xl: 24.00px; /* 24px */ - --font-size-3xl: 28.00px; /* 28px */ + /* 字号阶梯 —— 正文 16.00px(16px) 起,元信息下限 12.00px(12px) */ + --font-size-micro: 11.00px; /* 11px 仅角标/装饰,禁用于正文 */ + --font-size-xs: 12.00px; /* 12px 元信息下限 */ + --font-size-sm: 13.00px; /* 13px 次要说明 */ + --font-size-md: 14.00px; /* 14px 次要正文 */ + --font-size-base: 16.00px; /* 16px 正文 */ + --font-size-lg: 18.00px; /* 18px 小标题 */ + --font-size-xl: 20.00px; /* 20px 区块标题 */ + --font-size-2xl: 24.00px; /* 24px 页面标题 */ + --font-size-3xl: 28.00px; /* 28px 大标题 */ + --font-size-display: 32.00px; /* 32px Hero */ + /* 字重:只用 4 档。禁止 550/650/750 等非百位值 —— Android 无对应字重会回退, + 导致同一设计在不同机型上粗细不一致(审计发现 30 处)。 */ --font-weight-regular: 400; --font-weight-medium: 500; --font-weight-semibold: 600; @@ -1784,51 +3198,68 @@ --line-height-tight: 1.25; --line-height-normal: 1.5; - --line-height-relaxed: 1.7; + --line-height-relaxed: 1.65; - /* ============ 间距(规范 §12,4px 栅格) ============ */ - --spacing-1: 4.00px; /* 4px */ - --spacing-2: 8.00px; /* 8px */ - --spacing-3: 12.00px; /* 12px */ - --spacing-4: 16.00px; /* 16px */ - --spacing-5: 20.00px; /* 20px */ - --spacing-6: 24.00px; /* 24px */ - --spacing-8: 32.00px; /* 32px */ - --spacing-10: 40.00px; /* 40px */ - --spacing-12: 48.00px; /* 48px */ + --letter-spacing-tight: 0; + --letter-spacing-wide: 0.50px; + --letter-spacing-wider: 1.00px; - --spacing-page-x: 16.00px; /* 页面左右 16px */ - --spacing-section: 24.00px; /* 区块间 24px */ - --spacing-card-inner: 16.00px; /* 卡片内部 16px */ - --spacing-tight: 8.00px; /* 紧密 8px */ + /* ============ 间距(4px 栅格) ============ */ + --spacing-1: 4.00px; + --spacing-2: 8.00px; + --spacing-3: 12.00px; + --spacing-4: 16.00px; + --spacing-5: 20.00px; + --spacing-6: 24.00px; + --spacing-8: 32.00px; + --spacing-10: 40.00px; + --spacing-12: 48.00px; - /* ============ 圆角(规范 §14) ============ */ - --radius-sm: 8.00px; /* 8px */ - --radius-md: 12.00px; /* 12px */ - --radius-lg: 16.00px; /* 16px */ - --radius-xl: 20.00px; /* 20px */ + --spacing-page-x: 16.00px; + --spacing-section: 24.00px; + --spacing-card-inner: 16.00px; + --spacing-tight: 8.00px; + + /* ============ 圆角 ============ */ + --radius-sm: 8.00px; + --radius-md: 12.00px; + --radius-lg: 16.00px; + --radius-xl: 20.00px; + --radius-2xl: 24.00px; --radius-full: 4999.50px; - /* ============ 阴影(规范 §15,极轻) ============ */ - --shadow-card: 0 4.00px 16.00px rgba(0, 0, 0, 0.04); + /* ============ 阴影(统一为一套,此前 30+ 种近似值) ============ */ + --shadow-card: 0 4.00px 14.00px rgba(35, 35, 95, 0.07); + --shadow-raised: 0 6.00px 18.00px rgba(35, 35, 95, 0.10); --shadow-popup: 0 8.00px 32.00px rgba(0, 0, 0, 0.10); + --shadow-night: 0 8.00px 20.00px rgba(28, 30, 88, 0.18); - /* ============ 边框(规范 §16) ============ */ + /* ============ 边框宽度 ============ */ --border-width: 0.50px; + --border-width-strong: 1.00px; - /* ============ 动效(规范 §17) ============ */ + /* ============ 触摸目标(无障碍下限 44×44px) ============ */ + --tap-min: 44.00px; /* 44px 最小可点区域 */ + --tap-comfortable: 48.00px; /* 48px 舒适尺寸:主操作 */ + --tap-gap: 8.00px; /* 8px 相邻目标最小间距 */ + + /* ============ 动效 ============ */ --motion-fast: 120ms; --motion-normal: 200ms; --motion-slow: 300ms; - --ease-standard: ease-out; + --ease-standard: cubic-bezier(0.32, 0.72, 0, 1); + --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1); + --press-scale: 0.97; + --press-opacity: 0.88; - /* ============ 层级 z-index(规范 §90) ============ */ + /* ============ 层级 z-index ============ */ --z-base: 1; --z-sticky: 100; --z-tabbar: 200; --z-dropdown: 500; --z-modal: 1000; --z-toast: 2000; + --z-ambient: 0; /* ============ 页面基础样式 ============ */ background-color: var(--color-bg-page); @@ -1838,7 +3269,10 @@ line-height: var(--line-height-normal); } -/* ============ 通用工具类 ============ */ +/* ========================================================================== + 通用工具类 + ========================================================================== */ + .container { padding: var(--spacing-page-x); } @@ -1852,17 +3286,34 @@ .flex-shrink-0 { flex-shrink: 0; } .wrap { flex-wrap: wrap; } +/* 4 列宫格:用 flex + 百分比宽度实现。 + 注:display:grid 在 WebView 渲染下可用,但 Skyline 不支持,故统一改为 flex 以免疫渲染引擎迁移。*/ +.grid-4 { + display: flex; + flex-wrap: wrap; +} +.grid-4 > .grid-item { + width: 25%; + box-sizing: border-box; +} + +.text-strong { color: var(--color-text-strong); } .text-primary { color: var(--color-text-primary); } .text-secondary { color: var(--color-text-secondary); } .text-tertiary { color: var(--color-text-tertiary); } .text-placeholder { color: var(--color-text-placeholder); } .text-white { color: var(--color-text-inverse); } -.text-brand { color: var(--color-primary); } -.text-success { color: var(--color-success); } -.text-warning { color: var(--color-warning); } -.text-danger { color: var(--color-danger); } -.text-info { color: var(--color-info); } +.text-brand { color: var(--color-primary-strong); } +/* 品牌色作文字只能用 -strong 变体:基础色 #E96B6B 在白底仅 3.10:1。 + 保留 .text-brand-soft 这个类名是为了不破坏既有引用,取值已统一到 -strong, + 如需「更亮的品牌色」请用于背景/图形而非文字。 */ +.text-brand-soft { color: var(--color-primary-strong); } +.text-success { color: var(--color-success-strong); } +.text-warning { color: var(--color-warning-strong); } +.text-danger { color: var(--color-danger-strong); } +.text-info { color: var(--color-info-strong); } +.font-micro { font-size: var(--font-size-micro); } .font-xs { font-size: var(--font-size-xs); } .font-sm { font-size: var(--font-size-sm); } .font-md { font-size: var(--font-size-md); } @@ -1871,6 +3322,7 @@ .font-xl { font-size: var(--font-size-xl); } .font-2xl { font-size: var(--font-size-2xl); } .font-3xl { font-size: var(--font-size-3xl); } +.font-display { font-size: var(--font-size-display); } .font-regular { font-weight: var(--font-weight-regular); } .font-medium { font-weight: var(--font-weight-medium); } @@ -1908,7 +3360,7 @@ padding-bottom: 0px; } -/* 页面卡片基础样式(中低密度留白) */ +/* 页面卡片基础样式 */ .card-base { background: var(--color-bg-card); border-radius: var(--radius-lg); @@ -1922,273 +3374,423 @@ background: var(--color-divider); } -.wx-page{background:var(--color-bg-page)}.service-page{min-height:100vh;padding-bottom:calc(70.00px + 0px)}.hero{padding:22.00px 16.00px 27.00px;background:linear-gradient(140deg,var(--color-primary-lighter),#FFF8EE);position:relative;overflow:hidden}.eyebrow{display:inline-flex;padding:3.50px 7.00px;border-radius:499.50px;background:rgba(255,255,255,.72);color:var(--color-primary);font-size:10.50px}.hero-title{display:block;margin-top:9.00px;font-size:20.00px;font-weight:700;line-height:1.35}.hero-desc{display:block;width:82%;margin-top:7.00px;font-size:12.50px;color:var(--color-text-secondary);line-height:1.7}.content{padding:0 var(--spacing-page-x)}.block{margin-top:var(--spacing-section)}.block-title{display:block;font-size:15.50px;font-weight:650}.block-subtitle{display:block;margin-top:4.00px;font-size:11.50px;color:var(--color-text-tertiary)}.card{margin-top:9.00px;padding:14.00px;background:var(--color-bg-card);border:0.50px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.feature-row,.menu-row,.record-row{display:flex;align-items:center;gap:10.00px;min-height:56.00px;padding:9.00px 0;border-bottom:0.50px solid var(--color-divider)}.feature-row:last-child,.menu-row:last-child,.record-row:last-child{border-bottom:0}.feature-icon{width:36.00px;height:36.00px;display:flex;align-items:center;justify-content:center;flex:none;border-radius:11.00px;background:var(--color-primary-light);color:var(--color-primary);font-weight:700}.feature-copy{flex:1;min-width:0}.feature-title{display:block;font-size:14.00px;font-weight:600}.feature-desc,.meta{display:block;margin-top:3.50px;font-size:11.50px;color:var(--color-text-tertiary);line-height:1.55}.arrow{font-size:20.00px;color:var(--color-text-disabled)}.tag{display:inline-flex;margin-right:5.00px;margin-top:5.00px;padding:3.00px 6.50px;border-radius:499.50px;background:var(--color-success-light);color:var(--color-success);font-size:10.00px}.tag.warning{background:var(--color-warning-light);color:var(--color-warning)}.primary-btn,.secondary-btn{height:44.00px;display:flex;align-items:center;justify-content:center;border-radius:22.00px;font-size:14.00px;font-weight:600}.primary-btn{background:linear-gradient(135deg,var(--mini-accent-coral),var(--mini-accent-pink));color:var(--color-text-inverse);box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)}.primary-btn.disabled{background:#E6E8EF;color:#989DAF;box-shadow:none}.secondary-btn{background:var(--color-primary-light);color:var(--color-primary)}.fixed-action{position:fixed;left:0;right:0;bottom:0;padding:9.00px var(--spacing-page-x) calc(9.00px + 0px);background:rgba(255,255,255,.96);border-top:0.50px solid var(--color-divider);z-index:100}.field{margin-top:13.00px}.label{display:block;margin-bottom:6.00px;font-size:12.50px;font-weight:600}.input,.select-box,.textarea{width:100%;box-sizing:border-box;background:#FCFAF8;border:0.50px solid var(--color-border);border-radius:var(--radius-md);font-size:13.00px}.input,.select-box{height:44.00px;padding:0 12.00px;display:flex;align-items:center}.textarea{min-height:90.00px;padding:11.00px}.notice{margin-top:10.00px;padding:11.00px;border-radius:var(--radius-md);background:#F3F7FC;color:var(--color-text-secondary);font-size:11.50px;line-height:1.65}.empty-panel{text-align:center;padding:35.00px 15.00px}.empty-symbol{width:48.00px;height:48.00px;margin:auto;display:flex;align-items:center;justify-content:center;border-radius:15.00px;background:var(--color-primary-light);color:var(--color-primary);font-size:18.00px;font-weight:700}.empty-title{display:block;margin-top:11.00px;font-size:15.00px;font-weight:600}.article-card{margin-top:9.00px;background:var(--color-bg-card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.article-cover{height:110.00px;padding:12.00px;background:linear-gradient(135deg,#F5E5DE,#F9F1E8);display:flex;align-items:flex-end}.article-cover text{font-size:21.00px;color:rgba(125,76,63,.52);font-weight:700}.article-body{padding:12.00px}.article-title{display:block;font-size:14.50px;font-weight:650;line-height:1.45}.article-meta{display:block;margin-top:5.00px;font-size:11.00px;color:var(--color-text-tertiary)}.article-content{padding:16.00px;background:var(--color-bg-card);font-size:14.00px;line-height:1.9;color:var(--color-text-secondary)}.article-content .lead{display:block;font-size:15.50px;color:var(--color-text-primary);font-weight:600;margin-bottom:12.00px}.danger-card{background:#FFF8F4;border-color:#F5DED2}.danger-card .feature-icon{background:#FFF0EA;color:#C85D43}@media(max-width:340px){.hero-title{font-size:18.00px}.hero-desc{width:92%}} +/* ========================================================================== + 可访问性:只用 token,不用工具类(2026-09-23 修订) + -------------------------------------------------------------------------- + v2 曾在此处新增 .tap-min / .tap-gap / .focusable / .pressable 四个工具类。 + 复检发现全部零引用(等价能力已各自写在组件样式内,例如 button/index.wxss + 直接使用 min-height:var(--tap-min)),且存在两个硬问题: -.service-shell{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:#F4F5FA}.service-content{padding:4.00px 12.00px 18.00px}.service-status{display:flex;align-items:center;justify-content:space-between;margin-top:12.00px;padding:10.00px 12.00px;border-radius:11.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-status__label{color:#7B8198;font-size:10.50px}.service-status__value{padding:3.00px 7.00px;border-radius:9.00px;background:#EAF8F2;color:#329472;font-size:9.50px;font-weight:650}.service-status__value.disabled{background:#FFF0F0;color:#D45A60}.service-topics{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.service-topic{min-height:74.00px;padding:10.00px;border-radius:12.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-topic__icon{display:flex;align-items:center;justify-content:center;width:27.00px;height:27.00px;border-radius:8.50px;background:#FFF0F5}.service-topic__icon image{width:17.00px;height:17.00px}.service-topic__title{display:block;margin-top:6.50px;color:#283056;font-size:12.00px;font-weight:650}.service-topic__desc{display:block;margin-top:3.00px;color:#858A9E;font-size:9.50px;line-height:1.45}.service-actions{display:flex;gap:7.00px}.service-actions .secondary-btn{width:95.00px;flex:none}.service-actions .primary-btn{flex:1}.privacy-note{display:flex;align-items:flex-start;gap:7.00px;margin-top:11.00px;padding:10.00px;border-radius:11.00px;background:#F1F4FF;color:#69718E;font-size:10.00px;line-height:1.55}.privacy-note image{width:17.00px;height:17.00px;flex:none} + 1) `.tap-gap > * + *` 用了通配符与兄弟选择器 —— WXSS 不支持, + wcc 编译期直接报 `error at token '*'`,导致整个小程序编译失败。 + (这是编译错误,不是静默失效,代价最高。) + 2) `.pressable:active` / `.focusable:focus-visible` 的伪类在 view 上 + 不生效(小程序须用 hover-class),属于"写了等于没写"。 + + 故整块移除,保留 token。需要热区/间距时直接引用 token: + min-height: var(--tap-min); → 44.00px = 44px,最小可点区域 + gap: var(--tap-gap); → 8.00px = 8px,相邻目标间距(flex gap) + 【WXSS 禁用清单】星号通配符、兄弟选择器、属性选择器。 + 【注释约束】WXSS 注释**不可嵌套**:内层注释的结束标记会提前终止外层注释, + 其后的文字会被当成真实样式解析,导致编译失败或样式被污染。 + (2026-09-23 实证:本块注释初版即踩此坑。) + ========================================================================== */ + +.wx-page{background:var(--color-bg-page)}.service-page{min-height:100vh;padding-bottom:calc(70.00px + 0px)}.hero{padding:22.00px 16.00px 27.00px;background:linear-gradient(140deg,var(--color-primary-lighter),var(--color-warning-light));position:relative;overflow:hidden}.eyebrow{display:inline-flex;padding:3.50px 7.00px;border-radius:499.50px;background:rgba(255,255,255,.72);color:var(--color-primary-strong);font-size:12.00px}.hero-title{display:block;margin-top:9.00px;font-size:20.00px;font-weight:700;line-height:1.35}.hero-desc{display:block;width:82%;margin-top:7.00px;font-size:12.50px;color:var(--color-text-secondary);line-height:1.7}.content{padding:0 var(--spacing-page-x)}.block{margin-top:var(--spacing-section)}.block-title{display:block;font-size:15.50px;font-weight:600}.block-subtitle{display:block;margin-top:4.00px;font-size:12.00px;color:var(--color-text-tertiary)}.card{margin-top:9.00px;padding:14.00px;background:var(--color-bg-card);border:0.50px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.feature-row,.menu-row,.record-row{display:flex;align-items:center;gap:10.00px;min-height:56.00px;padding:9.00px 0;border-bottom:0.50px solid var(--color-divider)}.feature-row:last-child,.menu-row:last-child,.record-row:last-child{border-bottom:0}.feature-icon{width:36.00px;height:36.00px;display:flex;align-items:center;justify-content:center;flex:none;border-radius:11.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-weight:700}.feature-copy{flex:1;min-width:0}.feature-title{display:block;font-size:14.00px;font-weight:600}.feature-desc,.meta{display:block;margin-top:3.50px;font-size:12.00px;color:var(--color-text-tertiary);line-height:1.55}.arrow{font-size:20.00px;color:var(--color-text-disabled)}.tag{display:inline-flex;margin-right:5.00px;margin-top:5.00px;padding:3.00px 6.50px;border-radius:499.50px;background:var(--color-success-light);color:var(--color-success-strong);font-size:12.00px}.tag.warning{background:var(--color-warning-light);color:var(--color-warning-strong)}.primary-btn,.secondary-btn{height:44.00px;display:flex;align-items:center;justify-content:center;border-radius:22.00px;font-size:14.00px;font-weight:600}.primary-btn{background:var(--gradient-brand-solid);color:var(--color-text-inverse);box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)}.primary-btn.disabled{background:var(--color-bg-muted);color:var(--color-text-tertiary);box-shadow:none}.secondary-btn{background:var(--color-primary-light);color:var(--color-primary-strong)}.fixed-action{position:fixed;left:0;right:0;bottom:0;padding:9.00px var(--spacing-page-x) calc(9.00px + 0px);background:rgba(255,255,255,.96);border-top:0.50px solid var(--color-divider);z-index:100}.field{margin-top:13.00px}.label{display:block;margin-bottom:6.00px;font-size:12.50px;font-weight:600}.input,.select-box,.textarea{width:100%;box-sizing:border-box;background:var(--color-bg-page);border:0.50px solid var(--color-border);border-radius:var(--radius-md);font-size:13.00px}.input,.select-box{height:44.00px;padding:0 12.00px;display:flex;align-items:center}.textarea{min-height:90.00px;padding:11.00px}.notice{margin-top:10.00px;padding:11.00px;border-radius:var(--radius-md);background:var(--color-info-light);color:var(--color-text-secondary);font-size:12.00px;line-height:1.65}.select-box.is-readonly{background:var(--color-bg-subtle);color:var(--color-text-secondary)}.empty-panel{text-align:center;padding:35.00px 15.00px}.empty-symbol{width:48.00px;height:48.00px;margin:auto;display:flex;align-items:center;justify-content:center;border-radius:15.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-size:18.00px;font-weight:700}.empty-title{display:block;margin-top:11.00px;font-size:15.00px;font-weight:600}.article-card{margin-top:9.00px;background:var(--color-bg-card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.article-cover{height:110.00px;padding:12.00px;background:linear-gradient(135deg,var(--color-warning-light),var(--color-warning-light));display:flex;align-items:flex-end}.article-cover text{font-size:21.00px;color:rgba(125,76,63,.52);font-weight:700}.article-body{padding:12.00px}.article-title{display:block;font-size:14.50px;font-weight:600;line-height:1.45}.article-meta{display:block;margin-top:5.00px;font-size:12.00px;color:var(--color-text-tertiary)}.article-content{padding:16.00px;background:var(--color-bg-card);font-size:14.00px;line-height:1.9;color:var(--color-text-secondary)}.article-content .lead{display:block;font-size:15.50px;color:var(--color-text-primary);font-weight:600;margin-bottom:12.00px}.danger-card{background:var(--color-primary-lighter);border-color:var(--color-primary-light)}.danger-card .feature-icon{background:var(--color-warning-light);color:var(--color-warning-strong)}@media(max-width:340px){.hero-title{font-size:18.00px}.hero-desc{width:92%}} + +.service-shell{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:var(--color-bg-page)}.service-content{padding:4.00px 12.00px 18.00px}.service-status{display:flex;align-items:center;justify-content:space-between;margin-top:12.00px;padding:10.00px 12.00px;border-radius:11.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-status__label{color:var(--color-text-tertiary);font-size:12.00px}.service-status__value{padding:3.00px 7.00px;border-radius:9.00px;background:var(--color-success-light);color:var(--color-success-strong);font-size:12.00px;font-weight:600}.service-status__value.disabled{background:var(--color-danger-light);color:var(--color-danger-strong)}.service-topics{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.service-topic{min-height:74.00px;padding:10.00px;border-radius:12.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-topic__icon{display:flex;align-items:center;justify-content:center;width:27.00px;height:27.00px;border-radius:8.50px;background:var(--color-primary-light)}.service-topic__icon image{width:17.00px;height:17.00px}.service-topic__title{display:block;margin-top:6.50px;color:var(--color-text-strong);font-size:12.00px;font-weight:600}.service-topic__desc{display:block;margin-top:3.00px;color:var(--color-text-tertiary);font-size:12.00px;line-height:1.45}.service-actions{display:flex;gap:7.00px}.service-actions .secondary-btn{width:95.00px;flex:none}.service-actions .primary-btn{flex:1}.privacy-note{display:flex;align-items:flex-start;gap:7.00px;margin-top:11.00px;padding:10.00px;border-radius:11.00px;background:var(--color-info-light);color:var(--color-text-tertiary);font-size:12.00px;line-height:1.55}.privacy-note image{width:17.00px;height:17.00px;flex:none} /* ==== miniapp/components/section-header ==== */ +/** + * 区块标题(全站所有页面共用,是排版层级的关键一环) + * + * 2026-09-22 修订: + * 1) 层级拉开:标题 18.00px→20.00px(--font-size-xl),与正文 16.00px / 卡片标题 14.00px + * 形成「区块标题 > 卡片标题 > 正文 > 元信息」四级阶梯。 + * 旧值 18.00px 与卡片标题仅差 5.00px,层级读不出来。 + * 2) 右侧 action 是全站最容易被忽略的触摸目标:只有 13.00px 文字高(约 13px), + * 远低于 44px 下限。改为 min-height:--tap-min,热区向上补白。 + * 3) action 文字色原为 --color-primary(#E96B6B)=3.10:1,不达标,改 -strong。 + */ .ui-section { - display: flex; - align-items: center; - justify-content: space-between; - padding: var(--spacing-3) var(--spacing-page-x); + display:flex; + align-items:center; + justify-content:space-between; + padding:var(--spacing-2) var(--spacing-page-x); } .ui-section__left { - display: flex; - align-items: baseline; + display:flex; + align-items:baseline; + min-width:0; } .ui-section__title { - font-size: var(--font-size-lg); - font-weight: var(--font-weight-semibold); - color: var(--color-text-primary); + font-size:var(--font-size-xl); + font-weight:var(--font-weight-semibold); + color:var(--color-text-strong); + letter-spacing:var(--letter-spacing-tight); } .ui-section__subtitle { - margin-left: var(--spacing-2); - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); + margin-left:var(--spacing-2); + font-size:var(--font-size-xs); + color:var(--color-text-tertiary); } .ui-section__action { - display: flex; - align-items: center; - font-size: var(--font-size-sm); - color: var(--color-primary); + display:flex; + align-items:center; + flex:none; + min-height:var(--tap-min); + padding-left:var(--spacing-3); + font-size:var(--font-size-sm); + font-weight:var(--font-weight-medium); + color:var(--color-primary-strong); + transition:opacity var(--motion-fast) var(--ease-standard); +} +.ui-section__action:active { + opacity:var(--press-opacity); } .ui-section__arrow { - margin-left: 2.00px; - width: 12.00px; - height: 12.00px; + margin-left:2.00px; + width:12.00px; + height:12.00px; } /* ==== miniapp/components/activity-card ==== */ -.ui-act{overflow:hidden;border-radius:14.00px;background:#fff;box-shadow:0 5.00px 16.00px rgba(34,35,91,.08)}.ui-act__cover{position:relative;width:100%;height:120.00px;background:#F0F1F6}.ui-act__cover-img{display:block;width:100%;height:100%}.ui-act__fee-badge{position:absolute;top:9.00px;right:9.00px;padding:3.50px 7.50px;border-radius:11.00px;background:linear-gradient(135deg,var(--mini-accent-coral),var(--mini-accent-pink));color:#fff;font-size:9.00px;font-weight:600}.ui-act__body{padding:11.00px 12.00px}.ui-act__title{overflow:hidden;color:#222746;font-size:14.00px;font-weight:700;line-height:1.35;white-space:nowrap;text-overflow:ellipsis}.ui-act__meta{margin-top:3.50px;color:#767C94;font-size:10.00px;line-height:1.45}.ui-act__intro{display:-webkit-box;overflow:hidden;margin-top:6.00px;color:#626981;font-size:10.50px;line-height:1.55;-webkit-box-orient:vertical;-webkit-line-clamp:2}.ui-act__footer{display:flex;align-items:center;justify-content:space-between;margin-top:9.00px}.ui-act__capacity{color:#858A9E;font-size:9.50px}.ui-act__status-action{min-width:63.00px;height:28.00px;display:flex;align-items:center;justify-content:center;border-radius:14.00px;background:linear-gradient(135deg,var(--mini-accent-coral),var(--mini-accent-pink));color:#fff;font-size:10.50px;font-weight:650}.ui-act__status-action.disabled{background:#EFF0F5;color:#8E93A6}.ui-act--compact{display:flex;height:100.00px}.ui-act--compact .ui-act__cover{width:100.00px;height:100.00px;flex-shrink:0}.ui-act--compact .ui-act__body{flex:1;min-width:0;padding:8.00px 9.00px}.ui-act--compact .ui-act__intro{display:none} +.ui-act{overflow:hidden;border-radius:14.00px;background:var(--color-bg-card);box-shadow:0 5.00px 16.00px rgba(34,35,91,.08)}.ui-act__cover{position:relative;width:100%;height:120.00px;background:var(--color-bg-subtle)}.ui-act__cover-img{display:block;width:100%;height:100%}.ui-act__fee-badge{position:absolute;top:9.00px;right:9.00px;padding:3.50px 7.50px;border-radius:11.00px;background:var(--gradient-brand-solid);color:var(--color-text-inverse);font-size:9.00px;font-weight:600}.ui-act__body{padding:11.00px 12.00px}.ui-act__title{overflow:hidden;color:var(--color-text-strong);font-size:14.00px;font-weight:700;line-height:1.35;white-space:nowrap;text-overflow:ellipsis}.ui-act__meta{margin-top:3.50px;color:var(--color-text-tertiary);font-size:12.00px;line-height:1.45}.ui-act__intro{display:-webkit-box;overflow:hidden;margin-top:6.00px;color:var(--color-text-secondary);font-size:12.00px;line-height:1.55;-webkit-box-orient:vertical;-webkit-line-clamp:2}.ui-act__footer{display:flex;align-items:center;justify-content:space-between;margin-top:9.00px}.ui-act__capacity{color:var(--color-text-tertiary);font-size:12.00px}.ui-act__status-action{min-width:63.00px;min-height:var(--tap-min);display:flex;align-items:center;justify-content:center;border-radius:14.00px;background:var(--gradient-brand-solid);color:var(--color-text-inverse);font-size:12.00px;font-weight:600}.ui-act__status-action.disabled{background:var(--color-bg-subtle);color:var(--color-text-tertiary)}.ui-act--compact{display:flex;height:100.00px}.ui-act--compact .ui-act__cover{width:100.00px;height:100.00px;flex-shrink:0}.ui-act--compact .ui-act__body{flex:1;min-width:0;padding:8.00px 9.00px}.ui-act--compact .ui-act__intro{display:none} + .ui-act__type-row{display:flex;align-items:center;margin-top:5.00px;flex-wrap:wrap}.ui-act__type-badge{padding:2.00px 7.00px;border-radius:9.00px;background:var(--color-primary-light);color:var(--color-danger-strong);font-size:9.00px;font-weight:600}.ui-act__eligibility{margin-left:6.00px;color:var(--color-text-tertiary);font-size:12.00px} /* ==== miniapp/components/loading ==== */ .ui-loading--block { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: var(--spacing-8) var(--spacing-page-x); + display:flex; + flex-direction:column; + align-items:center; + justify-content:center; + padding:var(--spacing-8) var(--spacing-page-x); } .ui-loading--inline { - display: inline-flex; - align-items: center; + display:inline-flex; + align-items:center; } .ui-loading__spinner { - width: 30.00px; - height: 30.00px; - display: flex; - align-items: center; - justify-content: center; + width:30.00px; + height:30.00px; + display:flex; + align-items:center; + justify-content:center; } .ui-loading__spinner-icon { - width: 24.00px; - height: 24.00px; - animation: ui-loading-spin 0.8s linear infinite; + width:24.00px; + height:24.00px; + animation:ui-loading-spin 0.8s linear infinite; } @keyframes ui-loading-spin { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } + from { transform:rotate(0deg); } + to { transform:rotate(360deg); } } .ui-loading__text { - margin-top: var(--spacing-3); - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); + margin-top:var(--spacing-3); + font-size:var(--font-size-sm); + color:var(--color-text-tertiary); } /* Skeleton */ .ui-loading__skeleton { - width: 100%; + width:100%; } .ui-loading__skeleton-row { - display: flex; - align-items: center; - padding: var(--spacing-3) var(--spacing-page-x); - background: var(--color-bg-card); - border-bottom: 0.50px solid var(--color-divider); + display:flex; + align-items:center; + padding:var(--spacing-3) var(--spacing-page-x); + background:var(--color-bg-card); + border-bottom:0.50px solid var(--color-divider); } .ui-loading__skeleton-avatar { - width: 44.00px; - height: 44.00px; - border-radius: 50%; - background: var(--color-bg-disabled); - margin-right: var(--spacing-3); - flex-shrink: 0; + width:44.00px; + height:44.00px; + border-radius:50%; + background:var(--color-bg-disabled); + margin-right:var(--spacing-3); + flex-shrink:0; } .ui-loading__skeleton-content { - flex: 1; - min-width: 0; + flex:1; + min-width:0; } .ui-loading__skeleton-line { - height: 12.00px; - background: var(--color-bg-disabled); - border-radius: var(--radius-sm); - position: relative; - overflow: hidden; + height:12.00px; + background:var(--color-bg-disabled); + border-radius:var(--radius-sm); + position:relative; + overflow:hidden; } .ui-loading__skeleton-line--title { - width: 40%; - margin-bottom: var(--spacing-2); + width:40%; + margin-bottom:var(--spacing-2); } .ui-loading__skeleton-line--meta { - width: 70%; + width:70%; } /* shimmer */ .ui-loading__skeleton-line::after, .ui-loading__skeleton-avatar::after { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: linear-gradient( + content:''; + position:absolute; + top:0; + left:0; + width:100%; + height:100%; + background:linear-gradient( 90deg, transparent 0%, rgba(255, 255, 255, 0.55) 50%, transparent 100% ); - animation: ui-loading-shimmer 1.4s ease-in-out infinite; + animation:ui-loading-shimmer 1.4s ease-in-out infinite; } @keyframes ui-loading-shimmer { - 0% { transform: translateX(-100%); } - 100% { transform: translateX(100%); } + 0% { transform:translateX(-100%); } + 100% { transform:translateX(100%); } } /* ==== miniapp/components/empty ==== */ .ui-empty { - display: flex; - flex-direction: column; - align-items: center; - padding: var(--spacing-10) var(--spacing-page-x); - text-align: center; + display:flex; + flex-direction:column; + align-items:center; + padding:var(--spacing-10) var(--spacing-page-x); + text-align:center; } .ui-empty__illustration { - width: 80.00px; - height: 80.00px; - border-radius: 50%; - background: var(--color-bg-disabled); - display: flex; - align-items: center; - justify-content: center; - margin-bottom: var(--spacing-4); + width:80.00px; + height:80.00px; + border-radius:50%; + background:var(--color-bg-disabled); + display:flex; + align-items:center; + justify-content:center; + margin-bottom:var(--spacing-4); } .ui-empty__icon { - width: 36.00px; - height: 36.00px; - opacity: 0.72; + width:36.00px; + height:36.00px; + opacity:0.72; } .ui-empty__title { - font-size: var(--font-size-lg); - font-weight: var(--font-weight-medium); - color: var(--color-text-primary); - margin-bottom: var(--spacing-2); + font-size:var(--font-size-lg); + font-weight:var(--font-weight-medium); + color:var(--color-text-primary); + margin-bottom:var(--spacing-2); } .ui-empty__desc { - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); - line-height: var(--line-height-relaxed); - max-width: 240.00px; + font-size:var(--font-size-sm); + color:var(--color-text-tertiary); + line-height:var(--line-height-relaxed); + max-width:240.00px; } .ui-empty__actions { - display: flex; - flex-direction: column; - gap: var(--spacing-2); - margin-top: var(--spacing-6); - width: 100%; - max-width: 240.00px; + display:flex; + flex-direction:column; + gap:var(--spacing-2); + margin-top:var(--spacing-6); + width:100%; + max-width:240.00px; } .ui-empty__action { - display: flex; - align-items: center; - justify-content: center; - height: 40.00px; - border-radius: var(--radius-full); - font-size: var(--font-size-base); - font-weight: var(--font-weight-medium); -} + display:flex; + align-items:center; + justify-content:center; + min-height:var(--tap-min); + border-radius:var(--radius-full); + font-size:var(--font-size-base); + font-weight:var(--font-weight-medium); +min-width:var(--tap-min);} .ui-empty__action--primary { - background: var(--color-primary); - color: #FFFFFF; + background:var(--color-primary-solid); + color:var(--color-text-inverse); } .ui-empty__action--secondary { - background: var(--color-bg-card); - color: var(--color-primary); - border: 0.50px solid var(--color-primary); + background:var(--color-bg-card); + color:var(--color-primary-strong); + border:0.50px solid var(--color-primary); } -.act-page{min-height:100vh;padding-bottom:20.00px;background:#F4F5FA}.activity-hero{padding:20px 12.00px 13.00px;border-radius:0 0 18.00px 18.00px;background:linear-gradient(160deg,var(--mini-night-start),var(--mini-night-end));box-shadow:var(--mini-shadow)}.activity-nav{position:relative;display:flex;align-items:center;justify-content:center;height:44.00px}.activity-title{color:#fff;font-size:15.50px;font-weight:700}.activity-calendar{position:absolute;right:0;display:flex;align-items:center;justify-content:center;width:31.00px;height:31.00px;border:0.50px solid rgba(255,255,255,.18);border-radius:15.50px;background:rgba(255,255,255,.1)}.activity-calendar image{width:17.00px;height:17.00px;filter:brightness(0) invert(1)}.activity-categories{white-space:nowrap}.activity-category-row{display:inline-flex;gap:6.00px}.activity-category{padding:5.50px 11.00px;border-radius:12.50px;background:rgba(255,255,255,.1);color:rgba(255,255,255,.72);font-size:10.00px}.activity-category.active{background:#fff;color:var(--mini-accent-pink);font-weight:650}.activity-heading{display:flex;align-items:flex-end;justify-content:space-between;padding:16.00px 14.00px 8.00px}.activity-heading>view{display:flex;flex-direction:column}.heading-title{color:#252A49;font-size:15.00px;font-weight:700}.heading-subtitle{margin-top:2.50px;color:#8A8FA4;font-size:10.00px}.my-activity-link{color:var(--mini-accent-pink);font-size:10.50px}.act-loading{padding:6.00px 12.00px}.act-list{display:flex;flex-direction:column;gap:10.00px;padding:4.00px 12.00px 0}.act-list__more{display:flex;justify-content:center;padding:12.00px 0}.act-list__end{text-align:center;padding:12.00px 0;color:#9A9EB0;font-size:10.00px}.act-empty{padding-top:35.00px} +/* --nav-status / --nav-h / --nav-right 由 activity.ts 经 utils/nav-metrics 实测胶囊按钮后注入 */ +.act-page{min-height:100vh;padding-bottom:20.00px;background:var(--color-bg-page)}.activity-hero{padding:var(--nav-status, 44px) 12.00px 13.00px;border-radius:0 0 18.00px 18.00px;background:linear-gradient(160deg,var(--mini-night-start),var(--mini-night-end));box-shadow:var(--mini-shadow)}.activity-nav{position:relative;display:flex;align-items:center;justify-content:center;height:var(--nav-h, 40.00px)}.activity-title{color:var(--color-text-inverse);font-size:15.50px;font-weight:700}.activity-calendar{position:absolute;right:var(--nav-right, 102px);display:flex;align-items:center;justify-content:center;width:31.00px;height:31.00px;border:0.50px solid rgba(255,255,255,.18);border-radius:15.50px;background:rgba(255,255,255,.1)}.activity-calendar image{width:17.00px;height:17.00px;filter:brightness(0) invert(1)}.activity-categories{white-space:nowrap}.activity-category-row{display:inline-flex;gap:6.00px}.activity-category{padding:5.50px 11.00px;border-radius:12.50px;background:rgba(255,255,255,.1);color:rgba(255,255,255,.72);font-size:12.00px}.activity-category.active{background:var(--color-bg-card);color:var(--color-primary-strong);font-weight:600}.activity-heading{display:flex;align-items:flex-end;justify-content:space-between;padding:16.00px 14.00px 8.00px}.activity-heading>view{display:flex;flex-direction:column}.heading-title{color:var(--color-text-strong);font-size:15.00px;font-weight:700}.heading-subtitle{margin-top:2.50px;color:var(--color-text-tertiary);font-size:12.00px}.my-activity-link{color:var(--color-primary-strong);font-size:12.00px}.act-loading{padding:6.00px 12.00px}.act-list{display:flex;flex-direction:column;gap:10.00px;padding:4.00px 12.00px 0}.act-list__more{display:flex;justify-content:center;padding:12.00px 0}.act-list__end{text-align:center;padding:12.00px 0;color:var(--color-text-tertiary);font-size:12.00px}.act-empty{padding-top:35.00px} /** * 丹阳公益婚恋服务平台 - 全局 Design Token * - * 依据《前端组件库与 Design Token 规范 V1.0》 - * 单位说明:rpx(375.00px = 屏幕宽度),规范 px 值按 2x 映射为 rpx - * 禁止页面层写死颜色/间距/圆角,必须引用 var(--token) + * v2(2026-09-22 设计系统夯实) + * --------------------------------------------------------------- + * 本次修订针对审计发现的系统性问题,逐条给出依据: + * + * 1) 品牌色不能承载文字 → 引入「基础色 / -strong」分级 + * #E96B6B on 白 = 3.10:1,白字 on #E96B6B = 3.10:1,on #FFF3F2 = 2.85:1, + * 三条路径都不满足正文 4.5:1。故: + * --color-primary 仅用于大色块、渐变、光晕、装饰(非文字) + * --color-primary-strong 用于文字、小图标、纯文字链接(5.33:1 ✓) + * --color-primary-solid 实心按钮底(白字 ≥4.5:1 ✓) + * 功能色(success/warning/danger/info)同此分级。 + * + * 2) 次要文字对比度过低 + * 旧 --color-text-tertiary(#777) = 4.48(on 白,勉强)/ #999 实测 2.85 却被用了 71 次。 + * 现将三级文字压到 #646C85 = 5.22:1,占位符保留浅色(占位符非正文)。 + * + * 3) 颜色碎片化 + * 审计前全站 182 种 hex、770 次硬编码(54 种灰、60 种蓝紫、40 种红橙)。 + * 本文件是唯一的颜色事实源;页面层禁止再写 hex,一律 var(--token)。 + * + * 4) 触摸目标 + * 组件库默认按钮只有 40px、小号 28px、"喜欢"按钮 31px。 + * 统一以 --tap-min(44.00px=44px) 为下限,--tap-gap 为最小间距。 + * + * 5) 动效几乎未落地(--motion-* 全站仅 5 次引用) + * 补充 --ease-spring 与 --press-scale,让点击有即时反馈。 + * + * 6) 夜间氛围层缺失(参考图有明显的光晕/星点,代码只有纯渐变) + * 新增 --mini-glow-* / --mini-star / --mini-glass / --mini-hairline。 + * + * 单位说明:rpx(375.00px = 屏幕宽度,0.50px ≈ 0.5px @375pt) + * 旧 token 名全部保留(88 个 wxss 共 909 处引用),只更新取值,避免大范围失效。 */ .wx-page { - /* ============ 品牌主色(规范 §3) ============ */ - --color-primary: #E96B6B; - --color-primary-active: #D95F5F; + /* ============ 品牌主色(分级:色块 / 文字 / 实心按钮) ============ */ + --color-primary: #E96B6B; /* 基础色:渐变、光晕、装饰、非文字图形 */ + --color-primary-strong: #B8434A; /* 文字与小图标(5.33:1 on 白,4.91:1 on 浅粉底) */ + --color-primary-solid: #C24C50; /* 实心按钮底(白字 4.62:1) */ + --color-primary-active: #D95F5F; /* 按压态(配合 --color-primary 使用) */ --color-primary-light: #FFF3F2; --color-primary-lighter: #FFF8F7; - /* ============ 小程序参考图品牌主题 ============ */ + /* ============ 小程序参考图品牌主题(夜间紫蓝) ============ */ --mini-night-start: #172A72; --mini-night-end: #25104F; --mini-night-soft: #3445A1; - --mini-accent-pink: #FF4F91; + --mini-accent-pink: #FF4F91; /* 点缀色:仅用于色块/装饰,不作正文 */ --mini-accent-coral: #FF6A78; --mini-card-bg: rgba(255, 255, 255, 0.98); --mini-text: #1F2744; --mini-muted: #7D839B; --mini-card-radius: 12.00px; - --mini-text-on-night: #FFFFFF; - --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); + --mini-text-on-night: #FFFFFF; /* on 深底 13.04:1 ✓ */ + --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); /* on 深底 ≈8:1 ✓ */ --mini-shadow: 0 8.00px 20.00px rgba(28, 30, 88, 0.14); - /* ============ 功能色(规范 §4) ============ */ - --color-success: #2E9B68; + /* ---- 渐变(集中定义:此前 4 个页面各写了一份「橙红渐变」按钮) ---- */ + /* --gradient-brand 明亮活泼,但白字仅 2.77:1 —— 只能用于无文字的装饰填充。 */ + --gradient-brand: linear-gradient(135deg, #FF6A78 0%, #E96B6B 100%); + /* 承载白字的 CTA 渐变:两端 #C24C50(4.73:1) / #B8434A(5.33:1) 均达标。 */ + --gradient-brand-solid: linear-gradient(135deg, #C24C50 0%, #B8434A 100%); + --gradient-night: linear-gradient(160deg, #172A72 0%, #25104F 100%); + --gradient-night-soft: linear-gradient(160deg, #3445A1 0%, #172A72 100%); + + /* ---- 首页 4×2 入口宫格图标渐变(参考图 2:高饱和圆角砖 + 白色描画图标) ---- + 白图标的对比度判据是**非文本图形 3:1**(WCAG 1.4.11)。渐变是斜向的、图标又跨在 + 两色之间,所以**较亮的一端也必须达标** —— 下表注释给的是 0% 处实算值,100% 更暗只会更高。 + 色相按业务语义固定(不随 tone 名漂移):找对象/婚前辅导=玫瑰粉系、公益红娘/服务站=暖橙系、 + 公益活动=紫罗兰、婚恋咨询=蓝、婚恋课堂=紫、婚恋反诈=绿。 */ + --gradient-entry-rose: linear-gradient(135deg, #F56287 0%, #F34671 100%); /* 3.01:1 / 3.54:1 */ + --gradient-entry-orange: linear-gradient(135deg, #F66A06 0%, #D95E06 100%); /* 3.01:1 / 3.78:1 */ + --gradient-entry-violet: linear-gradient(135deg, #A380F5 0%, #8F64F2 100%); /* 3.02:1 / 3.98:1 */ + --gradient-entry-blue: linear-gradient(135deg, #5195F6 0%, #3484F4 100%); /* 3.01:1 / 3.65:1 */ + --gradient-entry-purple: linear-gradient(135deg, #B27BF0 0%, #A260ED 100%); /* 3.01:1 / 3.87:1 */ + --gradient-entry-pink: linear-gradient(135deg, #F2619E 0%, #F0458C 100%); /* 3.01:1 / 3.54:1 */ + --gradient-entry-green: linear-gradient(135deg, #18A979 0%, #148F66 100%); /* 3.00:1 / 4.08:1 */ + --gradient-entry-amber: linear-gradient(135deg, #E9740C 0%, #CC650B 100%); /* 3.01:1 / 3.86:1 */ + /* 图标砖落影:比 --mini-shadow 更小,避免 4 列宫格里相邻砖块的投影互相压边 */ + --mini-entry-shadow: 0 4.00px 9.00px rgba(28, 30, 88, 0.18); + + /* ---- 夜间氛围层(v2 新增;参考图有光晕与星点,此前完全没有) ---- */ + --mini-glow-coral: rgba(255, 79, 145, 0.40); + --mini-glow-indigo: rgba(94, 124, 255, 0.32); + --mini-glow-soft: rgba(255, 255, 255, 0.10); + --mini-star: rgba(255, 255, 255, 0.70); + --mini-glass: rgba(255, 255, 255, 0.10); /* 深底玻璃面 */ + --mini-glass-strong: rgba(255, 255, 255, 0.16); + --mini-hairline: rgba(255, 255, 255, 0.16); /* 深底分隔线 */ + --mini-glass-success: rgba(90, 226, 184, 0.16); /* 深底上的成功态玻璃面 */ + + /* 星点层:多个小径向渐变叠在夜空渐变之上。用 radial-gradient 而非图片, + 避免额外请求,也便于随主题换色(index 页脚注:装饰层不承载信息)。 */ + --mini-starfield: + radial-gradient(circle at 12% 18%, var(--mini-star) 0, transparent 1.25px), + radial-gradient(circle at 31% 66%, var(--mini-star) 0, transparent 1.00px), + radial-gradient(circle at 57% 12%, var(--mini-star) 0, transparent 1.00px), + radial-gradient(circle at 79% 52%, var(--mini-star) 0, transparent 1.50px), + radial-gradient(circle at 93% 84%, var(--mini-star) 0, transparent 1.00px); + + /* 横幅压暗层:保证任何底图上的白色标题都有足够对比度 */ + --mini-banner-scrim: linear-gradient(90deg, rgba(23, 42, 114, 0.84) 0%, rgba(37, 16, 79, 0.40) 56%, rgba(255, 79, 145, 0.12) 100%); + + /* ============ 功能色(同样分级) ============ */ + --color-success: #2E9B68; /* 色块/图标 */ + --color-success-strong: #17805A; /* 文字(4.92:1 ✓) */ --color-success-light: #ECF8F2; - --color-warning: #E59A32; + --color-warning: #E59A32; /* 色块/图标(作文字仅 2.33:1) */ + --color-warning-strong: #9C5F14; /* 文字(5.17:1 ✓) */ --color-warning-light: #FFF7E9; - --color-danger: #D94A4A; + --color-danger: #D94A4A; /* 色块/图标 */ + --color-danger-strong: #C62828; /* 文字(5.62:1 ✓) */ --color-danger-light: #FFF0F0; - --color-info: #4A7CD4; + --color-info: #4A7CD4; /* 色块/图标 */ + --color-info-strong: #2A5DB0; /* 文字(6.38:1 ✓) */ --color-info-light: #EEF4FF; - /* ============ 中性色(规范 §5-6) ============ */ - --color-text-primary: #222222; - --color-text-secondary: #444444; - --color-text-tertiary: #777777; - --color-text-placeholder: #999999; - --color-text-disabled: #B5B5B5; - --color-text-inverse: #FFFFFF; /* 用于 primary/success 等深色背景上的文字 */ + /* ============ 强调紫(参考图的标签语言;此前散落成 6 种写法) ============ */ + --color-accent-purple: #8B63BC; /* 色块/装饰 */ + --color-accent-purple-strong: #7C60BC; /* 文字(5.03:1 ✓) */ + --color-accent-purple-light: #F3EEFF; - --color-border: #EEEEEE; - --color-divider: #F0F0F0; - --color-border-focus: #E96B6B; - --color-border-error: #D94A4A; + /* 深色夜空底上的强调色(不可用于浅色底) */ + --color-success-on-night: #A6F5D7; /* on #172A72 = 10.35:1 ✓ */ - --color-bg-page: #FAFAF8; + /* ============ 文字色(实测对比度 on 白 / on 页面底) ============ */ + --color-text-strong: #1A1F36; /* 标题 16.24 / 14.90 ✓ */ + --color-text-primary: #2A3050; /* 正文 12.83 / 11.77 ✓ */ + --color-text-secondary: #4A5169; /* 次要正文 7.86 / 7.21 ✓ */ + --color-text-tertiary: #646C85; /* 说明文字 5.22 / 4.79 ✓(旧 #777 为 4.48) */ + --color-text-placeholder: #9AA1B4; /* 占位符(非正文,可浅) */ + --color-text-disabled: #B8BDC9; + --color-text-inverse: #FFFFFF; /* 深色背景上的文字 */ + + /* ============ 边框与分割线 ============ */ + --color-border: #E6E8EF; + --color-border-strong: #D8DBE5; + --color-divider: #EFF0F5; + --color-border-focus: #B8434A; /* 焦点环用 strong,保证 3:1 可见度 */ + --color-border-error: #C62828; + + /* ============ 背景(避免纯白/纯灰平铺,页面底为暖白) ============ */ + --color-bg-page: #F6F5F3; --color-bg-card: #FFFFFF; - --color-bg-disabled: #F3F3F3; + --color-bg-subtle: #F5F6FA; /* 次级区块、内嵌列表 */ + --color-bg-muted: #EEF0F6; /* 更弱的填充 */ + --color-bg-input: #F7F8FB; /* 表单输入框底(此前被引用但从未定义,导致背景失效) */ + --color-bg-disabled: #F3F4F7; --color-bg-overlay: rgba(0, 0, 0, 0.45); - /* ============ 字体(规范 §7-11) ============ */ + /* ============ 字体 ============ */ + /* 小程序无法可靠加载 Web Font(wx.loadFontFace 依赖 HTTPS 白名单且有闪动风险), + 故使用中文系统字栈:iOS 走苹方、Android 走思源/系统黑体。 + 排版辨识度靠字号阶梯与字重建立,而非依赖字体本身。 */ --font-family-cn: -apple-system, "PingFang SC", "Noto Sans SC", "Hiragino Sans GB", "Microsoft YaHei", system-ui, sans-serif; + --font-family-number: "SF Pro Display", -apple-system, "DIN Alternate", "PingFang SC", sans-serif; - --font-size-xs: 12.00px; /* 12px */ - --font-size-sm: 13.00px; /* 13px */ - --font-size-md: 14.00px; /* 14px */ - --font-size-base: 16.00px; /* 16px */ - --font-size-lg: 18.00px; /* 18px */ - --font-size-xl: 20.00px; /* 20px */ - --font-size-2xl: 24.00px; /* 24px */ - --font-size-3xl: 28.00px; /* 28px */ + /* 字号阶梯 —— 正文 16.00px(16px) 起,元信息下限 12.00px(12px) */ + --font-size-micro: 11.00px; /* 11px 仅角标/装饰,禁用于正文 */ + --font-size-xs: 12.00px; /* 12px 元信息下限 */ + --font-size-sm: 13.00px; /* 13px 次要说明 */ + --font-size-md: 14.00px; /* 14px 次要正文 */ + --font-size-base: 16.00px; /* 16px 正文 */ + --font-size-lg: 18.00px; /* 18px 小标题 */ + --font-size-xl: 20.00px; /* 20px 区块标题 */ + --font-size-2xl: 24.00px; /* 24px 页面标题 */ + --font-size-3xl: 28.00px; /* 28px 大标题 */ + --font-size-display: 32.00px; /* 32px Hero */ + /* 字重:只用 4 档。禁止 550/650/750 等非百位值 —— Android 无对应字重会回退, + 导致同一设计在不同机型上粗细不一致(审计发现 30 处)。 */ --font-weight-regular: 400; --font-weight-medium: 500; --font-weight-semibold: 600; @@ -2196,51 +3798,68 @@ --line-height-tight: 1.25; --line-height-normal: 1.5; - --line-height-relaxed: 1.7; + --line-height-relaxed: 1.65; - /* ============ 间距(规范 §12,4px 栅格) ============ */ - --spacing-1: 4.00px; /* 4px */ - --spacing-2: 8.00px; /* 8px */ - --spacing-3: 12.00px; /* 12px */ - --spacing-4: 16.00px; /* 16px */ - --spacing-5: 20.00px; /* 20px */ - --spacing-6: 24.00px; /* 24px */ - --spacing-8: 32.00px; /* 32px */ - --spacing-10: 40.00px; /* 40px */ - --spacing-12: 48.00px; /* 48px */ + --letter-spacing-tight: 0; + --letter-spacing-wide: 0.50px; + --letter-spacing-wider: 1.00px; - --spacing-page-x: 16.00px; /* 页面左右 16px */ - --spacing-section: 24.00px; /* 区块间 24px */ - --spacing-card-inner: 16.00px; /* 卡片内部 16px */ - --spacing-tight: 8.00px; /* 紧密 8px */ + /* ============ 间距(4px 栅格) ============ */ + --spacing-1: 4.00px; + --spacing-2: 8.00px; + --spacing-3: 12.00px; + --spacing-4: 16.00px; + --spacing-5: 20.00px; + --spacing-6: 24.00px; + --spacing-8: 32.00px; + --spacing-10: 40.00px; + --spacing-12: 48.00px; - /* ============ 圆角(规范 §14) ============ */ - --radius-sm: 8.00px; /* 8px */ - --radius-md: 12.00px; /* 12px */ - --radius-lg: 16.00px; /* 16px */ - --radius-xl: 20.00px; /* 20px */ + --spacing-page-x: 16.00px; + --spacing-section: 24.00px; + --spacing-card-inner: 16.00px; + --spacing-tight: 8.00px; + + /* ============ 圆角 ============ */ + --radius-sm: 8.00px; + --radius-md: 12.00px; + --radius-lg: 16.00px; + --radius-xl: 20.00px; + --radius-2xl: 24.00px; --radius-full: 4999.50px; - /* ============ 阴影(规范 §15,极轻) ============ */ - --shadow-card: 0 4.00px 16.00px rgba(0, 0, 0, 0.04); + /* ============ 阴影(统一为一套,此前 30+ 种近似值) ============ */ + --shadow-card: 0 4.00px 14.00px rgba(35, 35, 95, 0.07); + --shadow-raised: 0 6.00px 18.00px rgba(35, 35, 95, 0.10); --shadow-popup: 0 8.00px 32.00px rgba(0, 0, 0, 0.10); + --shadow-night: 0 8.00px 20.00px rgba(28, 30, 88, 0.18); - /* ============ 边框(规范 §16) ============ */ + /* ============ 边框宽度 ============ */ --border-width: 0.50px; + --border-width-strong: 1.00px; - /* ============ 动效(规范 §17) ============ */ + /* ============ 触摸目标(无障碍下限 44×44px) ============ */ + --tap-min: 44.00px; /* 44px 最小可点区域 */ + --tap-comfortable: 48.00px; /* 48px 舒适尺寸:主操作 */ + --tap-gap: 8.00px; /* 8px 相邻目标最小间距 */ + + /* ============ 动效 ============ */ --motion-fast: 120ms; --motion-normal: 200ms; --motion-slow: 300ms; - --ease-standard: ease-out; + --ease-standard: cubic-bezier(0.32, 0.72, 0, 1); + --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1); + --press-scale: 0.97; + --press-opacity: 0.88; - /* ============ 层级 z-index(规范 §90) ============ */ + /* ============ 层级 z-index ============ */ --z-base: 1; --z-sticky: 100; --z-tabbar: 200; --z-dropdown: 500; --z-modal: 1000; --z-toast: 2000; + --z-ambient: 0; /* ============ 页面基础样式 ============ */ background-color: var(--color-bg-page); @@ -2250,7 +3869,10 @@ line-height: var(--line-height-normal); } -/* ============ 通用工具类 ============ */ +/* ========================================================================== + 通用工具类 + ========================================================================== */ + .container { padding: var(--spacing-page-x); } @@ -2264,17 +3886,34 @@ .flex-shrink-0 { flex-shrink: 0; } .wrap { flex-wrap: wrap; } +/* 4 列宫格:用 flex + 百分比宽度实现。 + 注:display:grid 在 WebView 渲染下可用,但 Skyline 不支持,故统一改为 flex 以免疫渲染引擎迁移。*/ +.grid-4 { + display: flex; + flex-wrap: wrap; +} +.grid-4 > .grid-item { + width: 25%; + box-sizing: border-box; +} + +.text-strong { color: var(--color-text-strong); } .text-primary { color: var(--color-text-primary); } .text-secondary { color: var(--color-text-secondary); } .text-tertiary { color: var(--color-text-tertiary); } .text-placeholder { color: var(--color-text-placeholder); } .text-white { color: var(--color-text-inverse); } -.text-brand { color: var(--color-primary); } -.text-success { color: var(--color-success); } -.text-warning { color: var(--color-warning); } -.text-danger { color: var(--color-danger); } -.text-info { color: var(--color-info); } +.text-brand { color: var(--color-primary-strong); } +/* 品牌色作文字只能用 -strong 变体:基础色 #E96B6B 在白底仅 3.10:1。 + 保留 .text-brand-soft 这个类名是为了不破坏既有引用,取值已统一到 -strong, + 如需「更亮的品牌色」请用于背景/图形而非文字。 */ +.text-brand-soft { color: var(--color-primary-strong); } +.text-success { color: var(--color-success-strong); } +.text-warning { color: var(--color-warning-strong); } +.text-danger { color: var(--color-danger-strong); } +.text-info { color: var(--color-info-strong); } +.font-micro { font-size: var(--font-size-micro); } .font-xs { font-size: var(--font-size-xs); } .font-sm { font-size: var(--font-size-sm); } .font-md { font-size: var(--font-size-md); } @@ -2283,6 +3922,7 @@ .font-xl { font-size: var(--font-size-xl); } .font-2xl { font-size: var(--font-size-2xl); } .font-3xl { font-size: var(--font-size-3xl); } +.font-display { font-size: var(--font-size-display); } .font-regular { font-weight: var(--font-weight-regular); } .font-medium { font-weight: var(--font-weight-medium); } @@ -2320,7 +3960,7 @@ padding-bottom: 0px; } -/* 页面卡片基础样式(中低密度留白) */ +/* 页面卡片基础样式 */ .card-base { background: var(--color-bg-card); border-radius: var(--radius-lg); @@ -2334,535 +3974,697 @@ background: var(--color-divider); } -.wx-page{background:var(--color-bg-page)}.service-page{min-height:100vh;padding-bottom:calc(70.00px + 0px)}.hero{padding:22.00px 16.00px 27.00px;background:linear-gradient(140deg,var(--color-primary-lighter),#FFF8EE);position:relative;overflow:hidden}.eyebrow{display:inline-flex;padding:3.50px 7.00px;border-radius:499.50px;background:rgba(255,255,255,.72);color:var(--color-primary);font-size:10.50px}.hero-title{display:block;margin-top:9.00px;font-size:20.00px;font-weight:700;line-height:1.35}.hero-desc{display:block;width:82%;margin-top:7.00px;font-size:12.50px;color:var(--color-text-secondary);line-height:1.7}.content{padding:0 var(--spacing-page-x)}.block{margin-top:var(--spacing-section)}.block-title{display:block;font-size:15.50px;font-weight:650}.block-subtitle{display:block;margin-top:4.00px;font-size:11.50px;color:var(--color-text-tertiary)}.card{margin-top:9.00px;padding:14.00px;background:var(--color-bg-card);border:0.50px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.feature-row,.menu-row,.record-row{display:flex;align-items:center;gap:10.00px;min-height:56.00px;padding:9.00px 0;border-bottom:0.50px solid var(--color-divider)}.feature-row:last-child,.menu-row:last-child,.record-row:last-child{border-bottom:0}.feature-icon{width:36.00px;height:36.00px;display:flex;align-items:center;justify-content:center;flex:none;border-radius:11.00px;background:var(--color-primary-light);color:var(--color-primary);font-weight:700}.feature-copy{flex:1;min-width:0}.feature-title{display:block;font-size:14.00px;font-weight:600}.feature-desc,.meta{display:block;margin-top:3.50px;font-size:11.50px;color:var(--color-text-tertiary);line-height:1.55}.arrow{font-size:20.00px;color:var(--color-text-disabled)}.tag{display:inline-flex;margin-right:5.00px;margin-top:5.00px;padding:3.00px 6.50px;border-radius:499.50px;background:var(--color-success-light);color:var(--color-success);font-size:10.00px}.tag.warning{background:var(--color-warning-light);color:var(--color-warning)}.primary-btn,.secondary-btn{height:44.00px;display:flex;align-items:center;justify-content:center;border-radius:22.00px;font-size:14.00px;font-weight:600}.primary-btn{background:linear-gradient(135deg,var(--mini-accent-coral),var(--mini-accent-pink));color:var(--color-text-inverse);box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)}.primary-btn.disabled{background:#E6E8EF;color:#989DAF;box-shadow:none}.secondary-btn{background:var(--color-primary-light);color:var(--color-primary)}.fixed-action{position:fixed;left:0;right:0;bottom:0;padding:9.00px var(--spacing-page-x) calc(9.00px + 0px);background:rgba(255,255,255,.96);border-top:0.50px solid var(--color-divider);z-index:100}.field{margin-top:13.00px}.label{display:block;margin-bottom:6.00px;font-size:12.50px;font-weight:600}.input,.select-box,.textarea{width:100%;box-sizing:border-box;background:#FCFAF8;border:0.50px solid var(--color-border);border-radius:var(--radius-md);font-size:13.00px}.input,.select-box{height:44.00px;padding:0 12.00px;display:flex;align-items:center}.textarea{min-height:90.00px;padding:11.00px}.notice{margin-top:10.00px;padding:11.00px;border-radius:var(--radius-md);background:#F3F7FC;color:var(--color-text-secondary);font-size:11.50px;line-height:1.65}.empty-panel{text-align:center;padding:35.00px 15.00px}.empty-symbol{width:48.00px;height:48.00px;margin:auto;display:flex;align-items:center;justify-content:center;border-radius:15.00px;background:var(--color-primary-light);color:var(--color-primary);font-size:18.00px;font-weight:700}.empty-title{display:block;margin-top:11.00px;font-size:15.00px;font-weight:600}.article-card{margin-top:9.00px;background:var(--color-bg-card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.article-cover{height:110.00px;padding:12.00px;background:linear-gradient(135deg,#F5E5DE,#F9F1E8);display:flex;align-items:flex-end}.article-cover text{font-size:21.00px;color:rgba(125,76,63,.52);font-weight:700}.article-body{padding:12.00px}.article-title{display:block;font-size:14.50px;font-weight:650;line-height:1.45}.article-meta{display:block;margin-top:5.00px;font-size:11.00px;color:var(--color-text-tertiary)}.article-content{padding:16.00px;background:var(--color-bg-card);font-size:14.00px;line-height:1.9;color:var(--color-text-secondary)}.article-content .lead{display:block;font-size:15.50px;color:var(--color-text-primary);font-weight:600;margin-bottom:12.00px}.danger-card{background:#FFF8F4;border-color:#F5DED2}.danger-card .feature-icon{background:#FFF0EA;color:#C85D43}@media(max-width:340px){.hero-title{font-size:18.00px}.hero-desc{width:92%}} +/* ========================================================================== + 可访问性:只用 token,不用工具类(2026-09-23 修订) + -------------------------------------------------------------------------- + v2 曾在此处新增 .tap-min / .tap-gap / .focusable / .pressable 四个工具类。 + 复检发现全部零引用(等价能力已各自写在组件样式内,例如 button/index.wxss + 直接使用 min-height:var(--tap-min)),且存在两个硬问题: -.service-shell{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:#F4F5FA}.service-content{padding:4.00px 12.00px 18.00px}.service-status{display:flex;align-items:center;justify-content:space-between;margin-top:12.00px;padding:10.00px 12.00px;border-radius:11.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-status__label{color:#7B8198;font-size:10.50px}.service-status__value{padding:3.00px 7.00px;border-radius:9.00px;background:#EAF8F2;color:#329472;font-size:9.50px;font-weight:650}.service-status__value.disabled{background:#FFF0F0;color:#D45A60}.service-topics{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.service-topic{min-height:74.00px;padding:10.00px;border-radius:12.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-topic__icon{display:flex;align-items:center;justify-content:center;width:27.00px;height:27.00px;border-radius:8.50px;background:#FFF0F5}.service-topic__icon image{width:17.00px;height:17.00px}.service-topic__title{display:block;margin-top:6.50px;color:#283056;font-size:12.00px;font-weight:650}.service-topic__desc{display:block;margin-top:3.00px;color:#858A9E;font-size:9.50px;line-height:1.45}.service-actions{display:flex;gap:7.00px}.service-actions .secondary-btn{width:95.00px;flex:none}.service-actions .primary-btn{flex:1}.privacy-note{display:flex;align-items:flex-start;gap:7.00px;margin-top:11.00px;padding:10.00px;border-radius:11.00px;background:#F1F4FF;color:#69718E;font-size:10.00px;line-height:1.55}.privacy-note image{width:17.00px;height:17.00px;flex:none} + 1) `.tap-gap > * + *` 用了通配符与兄弟选择器 —— WXSS 不支持, + wcc 编译期直接报 `error at token '*'`,导致整个小程序编译失败。 + (这是编译错误,不是静默失效,代价最高。) + 2) `.pressable:active` / `.focusable:focus-visible` 的伪类在 view 上 + 不生效(小程序须用 hover-class),属于"写了等于没写"。 + + 故整块移除,保留 token。需要热区/间距时直接引用 token: + min-height: var(--tap-min); → 44.00px = 44px,最小可点区域 + gap: var(--tap-gap); → 8.00px = 8px,相邻目标间距(flex gap) + 【WXSS 禁用清单】星号通配符、兄弟选择器、属性选择器。 + 【注释约束】WXSS 注释**不可嵌套**:内层注释的结束标记会提前终止外层注释, + 其后的文字会被当成真实样式解析,导致编译失败或样式被污染。 + (2026-09-23 实证:本块注释初版即踩此坑。) + ========================================================================== */ + +.wx-page{background:var(--color-bg-page)}.service-page{min-height:100vh;padding-bottom:calc(70.00px + 0px)}.hero{padding:22.00px 16.00px 27.00px;background:linear-gradient(140deg,var(--color-primary-lighter),var(--color-warning-light));position:relative;overflow:hidden}.eyebrow{display:inline-flex;padding:3.50px 7.00px;border-radius:499.50px;background:rgba(255,255,255,.72);color:var(--color-primary-strong);font-size:12.00px}.hero-title{display:block;margin-top:9.00px;font-size:20.00px;font-weight:700;line-height:1.35}.hero-desc{display:block;width:82%;margin-top:7.00px;font-size:12.50px;color:var(--color-text-secondary);line-height:1.7}.content{padding:0 var(--spacing-page-x)}.block{margin-top:var(--spacing-section)}.block-title{display:block;font-size:15.50px;font-weight:600}.block-subtitle{display:block;margin-top:4.00px;font-size:12.00px;color:var(--color-text-tertiary)}.card{margin-top:9.00px;padding:14.00px;background:var(--color-bg-card);border:0.50px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.feature-row,.menu-row,.record-row{display:flex;align-items:center;gap:10.00px;min-height:56.00px;padding:9.00px 0;border-bottom:0.50px solid var(--color-divider)}.feature-row:last-child,.menu-row:last-child,.record-row:last-child{border-bottom:0}.feature-icon{width:36.00px;height:36.00px;display:flex;align-items:center;justify-content:center;flex:none;border-radius:11.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-weight:700}.feature-copy{flex:1;min-width:0}.feature-title{display:block;font-size:14.00px;font-weight:600}.feature-desc,.meta{display:block;margin-top:3.50px;font-size:12.00px;color:var(--color-text-tertiary);line-height:1.55}.arrow{font-size:20.00px;color:var(--color-text-disabled)}.tag{display:inline-flex;margin-right:5.00px;margin-top:5.00px;padding:3.00px 6.50px;border-radius:499.50px;background:var(--color-success-light);color:var(--color-success-strong);font-size:12.00px}.tag.warning{background:var(--color-warning-light);color:var(--color-warning-strong)}.primary-btn,.secondary-btn{height:44.00px;display:flex;align-items:center;justify-content:center;border-radius:22.00px;font-size:14.00px;font-weight:600}.primary-btn{background:var(--gradient-brand-solid);color:var(--color-text-inverse);box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)}.primary-btn.disabled{background:var(--color-bg-muted);color:var(--color-text-tertiary);box-shadow:none}.secondary-btn{background:var(--color-primary-light);color:var(--color-primary-strong)}.fixed-action{position:fixed;left:0;right:0;bottom:0;padding:9.00px var(--spacing-page-x) calc(9.00px + 0px);background:rgba(255,255,255,.96);border-top:0.50px solid var(--color-divider);z-index:100}.field{margin-top:13.00px}.label{display:block;margin-bottom:6.00px;font-size:12.50px;font-weight:600}.input,.select-box,.textarea{width:100%;box-sizing:border-box;background:var(--color-bg-page);border:0.50px solid var(--color-border);border-radius:var(--radius-md);font-size:13.00px}.input,.select-box{height:44.00px;padding:0 12.00px;display:flex;align-items:center}.textarea{min-height:90.00px;padding:11.00px}.notice{margin-top:10.00px;padding:11.00px;border-radius:var(--radius-md);background:var(--color-info-light);color:var(--color-text-secondary);font-size:12.00px;line-height:1.65}.select-box.is-readonly{background:var(--color-bg-subtle);color:var(--color-text-secondary)}.empty-panel{text-align:center;padding:35.00px 15.00px}.empty-symbol{width:48.00px;height:48.00px;margin:auto;display:flex;align-items:center;justify-content:center;border-radius:15.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-size:18.00px;font-weight:700}.empty-title{display:block;margin-top:11.00px;font-size:15.00px;font-weight:600}.article-card{margin-top:9.00px;background:var(--color-bg-card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.article-cover{height:110.00px;padding:12.00px;background:linear-gradient(135deg,var(--color-warning-light),var(--color-warning-light));display:flex;align-items:flex-end}.article-cover text{font-size:21.00px;color:rgba(125,76,63,.52);font-weight:700}.article-body{padding:12.00px}.article-title{display:block;font-size:14.50px;font-weight:600;line-height:1.45}.article-meta{display:block;margin-top:5.00px;font-size:12.00px;color:var(--color-text-tertiary)}.article-content{padding:16.00px;background:var(--color-bg-card);font-size:14.00px;line-height:1.9;color:var(--color-text-secondary)}.article-content .lead{display:block;font-size:15.50px;color:var(--color-text-primary);font-weight:600;margin-bottom:12.00px}.danger-card{background:var(--color-primary-lighter);border-color:var(--color-primary-light)}.danger-card .feature-icon{background:var(--color-warning-light);color:var(--color-warning-strong)}@media(max-width:340px){.hero-title{font-size:18.00px}.hero-desc{width:92%}} + +.service-shell{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:var(--color-bg-page)}.service-content{padding:4.00px 12.00px 18.00px}.service-status{display:flex;align-items:center;justify-content:space-between;margin-top:12.00px;padding:10.00px 12.00px;border-radius:11.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-status__label{color:var(--color-text-tertiary);font-size:12.00px}.service-status__value{padding:3.00px 7.00px;border-radius:9.00px;background:var(--color-success-light);color:var(--color-success-strong);font-size:12.00px;font-weight:600}.service-status__value.disabled{background:var(--color-danger-light);color:var(--color-danger-strong)}.service-topics{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.service-topic{min-height:74.00px;padding:10.00px;border-radius:12.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-topic__icon{display:flex;align-items:center;justify-content:center;width:27.00px;height:27.00px;border-radius:8.50px;background:var(--color-primary-light)}.service-topic__icon image{width:17.00px;height:17.00px}.service-topic__title{display:block;margin-top:6.50px;color:var(--color-text-strong);font-size:12.00px;font-weight:600}.service-topic__desc{display:block;margin-top:3.00px;color:var(--color-text-tertiary);font-size:12.00px;line-height:1.45}.service-actions{display:flex;gap:7.00px}.service-actions .secondary-btn{width:95.00px;flex:none}.service-actions .primary-btn{flex:1}.privacy-note{display:flex;align-items:flex-start;gap:7.00px;margin-top:11.00px;padding:10.00px;border-radius:11.00px;background:var(--color-info-light);color:var(--color-text-tertiary);font-size:12.00px;line-height:1.55}.privacy-note image{width:17.00px;height:17.00px;flex:none} /* ==== miniapp/components/section-header ==== */ +/** + * 区块标题(全站所有页面共用,是排版层级的关键一环) + * + * 2026-09-22 修订: + * 1) 层级拉开:标题 18.00px→20.00px(--font-size-xl),与正文 16.00px / 卡片标题 14.00px + * 形成「区块标题 > 卡片标题 > 正文 > 元信息」四级阶梯。 + * 旧值 18.00px 与卡片标题仅差 5.00px,层级读不出来。 + * 2) 右侧 action 是全站最容易被忽略的触摸目标:只有 13.00px 文字高(约 13px), + * 远低于 44px 下限。改为 min-height:--tap-min,热区向上补白。 + * 3) action 文字色原为 --color-primary(#E96B6B)=3.10:1,不达标,改 -strong。 + */ .ui-section { - display: flex; - align-items: center; - justify-content: space-between; - padding: var(--spacing-3) var(--spacing-page-x); + display:flex; + align-items:center; + justify-content:space-between; + padding:var(--spacing-2) var(--spacing-page-x); } .ui-section__left { - display: flex; - align-items: baseline; + display:flex; + align-items:baseline; + min-width:0; } .ui-section__title { - font-size: var(--font-size-lg); - font-weight: var(--font-weight-semibold); - color: var(--color-text-primary); + font-size:var(--font-size-xl); + font-weight:var(--font-weight-semibold); + color:var(--color-text-strong); + letter-spacing:var(--letter-spacing-tight); } .ui-section__subtitle { - margin-left: var(--spacing-2); - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); + margin-left:var(--spacing-2); + font-size:var(--font-size-xs); + color:var(--color-text-tertiary); } .ui-section__action { - display: flex; - align-items: center; - font-size: var(--font-size-sm); - color: var(--color-primary); + display:flex; + align-items:center; + flex:none; + min-height:var(--tap-min); + padding-left:var(--spacing-3); + font-size:var(--font-size-sm); + font-weight:var(--font-weight-medium); + color:var(--color-primary-strong); + transition:opacity var(--motion-fast) var(--ease-standard); +} +.ui-section__action:active { + opacity:var(--press-opacity); } .ui-section__arrow { - margin-left: 2.00px; - width: 12.00px; - height: 12.00px; + margin-left:2.00px; + width:12.00px; + height:12.00px; } /* ==== miniapp/components/avatar ==== */ .ui-avatar { - position: relative; - flex-shrink: 0; - background: var(--color-bg-disabled); - overflow: hidden; + position:relative; + flex-shrink:0; + background:var(--color-bg-disabled); + overflow:hidden; } -.ui-avatar--circle { border-radius: 50%; } -.ui-avatar--square { border-radius: var(--radius-md); } +.ui-avatar--circle { border-radius:50%; } +.ui-avatar--square { border-radius:var(--radius-md); } /* 尺寸:sm 60 / md 88 / lg 120 / xl 160 */ -.ui-avatar--sm { width: 30.00px; height: 30.00px; } -.ui-avatar--md { width: 44.00px; height: 44.00px; } -.ui-avatar--lg { width: 60.00px; height: 60.00px; } -.ui-avatar--xl { width: 80.00px; height: 80.00px; } +.ui-avatar--sm { width:30.00px; height:30.00px; } +.ui-avatar--md { width:44.00px; height:44.00px; } +.ui-avatar--lg { width:60.00px; height:60.00px; } +.ui-avatar--xl { width:80.00px; height:80.00px; } .ui-avatar__img { - width: 100%; - height: 100%; - display: block; + width:100%; + height:100%; + display:block; } .ui-avatar__fallback { - width: 100%; - height: 100%; - display: flex; - align-items: center; - justify-content: center; - background: var(--color-primary-light); + width:100%; + height:100%; + display:flex; + align-items:center; + justify-content:center; + background:var(--color-primary-light); } .ui-avatar__fallback-text { - font-size: var(--font-size-lg); - color: var(--color-primary); - font-weight: var(--font-weight-semibold); + font-size:var(--font-size-lg); + color:var(--color-primary-strong); + font-weight:var(--font-weight-semibold); } .ui-avatar__fallback-icon { - width: 100%; - height: 100%; + width:100%; + height:100%; } .ui-avatar__badges { - position: absolute; - bottom: -2.00px; - left: 50%; - transform: translateX(-50%); - display: flex; - gap: 3.00px; + position:absolute; + bottom:-2.00px; + left:50%; + transform:translateX(-50%); + display:flex; + gap:3.00px; } .ui-avatar__badge { - font-size: 8.00px; - line-height: 1; - padding: 2.00px 4.00px; - border-radius: var(--radius-full); - color: #FFFFFF; - font-weight: var(--font-weight-medium); - white-space: nowrap; + font-size:8.00px; + line-height:1; + padding:2.00px 4.00px; + border-radius:var(--radius-full); + color:var(--color-text-inverse); + font-weight:var(--font-weight-medium); + white-space:nowrap; } -.ui-avatar__badge--verified { background: var(--color-success); } -.ui-avatar__badge--reviewed { background: var(--color-info); } +.ui-avatar__badge--verified { background:var(--color-success); } +.ui-avatar__badge--reviewed { background:var(--color-info); } /* 小尺寸时隐藏徽标避免溢出 */ -.ui-avatar--sm .ui-avatar__badges { display: none; } +.ui-avatar--sm .ui-avatar__badges { display:none; } /* ==== miniapp/components/status-badge ==== */ .ui-badge { - display: inline-flex; - align-items: center; - padding: 2.00px 7.00px; - border-radius: var(--radius-full); - font-size: var(--font-size-xs); - font-weight: var(--font-weight-medium); - line-height: 1.4; - white-space: nowrap; + display:inline-flex; + align-items:center; + padding:2.00px 7.00px; + border-radius:var(--radius-full); + font-size:var(--font-size-xs); + font-weight:var(--font-weight-medium); + line-height:1.4; + white-space:nowrap; } .ui-badge__dot { - width: 4.00px; - height: 4.00px; - border-radius: 50%; - background: currentColor; - margin-right: 4.00px; + width:4.00px; + height:4.00px; + border-radius:50%; + background:currentColor; + margin-right:4.00px; } .ui-badge__label { - font-size: inherit; + font-size:inherit; } .ui-badge--success { - background: var(--color-success-light); - color: var(--color-success); + background:var(--color-success-light); + color:var(--color-success-strong); } .ui-badge--warning { - background: var(--color-warning-light); - color: var(--color-warning); + background:var(--color-warning-light); + color:var(--color-warning-strong); } .ui-badge--danger { - background: var(--color-danger-light); - color: var(--color-danger); + background:var(--color-danger-light); + color:var(--color-danger-strong); } .ui-badge--info { - background: var(--color-info-light); - color: var(--color-info); + background:var(--color-info-light); + color:var(--color-info-strong); } .ui-badge--disabled { - background: var(--color-bg-disabled); - color: var(--color-text-disabled); + background:var(--color-bg-disabled); + color:var(--color-text-disabled); } /* ==== miniapp/components/button ==== */ /** * Button 组件样式 - * 引用全局 Design Token(addGlobalClass: true) + * 引用全局 Design Token(addGlobalClass:true) + * + * 2026-09-22 修复: + * 1) 触摸目标:md 只有 40.00px(40px)、sm 只有 28.00px(28px),低于 44px 下限; + * text 变体更是 min-height:auto,几乎点不中。现统一以 --tap-min 兜底。 + * 2) 对比度:主按钮背景原为 --color-primary(#E96B6B),白字仅 3.10:1。 + * 改用 --color-primary-solid(#C24C50) = 4.73:1,视觉上仍是暖红。 + * secondary/text 的红色文字同理从 3.10 提到 --color-primary-strong 的 5.33。 + * 3) 危险按钮 --color-danger(#D94A4A) 白字 4.18:1 不达标,改用 -strong 变体。 + * 4) 按压反馈统一走 --press-scale / --press-opacity,替代硬编码 0.98 / 0.85。 */ .ui-btn { - display: inline-flex; - align-items: center; - justify-content: center; - box-sizing: border-box; - border-radius: var(--radius-full); - font-family: var(--font-family-cn); - font-weight: var(--font-weight-medium); - text-align: center; - transition: opacity var(--motion-fast) var(--ease-standard), - transform var(--motion-fast) var(--ease-standard); - user-select: none; - line-height: 1; - white-space: nowrap; + display:inline-flex; + align-items:center; + justify-content:center; + box-sizing:border-box; + border-radius:var(--radius-full); + font-family:var(--font-family-cn); + font-weight:var(--font-weight-semibold); + text-align:center; + transition:transform var(--motion-fast) var(--ease-spring), + opacity var(--motion-fast) var(--ease-standard), + background-color var(--motion-fast) var(--ease-standard); + user-select:none; + line-height:1.2; + white-space:nowrap; } -/* 尺寸 */ +/* 尺寸:全部以 44×44px 为热区下限 */ .ui-btn--sm { - padding: 7.00px 12.00px; - font-size: var(--font-size-sm); - min-height: 28.00px; + padding:7.00px 14.00px; + font-size:var(--font-size-sm); + min-height:var(--tap-min); } .ui-btn--md { - padding: 10.00px 18.00px; - font-size: var(--font-size-base); - min-height: 40.00px; + padding:10.00px 18.00px; + font-size:var(--font-size-base); + min-height:var(--tap-min); } .ui-btn--lg { - padding: 13.00px 24.00px; - font-size: var(--font-size-lg); - min-height: 48.00px; + padding:13.00px 24.00px; + font-size:var(--font-size-lg); + min-height:var(--tap-comfortable); } /* 撑满 */ .ui-btn--block { - display: flex; - width: 100%; + display:flex; + width:100%; } /* 变体 */ .ui-btn--primary { - background: var(--color-primary); - color: #FFFFFF; + background:var(--color-primary-solid); + color:var(--color-text-inverse); } .ui-btn--secondary { - background: var(--color-bg-card); - color: var(--color-primary); - border: 0.50px solid var(--color-primary); + background:var(--color-bg-card); + color:var(--color-primary-strong); + border:var(--border-width) solid var(--color-primary-strong); } .ui-btn--ghost { - background: transparent; - color: var(--color-text-primary); - border: 0.50px solid var(--color-border); + background:transparent; + color:var(--color-text-primary); + border:var(--border-width) solid var(--color-border-strong); } .ui-btn--danger { - background: var(--color-danger); - color: #FFFFFF; + background:var(--color-danger-strong); + color:var(--color-text-inverse); } .ui-btn--text { - background: transparent; - color: var(--color-primary); - padding-left: 0; - padding-right: 0; - min-height: auto; + background:transparent; + color:var(--color-primary-strong); + padding-left:var(--spacing-2); + padding-right:var(--spacing-2); + /* 视觉是纯文字,但热区仍需 44px:多出的部分由 align-items:center 居中留白 */ + min-height:var(--tap-min); } /* 状态 */ .ui-btn--disabled, .ui-btn--loading { - opacity: 0.55; + opacity:0.55; } .ui-btn--disabled.ui-btn--primary, .ui-btn--disabled.ui-btn--danger { - background: var(--color-text-disabled); + background:var(--color-text-disabled); } .ui-btn--disabled.ui-btn--secondary, .ui-btn--disabled.ui-btn--ghost { - color: var(--color-text-disabled); - border-color: var(--color-text-disabled); + color:var(--color-text-disabled); + border-color:var(--color-text-disabled); } -.ui-btn--hover { - opacity: 0.85; - transform: scale(0.98); +/* 按压反馈(hover-class 与 CSS :active 双保险) */ +.ui-btn--hover, +.ui-btn:active { + opacity:var(--press-opacity); + transform:scale(var(--press-scale)); } /* Loading spinner */ .ui-btn__spinner { - width: 14.00px; - height: 14.00px; - margin-right: 6.00px; - display: flex; - align-items: center; - justify-content: center; + width:14.00px; + height:14.00px; + margin-right:6.00px; + display:flex; + align-items:center; + justify-content:center; } .ui-btn__spinner-dot { - width: 9.00px; - height: 9.00px; - border-radius: 50%; - border: 1.50px solid currentColor; - border-top-color: transparent; - animation: ui-btn-spin 0.7s linear infinite; + width:9.00px; + height:9.00px; + border-radius:50%; + border:1.50px solid currentColor; + border-top-color:transparent; + animation:ui-btn-spin 0.7s linear infinite; } @keyframes ui-btn-spin { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } + from { transform:rotate(0deg); } + to { transform:rotate(360deg); } } /* ==== miniapp/components/loading ==== */ .ui-loading--block { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: var(--spacing-8) var(--spacing-page-x); + display:flex; + flex-direction:column; + align-items:center; + justify-content:center; + padding:var(--spacing-8) var(--spacing-page-x); } .ui-loading--inline { - display: inline-flex; - align-items: center; + display:inline-flex; + align-items:center; } .ui-loading__spinner { - width: 30.00px; - height: 30.00px; - display: flex; - align-items: center; - justify-content: center; + width:30.00px; + height:30.00px; + display:flex; + align-items:center; + justify-content:center; } .ui-loading__spinner-icon { - width: 24.00px; - height: 24.00px; - animation: ui-loading-spin 0.8s linear infinite; + width:24.00px; + height:24.00px; + animation:ui-loading-spin 0.8s linear infinite; } @keyframes ui-loading-spin { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } + from { transform:rotate(0deg); } + to { transform:rotate(360deg); } } .ui-loading__text { - margin-top: var(--spacing-3); - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); + margin-top:var(--spacing-3); + font-size:var(--font-size-sm); + color:var(--color-text-tertiary); } /* Skeleton */ .ui-loading__skeleton { - width: 100%; + width:100%; } .ui-loading__skeleton-row { - display: flex; - align-items: center; - padding: var(--spacing-3) var(--spacing-page-x); - background: var(--color-bg-card); - border-bottom: 0.50px solid var(--color-divider); + display:flex; + align-items:center; + padding:var(--spacing-3) var(--spacing-page-x); + background:var(--color-bg-card); + border-bottom:0.50px solid var(--color-divider); } .ui-loading__skeleton-avatar { - width: 44.00px; - height: 44.00px; - border-radius: 50%; - background: var(--color-bg-disabled); - margin-right: var(--spacing-3); - flex-shrink: 0; + width:44.00px; + height:44.00px; + border-radius:50%; + background:var(--color-bg-disabled); + margin-right:var(--spacing-3); + flex-shrink:0; } .ui-loading__skeleton-content { - flex: 1; - min-width: 0; + flex:1; + min-width:0; } .ui-loading__skeleton-line { - height: 12.00px; - background: var(--color-bg-disabled); - border-radius: var(--radius-sm); - position: relative; - overflow: hidden; + height:12.00px; + background:var(--color-bg-disabled); + border-radius:var(--radius-sm); + position:relative; + overflow:hidden; } .ui-loading__skeleton-line--title { - width: 40%; - margin-bottom: var(--spacing-2); + width:40%; + margin-bottom:var(--spacing-2); } .ui-loading__skeleton-line--meta { - width: 70%; + width:70%; } /* shimmer */ .ui-loading__skeleton-line::after, .ui-loading__skeleton-avatar::after { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: linear-gradient( + content:''; + position:absolute; + top:0; + left:0; + width:100%; + height:100%; + background:linear-gradient( 90deg, transparent 0%, rgba(255, 255, 255, 0.55) 50%, transparent 100% ); - animation: ui-loading-shimmer 1.4s ease-in-out infinite; + animation:ui-loading-shimmer 1.4s ease-in-out infinite; } @keyframes ui-loading-shimmer { - 0% { transform: translateX(-100%); } - 100% { transform: translateX(100%); } + 0% { transform:translateX(-100%); } + 100% { transform:translateX(100%); } } /* ==== miniapp/components/empty ==== */ .ui-empty { - display: flex; - flex-direction: column; - align-items: center; - padding: var(--spacing-10) var(--spacing-page-x); - text-align: center; + display:flex; + flex-direction:column; + align-items:center; + padding:var(--spacing-10) var(--spacing-page-x); + text-align:center; } .ui-empty__illustration { - width: 80.00px; - height: 80.00px; - border-radius: 50%; - background: var(--color-bg-disabled); - display: flex; - align-items: center; - justify-content: center; - margin-bottom: var(--spacing-4); + width:80.00px; + height:80.00px; + border-radius:50%; + background:var(--color-bg-disabled); + display:flex; + align-items:center; + justify-content:center; + margin-bottom:var(--spacing-4); } .ui-empty__icon { - width: 36.00px; - height: 36.00px; - opacity: 0.72; + width:36.00px; + height:36.00px; + opacity:0.72; } .ui-empty__title { - font-size: var(--font-size-lg); - font-weight: var(--font-weight-medium); - color: var(--color-text-primary); - margin-bottom: var(--spacing-2); + font-size:var(--font-size-lg); + font-weight:var(--font-weight-medium); + color:var(--color-text-primary); + margin-bottom:var(--spacing-2); } .ui-empty__desc { - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); - line-height: var(--line-height-relaxed); - max-width: 240.00px; + font-size:var(--font-size-sm); + color:var(--color-text-tertiary); + line-height:var(--line-height-relaxed); + max-width:240.00px; } .ui-empty__actions { - display: flex; - flex-direction: column; - gap: var(--spacing-2); - margin-top: var(--spacing-6); - width: 100%; - max-width: 240.00px; + display:flex; + flex-direction:column; + gap:var(--spacing-2); + margin-top:var(--spacing-6); + width:100%; + max-width:240.00px; } .ui-empty__action { - display: flex; - align-items: center; - justify-content: center; - height: 40.00px; - border-radius: var(--radius-full); - font-size: var(--font-size-base); - font-weight: var(--font-weight-medium); -} + display:flex; + align-items:center; + justify-content:center; + min-height:var(--tap-min); + border-radius:var(--radius-full); + font-size:var(--font-size-base); + font-weight:var(--font-weight-medium); +min-width:var(--tap-min);} .ui-empty__action--primary { - background: var(--color-primary); - color: #FFFFFF; + background:var(--color-primary-solid); + color:var(--color-text-inverse); } .ui-empty__action--secondary { - background: var(--color-bg-card); - color: var(--color-primary); - border: 0.50px solid var(--color-primary); + background:var(--color-bg-card); + color:var(--color-primary-strong); + border:0.50px solid var(--color-primary); } /* ==== miniapp/components/danger-action-dialog ==== */ .ui-dialog-mask { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: var(--color-bg-overlay); - z-index: var(--z-modal); - display: flex; - align-items: center; - justify-content: center; - padding: 0 var(--spacing-6); + position:fixed; + top:0; + left:0; + right:0; + bottom:0; + background:var(--color-bg-overlay); + z-index:var(--z-modal); + display:flex; + align-items:center; + justify-content:center; + padding:0 var(--spacing-6); } .ui-dialog { - width: 100%; - max-width: 300.00px; - background: var(--color-bg-card); - border-radius: var(--radius-lg); - padding: var(--spacing-5) var(--spacing-4) var(--spacing-4); - box-shadow: var(--shadow-popup); - animation: ui-dialog-in var(--motion-normal) var(--ease-standard); + width:100%; + max-width:300.00px; + background:var(--color-bg-card); + border-radius:var(--radius-lg); + padding:var(--spacing-5) var(--spacing-4) var(--spacing-4); + box-shadow:var(--shadow-popup); + animation:ui-dialog-in var(--motion-normal) var(--ease-standard); } @keyframes ui-dialog-in { - from { transform: scale(0.92); opacity: 0; } - to { transform: scale(1); opacity: 1; } + from { transform:scale(0.92); opacity:0; } + to { transform:scale(1); opacity:1; } } .ui-dialog__title { - font-size: var(--font-size-xl); - font-weight: var(--font-weight-semibold); - color: var(--color-text-primary); - text-align: center; - margin-bottom: var(--spacing-3); + font-size:var(--font-size-xl); + font-weight:var(--font-weight-semibold); + color:var(--color-text-primary); + text-align:center; + margin-bottom:var(--spacing-3); } .ui-dialog__content { - font-size: var(--font-size-md); - color: var(--color-text-secondary); - line-height: var(--line-height-relaxed); - text-align: center; - margin-bottom: var(--spacing-5); + font-size:var(--font-size-md); + color:var(--color-text-secondary); + line-height:var(--line-height-relaxed); + text-align:center; + margin-bottom:var(--spacing-5); } .ui-dialog__actions { - display: flex; - gap: var(--spacing-2); + display:flex; + gap:var(--spacing-2); } .ui-dialog__btn { - flex: 1; + flex:1; } -.page{min-height:100vh;padding-bottom:24.00px;background:#F4F5FA}.mine-guest{min-height:100vh;background:linear-gradient(160deg,var(--mini-night-start) 0,var(--mini-night-end) 34%,#F4F5FA 34%)}.guest-brand{display:flex;flex-direction:column;align-items:center;padding:calc(20px + 35.00px) 0 40.00px;color:#fff}.guest-brand image{width:46.00px;height:46.00px}.guest-brand>text{margin-top:6.00px;font-size:17.00px;font-weight:700}.guest-brand .guest-subtitle{margin-top:2.50px;color:rgba(255,255,255,.72);font-size:10.00px;font-weight:400;letter-spacing:2.00px}.profile-hero{padding:20px 12.00px 27.00px;border-radius:0 0 21.00px 21.00px;background:linear-gradient(160deg,var(--mini-night-start),var(--mini-night-end));box-shadow:var(--mini-shadow)}.mine-nav{position:relative;display:flex;align-items:center;justify-content:center;height:44.00px;color:#fff;font-size:15.50px;font-weight:700}.mine-nav image{position:absolute;right:6.00px;width:18.00px;height:18.00px;filter:brightness(0) invert(1)}.profile-main{position:relative;display:flex;align-items:center}.profile-copy{flex:1;min-width:0;margin-left:10.00px;color:#fff}.profile-name-row{display:flex;align-items:center;gap:6.00px}.profile-name{font-size:15.50px;font-weight:700}.profile-status{padding:2.50px 5.00px;border-radius:7.50px;background:rgba(255,255,255,.12);color:rgba(255,255,255,.78);font-size:8.50px}.profile-meta{display:block;margin-top:4.00px;color:rgba(255,255,255,.72);font-size:10.00px}.profile-progress{width:78%;height:3.50px;margin:5.00px 0 6.50px;overflow:hidden;border-radius:4.00px;background:rgba(255,255,255,.14)}.profile-progress view{height:100%;border-radius:4.00px;background:linear-gradient(90deg,#FF8C9C,#FF5C82)}.profile-badges{display:flex;gap:4.00px}.edit-profile{position:absolute;right:0;top:2.00px;color:rgba(255,255,255,.82);font-size:9.50px}.profile-stats{position:relative;z-index:2;display:grid;grid-template-columns:repeat(4,1fr);margin:-12.00px 12.00px 0;padding:12.00px 4.00px;border-radius:14.00px;background:#fff;box-shadow:var(--mini-shadow)}.profile-stat{display:flex;flex-direction:column;align-items:center;border-right:0.50px solid #EFF0F5}.profile-stat:last-child{border-right:0}.stat-value{color:#283056;font-size:14.50px;font-weight:700}.stat-value--text{font-size:11.00px}.stat-label{margin-top:2.50px;color:#8A8FA4;font-size:9.00px}.public-identity-card{display:flex;align-items:center;margin:12.00px;padding:11.00px;border-radius:13.00px;background:linear-gradient(135deg,#FFF0F5,#F7EEFF);box-shadow:0 4.00px 13.00px rgba(87,62,145,.08)}.public-identity-card>image:first-child{width:36.00px;height:36.00px}.public-identity-card>view{flex:1;display:flex;flex-direction:column;margin-left:8.00px}.identity-title{color:#F14D79;font-size:13.00px;font-weight:700}.identity-desc{margin-top:2.50px;color:#8A6F91;font-size:9.50px}.public-identity-card .identity-arrow{width:13.00px;height:13.00px}.service-grid{display:grid;grid-template-columns:repeat(4,1fr);margin:0 12.00px 14.00px;padding:12.00px 4.00px;border-radius:13.00px;background:#fff;box-shadow:0 4.00px 14.00px rgba(35,35,95,.07)}.service-entry{display:flex;flex-direction:column;align-items:center;color:#343957;font-size:10.00px}.service-icon{display:flex;align-items:center;justify-content:center;width:32.00px;height:32.00px;margin-bottom:5.00px;border-radius:10.00px}.service-icon image{width:21.00px;height:21.00px}.service-icon.rose{background:#FFF0F5}.service-icon.blue{background:#EAF3FF}.service-icon.amber{background:#FFF3E5}.service-icon.green{background:#EAF8F2}.list-group{overflow:hidden;margin:0 12.00px 11.00px;border-radius:13.00px;background:#fff;box-shadow:0 4.00px 14.00px rgba(35,35,95,.06)}.list-row{display:flex;align-items:center;min-height:44.00px;padding:0 12.00px;border-bottom:0.50px solid #EFF0F5}.list-row:last-child{border-bottom:0}.list-label{flex:1;color:#2B304E;font-size:11.50px}.list-value{margin-right:6.00px;color:#8A8FA4;font-size:9.50px}.list-arrow{width:12.00px;height:12.00px}.secondary-list{margin-top:0}.logout-row{margin:13.00px 12.00px 0;padding:12.00px;text-align:center;color:#D95561;font-size:11.50px;background:#fff;border-radius:13.00px} +.page{min-height:100vh;padding-bottom:24.00px;background:var(--color-bg-page)}.mine-guest{min-height:100vh;background:linear-gradient(160deg,var(--mini-night-start) 0,var(--mini-night-end) 34%,var(--color-bg-page) 34%)}.guest-brand{display:flex;flex-direction:column;align-items:center;padding:calc(var(--nav-top, 84px) + 35.00px) 0 40.00px;color:var(--color-text-inverse)}.guest-brand image{width:46.00px;height:46.00px}.guest-brand>text{margin-top:6.00px;font-size:17.00px;font-weight:700}.guest-brand .guest-subtitle{margin-top:2.50px;color:rgba(255,255,255,.72);font-size:12.00px;font-weight:400;letter-spacing:2.00px}/* --nav-status / --nav-h / --nav-right 由 mine.ts 经 utils/nav-metrics 实测胶囊按钮后注入 */ +.profile-hero{padding:var(--nav-status, 44px) 12.00px 27.00px;border-radius:0 0 21.00px 21.00px;background:linear-gradient(160deg,var(--mini-night-start),var(--mini-night-end));box-shadow:var(--mini-shadow)}.mine-nav{position:relative;display:flex;align-items:center;justify-content:center;height:var(--nav-h, 40.00px);color:var(--color-text-inverse);font-size:15.50px;font-weight:700}.mine-nav image{position:absolute;right:var(--nav-right, 102px);width:18.00px;height:18.00px;filter:brightness(0) invert(1)}.profile-main{position:relative;display:flex;align-items:center}.profile-copy{flex:1;min-width:0;margin-left:10.00px;color:var(--color-text-inverse)}.profile-name-row{display:flex;align-items:center;gap:6.00px}.profile-name{font-size:15.50px;font-weight:700}.profile-status{padding:2.50px 5.00px;border-radius:7.50px;background:rgba(255,255,255,.12);color:rgba(255,255,255,.78);font-size:12.00px}.profile-meta{display:block;margin-top:4.00px;color:rgba(255,255,255,.72);font-size:12.00px}.profile-progress{width:78%;height:3.50px;margin:5.00px 0 6.50px;overflow:hidden;border-radius:4.00px;background:rgba(255,255,255,.14)}.profile-progress view{height:100%;border-radius:4.00px;background:linear-gradient(90deg,var(--color-primary-light),var(--color-primary-light))}.profile-badges{display:flex;gap:4.00px}.edit-profile{position:absolute;right:0;top:2.00px;color:rgba(255,255,255,.82);font-size:12.00px}.profile-stats{position:relative;z-index:2;display:grid;grid-template-columns:repeat(4,1fr);margin:-12.00px 12.00px 0;padding:12.00px 4.00px;border-radius:14.00px;background:var(--color-bg-card);box-shadow:var(--mini-shadow)}.profile-stat{display:flex;flex-direction:column;align-items:center;border-right:0.50px solid var(--color-divider)}.profile-stat:last-child{border-right:0}.stat-value{color:var(--color-text-strong);font-size:14.50px;font-weight:700}.stat-value--text{font-size:12.00px}.stat-label{margin-top:2.50px;color:var(--color-text-tertiary);font-size:12.00px}.public-identity-card{display:flex;align-items:center;margin:12.00px;padding:11.00px;border-radius:13.00px;background:linear-gradient(135deg,var(--color-primary-light),var(--color-accent-purple-light));box-shadow:0 4.00px 13.00px rgba(87,62,145,.08)}.public-identity-card>image:first-child{width:36.00px;height:36.00px}.public-identity-card>view{flex:1;display:flex;flex-direction:column;margin-left:8.00px}.identity-title{color:var(--color-primary-strong);font-size:13.00px;font-weight:700}.identity-desc{margin-top:2.50px;color:var(--color-accent-purple-strong);font-size:12.00px}.public-identity-card .identity-arrow{width:13.00px;height:13.00px}.service-grid{display:grid;grid-template-columns:repeat(4,1fr);margin:0 12.00px 14.00px;padding:12.00px 4.00px;border-radius:13.00px;background:var(--color-bg-card);box-shadow:0 4.00px 14.00px rgba(35,35,95,.07)}.service-entry{display:flex;flex-direction:column;align-items:center;color:var(--color-text-strong);font-size:12.00px}.service-icon{display:flex;align-items:center;justify-content:center;width:32.00px;height:32.00px;margin-bottom:5.00px;border-radius:10.00px}.service-icon image{width:21.00px;height:21.00px}.service-icon.rose{background:var(--color-primary-light)}.service-icon.blue{background:var(--color-info-light)}.service-icon.amber{background:var(--color-warning-light)}.service-icon.green{background:var(--color-success-light)}.list-group{overflow:hidden;margin:0 12.00px 11.00px;border-radius:13.00px;background:var(--color-bg-card);box-shadow:0 4.00px 14.00px rgba(35,35,95,.06)}.list-row{display:flex;align-items:center;min-height:44.00px;padding:0 12.00px;border-bottom:0.50px solid var(--color-divider)}.list-row:last-child{border-bottom:0}.list-label{flex:1;color:var(--color-text-strong);font-size:12.00px}.list-value{margin-right:6.00px;color:var(--color-text-tertiary);font-size:12.00px}.list-arrow{width:12.00px;height:12.00px}.secondary-list{margin-top:0}.logout-row{margin:13.00px 12.00px 0;padding:12.00px;text-align:center;color:var(--color-danger-strong);font-size:12.00px;background:var(--color-bg-card);border-radius:13.00px} /** * 丹阳公益婚恋服务平台 - 全局 Design Token * - * 依据《前端组件库与 Design Token 规范 V1.0》 - * 单位说明:rpx(375.00px = 屏幕宽度),规范 px 值按 2x 映射为 rpx - * 禁止页面层写死颜色/间距/圆角,必须引用 var(--token) + * v2(2026-09-22 设计系统夯实) + * --------------------------------------------------------------- + * 本次修订针对审计发现的系统性问题,逐条给出依据: + * + * 1) 品牌色不能承载文字 → 引入「基础色 / -strong」分级 + * #E96B6B on 白 = 3.10:1,白字 on #E96B6B = 3.10:1,on #FFF3F2 = 2.85:1, + * 三条路径都不满足正文 4.5:1。故: + * --color-primary 仅用于大色块、渐变、光晕、装饰(非文字) + * --color-primary-strong 用于文字、小图标、纯文字链接(5.33:1 ✓) + * --color-primary-solid 实心按钮底(白字 ≥4.5:1 ✓) + * 功能色(success/warning/danger/info)同此分级。 + * + * 2) 次要文字对比度过低 + * 旧 --color-text-tertiary(#777) = 4.48(on 白,勉强)/ #999 实测 2.85 却被用了 71 次。 + * 现将三级文字压到 #646C85 = 5.22:1,占位符保留浅色(占位符非正文)。 + * + * 3) 颜色碎片化 + * 审计前全站 182 种 hex、770 次硬编码(54 种灰、60 种蓝紫、40 种红橙)。 + * 本文件是唯一的颜色事实源;页面层禁止再写 hex,一律 var(--token)。 + * + * 4) 触摸目标 + * 组件库默认按钮只有 40px、小号 28px、"喜欢"按钮 31px。 + * 统一以 --tap-min(44.00px=44px) 为下限,--tap-gap 为最小间距。 + * + * 5) 动效几乎未落地(--motion-* 全站仅 5 次引用) + * 补充 --ease-spring 与 --press-scale,让点击有即时反馈。 + * + * 6) 夜间氛围层缺失(参考图有明显的光晕/星点,代码只有纯渐变) + * 新增 --mini-glow-* / --mini-star / --mini-glass / --mini-hairline。 + * + * 单位说明:rpx(375.00px = 屏幕宽度,0.50px ≈ 0.5px @375pt) + * 旧 token 名全部保留(88 个 wxss 共 909 处引用),只更新取值,避免大范围失效。 */ .wx-page { - /* ============ 品牌主色(规范 §3) ============ */ - --color-primary: #E96B6B; - --color-primary-active: #D95F5F; + /* ============ 品牌主色(分级:色块 / 文字 / 实心按钮) ============ */ + --color-primary: #E96B6B; /* 基础色:渐变、光晕、装饰、非文字图形 */ + --color-primary-strong: #B8434A; /* 文字与小图标(5.33:1 on 白,4.91:1 on 浅粉底) */ + --color-primary-solid: #C24C50; /* 实心按钮底(白字 4.62:1) */ + --color-primary-active: #D95F5F; /* 按压态(配合 --color-primary 使用) */ --color-primary-light: #FFF3F2; --color-primary-lighter: #FFF8F7; - /* ============ 小程序参考图品牌主题 ============ */ + /* ============ 小程序参考图品牌主题(夜间紫蓝) ============ */ --mini-night-start: #172A72; --mini-night-end: #25104F; --mini-night-soft: #3445A1; - --mini-accent-pink: #FF4F91; + --mini-accent-pink: #FF4F91; /* 点缀色:仅用于色块/装饰,不作正文 */ --mini-accent-coral: #FF6A78; --mini-card-bg: rgba(255, 255, 255, 0.98); --mini-text: #1F2744; --mini-muted: #7D839B; --mini-card-radius: 12.00px; - --mini-text-on-night: #FFFFFF; - --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); + --mini-text-on-night: #FFFFFF; /* on 深底 13.04:1 ✓ */ + --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); /* on 深底 ≈8:1 ✓ */ --mini-shadow: 0 8.00px 20.00px rgba(28, 30, 88, 0.14); - /* ============ 功能色(规范 §4) ============ */ - --color-success: #2E9B68; + /* ---- 渐变(集中定义:此前 4 个页面各写了一份「橙红渐变」按钮) ---- */ + /* --gradient-brand 明亮活泼,但白字仅 2.77:1 —— 只能用于无文字的装饰填充。 */ + --gradient-brand: linear-gradient(135deg, #FF6A78 0%, #E96B6B 100%); + /* 承载白字的 CTA 渐变:两端 #C24C50(4.73:1) / #B8434A(5.33:1) 均达标。 */ + --gradient-brand-solid: linear-gradient(135deg, #C24C50 0%, #B8434A 100%); + --gradient-night: linear-gradient(160deg, #172A72 0%, #25104F 100%); + --gradient-night-soft: linear-gradient(160deg, #3445A1 0%, #172A72 100%); + + /* ---- 首页 4×2 入口宫格图标渐变(参考图 2:高饱和圆角砖 + 白色描画图标) ---- + 白图标的对比度判据是**非文本图形 3:1**(WCAG 1.4.11)。渐变是斜向的、图标又跨在 + 两色之间,所以**较亮的一端也必须达标** —— 下表注释给的是 0% 处实算值,100% 更暗只会更高。 + 色相按业务语义固定(不随 tone 名漂移):找对象/婚前辅导=玫瑰粉系、公益红娘/服务站=暖橙系、 + 公益活动=紫罗兰、婚恋咨询=蓝、婚恋课堂=紫、婚恋反诈=绿。 */ + --gradient-entry-rose: linear-gradient(135deg, #F56287 0%, #F34671 100%); /* 3.01:1 / 3.54:1 */ + --gradient-entry-orange: linear-gradient(135deg, #F66A06 0%, #D95E06 100%); /* 3.01:1 / 3.78:1 */ + --gradient-entry-violet: linear-gradient(135deg, #A380F5 0%, #8F64F2 100%); /* 3.02:1 / 3.98:1 */ + --gradient-entry-blue: linear-gradient(135deg, #5195F6 0%, #3484F4 100%); /* 3.01:1 / 3.65:1 */ + --gradient-entry-purple: linear-gradient(135deg, #B27BF0 0%, #A260ED 100%); /* 3.01:1 / 3.87:1 */ + --gradient-entry-pink: linear-gradient(135deg, #F2619E 0%, #F0458C 100%); /* 3.01:1 / 3.54:1 */ + --gradient-entry-green: linear-gradient(135deg, #18A979 0%, #148F66 100%); /* 3.00:1 / 4.08:1 */ + --gradient-entry-amber: linear-gradient(135deg, #E9740C 0%, #CC650B 100%); /* 3.01:1 / 3.86:1 */ + /* 图标砖落影:比 --mini-shadow 更小,避免 4 列宫格里相邻砖块的投影互相压边 */ + --mini-entry-shadow: 0 4.00px 9.00px rgba(28, 30, 88, 0.18); + + /* ---- 夜间氛围层(v2 新增;参考图有光晕与星点,此前完全没有) ---- */ + --mini-glow-coral: rgba(255, 79, 145, 0.40); + --mini-glow-indigo: rgba(94, 124, 255, 0.32); + --mini-glow-soft: rgba(255, 255, 255, 0.10); + --mini-star: rgba(255, 255, 255, 0.70); + --mini-glass: rgba(255, 255, 255, 0.10); /* 深底玻璃面 */ + --mini-glass-strong: rgba(255, 255, 255, 0.16); + --mini-hairline: rgba(255, 255, 255, 0.16); /* 深底分隔线 */ + --mini-glass-success: rgba(90, 226, 184, 0.16); /* 深底上的成功态玻璃面 */ + + /* 星点层:多个小径向渐变叠在夜空渐变之上。用 radial-gradient 而非图片, + 避免额外请求,也便于随主题换色(index 页脚注:装饰层不承载信息)。 */ + --mini-starfield: + radial-gradient(circle at 12% 18%, var(--mini-star) 0, transparent 1.25px), + radial-gradient(circle at 31% 66%, var(--mini-star) 0, transparent 1.00px), + radial-gradient(circle at 57% 12%, var(--mini-star) 0, transparent 1.00px), + radial-gradient(circle at 79% 52%, var(--mini-star) 0, transparent 1.50px), + radial-gradient(circle at 93% 84%, var(--mini-star) 0, transparent 1.00px); + + /* 横幅压暗层:保证任何底图上的白色标题都有足够对比度 */ + --mini-banner-scrim: linear-gradient(90deg, rgba(23, 42, 114, 0.84) 0%, rgba(37, 16, 79, 0.40) 56%, rgba(255, 79, 145, 0.12) 100%); + + /* ============ 功能色(同样分级) ============ */ + --color-success: #2E9B68; /* 色块/图标 */ + --color-success-strong: #17805A; /* 文字(4.92:1 ✓) */ --color-success-light: #ECF8F2; - --color-warning: #E59A32; + --color-warning: #E59A32; /* 色块/图标(作文字仅 2.33:1) */ + --color-warning-strong: #9C5F14; /* 文字(5.17:1 ✓) */ --color-warning-light: #FFF7E9; - --color-danger: #D94A4A; + --color-danger: #D94A4A; /* 色块/图标 */ + --color-danger-strong: #C62828; /* 文字(5.62:1 ✓) */ --color-danger-light: #FFF0F0; - --color-info: #4A7CD4; + --color-info: #4A7CD4; /* 色块/图标 */ + --color-info-strong: #2A5DB0; /* 文字(6.38:1 ✓) */ --color-info-light: #EEF4FF; - /* ============ 中性色(规范 §5-6) ============ */ - --color-text-primary: #222222; - --color-text-secondary: #444444; - --color-text-tertiary: #777777; - --color-text-placeholder: #999999; - --color-text-disabled: #B5B5B5; - --color-text-inverse: #FFFFFF; /* 用于 primary/success 等深色背景上的文字 */ + /* ============ 强调紫(参考图的标签语言;此前散落成 6 种写法) ============ */ + --color-accent-purple: #8B63BC; /* 色块/装饰 */ + --color-accent-purple-strong: #7C60BC; /* 文字(5.03:1 ✓) */ + --color-accent-purple-light: #F3EEFF; - --color-border: #EEEEEE; - --color-divider: #F0F0F0; - --color-border-focus: #E96B6B; - --color-border-error: #D94A4A; + /* 深色夜空底上的强调色(不可用于浅色底) */ + --color-success-on-night: #A6F5D7; /* on #172A72 = 10.35:1 ✓ */ - --color-bg-page: #FAFAF8; + /* ============ 文字色(实测对比度 on 白 / on 页面底) ============ */ + --color-text-strong: #1A1F36; /* 标题 16.24 / 14.90 ✓ */ + --color-text-primary: #2A3050; /* 正文 12.83 / 11.77 ✓ */ + --color-text-secondary: #4A5169; /* 次要正文 7.86 / 7.21 ✓ */ + --color-text-tertiary: #646C85; /* 说明文字 5.22 / 4.79 ✓(旧 #777 为 4.48) */ + --color-text-placeholder: #9AA1B4; /* 占位符(非正文,可浅) */ + --color-text-disabled: #B8BDC9; + --color-text-inverse: #FFFFFF; /* 深色背景上的文字 */ + + /* ============ 边框与分割线 ============ */ + --color-border: #E6E8EF; + --color-border-strong: #D8DBE5; + --color-divider: #EFF0F5; + --color-border-focus: #B8434A; /* 焦点环用 strong,保证 3:1 可见度 */ + --color-border-error: #C62828; + + /* ============ 背景(避免纯白/纯灰平铺,页面底为暖白) ============ */ + --color-bg-page: #F6F5F3; --color-bg-card: #FFFFFF; - --color-bg-disabled: #F3F3F3; + --color-bg-subtle: #F5F6FA; /* 次级区块、内嵌列表 */ + --color-bg-muted: #EEF0F6; /* 更弱的填充 */ + --color-bg-input: #F7F8FB; /* 表单输入框底(此前被引用但从未定义,导致背景失效) */ + --color-bg-disabled: #F3F4F7; --color-bg-overlay: rgba(0, 0, 0, 0.45); - /* ============ 字体(规范 §7-11) ============ */ + /* ============ 字体 ============ */ + /* 小程序无法可靠加载 Web Font(wx.loadFontFace 依赖 HTTPS 白名单且有闪动风险), + 故使用中文系统字栈:iOS 走苹方、Android 走思源/系统黑体。 + 排版辨识度靠字号阶梯与字重建立,而非依赖字体本身。 */ --font-family-cn: -apple-system, "PingFang SC", "Noto Sans SC", "Hiragino Sans GB", "Microsoft YaHei", system-ui, sans-serif; + --font-family-number: "SF Pro Display", -apple-system, "DIN Alternate", "PingFang SC", sans-serif; - --font-size-xs: 12.00px; /* 12px */ - --font-size-sm: 13.00px; /* 13px */ - --font-size-md: 14.00px; /* 14px */ - --font-size-base: 16.00px; /* 16px */ - --font-size-lg: 18.00px; /* 18px */ - --font-size-xl: 20.00px; /* 20px */ - --font-size-2xl: 24.00px; /* 24px */ - --font-size-3xl: 28.00px; /* 28px */ + /* 字号阶梯 —— 正文 16.00px(16px) 起,元信息下限 12.00px(12px) */ + --font-size-micro: 11.00px; /* 11px 仅角标/装饰,禁用于正文 */ + --font-size-xs: 12.00px; /* 12px 元信息下限 */ + --font-size-sm: 13.00px; /* 13px 次要说明 */ + --font-size-md: 14.00px; /* 14px 次要正文 */ + --font-size-base: 16.00px; /* 16px 正文 */ + --font-size-lg: 18.00px; /* 18px 小标题 */ + --font-size-xl: 20.00px; /* 20px 区块标题 */ + --font-size-2xl: 24.00px; /* 24px 页面标题 */ + --font-size-3xl: 28.00px; /* 28px 大标题 */ + --font-size-display: 32.00px; /* 32px Hero */ + /* 字重:只用 4 档。禁止 550/650/750 等非百位值 —— Android 无对应字重会回退, + 导致同一设计在不同机型上粗细不一致(审计发现 30 处)。 */ --font-weight-regular: 400; --font-weight-medium: 500; --font-weight-semibold: 600; @@ -2870,51 +4672,68 @@ --line-height-tight: 1.25; --line-height-normal: 1.5; - --line-height-relaxed: 1.7; + --line-height-relaxed: 1.65; - /* ============ 间距(规范 §12,4px 栅格) ============ */ - --spacing-1: 4.00px; /* 4px */ - --spacing-2: 8.00px; /* 8px */ - --spacing-3: 12.00px; /* 12px */ - --spacing-4: 16.00px; /* 16px */ - --spacing-5: 20.00px; /* 20px */ - --spacing-6: 24.00px; /* 24px */ - --spacing-8: 32.00px; /* 32px */ - --spacing-10: 40.00px; /* 40px */ - --spacing-12: 48.00px; /* 48px */ + --letter-spacing-tight: 0; + --letter-spacing-wide: 0.50px; + --letter-spacing-wider: 1.00px; - --spacing-page-x: 16.00px; /* 页面左右 16px */ - --spacing-section: 24.00px; /* 区块间 24px */ - --spacing-card-inner: 16.00px; /* 卡片内部 16px */ - --spacing-tight: 8.00px; /* 紧密 8px */ + /* ============ 间距(4px 栅格) ============ */ + --spacing-1: 4.00px; + --spacing-2: 8.00px; + --spacing-3: 12.00px; + --spacing-4: 16.00px; + --spacing-5: 20.00px; + --spacing-6: 24.00px; + --spacing-8: 32.00px; + --spacing-10: 40.00px; + --spacing-12: 48.00px; - /* ============ 圆角(规范 §14) ============ */ - --radius-sm: 8.00px; /* 8px */ - --radius-md: 12.00px; /* 12px */ - --radius-lg: 16.00px; /* 16px */ - --radius-xl: 20.00px; /* 20px */ + --spacing-page-x: 16.00px; + --spacing-section: 24.00px; + --spacing-card-inner: 16.00px; + --spacing-tight: 8.00px; + + /* ============ 圆角 ============ */ + --radius-sm: 8.00px; + --radius-md: 12.00px; + --radius-lg: 16.00px; + --radius-xl: 20.00px; + --radius-2xl: 24.00px; --radius-full: 4999.50px; - /* ============ 阴影(规范 §15,极轻) ============ */ - --shadow-card: 0 4.00px 16.00px rgba(0, 0, 0, 0.04); + /* ============ 阴影(统一为一套,此前 30+ 种近似值) ============ */ + --shadow-card: 0 4.00px 14.00px rgba(35, 35, 95, 0.07); + --shadow-raised: 0 6.00px 18.00px rgba(35, 35, 95, 0.10); --shadow-popup: 0 8.00px 32.00px rgba(0, 0, 0, 0.10); + --shadow-night: 0 8.00px 20.00px rgba(28, 30, 88, 0.18); - /* ============ 边框(规范 §16) ============ */ + /* ============ 边框宽度 ============ */ --border-width: 0.50px; + --border-width-strong: 1.00px; - /* ============ 动效(规范 §17) ============ */ + /* ============ 触摸目标(无障碍下限 44×44px) ============ */ + --tap-min: 44.00px; /* 44px 最小可点区域 */ + --tap-comfortable: 48.00px; /* 48px 舒适尺寸:主操作 */ + --tap-gap: 8.00px; /* 8px 相邻目标最小间距 */ + + /* ============ 动效 ============ */ --motion-fast: 120ms; --motion-normal: 200ms; --motion-slow: 300ms; - --ease-standard: ease-out; + --ease-standard: cubic-bezier(0.32, 0.72, 0, 1); + --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1); + --press-scale: 0.97; + --press-opacity: 0.88; - /* ============ 层级 z-index(规范 §90) ============ */ + /* ============ 层级 z-index ============ */ --z-base: 1; --z-sticky: 100; --z-tabbar: 200; --z-dropdown: 500; --z-modal: 1000; --z-toast: 2000; + --z-ambient: 0; /* ============ 页面基础样式 ============ */ background-color: var(--color-bg-page); @@ -2924,7 +4743,10 @@ line-height: var(--line-height-normal); } -/* ============ 通用工具类 ============ */ +/* ========================================================================== + 通用工具类 + ========================================================================== */ + .container { padding: var(--spacing-page-x); } @@ -2938,17 +4760,34 @@ .flex-shrink-0 { flex-shrink: 0; } .wrap { flex-wrap: wrap; } +/* 4 列宫格:用 flex + 百分比宽度实现。 + 注:display:grid 在 WebView 渲染下可用,但 Skyline 不支持,故统一改为 flex 以免疫渲染引擎迁移。*/ +.grid-4 { + display: flex; + flex-wrap: wrap; +} +.grid-4 > .grid-item { + width: 25%; + box-sizing: border-box; +} + +.text-strong { color: var(--color-text-strong); } .text-primary { color: var(--color-text-primary); } .text-secondary { color: var(--color-text-secondary); } .text-tertiary { color: var(--color-text-tertiary); } .text-placeholder { color: var(--color-text-placeholder); } .text-white { color: var(--color-text-inverse); } -.text-brand { color: var(--color-primary); } -.text-success { color: var(--color-success); } -.text-warning { color: var(--color-warning); } -.text-danger { color: var(--color-danger); } -.text-info { color: var(--color-info); } +.text-brand { color: var(--color-primary-strong); } +/* 品牌色作文字只能用 -strong 变体:基础色 #E96B6B 在白底仅 3.10:1。 + 保留 .text-brand-soft 这个类名是为了不破坏既有引用,取值已统一到 -strong, + 如需「更亮的品牌色」请用于背景/图形而非文字。 */ +.text-brand-soft { color: var(--color-primary-strong); } +.text-success { color: var(--color-success-strong); } +.text-warning { color: var(--color-warning-strong); } +.text-danger { color: var(--color-danger-strong); } +.text-info { color: var(--color-info-strong); } +.font-micro { font-size: var(--font-size-micro); } .font-xs { font-size: var(--font-size-xs); } .font-sm { font-size: var(--font-size-sm); } .font-md { font-size: var(--font-size-md); } @@ -2957,6 +4796,7 @@ .font-xl { font-size: var(--font-size-xl); } .font-2xl { font-size: var(--font-size-2xl); } .font-3xl { font-size: var(--font-size-3xl); } +.font-display { font-size: var(--font-size-display); } .font-regular { font-weight: var(--font-weight-regular); } .font-medium { font-weight: var(--font-weight-medium); } @@ -2994,7 +4834,7 @@ padding-bottom: 0px; } -/* 页面卡片基础样式(中低密度留白) */ +/* 页面卡片基础样式 */ .card-base { background: var(--color-bg-card); border-radius: var(--radius-lg); @@ -3008,555 +4848,730 @@ background: var(--color-divider); } -.wx-page{background:var(--color-bg-page)}.service-page{min-height:100vh;padding-bottom:calc(70.00px + 0px)}.hero{padding:22.00px 16.00px 27.00px;background:linear-gradient(140deg,var(--color-primary-lighter),#FFF8EE);position:relative;overflow:hidden}.eyebrow{display:inline-flex;padding:3.50px 7.00px;border-radius:499.50px;background:rgba(255,255,255,.72);color:var(--color-primary);font-size:10.50px}.hero-title{display:block;margin-top:9.00px;font-size:20.00px;font-weight:700;line-height:1.35}.hero-desc{display:block;width:82%;margin-top:7.00px;font-size:12.50px;color:var(--color-text-secondary);line-height:1.7}.content{padding:0 var(--spacing-page-x)}.block{margin-top:var(--spacing-section)}.block-title{display:block;font-size:15.50px;font-weight:650}.block-subtitle{display:block;margin-top:4.00px;font-size:11.50px;color:var(--color-text-tertiary)}.card{margin-top:9.00px;padding:14.00px;background:var(--color-bg-card);border:0.50px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.feature-row,.menu-row,.record-row{display:flex;align-items:center;gap:10.00px;min-height:56.00px;padding:9.00px 0;border-bottom:0.50px solid var(--color-divider)}.feature-row:last-child,.menu-row:last-child,.record-row:last-child{border-bottom:0}.feature-icon{width:36.00px;height:36.00px;display:flex;align-items:center;justify-content:center;flex:none;border-radius:11.00px;background:var(--color-primary-light);color:var(--color-primary);font-weight:700}.feature-copy{flex:1;min-width:0}.feature-title{display:block;font-size:14.00px;font-weight:600}.feature-desc,.meta{display:block;margin-top:3.50px;font-size:11.50px;color:var(--color-text-tertiary);line-height:1.55}.arrow{font-size:20.00px;color:var(--color-text-disabled)}.tag{display:inline-flex;margin-right:5.00px;margin-top:5.00px;padding:3.00px 6.50px;border-radius:499.50px;background:var(--color-success-light);color:var(--color-success);font-size:10.00px}.tag.warning{background:var(--color-warning-light);color:var(--color-warning)}.primary-btn,.secondary-btn{height:44.00px;display:flex;align-items:center;justify-content:center;border-radius:22.00px;font-size:14.00px;font-weight:600}.primary-btn{background:linear-gradient(135deg,var(--mini-accent-coral),var(--mini-accent-pink));color:var(--color-text-inverse);box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)}.primary-btn.disabled{background:#E6E8EF;color:#989DAF;box-shadow:none}.secondary-btn{background:var(--color-primary-light);color:var(--color-primary)}.fixed-action{position:fixed;left:0;right:0;bottom:0;padding:9.00px var(--spacing-page-x) calc(9.00px + 0px);background:rgba(255,255,255,.96);border-top:0.50px solid var(--color-divider);z-index:100}.field{margin-top:13.00px}.label{display:block;margin-bottom:6.00px;font-size:12.50px;font-weight:600}.input,.select-box,.textarea{width:100%;box-sizing:border-box;background:#FCFAF8;border:0.50px solid var(--color-border);border-radius:var(--radius-md);font-size:13.00px}.input,.select-box{height:44.00px;padding:0 12.00px;display:flex;align-items:center}.textarea{min-height:90.00px;padding:11.00px}.notice{margin-top:10.00px;padding:11.00px;border-radius:var(--radius-md);background:#F3F7FC;color:var(--color-text-secondary);font-size:11.50px;line-height:1.65}.empty-panel{text-align:center;padding:35.00px 15.00px}.empty-symbol{width:48.00px;height:48.00px;margin:auto;display:flex;align-items:center;justify-content:center;border-radius:15.00px;background:var(--color-primary-light);color:var(--color-primary);font-size:18.00px;font-weight:700}.empty-title{display:block;margin-top:11.00px;font-size:15.00px;font-weight:600}.article-card{margin-top:9.00px;background:var(--color-bg-card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.article-cover{height:110.00px;padding:12.00px;background:linear-gradient(135deg,#F5E5DE,#F9F1E8);display:flex;align-items:flex-end}.article-cover text{font-size:21.00px;color:rgba(125,76,63,.52);font-weight:700}.article-body{padding:12.00px}.article-title{display:block;font-size:14.50px;font-weight:650;line-height:1.45}.article-meta{display:block;margin-top:5.00px;font-size:11.00px;color:var(--color-text-tertiary)}.article-content{padding:16.00px;background:var(--color-bg-card);font-size:14.00px;line-height:1.9;color:var(--color-text-secondary)}.article-content .lead{display:block;font-size:15.50px;color:var(--color-text-primary);font-weight:600;margin-bottom:12.00px}.danger-card{background:#FFF8F4;border-color:#F5DED2}.danger-card .feature-icon{background:#FFF0EA;color:#C85D43}@media(max-width:340px){.hero-title{font-size:18.00px}.hero-desc{width:92%}} +/* ========================================================================== + 可访问性:只用 token,不用工具类(2026-09-23 修订) + -------------------------------------------------------------------------- + v2 曾在此处新增 .tap-min / .tap-gap / .focusable / .pressable 四个工具类。 + 复检发现全部零引用(等价能力已各自写在组件样式内,例如 button/index.wxss + 直接使用 min-height:var(--tap-min)),且存在两个硬问题: -.service-shell{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:#F4F5FA}.service-content{padding:4.00px 12.00px 18.00px}.service-status{display:flex;align-items:center;justify-content:space-between;margin-top:12.00px;padding:10.00px 12.00px;border-radius:11.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-status__label{color:#7B8198;font-size:10.50px}.service-status__value{padding:3.00px 7.00px;border-radius:9.00px;background:#EAF8F2;color:#329472;font-size:9.50px;font-weight:650}.service-status__value.disabled{background:#FFF0F0;color:#D45A60}.service-topics{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.service-topic{min-height:74.00px;padding:10.00px;border-radius:12.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-topic__icon{display:flex;align-items:center;justify-content:center;width:27.00px;height:27.00px;border-radius:8.50px;background:#FFF0F5}.service-topic__icon image{width:17.00px;height:17.00px}.service-topic__title{display:block;margin-top:6.50px;color:#283056;font-size:12.00px;font-weight:650}.service-topic__desc{display:block;margin-top:3.00px;color:#858A9E;font-size:9.50px;line-height:1.45}.service-actions{display:flex;gap:7.00px}.service-actions .secondary-btn{width:95.00px;flex:none}.service-actions .primary-btn{flex:1}.privacy-note{display:flex;align-items:flex-start;gap:7.00px;margin-top:11.00px;padding:10.00px;border-radius:11.00px;background:#F1F4FF;color:#69718E;font-size:10.00px;line-height:1.55}.privacy-note image{width:17.00px;height:17.00px;flex:none} + 1) `.tap-gap > * + *` 用了通配符与兄弟选择器 —— WXSS 不支持, + wcc 编译期直接报 `error at token '*'`,导致整个小程序编译失败。 + (这是编译错误,不是静默失效,代价最高。) + 2) `.pressable:active` / `.focusable:focus-visible` 的伪类在 view 上 + 不生效(小程序须用 hover-class),属于"写了等于没写"。 + + 故整块移除,保留 token。需要热区/间距时直接引用 token: + min-height: var(--tap-min); → 44.00px = 44px,最小可点区域 + gap: var(--tap-gap); → 8.00px = 8px,相邻目标间距(flex gap) + 【WXSS 禁用清单】星号通配符、兄弟选择器、属性选择器。 + 【注释约束】WXSS 注释**不可嵌套**:内层注释的结束标记会提前终止外层注释, + 其后的文字会被当成真实样式解析,导致编译失败或样式被污染。 + (2026-09-23 实证:本块注释初版即踩此坑。) + ========================================================================== */ + +.wx-page{background:var(--color-bg-page)}.service-page{min-height:100vh;padding-bottom:calc(70.00px + 0px)}.hero{padding:22.00px 16.00px 27.00px;background:linear-gradient(140deg,var(--color-primary-lighter),var(--color-warning-light));position:relative;overflow:hidden}.eyebrow{display:inline-flex;padding:3.50px 7.00px;border-radius:499.50px;background:rgba(255,255,255,.72);color:var(--color-primary-strong);font-size:12.00px}.hero-title{display:block;margin-top:9.00px;font-size:20.00px;font-weight:700;line-height:1.35}.hero-desc{display:block;width:82%;margin-top:7.00px;font-size:12.50px;color:var(--color-text-secondary);line-height:1.7}.content{padding:0 var(--spacing-page-x)}.block{margin-top:var(--spacing-section)}.block-title{display:block;font-size:15.50px;font-weight:600}.block-subtitle{display:block;margin-top:4.00px;font-size:12.00px;color:var(--color-text-tertiary)}.card{margin-top:9.00px;padding:14.00px;background:var(--color-bg-card);border:0.50px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.feature-row,.menu-row,.record-row{display:flex;align-items:center;gap:10.00px;min-height:56.00px;padding:9.00px 0;border-bottom:0.50px solid var(--color-divider)}.feature-row:last-child,.menu-row:last-child,.record-row:last-child{border-bottom:0}.feature-icon{width:36.00px;height:36.00px;display:flex;align-items:center;justify-content:center;flex:none;border-radius:11.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-weight:700}.feature-copy{flex:1;min-width:0}.feature-title{display:block;font-size:14.00px;font-weight:600}.feature-desc,.meta{display:block;margin-top:3.50px;font-size:12.00px;color:var(--color-text-tertiary);line-height:1.55}.arrow{font-size:20.00px;color:var(--color-text-disabled)}.tag{display:inline-flex;margin-right:5.00px;margin-top:5.00px;padding:3.00px 6.50px;border-radius:499.50px;background:var(--color-success-light);color:var(--color-success-strong);font-size:12.00px}.tag.warning{background:var(--color-warning-light);color:var(--color-warning-strong)}.primary-btn,.secondary-btn{height:44.00px;display:flex;align-items:center;justify-content:center;border-radius:22.00px;font-size:14.00px;font-weight:600}.primary-btn{background:var(--gradient-brand-solid);color:var(--color-text-inverse);box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)}.primary-btn.disabled{background:var(--color-bg-muted);color:var(--color-text-tertiary);box-shadow:none}.secondary-btn{background:var(--color-primary-light);color:var(--color-primary-strong)}.fixed-action{position:fixed;left:0;right:0;bottom:0;padding:9.00px var(--spacing-page-x) calc(9.00px + 0px);background:rgba(255,255,255,.96);border-top:0.50px solid var(--color-divider);z-index:100}.field{margin-top:13.00px}.label{display:block;margin-bottom:6.00px;font-size:12.50px;font-weight:600}.input,.select-box,.textarea{width:100%;box-sizing:border-box;background:var(--color-bg-page);border:0.50px solid var(--color-border);border-radius:var(--radius-md);font-size:13.00px}.input,.select-box{height:44.00px;padding:0 12.00px;display:flex;align-items:center}.textarea{min-height:90.00px;padding:11.00px}.notice{margin-top:10.00px;padding:11.00px;border-radius:var(--radius-md);background:var(--color-info-light);color:var(--color-text-secondary);font-size:12.00px;line-height:1.65}.select-box.is-readonly{background:var(--color-bg-subtle);color:var(--color-text-secondary)}.empty-panel{text-align:center;padding:35.00px 15.00px}.empty-symbol{width:48.00px;height:48.00px;margin:auto;display:flex;align-items:center;justify-content:center;border-radius:15.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-size:18.00px;font-weight:700}.empty-title{display:block;margin-top:11.00px;font-size:15.00px;font-weight:600}.article-card{margin-top:9.00px;background:var(--color-bg-card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.article-cover{height:110.00px;padding:12.00px;background:linear-gradient(135deg,var(--color-warning-light),var(--color-warning-light));display:flex;align-items:flex-end}.article-cover text{font-size:21.00px;color:rgba(125,76,63,.52);font-weight:700}.article-body{padding:12.00px}.article-title{display:block;font-size:14.50px;font-weight:600;line-height:1.45}.article-meta{display:block;margin-top:5.00px;font-size:12.00px;color:var(--color-text-tertiary)}.article-content{padding:16.00px;background:var(--color-bg-card);font-size:14.00px;line-height:1.9;color:var(--color-text-secondary)}.article-content .lead{display:block;font-size:15.50px;color:var(--color-text-primary);font-weight:600;margin-bottom:12.00px}.danger-card{background:var(--color-primary-lighter);border-color:var(--color-primary-light)}.danger-card .feature-icon{background:var(--color-warning-light);color:var(--color-warning-strong)}@media(max-width:340px){.hero-title{font-size:18.00px}.hero-desc{width:92%}} + +.service-shell{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:var(--color-bg-page)}.service-content{padding:4.00px 12.00px 18.00px}.service-status{display:flex;align-items:center;justify-content:space-between;margin-top:12.00px;padding:10.00px 12.00px;border-radius:11.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-status__label{color:var(--color-text-tertiary);font-size:12.00px}.service-status__value{padding:3.00px 7.00px;border-radius:9.00px;background:var(--color-success-light);color:var(--color-success-strong);font-size:12.00px;font-weight:600}.service-status__value.disabled{background:var(--color-danger-light);color:var(--color-danger-strong)}.service-topics{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.service-topic{min-height:74.00px;padding:10.00px;border-radius:12.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-topic__icon{display:flex;align-items:center;justify-content:center;width:27.00px;height:27.00px;border-radius:8.50px;background:var(--color-primary-light)}.service-topic__icon image{width:17.00px;height:17.00px}.service-topic__title{display:block;margin-top:6.50px;color:var(--color-text-strong);font-size:12.00px;font-weight:600}.service-topic__desc{display:block;margin-top:3.00px;color:var(--color-text-tertiary);font-size:12.00px;line-height:1.45}.service-actions{display:flex;gap:7.00px}.service-actions .secondary-btn{width:95.00px;flex:none}.service-actions .primary-btn{flex:1}.privacy-note{display:flex;align-items:flex-start;gap:7.00px;margin-top:11.00px;padding:10.00px;border-radius:11.00px;background:var(--color-info-light);color:var(--color-text-tertiary);font-size:12.00px;line-height:1.55}.privacy-note image{width:17.00px;height:17.00px;flex:none} /* ==== miniapp/components/nav-bar ==== */ +/* --nav-h / --nav-right 由 index.js 实测胶囊按钮矩形后注入(见 utils/nav-metrics.js) */ .ui-nav { - position: sticky; - top: 0; - left: 0; - width: 100%; - z-index: var(--z-sticky); - box-sizing: border-box; + position:sticky; + top:0; + left:0; + width:100%; + z-index:var(--z-sticky); + box-sizing:border-box; } .ui-nav--card { - background: var(--color-bg-card); - border-bottom: 0.50px solid var(--color-divider); + background:var(--color-bg-card); + border-bottom:0.50px solid var(--color-divider); } .ui-nav--transparent { - background: transparent; + background:transparent; } .ui-nav__bar { - display: flex; - align-items: center; - height: 44.00px; - padding: 0 var(--spacing-2); + position:relative; + display:flex; + align-items:center; + justify-content:space-between; + height:var(--nav-h, 44.00px); + padding:0 var(--spacing-2); } .ui-nav__back, .ui-nav__placeholder { - width: 32.00px; - height: 32.00px; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; -} + width:32.00px; + min-height:var(--tap-min); + display:flex; + align-items:center; + justify-content:center; + flex-shrink:0; +min-width:var(--tap-min);} .ui-nav__back-icon { - width: 18.00px; - height: 18.00px; + width:18.00px; + height:18.00px; } +/* 标题绝对居中:max-width 左右各让开一个胶囊安全区,因此 + (1)文字精确居中于屏幕,不受返回键/右侧操作宽度影响; + (2)不会伸到胶囊下面; + (3)盒子只覆盖文字自身,不会挡住返回键与右侧 slot 的点击。 */ .ui-nav__title { - flex: 1; - text-align: center; - font-size: var(--font-size-lg); - font-weight: var(--font-weight-semibold); - color: var(--color-text-primary); - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; + position:absolute; + left:50%; + top:50%; + transform:translate(-50%, -50%); + max-width:calc(100% - 2 * var(--nav-right, 96.00px)); + box-sizing:border-box; + text-align:center; + font-size:var(--font-size-lg); + font-weight:var(--font-weight-semibold); + color:var(--color-text-primary); + overflow:hidden; + white-space:nowrap; + text-overflow:ellipsis; } .ui-nav__right { - flex-shrink: 0; - min-width: 32.00px; - display: flex; - align-items: center; - justify-content: flex-end; + flex-shrink:0; + min-width:32.00px; + /* 右侧操作整体左移到胶囊左侧,否则会被胶囊盖住点不到 */ + padding-right:var(--nav-right, 0); + display:flex; + align-items:center; + justify-content:flex-end; } /* ==== miniapp/components/section-header ==== */ +/** + * 区块标题(全站所有页面共用,是排版层级的关键一环) + * + * 2026-09-22 修订: + * 1) 层级拉开:标题 18.00px→20.00px(--font-size-xl),与正文 16.00px / 卡片标题 14.00px + * 形成「区块标题 > 卡片标题 > 正文 > 元信息」四级阶梯。 + * 旧值 18.00px 与卡片标题仅差 5.00px,层级读不出来。 + * 2) 右侧 action 是全站最容易被忽略的触摸目标:只有 13.00px 文字高(约 13px), + * 远低于 44px 下限。改为 min-height:--tap-min,热区向上补白。 + * 3) action 文字色原为 --color-primary(#E96B6B)=3.10:1,不达标,改 -strong。 + */ .ui-section { - display: flex; - align-items: center; - justify-content: space-between; - padding: var(--spacing-3) var(--spacing-page-x); + display:flex; + align-items:center; + justify-content:space-between; + padding:var(--spacing-2) var(--spacing-page-x); } .ui-section__left { - display: flex; - align-items: baseline; + display:flex; + align-items:baseline; + min-width:0; } .ui-section__title { - font-size: var(--font-size-lg); - font-weight: var(--font-weight-semibold); - color: var(--color-text-primary); + font-size:var(--font-size-xl); + font-weight:var(--font-weight-semibold); + color:var(--color-text-strong); + letter-spacing:var(--letter-spacing-tight); } .ui-section__subtitle { - margin-left: var(--spacing-2); - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); + margin-left:var(--spacing-2); + font-size:var(--font-size-xs); + color:var(--color-text-tertiary); } .ui-section__action { - display: flex; - align-items: center; - font-size: var(--font-size-sm); - color: var(--color-primary); + display:flex; + align-items:center; + flex:none; + min-height:var(--tap-min); + padding-left:var(--spacing-3); + font-size:var(--font-size-sm); + font-weight:var(--font-weight-medium); + color:var(--color-primary-strong); + transition:opacity var(--motion-fast) var(--ease-standard); +} +.ui-section__action:active { + opacity:var(--press-opacity); } .ui-section__arrow { - margin-left: 2.00px; - width: 12.00px; - height: 12.00px; + margin-left:2.00px; + width:12.00px; + height:12.00px; } /* ==== miniapp/components/matchmaker-card ==== */ .ui-mm { - background: var(--color-bg-card); - border-radius: 13.00px; - padding: 12.00px; - margin-top: 5.00px; - box-shadow: 0 4.00px 14.00px rgba(35,35,95,.06); + background:var(--color-bg-card); + border-radius:13.00px; + padding:12.00px; + margin-top:5.00px; + box-shadow:0 4.00px 14.00px rgba(35,35,95,.06); } .ui-mm__header { - display: block; + display:block; } .ui-mm__title-row { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: var(--spacing-2); + display:flex; + justify-content:space-between; + align-items:center; + margin-bottom:var(--spacing-2); } .ui-mm__title { - font-size: var(--font-size-lg); - font-weight: var(--font-weight-semibold); - color: var(--color-text-primary); + font-size:var(--font-size-lg); + font-weight:var(--font-weight-semibold); + color:var(--color-text-primary); } .ui-mm__mm-info { - font-size: var(--font-size-md); - color: var(--color-text-secondary); - margin-bottom: var(--spacing-2); + font-size:var(--font-size-md); + color:var(--color-text-secondary); + margin-bottom:var(--spacing-2); } .ui-mm__req { - padding: var(--spacing-2) var(--spacing-3); - background: var(--color-bg-disabled); - border-radius: var(--radius-sm); - margin-bottom: var(--spacing-2); + padding:var(--spacing-2) var(--spacing-3); + background:var(--color-bg-disabled); + border-radius:var(--radius-sm); + margin-bottom:var(--spacing-2); } .ui-mm__req-label { - font-size: var(--font-size-xs); - color: var(--color-text-tertiary); + font-size:var(--font-size-xs); + color:var(--color-text-tertiary); } .ui-mm__req-content { - font-size: var(--font-size-sm); - color: var(--color-text-secondary); - line-height: var(--line-height-normal); - display: block; - margin-top: 2.00px; + font-size:var(--font-size-sm); + color:var(--color-text-secondary); + line-height:var(--line-height-normal); + display:block; + margin-top:2.00px; } .ui-mm__follow-up { - font-size: var(--font-size-xs); - color: var(--color-text-tertiary); + font-size:var(--font-size-xs); + color:var(--color-text-tertiary); } .ui-mm__footer { - margin-top: var(--spacing-3); - padding-top: var(--spacing-3); - border-top: 0.50px solid var(--color-divider); + margin-top:var(--spacing-3); + padding-top:var(--spacing-3); + border-top:0.50px solid var(--color-divider); } /* ==== miniapp/components/button ==== */ /** * Button 组件样式 - * 引用全局 Design Token(addGlobalClass: true) + * 引用全局 Design Token(addGlobalClass:true) + * + * 2026-09-22 修复: + * 1) 触摸目标:md 只有 40.00px(40px)、sm 只有 28.00px(28px),低于 44px 下限; + * text 变体更是 min-height:auto,几乎点不中。现统一以 --tap-min 兜底。 + * 2) 对比度:主按钮背景原为 --color-primary(#E96B6B),白字仅 3.10:1。 + * 改用 --color-primary-solid(#C24C50) = 4.73:1,视觉上仍是暖红。 + * secondary/text 的红色文字同理从 3.10 提到 --color-primary-strong 的 5.33。 + * 3) 危险按钮 --color-danger(#D94A4A) 白字 4.18:1 不达标,改用 -strong 变体。 + * 4) 按压反馈统一走 --press-scale / --press-opacity,替代硬编码 0.98 / 0.85。 */ .ui-btn { - display: inline-flex; - align-items: center; - justify-content: center; - box-sizing: border-box; - border-radius: var(--radius-full); - font-family: var(--font-family-cn); - font-weight: var(--font-weight-medium); - text-align: center; - transition: opacity var(--motion-fast) var(--ease-standard), - transform var(--motion-fast) var(--ease-standard); - user-select: none; - line-height: 1; - white-space: nowrap; + display:inline-flex; + align-items:center; + justify-content:center; + box-sizing:border-box; + border-radius:var(--radius-full); + font-family:var(--font-family-cn); + font-weight:var(--font-weight-semibold); + text-align:center; + transition:transform var(--motion-fast) var(--ease-spring), + opacity var(--motion-fast) var(--ease-standard), + background-color var(--motion-fast) var(--ease-standard); + user-select:none; + line-height:1.2; + white-space:nowrap; } -/* 尺寸 */ +/* 尺寸:全部以 44×44px 为热区下限 */ .ui-btn--sm { - padding: 7.00px 12.00px; - font-size: var(--font-size-sm); - min-height: 28.00px; + padding:7.00px 14.00px; + font-size:var(--font-size-sm); + min-height:var(--tap-min); } .ui-btn--md { - padding: 10.00px 18.00px; - font-size: var(--font-size-base); - min-height: 40.00px; + padding:10.00px 18.00px; + font-size:var(--font-size-base); + min-height:var(--tap-min); } .ui-btn--lg { - padding: 13.00px 24.00px; - font-size: var(--font-size-lg); - min-height: 48.00px; + padding:13.00px 24.00px; + font-size:var(--font-size-lg); + min-height:var(--tap-comfortable); } /* 撑满 */ .ui-btn--block { - display: flex; - width: 100%; + display:flex; + width:100%; } /* 变体 */ .ui-btn--primary { - background: var(--color-primary); - color: #FFFFFF; + background:var(--color-primary-solid); + color:var(--color-text-inverse); } .ui-btn--secondary { - background: var(--color-bg-card); - color: var(--color-primary); - border: 0.50px solid var(--color-primary); + background:var(--color-bg-card); + color:var(--color-primary-strong); + border:var(--border-width) solid var(--color-primary-strong); } .ui-btn--ghost { - background: transparent; - color: var(--color-text-primary); - border: 0.50px solid var(--color-border); + background:transparent; + color:var(--color-text-primary); + border:var(--border-width) solid var(--color-border-strong); } .ui-btn--danger { - background: var(--color-danger); - color: #FFFFFF; + background:var(--color-danger-strong); + color:var(--color-text-inverse); } .ui-btn--text { - background: transparent; - color: var(--color-primary); - padding-left: 0; - padding-right: 0; - min-height: auto; + background:transparent; + color:var(--color-primary-strong); + padding-left:var(--spacing-2); + padding-right:var(--spacing-2); + /* 视觉是纯文字,但热区仍需 44px:多出的部分由 align-items:center 居中留白 */ + min-height:var(--tap-min); } /* 状态 */ .ui-btn--disabled, .ui-btn--loading { - opacity: 0.55; + opacity:0.55; } .ui-btn--disabled.ui-btn--primary, .ui-btn--disabled.ui-btn--danger { - background: var(--color-text-disabled); + background:var(--color-text-disabled); } .ui-btn--disabled.ui-btn--secondary, .ui-btn--disabled.ui-btn--ghost { - color: var(--color-text-disabled); - border-color: var(--color-text-disabled); + color:var(--color-text-disabled); + border-color:var(--color-text-disabled); } -.ui-btn--hover { - opacity: 0.85; - transform: scale(0.98); +/* 按压反馈(hover-class 与 CSS :active 双保险) */ +.ui-btn--hover, +.ui-btn:active { + opacity:var(--press-opacity); + transform:scale(var(--press-scale)); } /* Loading spinner */ .ui-btn__spinner { - width: 14.00px; - height: 14.00px; - margin-right: 6.00px; - display: flex; - align-items: center; - justify-content: center; + width:14.00px; + height:14.00px; + margin-right:6.00px; + display:flex; + align-items:center; + justify-content:center; } .ui-btn__spinner-dot { - width: 9.00px; - height: 9.00px; - border-radius: 50%; - border: 1.50px solid currentColor; - border-top-color: transparent; - animation: ui-btn-spin 0.7s linear infinite; + width:9.00px; + height:9.00px; + border-radius:50%; + border:1.50px solid currentColor; + border-top-color:transparent; + animation:ui-btn-spin 0.7s linear infinite; } @keyframes ui-btn-spin { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } + from { transform:rotate(0deg); } + to { transform:rotate(360deg); } } /* ==== miniapp/components/loading ==== */ .ui-loading--block { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: var(--spacing-8) var(--spacing-page-x); + display:flex; + flex-direction:column; + align-items:center; + justify-content:center; + padding:var(--spacing-8) var(--spacing-page-x); } .ui-loading--inline { - display: inline-flex; - align-items: center; + display:inline-flex; + align-items:center; } .ui-loading__spinner { - width: 30.00px; - height: 30.00px; - display: flex; - align-items: center; - justify-content: center; + width:30.00px; + height:30.00px; + display:flex; + align-items:center; + justify-content:center; } .ui-loading__spinner-icon { - width: 24.00px; - height: 24.00px; - animation: ui-loading-spin 0.8s linear infinite; + width:24.00px; + height:24.00px; + animation:ui-loading-spin 0.8s linear infinite; } @keyframes ui-loading-spin { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } + from { transform:rotate(0deg); } + to { transform:rotate(360deg); } } .ui-loading__text { - margin-top: var(--spacing-3); - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); + margin-top:var(--spacing-3); + font-size:var(--font-size-sm); + color:var(--color-text-tertiary); } /* Skeleton */ .ui-loading__skeleton { - width: 100%; + width:100%; } .ui-loading__skeleton-row { - display: flex; - align-items: center; - padding: var(--spacing-3) var(--spacing-page-x); - background: var(--color-bg-card); - border-bottom: 0.50px solid var(--color-divider); + display:flex; + align-items:center; + padding:var(--spacing-3) var(--spacing-page-x); + background:var(--color-bg-card); + border-bottom:0.50px solid var(--color-divider); } .ui-loading__skeleton-avatar { - width: 44.00px; - height: 44.00px; - border-radius: 50%; - background: var(--color-bg-disabled); - margin-right: var(--spacing-3); - flex-shrink: 0; + width:44.00px; + height:44.00px; + border-radius:50%; + background:var(--color-bg-disabled); + margin-right:var(--spacing-3); + flex-shrink:0; } .ui-loading__skeleton-content { - flex: 1; - min-width: 0; + flex:1; + min-width:0; } .ui-loading__skeleton-line { - height: 12.00px; - background: var(--color-bg-disabled); - border-radius: var(--radius-sm); - position: relative; - overflow: hidden; + height:12.00px; + background:var(--color-bg-disabled); + border-radius:var(--radius-sm); + position:relative; + overflow:hidden; } .ui-loading__skeleton-line--title { - width: 40%; - margin-bottom: var(--spacing-2); + width:40%; + margin-bottom:var(--spacing-2); } .ui-loading__skeleton-line--meta { - width: 70%; + width:70%; } /* shimmer */ .ui-loading__skeleton-line::after, .ui-loading__skeleton-avatar::after { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: linear-gradient( + content:''; + position:absolute; + top:0; + left:0; + width:100%; + height:100%; + background:linear-gradient( 90deg, transparent 0%, rgba(255, 255, 255, 0.55) 50%, transparent 100% ); - animation: ui-loading-shimmer 1.4s ease-in-out infinite; + animation:ui-loading-shimmer 1.4s ease-in-out infinite; } @keyframes ui-loading-shimmer { - 0% { transform: translateX(-100%); } - 100% { transform: translateX(100%); } + 0% { transform:translateX(-100%); } + 100% { transform:translateX(100%); } } /* ==== miniapp/components/empty ==== */ .ui-empty { - display: flex; - flex-direction: column; - align-items: center; - padding: var(--spacing-10) var(--spacing-page-x); - text-align: center; + display:flex; + flex-direction:column; + align-items:center; + padding:var(--spacing-10) var(--spacing-page-x); + text-align:center; } .ui-empty__illustration { - width: 80.00px; - height: 80.00px; - border-radius: 50%; - background: var(--color-bg-disabled); - display: flex; - align-items: center; - justify-content: center; - margin-bottom: var(--spacing-4); + width:80.00px; + height:80.00px; + border-radius:50%; + background:var(--color-bg-disabled); + display:flex; + align-items:center; + justify-content:center; + margin-bottom:var(--spacing-4); } .ui-empty__icon { - width: 36.00px; - height: 36.00px; - opacity: 0.72; + width:36.00px; + height:36.00px; + opacity:0.72; } .ui-empty__title { - font-size: var(--font-size-lg); - font-weight: var(--font-weight-medium); - color: var(--color-text-primary); - margin-bottom: var(--spacing-2); + font-size:var(--font-size-lg); + font-weight:var(--font-weight-medium); + color:var(--color-text-primary); + margin-bottom:var(--spacing-2); } .ui-empty__desc { - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); - line-height: var(--line-height-relaxed); - max-width: 240.00px; + font-size:var(--font-size-sm); + color:var(--color-text-tertiary); + line-height:var(--line-height-relaxed); + max-width:240.00px; } .ui-empty__actions { - display: flex; - flex-direction: column; - gap: var(--spacing-2); - margin-top: var(--spacing-6); - width: 100%; - max-width: 240.00px; + display:flex; + flex-direction:column; + gap:var(--spacing-2); + margin-top:var(--spacing-6); + width:100%; + max-width:240.00px; } .ui-empty__action { - display: flex; - align-items: center; - justify-content: center; - height: 40.00px; - border-radius: var(--radius-full); - font-size: var(--font-size-base); - font-weight: var(--font-weight-medium); -} + display:flex; + align-items:center; + justify-content:center; + min-height:var(--tap-min); + border-radius:var(--radius-full); + font-size:var(--font-size-base); + font-weight:var(--font-weight-medium); +min-width:var(--tap-min);} .ui-empty__action--primary { - background: var(--color-primary); - color: #FFFFFF; + background:var(--color-primary-solid); + color:var(--color-text-inverse); } .ui-empty__action--secondary { - background: var(--color-bg-card); - color: var(--color-primary); - border: 0.50px solid var(--color-primary); + background:var(--color-bg-card); + color:var(--color-primary-strong); + border:0.50px solid var(--color-primary); } /* ==== miniapp/components/service-hero ==== */ .service-hero { - position: relative; - height: 150.00px; - overflow: hidden; - border-radius: 0 0 16.00px 16.00px; - background: #fff4f7; + position:relative; + height:150.00px; + overflow:hidden; + border-radius:0 0 16.00px 16.00px; + background:var(--color-primary-light); } .service-hero__image, .service-hero__veil { - position: absolute; - inset: 0; - width: 100%; - height: 100%; + position:absolute; + inset:0; + width:100%; + height:100%; } .service-hero__veil { - background: linear-gradient(90deg, rgba(255, 250, 252, 0.98) 0%, rgba(255, 250, 252, 0.82) 38%, rgba(255, 250, 252, 0.08) 70%); + background:linear-gradient(90deg, rgba(255, 250, 252, 0.98) 0%, rgba(255, 250, 252, 0.82) 38%, rgba(255, 250, 252, 0.08) 70%); } .service-hero--night .service-hero__veil { - background: linear-gradient(90deg, rgba(18, 24, 83, 0.92) 0%, rgba(34, 31, 111, 0.64) 42%, rgba(34, 31, 111, 0.08) 72%); + background:linear-gradient(90deg, rgba(18, 24, 83, 0.92) 0%, rgba(34, 31, 111, 0.64) 42%, rgba(34, 31, 111, 0.08) 72%); } .service-hero__content { - position: relative; - z-index: 1; - display: flex; - flex-direction: column; - justify-content: center; - width: 54%; - height: 100%; - padding: 0 18.00px; - box-sizing: border-box; + position:relative; + z-index:1; + display:flex; + flex-direction:column; + justify-content:center; + width:54%; + height:100%; + padding:0 18.00px; + box-sizing:border-box; } .service-hero__eyebrow { - margin-bottom: 5.00px; - color: var(--color-primary); - font-size: 11.00px; - font-weight: 600; - letter-spacing: 1.00px; + margin-bottom:5.00px; + color:var(--color-primary-strong); + font-size:12.00px; + font-weight:600; + letter-spacing:1.00px; } .service-hero__title { - color: #24305e; - font-size: 20.00px; - font-weight: 700; - line-height: 1.28; + color:var(--color-text-strong); + font-size:20.00px; + font-weight:700; + line-height:1.28; } .service-hero__subtitle { - margin-top: 7.00px; - color: #737c96; - font-size: 12.00px; - line-height: 1.55; + margin-top:7.00px; + color:var(--color-text-tertiary); + font-size:12.00px; + line-height:1.55; } .service-hero--night .service-hero__eyebrow, .service-hero--night .service-hero__title, .service-hero--night .service-hero__subtitle { - color: #ffffff; + color:var(--color-text-inverse); } -.mm-page{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:#F4F5FA}.mm-promises{position:relative;z-index:2;display:grid;grid-template-columns:repeat(3,1fr);margin:-11.00px 12.00px 0;padding:11.00px 4.00px;border-radius:14.00px;background:#fff;box-shadow:var(--mini-shadow)}.mm-promise{display:flex;flex-direction:column;align-items:center;padding:0 4.00px;text-align:center;color:#8A8FA4;font-size:8.50px;line-height:1.35}.mm-promise image{width:23.00px;height:23.00px;margin-bottom:4.00px}.mm-promise__title{margin-bottom:2.00px;color:#303654;font-size:10.50px;font-weight:650}.mm-loading{padding:15.00px 12.00px}.mm-body{padding-top:4.00px}.mm-section{padding:4.00px 12.00px}.mm-no-service{display:flex;align-items:center;gap:9.00px;margin-top:5.00px;padding:12.00px;border-radius:13.00px;background:#fff;box-shadow:0 4.00px 14.00px rgba(35,35,95,.06)}.mm-no-service image{width:34.00px;height:34.00px}.mm-no-service>view{display:flex;flex:1;flex-direction:column}.mm-no-service__title{color:#283056;font-size:12.50px;font-weight:650}.mm-no-service__desc{margin-top:3.50px;color:#858A9E;font-size:10.00px;line-height:1.5}.mm-capability-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:7.00px;margin-top:5.00px}.mm-capability{display:flex;align-items:center;gap:6.00px;min-height:44.00px;padding:8.00px;border-radius:11.00px;background:#fff;color:#555D79;font-size:10.00px;line-height:1.4;box-shadow:0 4.00px 12.00px rgba(35,35,95,.05)}.mm-capability image{width:18.00px;height:18.00px;flex:none}.mm-history{overflow:hidden;margin-top:5.00px;border-radius:12.00px;background:#fff}.mm-history__item{display:flex;align-items:center;min-height:46.00px;padding:0 10.00px;border-bottom:0.50px solid #EFF0F5}.mm-history__item:last-child{border-bottom:0}.mm-history__item>view{display:flex;flex:1;flex-direction:column}.mm-history__title{color:#303654;font-size:11.50px;font-weight:600}.mm-history__meta{margin-top:2.50px;color:#8A8FA4;font-size:9.00px}.mm-history__status{margin-right:4.00px;color:#8A6F91;font-size:9.50px}.mm-history__item>image{width:12.00px;height:12.00px}.mm-fixed-action{position:fixed;z-index:100;right:0;bottom:0;left:0;padding:9.00px 12.00px calc(9.00px + 0px);border-top:0.50px solid #EFF0F5;background:rgba(255,255,255,.96)}.mm-apply{display:flex;align-items:center;justify-content:center;height:44.00px;border-radius:22.00px;background:linear-gradient(135deg,var(--mini-accent-coral),var(--mini-accent-pink));color:#fff;font-size:14.00px;font-weight:650;box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)} +.mm-page{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:var(--color-bg-page)}.mm-promises{position:relative;z-index:2;display:grid;grid-template-columns:repeat(3,1fr);margin:-11.00px 12.00px 0;padding:11.00px 4.00px;border-radius:14.00px;background:var(--color-bg-card);box-shadow:var(--mini-shadow)}.mm-promise{display:flex;flex-direction:column;align-items:center;padding:0 4.00px;text-align:center;color:var(--color-text-tertiary);font-size:12.00px;line-height:1.35}.mm-promise image{width:23.00px;height:23.00px;margin-bottom:4.00px}.mm-promise__title{margin-bottom:2.00px;color:var(--color-text-strong);font-size:12.00px;font-weight:600}.mm-loading{padding:15.00px 12.00px}.mm-body{padding-top:4.00px}.mm-section{padding:4.00px 12.00px}.mm-no-service{display:flex;align-items:center;gap:9.00px;margin-top:5.00px;padding:12.00px;border-radius:13.00px;background:var(--color-bg-card);box-shadow:0 4.00px 14.00px rgba(35,35,95,.06)}.mm-no-service image{width:34.00px;height:34.00px}.mm-no-service>view{display:flex;flex:1;flex-direction:column}.mm-no-service__title{color:var(--color-text-strong);font-size:12.50px;font-weight:600}.mm-no-service__desc{margin-top:3.50px;color:var(--color-text-tertiary);font-size:12.00px;line-height:1.5}.mm-capability-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:7.00px;margin-top:5.00px}.mm-capability{display:flex;align-items:center;gap:6.00px;min-height:44.00px;padding:8.00px;border-radius:11.00px;background:var(--color-bg-card);color:var(--color-text-secondary);font-size:12.00px;line-height:1.4;box-shadow:0 4.00px 12.00px rgba(35,35,95,.05)}.mm-capability image{width:18.00px;height:18.00px;flex:none}.mm-history{overflow:hidden;margin-top:5.00px;border-radius:12.00px;background:var(--color-bg-card)}.mm-history__item{display:flex;align-items:center;min-height:46.00px;padding:0 10.00px;border-bottom:0.50px solid var(--color-divider)}.mm-history__item:last-child{border-bottom:0}.mm-history__item>view{display:flex;flex:1;flex-direction:column}.mm-history__title{color:var(--color-text-strong);font-size:12.00px;font-weight:600}.mm-history__meta{margin-top:2.50px;color:var(--color-text-tertiary);font-size:12.00px}.mm-history__status{margin-right:4.00px;color:var(--color-accent-purple-strong);font-size:12.00px}.mm-history__item>image{width:12.00px;height:12.00px}.mm-fixed-action{position:fixed;z-index:100;right:0;bottom:0;left:0;padding:9.00px 12.00px calc(9.00px + 0px);border-top:0.50px solid var(--color-divider);background:rgba(255,255,255,.96)}.mm-apply{display:flex;align-items:center;justify-content:center;height:44.00px;border-radius:22.00px;background:var(--gradient-brand-solid);color:var(--color-text-inverse);font-size:14.00px;font-weight:600;box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)} /** * 丹阳公益婚恋服务平台 - 全局 Design Token * - * 依据《前端组件库与 Design Token 规范 V1.0》 - * 单位说明:rpx(375.00px = 屏幕宽度),规范 px 值按 2x 映射为 rpx - * 禁止页面层写死颜色/间距/圆角,必须引用 var(--token) + * v2(2026-09-22 设计系统夯实) + * --------------------------------------------------------------- + * 本次修订针对审计发现的系统性问题,逐条给出依据: + * + * 1) 品牌色不能承载文字 → 引入「基础色 / -strong」分级 + * #E96B6B on 白 = 3.10:1,白字 on #E96B6B = 3.10:1,on #FFF3F2 = 2.85:1, + * 三条路径都不满足正文 4.5:1。故: + * --color-primary 仅用于大色块、渐变、光晕、装饰(非文字) + * --color-primary-strong 用于文字、小图标、纯文字链接(5.33:1 ✓) + * --color-primary-solid 实心按钮底(白字 ≥4.5:1 ✓) + * 功能色(success/warning/danger/info)同此分级。 + * + * 2) 次要文字对比度过低 + * 旧 --color-text-tertiary(#777) = 4.48(on 白,勉强)/ #999 实测 2.85 却被用了 71 次。 + * 现将三级文字压到 #646C85 = 5.22:1,占位符保留浅色(占位符非正文)。 + * + * 3) 颜色碎片化 + * 审计前全站 182 种 hex、770 次硬编码(54 种灰、60 种蓝紫、40 种红橙)。 + * 本文件是唯一的颜色事实源;页面层禁止再写 hex,一律 var(--token)。 + * + * 4) 触摸目标 + * 组件库默认按钮只有 40px、小号 28px、"喜欢"按钮 31px。 + * 统一以 --tap-min(44.00px=44px) 为下限,--tap-gap 为最小间距。 + * + * 5) 动效几乎未落地(--motion-* 全站仅 5 次引用) + * 补充 --ease-spring 与 --press-scale,让点击有即时反馈。 + * + * 6) 夜间氛围层缺失(参考图有明显的光晕/星点,代码只有纯渐变) + * 新增 --mini-glow-* / --mini-star / --mini-glass / --mini-hairline。 + * + * 单位说明:rpx(375.00px = 屏幕宽度,0.50px ≈ 0.5px @375pt) + * 旧 token 名全部保留(88 个 wxss 共 909 处引用),只更新取值,避免大范围失效。 */ .wx-page { - /* ============ 品牌主色(规范 §3) ============ */ - --color-primary: #E96B6B; - --color-primary-active: #D95F5F; + /* ============ 品牌主色(分级:色块 / 文字 / 实心按钮) ============ */ + --color-primary: #E96B6B; /* 基础色:渐变、光晕、装饰、非文字图形 */ + --color-primary-strong: #B8434A; /* 文字与小图标(5.33:1 on 白,4.91:1 on 浅粉底) */ + --color-primary-solid: #C24C50; /* 实心按钮底(白字 4.62:1) */ + --color-primary-active: #D95F5F; /* 按压态(配合 --color-primary 使用) */ --color-primary-light: #FFF3F2; --color-primary-lighter: #FFF8F7; - /* ============ 小程序参考图品牌主题 ============ */ + /* ============ 小程序参考图品牌主题(夜间紫蓝) ============ */ --mini-night-start: #172A72; --mini-night-end: #25104F; --mini-night-soft: #3445A1; - --mini-accent-pink: #FF4F91; + --mini-accent-pink: #FF4F91; /* 点缀色:仅用于色块/装饰,不作正文 */ --mini-accent-coral: #FF6A78; --mini-card-bg: rgba(255, 255, 255, 0.98); --mini-text: #1F2744; --mini-muted: #7D839B; --mini-card-radius: 12.00px; - --mini-text-on-night: #FFFFFF; - --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); + --mini-text-on-night: #FFFFFF; /* on 深底 13.04:1 ✓ */ + --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); /* on 深底 ≈8:1 ✓ */ --mini-shadow: 0 8.00px 20.00px rgba(28, 30, 88, 0.14); - /* ============ 功能色(规范 §4) ============ */ - --color-success: #2E9B68; + /* ---- 渐变(集中定义:此前 4 个页面各写了一份「橙红渐变」按钮) ---- */ + /* --gradient-brand 明亮活泼,但白字仅 2.77:1 —— 只能用于无文字的装饰填充。 */ + --gradient-brand: linear-gradient(135deg, #FF6A78 0%, #E96B6B 100%); + /* 承载白字的 CTA 渐变:两端 #C24C50(4.73:1) / #B8434A(5.33:1) 均达标。 */ + --gradient-brand-solid: linear-gradient(135deg, #C24C50 0%, #B8434A 100%); + --gradient-night: linear-gradient(160deg, #172A72 0%, #25104F 100%); + --gradient-night-soft: linear-gradient(160deg, #3445A1 0%, #172A72 100%); + + /* ---- 首页 4×2 入口宫格图标渐变(参考图 2:高饱和圆角砖 + 白色描画图标) ---- + 白图标的对比度判据是**非文本图形 3:1**(WCAG 1.4.11)。渐变是斜向的、图标又跨在 + 两色之间,所以**较亮的一端也必须达标** —— 下表注释给的是 0% 处实算值,100% 更暗只会更高。 + 色相按业务语义固定(不随 tone 名漂移):找对象/婚前辅导=玫瑰粉系、公益红娘/服务站=暖橙系、 + 公益活动=紫罗兰、婚恋咨询=蓝、婚恋课堂=紫、婚恋反诈=绿。 */ + --gradient-entry-rose: linear-gradient(135deg, #F56287 0%, #F34671 100%); /* 3.01:1 / 3.54:1 */ + --gradient-entry-orange: linear-gradient(135deg, #F66A06 0%, #D95E06 100%); /* 3.01:1 / 3.78:1 */ + --gradient-entry-violet: linear-gradient(135deg, #A380F5 0%, #8F64F2 100%); /* 3.02:1 / 3.98:1 */ + --gradient-entry-blue: linear-gradient(135deg, #5195F6 0%, #3484F4 100%); /* 3.01:1 / 3.65:1 */ + --gradient-entry-purple: linear-gradient(135deg, #B27BF0 0%, #A260ED 100%); /* 3.01:1 / 3.87:1 */ + --gradient-entry-pink: linear-gradient(135deg, #F2619E 0%, #F0458C 100%); /* 3.01:1 / 3.54:1 */ + --gradient-entry-green: linear-gradient(135deg, #18A979 0%, #148F66 100%); /* 3.00:1 / 4.08:1 */ + --gradient-entry-amber: linear-gradient(135deg, #E9740C 0%, #CC650B 100%); /* 3.01:1 / 3.86:1 */ + /* 图标砖落影:比 --mini-shadow 更小,避免 4 列宫格里相邻砖块的投影互相压边 */ + --mini-entry-shadow: 0 4.00px 9.00px rgba(28, 30, 88, 0.18); + + /* ---- 夜间氛围层(v2 新增;参考图有光晕与星点,此前完全没有) ---- */ + --mini-glow-coral: rgba(255, 79, 145, 0.40); + --mini-glow-indigo: rgba(94, 124, 255, 0.32); + --mini-glow-soft: rgba(255, 255, 255, 0.10); + --mini-star: rgba(255, 255, 255, 0.70); + --mini-glass: rgba(255, 255, 255, 0.10); /* 深底玻璃面 */ + --mini-glass-strong: rgba(255, 255, 255, 0.16); + --mini-hairline: rgba(255, 255, 255, 0.16); /* 深底分隔线 */ + --mini-glass-success: rgba(90, 226, 184, 0.16); /* 深底上的成功态玻璃面 */ + + /* 星点层:多个小径向渐变叠在夜空渐变之上。用 radial-gradient 而非图片, + 避免额外请求,也便于随主题换色(index 页脚注:装饰层不承载信息)。 */ + --mini-starfield: + radial-gradient(circle at 12% 18%, var(--mini-star) 0, transparent 1.25px), + radial-gradient(circle at 31% 66%, var(--mini-star) 0, transparent 1.00px), + radial-gradient(circle at 57% 12%, var(--mini-star) 0, transparent 1.00px), + radial-gradient(circle at 79% 52%, var(--mini-star) 0, transparent 1.50px), + radial-gradient(circle at 93% 84%, var(--mini-star) 0, transparent 1.00px); + + /* 横幅压暗层:保证任何底图上的白色标题都有足够对比度 */ + --mini-banner-scrim: linear-gradient(90deg, rgba(23, 42, 114, 0.84) 0%, rgba(37, 16, 79, 0.40) 56%, rgba(255, 79, 145, 0.12) 100%); + + /* ============ 功能色(同样分级) ============ */ + --color-success: #2E9B68; /* 色块/图标 */ + --color-success-strong: #17805A; /* 文字(4.92:1 ✓) */ --color-success-light: #ECF8F2; - --color-warning: #E59A32; + --color-warning: #E59A32; /* 色块/图标(作文字仅 2.33:1) */ + --color-warning-strong: #9C5F14; /* 文字(5.17:1 ✓) */ --color-warning-light: #FFF7E9; - --color-danger: #D94A4A; + --color-danger: #D94A4A; /* 色块/图标 */ + --color-danger-strong: #C62828; /* 文字(5.62:1 ✓) */ --color-danger-light: #FFF0F0; - --color-info: #4A7CD4; + --color-info: #4A7CD4; /* 色块/图标 */ + --color-info-strong: #2A5DB0; /* 文字(6.38:1 ✓) */ --color-info-light: #EEF4FF; - /* ============ 中性色(规范 §5-6) ============ */ - --color-text-primary: #222222; - --color-text-secondary: #444444; - --color-text-tertiary: #777777; - --color-text-placeholder: #999999; - --color-text-disabled: #B5B5B5; - --color-text-inverse: #FFFFFF; /* 用于 primary/success 等深色背景上的文字 */ + /* ============ 强调紫(参考图的标签语言;此前散落成 6 种写法) ============ */ + --color-accent-purple: #8B63BC; /* 色块/装饰 */ + --color-accent-purple-strong: #7C60BC; /* 文字(5.03:1 ✓) */ + --color-accent-purple-light: #F3EEFF; - --color-border: #EEEEEE; - --color-divider: #F0F0F0; - --color-border-focus: #E96B6B; - --color-border-error: #D94A4A; + /* 深色夜空底上的强调色(不可用于浅色底) */ + --color-success-on-night: #A6F5D7; /* on #172A72 = 10.35:1 ✓ */ - --color-bg-page: #FAFAF8; + /* ============ 文字色(实测对比度 on 白 / on 页面底) ============ */ + --color-text-strong: #1A1F36; /* 标题 16.24 / 14.90 ✓ */ + --color-text-primary: #2A3050; /* 正文 12.83 / 11.77 ✓ */ + --color-text-secondary: #4A5169; /* 次要正文 7.86 / 7.21 ✓ */ + --color-text-tertiary: #646C85; /* 说明文字 5.22 / 4.79 ✓(旧 #777 为 4.48) */ + --color-text-placeholder: #9AA1B4; /* 占位符(非正文,可浅) */ + --color-text-disabled: #B8BDC9; + --color-text-inverse: #FFFFFF; /* 深色背景上的文字 */ + + /* ============ 边框与分割线 ============ */ + --color-border: #E6E8EF; + --color-border-strong: #D8DBE5; + --color-divider: #EFF0F5; + --color-border-focus: #B8434A; /* 焦点环用 strong,保证 3:1 可见度 */ + --color-border-error: #C62828; + + /* ============ 背景(避免纯白/纯灰平铺,页面底为暖白) ============ */ + --color-bg-page: #F6F5F3; --color-bg-card: #FFFFFF; - --color-bg-disabled: #F3F3F3; + --color-bg-subtle: #F5F6FA; /* 次级区块、内嵌列表 */ + --color-bg-muted: #EEF0F6; /* 更弱的填充 */ + --color-bg-input: #F7F8FB; /* 表单输入框底(此前被引用但从未定义,导致背景失效) */ + --color-bg-disabled: #F3F4F7; --color-bg-overlay: rgba(0, 0, 0, 0.45); - /* ============ 字体(规范 §7-11) ============ */ + /* ============ 字体 ============ */ + /* 小程序无法可靠加载 Web Font(wx.loadFontFace 依赖 HTTPS 白名单且有闪动风险), + 故使用中文系统字栈:iOS 走苹方、Android 走思源/系统黑体。 + 排版辨识度靠字号阶梯与字重建立,而非依赖字体本身。 */ --font-family-cn: -apple-system, "PingFang SC", "Noto Sans SC", "Hiragino Sans GB", "Microsoft YaHei", system-ui, sans-serif; + --font-family-number: "SF Pro Display", -apple-system, "DIN Alternate", "PingFang SC", sans-serif; - --font-size-xs: 12.00px; /* 12px */ - --font-size-sm: 13.00px; /* 13px */ - --font-size-md: 14.00px; /* 14px */ - --font-size-base: 16.00px; /* 16px */ - --font-size-lg: 18.00px; /* 18px */ - --font-size-xl: 20.00px; /* 20px */ - --font-size-2xl: 24.00px; /* 24px */ - --font-size-3xl: 28.00px; /* 28px */ + /* 字号阶梯 —— 正文 16.00px(16px) 起,元信息下限 12.00px(12px) */ + --font-size-micro: 11.00px; /* 11px 仅角标/装饰,禁用于正文 */ + --font-size-xs: 12.00px; /* 12px 元信息下限 */ + --font-size-sm: 13.00px; /* 13px 次要说明 */ + --font-size-md: 14.00px; /* 14px 次要正文 */ + --font-size-base: 16.00px; /* 16px 正文 */ + --font-size-lg: 18.00px; /* 18px 小标题 */ + --font-size-xl: 20.00px; /* 20px 区块标题 */ + --font-size-2xl: 24.00px; /* 24px 页面标题 */ + --font-size-3xl: 28.00px; /* 28px 大标题 */ + --font-size-display: 32.00px; /* 32px Hero */ + /* 字重:只用 4 档。禁止 550/650/750 等非百位值 —— Android 无对应字重会回退, + 导致同一设计在不同机型上粗细不一致(审计发现 30 处)。 */ --font-weight-regular: 400; --font-weight-medium: 500; --font-weight-semibold: 600; @@ -3564,51 +5579,68 @@ --line-height-tight: 1.25; --line-height-normal: 1.5; - --line-height-relaxed: 1.7; + --line-height-relaxed: 1.65; - /* ============ 间距(规范 §12,4px 栅格) ============ */ - --spacing-1: 4.00px; /* 4px */ - --spacing-2: 8.00px; /* 8px */ - --spacing-3: 12.00px; /* 12px */ - --spacing-4: 16.00px; /* 16px */ - --spacing-5: 20.00px; /* 20px */ - --spacing-6: 24.00px; /* 24px */ - --spacing-8: 32.00px; /* 32px */ - --spacing-10: 40.00px; /* 40px */ - --spacing-12: 48.00px; /* 48px */ + --letter-spacing-tight: 0; + --letter-spacing-wide: 0.50px; + --letter-spacing-wider: 1.00px; - --spacing-page-x: 16.00px; /* 页面左右 16px */ - --spacing-section: 24.00px; /* 区块间 24px */ - --spacing-card-inner: 16.00px; /* 卡片内部 16px */ - --spacing-tight: 8.00px; /* 紧密 8px */ + /* ============ 间距(4px 栅格) ============ */ + --spacing-1: 4.00px; + --spacing-2: 8.00px; + --spacing-3: 12.00px; + --spacing-4: 16.00px; + --spacing-5: 20.00px; + --spacing-6: 24.00px; + --spacing-8: 32.00px; + --spacing-10: 40.00px; + --spacing-12: 48.00px; - /* ============ 圆角(规范 §14) ============ */ - --radius-sm: 8.00px; /* 8px */ - --radius-md: 12.00px; /* 12px */ - --radius-lg: 16.00px; /* 16px */ - --radius-xl: 20.00px; /* 20px */ + --spacing-page-x: 16.00px; + --spacing-section: 24.00px; + --spacing-card-inner: 16.00px; + --spacing-tight: 8.00px; + + /* ============ 圆角 ============ */ + --radius-sm: 8.00px; + --radius-md: 12.00px; + --radius-lg: 16.00px; + --radius-xl: 20.00px; + --radius-2xl: 24.00px; --radius-full: 4999.50px; - /* ============ 阴影(规范 §15,极轻) ============ */ - --shadow-card: 0 4.00px 16.00px rgba(0, 0, 0, 0.04); + /* ============ 阴影(统一为一套,此前 30+ 种近似值) ============ */ + --shadow-card: 0 4.00px 14.00px rgba(35, 35, 95, 0.07); + --shadow-raised: 0 6.00px 18.00px rgba(35, 35, 95, 0.10); --shadow-popup: 0 8.00px 32.00px rgba(0, 0, 0, 0.10); + --shadow-night: 0 8.00px 20.00px rgba(28, 30, 88, 0.18); - /* ============ 边框(规范 §16) ============ */ + /* ============ 边框宽度 ============ */ --border-width: 0.50px; + --border-width-strong: 1.00px; - /* ============ 动效(规范 §17) ============ */ + /* ============ 触摸目标(无障碍下限 44×44px) ============ */ + --tap-min: 44.00px; /* 44px 最小可点区域 */ + --tap-comfortable: 48.00px; /* 48px 舒适尺寸:主操作 */ + --tap-gap: 8.00px; /* 8px 相邻目标最小间距 */ + + /* ============ 动效 ============ */ --motion-fast: 120ms; --motion-normal: 200ms; --motion-slow: 300ms; - --ease-standard: ease-out; + --ease-standard: cubic-bezier(0.32, 0.72, 0, 1); + --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1); + --press-scale: 0.97; + --press-opacity: 0.88; - /* ============ 层级 z-index(规范 §90) ============ */ + /* ============ 层级 z-index ============ */ --z-base: 1; --z-sticky: 100; --z-tabbar: 200; --z-dropdown: 500; --z-modal: 1000; --z-toast: 2000; + --z-ambient: 0; /* ============ 页面基础样式 ============ */ background-color: var(--color-bg-page); @@ -3618,7 +5650,10 @@ line-height: var(--line-height-normal); } -/* ============ 通用工具类 ============ */ +/* ========================================================================== + 通用工具类 + ========================================================================== */ + .container { padding: var(--spacing-page-x); } @@ -3632,17 +5667,34 @@ .flex-shrink-0 { flex-shrink: 0; } .wrap { flex-wrap: wrap; } +/* 4 列宫格:用 flex + 百分比宽度实现。 + 注:display:grid 在 WebView 渲染下可用,但 Skyline 不支持,故统一改为 flex 以免疫渲染引擎迁移。*/ +.grid-4 { + display: flex; + flex-wrap: wrap; +} +.grid-4 > .grid-item { + width: 25%; + box-sizing: border-box; +} + +.text-strong { color: var(--color-text-strong); } .text-primary { color: var(--color-text-primary); } .text-secondary { color: var(--color-text-secondary); } .text-tertiary { color: var(--color-text-tertiary); } .text-placeholder { color: var(--color-text-placeholder); } .text-white { color: var(--color-text-inverse); } -.text-brand { color: var(--color-primary); } -.text-success { color: var(--color-success); } -.text-warning { color: var(--color-warning); } -.text-danger { color: var(--color-danger); } -.text-info { color: var(--color-info); } +.text-brand { color: var(--color-primary-strong); } +/* 品牌色作文字只能用 -strong 变体:基础色 #E96B6B 在白底仅 3.10:1。 + 保留 .text-brand-soft 这个类名是为了不破坏既有引用,取值已统一到 -strong, + 如需「更亮的品牌色」请用于背景/图形而非文字。 */ +.text-brand-soft { color: var(--color-primary-strong); } +.text-success { color: var(--color-success-strong); } +.text-warning { color: var(--color-warning-strong); } +.text-danger { color: var(--color-danger-strong); } +.text-info { color: var(--color-info-strong); } +.font-micro { font-size: var(--font-size-micro); } .font-xs { font-size: var(--font-size-xs); } .font-sm { font-size: var(--font-size-sm); } .font-md { font-size: var(--font-size-md); } @@ -3651,6 +5703,7 @@ .font-xl { font-size: var(--font-size-xl); } .font-2xl { font-size: var(--font-size-2xl); } .font-3xl { font-size: var(--font-size-3xl); } +.font-display { font-size: var(--font-size-display); } .font-regular { font-weight: var(--font-weight-regular); } .font-medium { font-weight: var(--font-weight-medium); } @@ -3688,7 +5741,7 @@ padding-bottom: 0px; } -/* 页面卡片基础样式(中低密度留白) */ +/* 页面卡片基础样式 */ .card-base { background: var(--color-bg-card); border-radius: var(--radius-lg); @@ -3702,239 +5755,366 @@ background: var(--color-divider); } -.wx-page{background:var(--color-bg-page)}.service-page{min-height:100vh;padding-bottom:calc(70.00px + 0px)}.hero{padding:22.00px 16.00px 27.00px;background:linear-gradient(140deg,var(--color-primary-lighter),#FFF8EE);position:relative;overflow:hidden}.eyebrow{display:inline-flex;padding:3.50px 7.00px;border-radius:499.50px;background:rgba(255,255,255,.72);color:var(--color-primary);font-size:10.50px}.hero-title{display:block;margin-top:9.00px;font-size:20.00px;font-weight:700;line-height:1.35}.hero-desc{display:block;width:82%;margin-top:7.00px;font-size:12.50px;color:var(--color-text-secondary);line-height:1.7}.content{padding:0 var(--spacing-page-x)}.block{margin-top:var(--spacing-section)}.block-title{display:block;font-size:15.50px;font-weight:650}.block-subtitle{display:block;margin-top:4.00px;font-size:11.50px;color:var(--color-text-tertiary)}.card{margin-top:9.00px;padding:14.00px;background:var(--color-bg-card);border:0.50px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.feature-row,.menu-row,.record-row{display:flex;align-items:center;gap:10.00px;min-height:56.00px;padding:9.00px 0;border-bottom:0.50px solid var(--color-divider)}.feature-row:last-child,.menu-row:last-child,.record-row:last-child{border-bottom:0}.feature-icon{width:36.00px;height:36.00px;display:flex;align-items:center;justify-content:center;flex:none;border-radius:11.00px;background:var(--color-primary-light);color:var(--color-primary);font-weight:700}.feature-copy{flex:1;min-width:0}.feature-title{display:block;font-size:14.00px;font-weight:600}.feature-desc,.meta{display:block;margin-top:3.50px;font-size:11.50px;color:var(--color-text-tertiary);line-height:1.55}.arrow{font-size:20.00px;color:var(--color-text-disabled)}.tag{display:inline-flex;margin-right:5.00px;margin-top:5.00px;padding:3.00px 6.50px;border-radius:499.50px;background:var(--color-success-light);color:var(--color-success);font-size:10.00px}.tag.warning{background:var(--color-warning-light);color:var(--color-warning)}.primary-btn,.secondary-btn{height:44.00px;display:flex;align-items:center;justify-content:center;border-radius:22.00px;font-size:14.00px;font-weight:600}.primary-btn{background:linear-gradient(135deg,var(--mini-accent-coral),var(--mini-accent-pink));color:var(--color-text-inverse);box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)}.primary-btn.disabled{background:#E6E8EF;color:#989DAF;box-shadow:none}.secondary-btn{background:var(--color-primary-light);color:var(--color-primary)}.fixed-action{position:fixed;left:0;right:0;bottom:0;padding:9.00px var(--spacing-page-x) calc(9.00px + 0px);background:rgba(255,255,255,.96);border-top:0.50px solid var(--color-divider);z-index:100}.field{margin-top:13.00px}.label{display:block;margin-bottom:6.00px;font-size:12.50px;font-weight:600}.input,.select-box,.textarea{width:100%;box-sizing:border-box;background:#FCFAF8;border:0.50px solid var(--color-border);border-radius:var(--radius-md);font-size:13.00px}.input,.select-box{height:44.00px;padding:0 12.00px;display:flex;align-items:center}.textarea{min-height:90.00px;padding:11.00px}.notice{margin-top:10.00px;padding:11.00px;border-radius:var(--radius-md);background:#F3F7FC;color:var(--color-text-secondary);font-size:11.50px;line-height:1.65}.empty-panel{text-align:center;padding:35.00px 15.00px}.empty-symbol{width:48.00px;height:48.00px;margin:auto;display:flex;align-items:center;justify-content:center;border-radius:15.00px;background:var(--color-primary-light);color:var(--color-primary);font-size:18.00px;font-weight:700}.empty-title{display:block;margin-top:11.00px;font-size:15.00px;font-weight:600}.article-card{margin-top:9.00px;background:var(--color-bg-card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.article-cover{height:110.00px;padding:12.00px;background:linear-gradient(135deg,#F5E5DE,#F9F1E8);display:flex;align-items:flex-end}.article-cover text{font-size:21.00px;color:rgba(125,76,63,.52);font-weight:700}.article-body{padding:12.00px}.article-title{display:block;font-size:14.50px;font-weight:650;line-height:1.45}.article-meta{display:block;margin-top:5.00px;font-size:11.00px;color:var(--color-text-tertiary)}.article-content{padding:16.00px;background:var(--color-bg-card);font-size:14.00px;line-height:1.9;color:var(--color-text-secondary)}.article-content .lead{display:block;font-size:15.50px;color:var(--color-text-primary);font-weight:600;margin-bottom:12.00px}.danger-card{background:#FFF8F4;border-color:#F5DED2}.danger-card .feature-icon{background:#FFF0EA;color:#C85D43}@media(max-width:340px){.hero-title{font-size:18.00px}.hero-desc{width:92%}} +/* ========================================================================== + 可访问性:只用 token,不用工具类(2026-09-23 修订) + -------------------------------------------------------------------------- + v2 曾在此处新增 .tap-min / .tap-gap / .focusable / .pressable 四个工具类。 + 复检发现全部零引用(等价能力已各自写在组件样式内,例如 button/index.wxss + 直接使用 min-height:var(--tap-min)),且存在两个硬问题: -.service-shell{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:#F4F5FA}.service-content{padding:4.00px 12.00px 18.00px}.service-status{display:flex;align-items:center;justify-content:space-between;margin-top:12.00px;padding:10.00px 12.00px;border-radius:11.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-status__label{color:#7B8198;font-size:10.50px}.service-status__value{padding:3.00px 7.00px;border-radius:9.00px;background:#EAF8F2;color:#329472;font-size:9.50px;font-weight:650}.service-status__value.disabled{background:#FFF0F0;color:#D45A60}.service-topics{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.service-topic{min-height:74.00px;padding:10.00px;border-radius:12.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-topic__icon{display:flex;align-items:center;justify-content:center;width:27.00px;height:27.00px;border-radius:8.50px;background:#FFF0F5}.service-topic__icon image{width:17.00px;height:17.00px}.service-topic__title{display:block;margin-top:6.50px;color:#283056;font-size:12.00px;font-weight:650}.service-topic__desc{display:block;margin-top:3.00px;color:#858A9E;font-size:9.50px;line-height:1.45}.service-actions{display:flex;gap:7.00px}.service-actions .secondary-btn{width:95.00px;flex:none}.service-actions .primary-btn{flex:1}.privacy-note{display:flex;align-items:flex-start;gap:7.00px;margin-top:11.00px;padding:10.00px;border-radius:11.00px;background:#F1F4FF;color:#69718E;font-size:10.00px;line-height:1.55}.privacy-note image{width:17.00px;height:17.00px;flex:none} + 1) `.tap-gap > * + *` 用了通配符与兄弟选择器 —— WXSS 不支持, + wcc 编译期直接报 `error at token '*'`,导致整个小程序编译失败。 + (这是编译错误,不是静默失效,代价最高。) + 2) `.pressable:active` / `.focusable:focus-visible` 的伪类在 view 上 + 不生效(小程序须用 hover-class),属于"写了等于没写"。 + + 故整块移除,保留 token。需要热区/间距时直接引用 token: + min-height: var(--tap-min); → 44.00px = 44px,最小可点区域 + gap: var(--tap-gap); → 8.00px = 8px,相邻目标间距(flex gap) + 【WXSS 禁用清单】星号通配符、兄弟选择器、属性选择器。 + 【注释约束】WXSS 注释**不可嵌套**:内层注释的结束标记会提前终止外层注释, + 其后的文字会被当成真实样式解析,导致编译失败或样式被污染。 + (2026-09-23 实证:本块注释初版即踩此坑。) + ========================================================================== */ + +.wx-page{background:var(--color-bg-page)}.service-page{min-height:100vh;padding-bottom:calc(70.00px + 0px)}.hero{padding:22.00px 16.00px 27.00px;background:linear-gradient(140deg,var(--color-primary-lighter),var(--color-warning-light));position:relative;overflow:hidden}.eyebrow{display:inline-flex;padding:3.50px 7.00px;border-radius:499.50px;background:rgba(255,255,255,.72);color:var(--color-primary-strong);font-size:12.00px}.hero-title{display:block;margin-top:9.00px;font-size:20.00px;font-weight:700;line-height:1.35}.hero-desc{display:block;width:82%;margin-top:7.00px;font-size:12.50px;color:var(--color-text-secondary);line-height:1.7}.content{padding:0 var(--spacing-page-x)}.block{margin-top:var(--spacing-section)}.block-title{display:block;font-size:15.50px;font-weight:600}.block-subtitle{display:block;margin-top:4.00px;font-size:12.00px;color:var(--color-text-tertiary)}.card{margin-top:9.00px;padding:14.00px;background:var(--color-bg-card);border:0.50px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.feature-row,.menu-row,.record-row{display:flex;align-items:center;gap:10.00px;min-height:56.00px;padding:9.00px 0;border-bottom:0.50px solid var(--color-divider)}.feature-row:last-child,.menu-row:last-child,.record-row:last-child{border-bottom:0}.feature-icon{width:36.00px;height:36.00px;display:flex;align-items:center;justify-content:center;flex:none;border-radius:11.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-weight:700}.feature-copy{flex:1;min-width:0}.feature-title{display:block;font-size:14.00px;font-weight:600}.feature-desc,.meta{display:block;margin-top:3.50px;font-size:12.00px;color:var(--color-text-tertiary);line-height:1.55}.arrow{font-size:20.00px;color:var(--color-text-disabled)}.tag{display:inline-flex;margin-right:5.00px;margin-top:5.00px;padding:3.00px 6.50px;border-radius:499.50px;background:var(--color-success-light);color:var(--color-success-strong);font-size:12.00px}.tag.warning{background:var(--color-warning-light);color:var(--color-warning-strong)}.primary-btn,.secondary-btn{height:44.00px;display:flex;align-items:center;justify-content:center;border-radius:22.00px;font-size:14.00px;font-weight:600}.primary-btn{background:var(--gradient-brand-solid);color:var(--color-text-inverse);box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)}.primary-btn.disabled{background:var(--color-bg-muted);color:var(--color-text-tertiary);box-shadow:none}.secondary-btn{background:var(--color-primary-light);color:var(--color-primary-strong)}.fixed-action{position:fixed;left:0;right:0;bottom:0;padding:9.00px var(--spacing-page-x) calc(9.00px + 0px);background:rgba(255,255,255,.96);border-top:0.50px solid var(--color-divider);z-index:100}.field{margin-top:13.00px}.label{display:block;margin-bottom:6.00px;font-size:12.50px;font-weight:600}.input,.select-box,.textarea{width:100%;box-sizing:border-box;background:var(--color-bg-page);border:0.50px solid var(--color-border);border-radius:var(--radius-md);font-size:13.00px}.input,.select-box{height:44.00px;padding:0 12.00px;display:flex;align-items:center}.textarea{min-height:90.00px;padding:11.00px}.notice{margin-top:10.00px;padding:11.00px;border-radius:var(--radius-md);background:var(--color-info-light);color:var(--color-text-secondary);font-size:12.00px;line-height:1.65}.select-box.is-readonly{background:var(--color-bg-subtle);color:var(--color-text-secondary)}.empty-panel{text-align:center;padding:35.00px 15.00px}.empty-symbol{width:48.00px;height:48.00px;margin:auto;display:flex;align-items:center;justify-content:center;border-radius:15.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-size:18.00px;font-weight:700}.empty-title{display:block;margin-top:11.00px;font-size:15.00px;font-weight:600}.article-card{margin-top:9.00px;background:var(--color-bg-card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.article-cover{height:110.00px;padding:12.00px;background:linear-gradient(135deg,var(--color-warning-light),var(--color-warning-light));display:flex;align-items:flex-end}.article-cover text{font-size:21.00px;color:rgba(125,76,63,.52);font-weight:700}.article-body{padding:12.00px}.article-title{display:block;font-size:14.50px;font-weight:600;line-height:1.45}.article-meta{display:block;margin-top:5.00px;font-size:12.00px;color:var(--color-text-tertiary)}.article-content{padding:16.00px;background:var(--color-bg-card);font-size:14.00px;line-height:1.9;color:var(--color-text-secondary)}.article-content .lead{display:block;font-size:15.50px;color:var(--color-text-primary);font-weight:600;margin-bottom:12.00px}.danger-card{background:var(--color-primary-lighter);border-color:var(--color-primary-light)}.danger-card .feature-icon{background:var(--color-warning-light);color:var(--color-warning-strong)}@media(max-width:340px){.hero-title{font-size:18.00px}.hero-desc{width:92%}} + +.service-shell{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:var(--color-bg-page)}.service-content{padding:4.00px 12.00px 18.00px}.service-status{display:flex;align-items:center;justify-content:space-between;margin-top:12.00px;padding:10.00px 12.00px;border-radius:11.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-status__label{color:var(--color-text-tertiary);font-size:12.00px}.service-status__value{padding:3.00px 7.00px;border-radius:9.00px;background:var(--color-success-light);color:var(--color-success-strong);font-size:12.00px;font-weight:600}.service-status__value.disabled{background:var(--color-danger-light);color:var(--color-danger-strong)}.service-topics{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.service-topic{min-height:74.00px;padding:10.00px;border-radius:12.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-topic__icon{display:flex;align-items:center;justify-content:center;width:27.00px;height:27.00px;border-radius:8.50px;background:var(--color-primary-light)}.service-topic__icon image{width:17.00px;height:17.00px}.service-topic__title{display:block;margin-top:6.50px;color:var(--color-text-strong);font-size:12.00px;font-weight:600}.service-topic__desc{display:block;margin-top:3.00px;color:var(--color-text-tertiary);font-size:12.00px;line-height:1.45}.service-actions{display:flex;gap:7.00px}.service-actions .secondary-btn{width:95.00px;flex:none}.service-actions .primary-btn{flex:1}.privacy-note{display:flex;align-items:flex-start;gap:7.00px;margin-top:11.00px;padding:10.00px;border-radius:11.00px;background:var(--color-info-light);color:var(--color-text-tertiary);font-size:12.00px;line-height:1.55}.privacy-note image{width:17.00px;height:17.00px;flex:none} /* ==== miniapp/components/service-hero ==== */ .service-hero { - position: relative; - height: 150.00px; - overflow: hidden; - border-radius: 0 0 16.00px 16.00px; - background: #fff4f7; + position:relative; + height:150.00px; + overflow:hidden; + border-radius:0 0 16.00px 16.00px; + background:var(--color-primary-light); } .service-hero__image, .service-hero__veil { - position: absolute; - inset: 0; - width: 100%; - height: 100%; + position:absolute; + inset:0; + width:100%; + height:100%; } .service-hero__veil { - background: linear-gradient(90deg, rgba(255, 250, 252, 0.98) 0%, rgba(255, 250, 252, 0.82) 38%, rgba(255, 250, 252, 0.08) 70%); + background:linear-gradient(90deg, rgba(255, 250, 252, 0.98) 0%, rgba(255, 250, 252, 0.82) 38%, rgba(255, 250, 252, 0.08) 70%); } .service-hero--night .service-hero__veil { - background: linear-gradient(90deg, rgba(18, 24, 83, 0.92) 0%, rgba(34, 31, 111, 0.64) 42%, rgba(34, 31, 111, 0.08) 72%); + background:linear-gradient(90deg, rgba(18, 24, 83, 0.92) 0%, rgba(34, 31, 111, 0.64) 42%, rgba(34, 31, 111, 0.08) 72%); } .service-hero__content { - position: relative; - z-index: 1; - display: flex; - flex-direction: column; - justify-content: center; - width: 54%; - height: 100%; - padding: 0 18.00px; - box-sizing: border-box; + position:relative; + z-index:1; + display:flex; + flex-direction:column; + justify-content:center; + width:54%; + height:100%; + padding:0 18.00px; + box-sizing:border-box; } .service-hero__eyebrow { - margin-bottom: 5.00px; - color: var(--color-primary); - font-size: 11.00px; - font-weight: 600; - letter-spacing: 1.00px; + margin-bottom:5.00px; + color:var(--color-primary-strong); + font-size:12.00px; + font-weight:600; + letter-spacing:1.00px; } .service-hero__title { - color: #24305e; - font-size: 20.00px; - font-weight: 700; - line-height: 1.28; + color:var(--color-text-strong); + font-size:20.00px; + font-weight:700; + line-height:1.28; } .service-hero__subtitle { - margin-top: 7.00px; - color: #737c96; - font-size: 12.00px; - line-height: 1.55; + margin-top:7.00px; + color:var(--color-text-tertiary); + font-size:12.00px; + line-height:1.55; } .service-hero--night .service-hero__eyebrow, .service-hero--night .service-hero__title, .service-hero--night .service-hero__subtitle { - color: #ffffff; + color:var(--color-text-inverse); } /* ==== miniapp/components/loading ==== */ .ui-loading--block { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: var(--spacing-8) var(--spacing-page-x); + display:flex; + flex-direction:column; + align-items:center; + justify-content:center; + padding:var(--spacing-8) var(--spacing-page-x); } .ui-loading--inline { - display: inline-flex; - align-items: center; + display:inline-flex; + align-items:center; } .ui-loading__spinner { - width: 30.00px; - height: 30.00px; - display: flex; - align-items: center; - justify-content: center; + width:30.00px; + height:30.00px; + display:flex; + align-items:center; + justify-content:center; } .ui-loading__spinner-icon { - width: 24.00px; - height: 24.00px; - animation: ui-loading-spin 0.8s linear infinite; + width:24.00px; + height:24.00px; + animation:ui-loading-spin 0.8s linear infinite; } @keyframes ui-loading-spin { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } + from { transform:rotate(0deg); } + to { transform:rotate(360deg); } } .ui-loading__text { - margin-top: var(--spacing-3); - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); + margin-top:var(--spacing-3); + font-size:var(--font-size-sm); + color:var(--color-text-tertiary); } /* Skeleton */ .ui-loading__skeleton { - width: 100%; + width:100%; } .ui-loading__skeleton-row { - display: flex; - align-items: center; - padding: var(--spacing-3) var(--spacing-page-x); - background: var(--color-bg-card); - border-bottom: 0.50px solid var(--color-divider); + display:flex; + align-items:center; + padding:var(--spacing-3) var(--spacing-page-x); + background:var(--color-bg-card); + border-bottom:0.50px solid var(--color-divider); } .ui-loading__skeleton-avatar { - width: 44.00px; - height: 44.00px; - border-radius: 50%; - background: var(--color-bg-disabled); - margin-right: var(--spacing-3); - flex-shrink: 0; + width:44.00px; + height:44.00px; + border-radius:50%; + background:var(--color-bg-disabled); + margin-right:var(--spacing-3); + flex-shrink:0; } .ui-loading__skeleton-content { - flex: 1; - min-width: 0; + flex:1; + min-width:0; } .ui-loading__skeleton-line { - height: 12.00px; - background: var(--color-bg-disabled); - border-radius: var(--radius-sm); - position: relative; - overflow: hidden; + height:12.00px; + background:var(--color-bg-disabled); + border-radius:var(--radius-sm); + position:relative; + overflow:hidden; } .ui-loading__skeleton-line--title { - width: 40%; - margin-bottom: var(--spacing-2); + width:40%; + margin-bottom:var(--spacing-2); } .ui-loading__skeleton-line--meta { - width: 70%; + width:70%; } /* shimmer */ .ui-loading__skeleton-line::after, .ui-loading__skeleton-avatar::after { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: linear-gradient( + content:''; + position:absolute; + top:0; + left:0; + width:100%; + height:100%; + background:linear-gradient( 90deg, transparent 0%, rgba(255, 255, 255, 0.55) 50%, transparent 100% ); - animation: ui-loading-shimmer 1.4s ease-in-out infinite; + animation:ui-loading-shimmer 1.4s ease-in-out infinite; } @keyframes ui-loading-shimmer { - 0% { transform: translateX(-100%); } - 100% { transform: translateX(100%); } + 0% { transform:translateX(-100%); } + 100% { transform:translateX(100%); } } @import "../../styles/service-page.wxss"; /** * 丹阳公益婚恋服务平台 - 全局 Design Token * - * 依据《前端组件库与 Design Token 规范 V1.0》 - * 单位说明:rpx(375.00px = 屏幕宽度),规范 px 值按 2x 映射为 rpx - * 禁止页面层写死颜色/间距/圆角,必须引用 var(--token) + * v2(2026-09-22 设计系统夯实) + * --------------------------------------------------------------- + * 本次修订针对审计发现的系统性问题,逐条给出依据: + * + * 1) 品牌色不能承载文字 → 引入「基础色 / -strong」分级 + * #E96B6B on 白 = 3.10:1,白字 on #E96B6B = 3.10:1,on #FFF3F2 = 2.85:1, + * 三条路径都不满足正文 4.5:1。故: + * --color-primary 仅用于大色块、渐变、光晕、装饰(非文字) + * --color-primary-strong 用于文字、小图标、纯文字链接(5.33:1 ✓) + * --color-primary-solid 实心按钮底(白字 ≥4.5:1 ✓) + * 功能色(success/warning/danger/info)同此分级。 + * + * 2) 次要文字对比度过低 + * 旧 --color-text-tertiary(#777) = 4.48(on 白,勉强)/ #999 实测 2.85 却被用了 71 次。 + * 现将三级文字压到 #646C85 = 5.22:1,占位符保留浅色(占位符非正文)。 + * + * 3) 颜色碎片化 + * 审计前全站 182 种 hex、770 次硬编码(54 种灰、60 种蓝紫、40 种红橙)。 + * 本文件是唯一的颜色事实源;页面层禁止再写 hex,一律 var(--token)。 + * + * 4) 触摸目标 + * 组件库默认按钮只有 40px、小号 28px、"喜欢"按钮 31px。 + * 统一以 --tap-min(44.00px=44px) 为下限,--tap-gap 为最小间距。 + * + * 5) 动效几乎未落地(--motion-* 全站仅 5 次引用) + * 补充 --ease-spring 与 --press-scale,让点击有即时反馈。 + * + * 6) 夜间氛围层缺失(参考图有明显的光晕/星点,代码只有纯渐变) + * 新增 --mini-glow-* / --mini-star / --mini-glass / --mini-hairline。 + * + * 单位说明:rpx(375.00px = 屏幕宽度,0.50px ≈ 0.5px @375pt) + * 旧 token 名全部保留(88 个 wxss 共 909 处引用),只更新取值,避免大范围失效。 */ .wx-page { - /* ============ 品牌主色(规范 §3) ============ */ - --color-primary: #E96B6B; - --color-primary-active: #D95F5F; + /* ============ 品牌主色(分级:色块 / 文字 / 实心按钮) ============ */ + --color-primary: #E96B6B; /* 基础色:渐变、光晕、装饰、非文字图形 */ + --color-primary-strong: #B8434A; /* 文字与小图标(5.33:1 on 白,4.91:1 on 浅粉底) */ + --color-primary-solid: #C24C50; /* 实心按钮底(白字 4.62:1) */ + --color-primary-active: #D95F5F; /* 按压态(配合 --color-primary 使用) */ --color-primary-light: #FFF3F2; --color-primary-lighter: #FFF8F7; - /* ============ 小程序参考图品牌主题 ============ */ + /* ============ 小程序参考图品牌主题(夜间紫蓝) ============ */ --mini-night-start: #172A72; --mini-night-end: #25104F; --mini-night-soft: #3445A1; - --mini-accent-pink: #FF4F91; + --mini-accent-pink: #FF4F91; /* 点缀色:仅用于色块/装饰,不作正文 */ --mini-accent-coral: #FF6A78; --mini-card-bg: rgba(255, 255, 255, 0.98); --mini-text: #1F2744; --mini-muted: #7D839B; --mini-card-radius: 12.00px; - --mini-text-on-night: #FFFFFF; - --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); + --mini-text-on-night: #FFFFFF; /* on 深底 13.04:1 ✓ */ + --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); /* on 深底 ≈8:1 ✓ */ --mini-shadow: 0 8.00px 20.00px rgba(28, 30, 88, 0.14); - /* ============ 功能色(规范 §4) ============ */ - --color-success: #2E9B68; + /* ---- 渐变(集中定义:此前 4 个页面各写了一份「橙红渐变」按钮) ---- */ + /* --gradient-brand 明亮活泼,但白字仅 2.77:1 —— 只能用于无文字的装饰填充。 */ + --gradient-brand: linear-gradient(135deg, #FF6A78 0%, #E96B6B 100%); + /* 承载白字的 CTA 渐变:两端 #C24C50(4.73:1) / #B8434A(5.33:1) 均达标。 */ + --gradient-brand-solid: linear-gradient(135deg, #C24C50 0%, #B8434A 100%); + --gradient-night: linear-gradient(160deg, #172A72 0%, #25104F 100%); + --gradient-night-soft: linear-gradient(160deg, #3445A1 0%, #172A72 100%); + + /* ---- 首页 4×2 入口宫格图标渐变(参考图 2:高饱和圆角砖 + 白色描画图标) ---- + 白图标的对比度判据是**非文本图形 3:1**(WCAG 1.4.11)。渐变是斜向的、图标又跨在 + 两色之间,所以**较亮的一端也必须达标** —— 下表注释给的是 0% 处实算值,100% 更暗只会更高。 + 色相按业务语义固定(不随 tone 名漂移):找对象/婚前辅导=玫瑰粉系、公益红娘/服务站=暖橙系、 + 公益活动=紫罗兰、婚恋咨询=蓝、婚恋课堂=紫、婚恋反诈=绿。 */ + --gradient-entry-rose: linear-gradient(135deg, #F56287 0%, #F34671 100%); /* 3.01:1 / 3.54:1 */ + --gradient-entry-orange: linear-gradient(135deg, #F66A06 0%, #D95E06 100%); /* 3.01:1 / 3.78:1 */ + --gradient-entry-violet: linear-gradient(135deg, #A380F5 0%, #8F64F2 100%); /* 3.02:1 / 3.98:1 */ + --gradient-entry-blue: linear-gradient(135deg, #5195F6 0%, #3484F4 100%); /* 3.01:1 / 3.65:1 */ + --gradient-entry-purple: linear-gradient(135deg, #B27BF0 0%, #A260ED 100%); /* 3.01:1 / 3.87:1 */ + --gradient-entry-pink: linear-gradient(135deg, #F2619E 0%, #F0458C 100%); /* 3.01:1 / 3.54:1 */ + --gradient-entry-green: linear-gradient(135deg, #18A979 0%, #148F66 100%); /* 3.00:1 / 4.08:1 */ + --gradient-entry-amber: linear-gradient(135deg, #E9740C 0%, #CC650B 100%); /* 3.01:1 / 3.86:1 */ + /* 图标砖落影:比 --mini-shadow 更小,避免 4 列宫格里相邻砖块的投影互相压边 */ + --mini-entry-shadow: 0 4.00px 9.00px rgba(28, 30, 88, 0.18); + + /* ---- 夜间氛围层(v2 新增;参考图有光晕与星点,此前完全没有) ---- */ + --mini-glow-coral: rgba(255, 79, 145, 0.40); + --mini-glow-indigo: rgba(94, 124, 255, 0.32); + --mini-glow-soft: rgba(255, 255, 255, 0.10); + --mini-star: rgba(255, 255, 255, 0.70); + --mini-glass: rgba(255, 255, 255, 0.10); /* 深底玻璃面 */ + --mini-glass-strong: rgba(255, 255, 255, 0.16); + --mini-hairline: rgba(255, 255, 255, 0.16); /* 深底分隔线 */ + --mini-glass-success: rgba(90, 226, 184, 0.16); /* 深底上的成功态玻璃面 */ + + /* 星点层:多个小径向渐变叠在夜空渐变之上。用 radial-gradient 而非图片, + 避免额外请求,也便于随主题换色(index 页脚注:装饰层不承载信息)。 */ + --mini-starfield: + radial-gradient(circle at 12% 18%, var(--mini-star) 0, transparent 1.25px), + radial-gradient(circle at 31% 66%, var(--mini-star) 0, transparent 1.00px), + radial-gradient(circle at 57% 12%, var(--mini-star) 0, transparent 1.00px), + radial-gradient(circle at 79% 52%, var(--mini-star) 0, transparent 1.50px), + radial-gradient(circle at 93% 84%, var(--mini-star) 0, transparent 1.00px); + + /* 横幅压暗层:保证任何底图上的白色标题都有足够对比度 */ + --mini-banner-scrim: linear-gradient(90deg, rgba(23, 42, 114, 0.84) 0%, rgba(37, 16, 79, 0.40) 56%, rgba(255, 79, 145, 0.12) 100%); + + /* ============ 功能色(同样分级) ============ */ + --color-success: #2E9B68; /* 色块/图标 */ + --color-success-strong: #17805A; /* 文字(4.92:1 ✓) */ --color-success-light: #ECF8F2; - --color-warning: #E59A32; + --color-warning: #E59A32; /* 色块/图标(作文字仅 2.33:1) */ + --color-warning-strong: #9C5F14; /* 文字(5.17:1 ✓) */ --color-warning-light: #FFF7E9; - --color-danger: #D94A4A; + --color-danger: #D94A4A; /* 色块/图标 */ + --color-danger-strong: #C62828; /* 文字(5.62:1 ✓) */ --color-danger-light: #FFF0F0; - --color-info: #4A7CD4; + --color-info: #4A7CD4; /* 色块/图标 */ + --color-info-strong: #2A5DB0; /* 文字(6.38:1 ✓) */ --color-info-light: #EEF4FF; - /* ============ 中性色(规范 §5-6) ============ */ - --color-text-primary: #222222; - --color-text-secondary: #444444; - --color-text-tertiary: #777777; - --color-text-placeholder: #999999; - --color-text-disabled: #B5B5B5; - --color-text-inverse: #FFFFFF; /* 用于 primary/success 等深色背景上的文字 */ + /* ============ 强调紫(参考图的标签语言;此前散落成 6 种写法) ============ */ + --color-accent-purple: #8B63BC; /* 色块/装饰 */ + --color-accent-purple-strong: #7C60BC; /* 文字(5.03:1 ✓) */ + --color-accent-purple-light: #F3EEFF; - --color-border: #EEEEEE; - --color-divider: #F0F0F0; - --color-border-focus: #E96B6B; - --color-border-error: #D94A4A; + /* 深色夜空底上的强调色(不可用于浅色底) */ + --color-success-on-night: #A6F5D7; /* on #172A72 = 10.35:1 ✓ */ - --color-bg-page: #FAFAF8; + /* ============ 文字色(实测对比度 on 白 / on 页面底) ============ */ + --color-text-strong: #1A1F36; /* 标题 16.24 / 14.90 ✓ */ + --color-text-primary: #2A3050; /* 正文 12.83 / 11.77 ✓ */ + --color-text-secondary: #4A5169; /* 次要正文 7.86 / 7.21 ✓ */ + --color-text-tertiary: #646C85; /* 说明文字 5.22 / 4.79 ✓(旧 #777 为 4.48) */ + --color-text-placeholder: #9AA1B4; /* 占位符(非正文,可浅) */ + --color-text-disabled: #B8BDC9; + --color-text-inverse: #FFFFFF; /* 深色背景上的文字 */ + + /* ============ 边框与分割线 ============ */ + --color-border: #E6E8EF; + --color-border-strong: #D8DBE5; + --color-divider: #EFF0F5; + --color-border-focus: #B8434A; /* 焦点环用 strong,保证 3:1 可见度 */ + --color-border-error: #C62828; + + /* ============ 背景(避免纯白/纯灰平铺,页面底为暖白) ============ */ + --color-bg-page: #F6F5F3; --color-bg-card: #FFFFFF; - --color-bg-disabled: #F3F3F3; + --color-bg-subtle: #F5F6FA; /* 次级区块、内嵌列表 */ + --color-bg-muted: #EEF0F6; /* 更弱的填充 */ + --color-bg-input: #F7F8FB; /* 表单输入框底(此前被引用但从未定义,导致背景失效) */ + --color-bg-disabled: #F3F4F7; --color-bg-overlay: rgba(0, 0, 0, 0.45); - /* ============ 字体(规范 §7-11) ============ */ + /* ============ 字体 ============ */ + /* 小程序无法可靠加载 Web Font(wx.loadFontFace 依赖 HTTPS 白名单且有闪动风险), + 故使用中文系统字栈:iOS 走苹方、Android 走思源/系统黑体。 + 排版辨识度靠字号阶梯与字重建立,而非依赖字体本身。 */ --font-family-cn: -apple-system, "PingFang SC", "Noto Sans SC", "Hiragino Sans GB", "Microsoft YaHei", system-ui, sans-serif; + --font-family-number: "SF Pro Display", -apple-system, "DIN Alternate", "PingFang SC", sans-serif; - --font-size-xs: 12.00px; /* 12px */ - --font-size-sm: 13.00px; /* 13px */ - --font-size-md: 14.00px; /* 14px */ - --font-size-base: 16.00px; /* 16px */ - --font-size-lg: 18.00px; /* 18px */ - --font-size-xl: 20.00px; /* 20px */ - --font-size-2xl: 24.00px; /* 24px */ - --font-size-3xl: 28.00px; /* 28px */ + /* 字号阶梯 —— 正文 16.00px(16px) 起,元信息下限 12.00px(12px) */ + --font-size-micro: 11.00px; /* 11px 仅角标/装饰,禁用于正文 */ + --font-size-xs: 12.00px; /* 12px 元信息下限 */ + --font-size-sm: 13.00px; /* 13px 次要说明 */ + --font-size-md: 14.00px; /* 14px 次要正文 */ + --font-size-base: 16.00px; /* 16px 正文 */ + --font-size-lg: 18.00px; /* 18px 小标题 */ + --font-size-xl: 20.00px; /* 20px 区块标题 */ + --font-size-2xl: 24.00px; /* 24px 页面标题 */ + --font-size-3xl: 28.00px; /* 28px 大标题 */ + --font-size-display: 32.00px; /* 32px Hero */ + /* 字重:只用 4 档。禁止 550/650/750 等非百位值 —— Android 无对应字重会回退, + 导致同一设计在不同机型上粗细不一致(审计发现 30 处)。 */ --font-weight-regular: 400; --font-weight-medium: 500; --font-weight-semibold: 600; @@ -3942,51 +6122,68 @@ --line-height-tight: 1.25; --line-height-normal: 1.5; - --line-height-relaxed: 1.7; + --line-height-relaxed: 1.65; - /* ============ 间距(规范 §12,4px 栅格) ============ */ - --spacing-1: 4.00px; /* 4px */ - --spacing-2: 8.00px; /* 8px */ - --spacing-3: 12.00px; /* 12px */ - --spacing-4: 16.00px; /* 16px */ - --spacing-5: 20.00px; /* 20px */ - --spacing-6: 24.00px; /* 24px */ - --spacing-8: 32.00px; /* 32px */ - --spacing-10: 40.00px; /* 40px */ - --spacing-12: 48.00px; /* 48px */ + --letter-spacing-tight: 0; + --letter-spacing-wide: 0.50px; + --letter-spacing-wider: 1.00px; - --spacing-page-x: 16.00px; /* 页面左右 16px */ - --spacing-section: 24.00px; /* 区块间 24px */ - --spacing-card-inner: 16.00px; /* 卡片内部 16px */ - --spacing-tight: 8.00px; /* 紧密 8px */ + /* ============ 间距(4px 栅格) ============ */ + --spacing-1: 4.00px; + --spacing-2: 8.00px; + --spacing-3: 12.00px; + --spacing-4: 16.00px; + --spacing-5: 20.00px; + --spacing-6: 24.00px; + --spacing-8: 32.00px; + --spacing-10: 40.00px; + --spacing-12: 48.00px; - /* ============ 圆角(规范 §14) ============ */ - --radius-sm: 8.00px; /* 8px */ - --radius-md: 12.00px; /* 12px */ - --radius-lg: 16.00px; /* 16px */ - --radius-xl: 20.00px; /* 20px */ + --spacing-page-x: 16.00px; + --spacing-section: 24.00px; + --spacing-card-inner: 16.00px; + --spacing-tight: 8.00px; + + /* ============ 圆角 ============ */ + --radius-sm: 8.00px; + --radius-md: 12.00px; + --radius-lg: 16.00px; + --radius-xl: 20.00px; + --radius-2xl: 24.00px; --radius-full: 4999.50px; - /* ============ 阴影(规范 §15,极轻) ============ */ - --shadow-card: 0 4.00px 16.00px rgba(0, 0, 0, 0.04); + /* ============ 阴影(统一为一套,此前 30+ 种近似值) ============ */ + --shadow-card: 0 4.00px 14.00px rgba(35, 35, 95, 0.07); + --shadow-raised: 0 6.00px 18.00px rgba(35, 35, 95, 0.10); --shadow-popup: 0 8.00px 32.00px rgba(0, 0, 0, 0.10); + --shadow-night: 0 8.00px 20.00px rgba(28, 30, 88, 0.18); - /* ============ 边框(规范 §16) ============ */ + /* ============ 边框宽度 ============ */ --border-width: 0.50px; + --border-width-strong: 1.00px; - /* ============ 动效(规范 §17) ============ */ + /* ============ 触摸目标(无障碍下限 44×44px) ============ */ + --tap-min: 44.00px; /* 44px 最小可点区域 */ + --tap-comfortable: 48.00px; /* 48px 舒适尺寸:主操作 */ + --tap-gap: 8.00px; /* 8px 相邻目标最小间距 */ + + /* ============ 动效 ============ */ --motion-fast: 120ms; --motion-normal: 200ms; --motion-slow: 300ms; - --ease-standard: ease-out; + --ease-standard: cubic-bezier(0.32, 0.72, 0, 1); + --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1); + --press-scale: 0.97; + --press-opacity: 0.88; - /* ============ 层级 z-index(规范 §90) ============ */ + /* ============ 层级 z-index ============ */ --z-base: 1; --z-sticky: 100; --z-tabbar: 200; --z-dropdown: 500; --z-modal: 1000; --z-toast: 2000; + --z-ambient: 0; /* ============ 页面基础样式 ============ */ background-color: var(--color-bg-page); @@ -3996,7 +6193,10 @@ line-height: var(--line-height-normal); } -/* ============ 通用工具类 ============ */ +/* ========================================================================== + 通用工具类 + ========================================================================== */ + .container { padding: var(--spacing-page-x); } @@ -4010,17 +6210,34 @@ .flex-shrink-0 { flex-shrink: 0; } .wrap { flex-wrap: wrap; } +/* 4 列宫格:用 flex + 百分比宽度实现。 + 注:display:grid 在 WebView 渲染下可用,但 Skyline 不支持,故统一改为 flex 以免疫渲染引擎迁移。*/ +.grid-4 { + display: flex; + flex-wrap: wrap; +} +.grid-4 > .grid-item { + width: 25%; + box-sizing: border-box; +} + +.text-strong { color: var(--color-text-strong); } .text-primary { color: var(--color-text-primary); } .text-secondary { color: var(--color-text-secondary); } .text-tertiary { color: var(--color-text-tertiary); } .text-placeholder { color: var(--color-text-placeholder); } .text-white { color: var(--color-text-inverse); } -.text-brand { color: var(--color-primary); } -.text-success { color: var(--color-success); } -.text-warning { color: var(--color-warning); } -.text-danger { color: var(--color-danger); } -.text-info { color: var(--color-info); } +.text-brand { color: var(--color-primary-strong); } +/* 品牌色作文字只能用 -strong 变体:基础色 #E96B6B 在白底仅 3.10:1。 + 保留 .text-brand-soft 这个类名是为了不破坏既有引用,取值已统一到 -strong, + 如需「更亮的品牌色」请用于背景/图形而非文字。 */ +.text-brand-soft { color: var(--color-primary-strong); } +.text-success { color: var(--color-success-strong); } +.text-warning { color: var(--color-warning-strong); } +.text-danger { color: var(--color-danger-strong); } +.text-info { color: var(--color-info-strong); } +.font-micro { font-size: var(--font-size-micro); } .font-xs { font-size: var(--font-size-xs); } .font-sm { font-size: var(--font-size-sm); } .font-md { font-size: var(--font-size-md); } @@ -4029,6 +6246,7 @@ .font-xl { font-size: var(--font-size-xl); } .font-2xl { font-size: var(--font-size-2xl); } .font-3xl { font-size: var(--font-size-3xl); } +.font-display { font-size: var(--font-size-display); } .font-regular { font-weight: var(--font-weight-regular); } .font-medium { font-weight: var(--font-weight-medium); } @@ -4066,7 +6284,7 @@ padding-bottom: 0px; } -/* 页面卡片基础样式(中低密度留白) */ +/* 页面卡片基础样式 */ .card-base { background: var(--color-bg-card); border-radius: var(--radius-lg); @@ -4080,146 +6298,273 @@ background: var(--color-divider); } -.wx-page{background:var(--color-bg-page)}.service-page{min-height:100vh;padding-bottom:calc(70.00px + 0px)}.hero{padding:22.00px 16.00px 27.00px;background:linear-gradient(140deg,var(--color-primary-lighter),#FFF8EE);position:relative;overflow:hidden}.eyebrow{display:inline-flex;padding:3.50px 7.00px;border-radius:499.50px;background:rgba(255,255,255,.72);color:var(--color-primary);font-size:10.50px}.hero-title{display:block;margin-top:9.00px;font-size:20.00px;font-weight:700;line-height:1.35}.hero-desc{display:block;width:82%;margin-top:7.00px;font-size:12.50px;color:var(--color-text-secondary);line-height:1.7}.content{padding:0 var(--spacing-page-x)}.block{margin-top:var(--spacing-section)}.block-title{display:block;font-size:15.50px;font-weight:650}.block-subtitle{display:block;margin-top:4.00px;font-size:11.50px;color:var(--color-text-tertiary)}.card{margin-top:9.00px;padding:14.00px;background:var(--color-bg-card);border:0.50px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.feature-row,.menu-row,.record-row{display:flex;align-items:center;gap:10.00px;min-height:56.00px;padding:9.00px 0;border-bottom:0.50px solid var(--color-divider)}.feature-row:last-child,.menu-row:last-child,.record-row:last-child{border-bottom:0}.feature-icon{width:36.00px;height:36.00px;display:flex;align-items:center;justify-content:center;flex:none;border-radius:11.00px;background:var(--color-primary-light);color:var(--color-primary);font-weight:700}.feature-copy{flex:1;min-width:0}.feature-title{display:block;font-size:14.00px;font-weight:600}.feature-desc,.meta{display:block;margin-top:3.50px;font-size:11.50px;color:var(--color-text-tertiary);line-height:1.55}.arrow{font-size:20.00px;color:var(--color-text-disabled)}.tag{display:inline-flex;margin-right:5.00px;margin-top:5.00px;padding:3.00px 6.50px;border-radius:499.50px;background:var(--color-success-light);color:var(--color-success);font-size:10.00px}.tag.warning{background:var(--color-warning-light);color:var(--color-warning)}.primary-btn,.secondary-btn{height:44.00px;display:flex;align-items:center;justify-content:center;border-radius:22.00px;font-size:14.00px;font-weight:600}.primary-btn{background:linear-gradient(135deg,var(--mini-accent-coral),var(--mini-accent-pink));color:var(--color-text-inverse);box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)}.primary-btn.disabled{background:#E6E8EF;color:#989DAF;box-shadow:none}.secondary-btn{background:var(--color-primary-light);color:var(--color-primary)}.fixed-action{position:fixed;left:0;right:0;bottom:0;padding:9.00px var(--spacing-page-x) calc(9.00px + 0px);background:rgba(255,255,255,.96);border-top:0.50px solid var(--color-divider);z-index:100}.field{margin-top:13.00px}.label{display:block;margin-bottom:6.00px;font-size:12.50px;font-weight:600}.input,.select-box,.textarea{width:100%;box-sizing:border-box;background:#FCFAF8;border:0.50px solid var(--color-border);border-radius:var(--radius-md);font-size:13.00px}.input,.select-box{height:44.00px;padding:0 12.00px;display:flex;align-items:center}.textarea{min-height:90.00px;padding:11.00px}.notice{margin-top:10.00px;padding:11.00px;border-radius:var(--radius-md);background:#F3F7FC;color:var(--color-text-secondary);font-size:11.50px;line-height:1.65}.empty-panel{text-align:center;padding:35.00px 15.00px}.empty-symbol{width:48.00px;height:48.00px;margin:auto;display:flex;align-items:center;justify-content:center;border-radius:15.00px;background:var(--color-primary-light);color:var(--color-primary);font-size:18.00px;font-weight:700}.empty-title{display:block;margin-top:11.00px;font-size:15.00px;font-weight:600}.article-card{margin-top:9.00px;background:var(--color-bg-card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.article-cover{height:110.00px;padding:12.00px;background:linear-gradient(135deg,#F5E5DE,#F9F1E8);display:flex;align-items:flex-end}.article-cover text{font-size:21.00px;color:rgba(125,76,63,.52);font-weight:700}.article-body{padding:12.00px}.article-title{display:block;font-size:14.50px;font-weight:650;line-height:1.45}.article-meta{display:block;margin-top:5.00px;font-size:11.00px;color:var(--color-text-tertiary)}.article-content{padding:16.00px;background:var(--color-bg-card);font-size:14.00px;line-height:1.9;color:var(--color-text-secondary)}.article-content .lead{display:block;font-size:15.50px;color:var(--color-text-primary);font-weight:600;margin-bottom:12.00px}.danger-card{background:#FFF8F4;border-color:#F5DED2}.danger-card .feature-icon{background:#FFF0EA;color:#C85D43}@media(max-width:340px){.hero-title{font-size:18.00px}.hero-desc{width:92%}} +/* ========================================================================== + 可访问性:只用 token,不用工具类(2026-09-23 修订) + -------------------------------------------------------------------------- + v2 曾在此处新增 .tap-min / .tap-gap / .focusable / .pressable 四个工具类。 + 复检发现全部零引用(等价能力已各自写在组件样式内,例如 button/index.wxss + 直接使用 min-height:var(--tap-min)),且存在两个硬问题: -.service-shell{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:#F4F5FA}.service-content{padding:4.00px 12.00px 18.00px}.service-status{display:flex;align-items:center;justify-content:space-between;margin-top:12.00px;padding:10.00px 12.00px;border-radius:11.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-status__label{color:#7B8198;font-size:10.50px}.service-status__value{padding:3.00px 7.00px;border-radius:9.00px;background:#EAF8F2;color:#329472;font-size:9.50px;font-weight:650}.service-status__value.disabled{background:#FFF0F0;color:#D45A60}.service-topics{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.service-topic{min-height:74.00px;padding:10.00px;border-radius:12.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-topic__icon{display:flex;align-items:center;justify-content:center;width:27.00px;height:27.00px;border-radius:8.50px;background:#FFF0F5}.service-topic__icon image{width:17.00px;height:17.00px}.service-topic__title{display:block;margin-top:6.50px;color:#283056;font-size:12.00px;font-weight:650}.service-topic__desc{display:block;margin-top:3.00px;color:#858A9E;font-size:9.50px;line-height:1.45}.service-actions{display:flex;gap:7.00px}.service-actions .secondary-btn{width:95.00px;flex:none}.service-actions .primary-btn{flex:1}.privacy-note{display:flex;align-items:flex-start;gap:7.00px;margin-top:11.00px;padding:10.00px;border-radius:11.00px;background:#F1F4FF;color:#69718E;font-size:10.00px;line-height:1.55}.privacy-note image{width:17.00px;height:17.00px;flex:none} + 1) `.tap-gap > * + *` 用了通配符与兄弟选择器 —— WXSS 不支持, + wcc 编译期直接报 `error at token '*'`,导致整个小程序编译失败。 + (这是编译错误,不是静默失效,代价最高。) + 2) `.pressable:active` / `.focusable:focus-visible` 的伪类在 view 上 + 不生效(小程序须用 hover-class),属于"写了等于没写"。 + + 故整块移除,保留 token。需要热区/间距时直接引用 token: + min-height: var(--tap-min); → 44.00px = 44px,最小可点区域 + gap: var(--tap-gap); → 8.00px = 8px,相邻目标间距(flex gap) + 【WXSS 禁用清单】星号通配符、兄弟选择器、属性选择器。 + 【注释约束】WXSS 注释**不可嵌套**:内层注释的结束标记会提前终止外层注释, + 其后的文字会被当成真实样式解析,导致编译失败或样式被污染。 + (2026-09-23 实证:本块注释初版即踩此坑。) + ========================================================================== */ + +.wx-page{background:var(--color-bg-page)}.service-page{min-height:100vh;padding-bottom:calc(70.00px + 0px)}.hero{padding:22.00px 16.00px 27.00px;background:linear-gradient(140deg,var(--color-primary-lighter),var(--color-warning-light));position:relative;overflow:hidden}.eyebrow{display:inline-flex;padding:3.50px 7.00px;border-radius:499.50px;background:rgba(255,255,255,.72);color:var(--color-primary-strong);font-size:12.00px}.hero-title{display:block;margin-top:9.00px;font-size:20.00px;font-weight:700;line-height:1.35}.hero-desc{display:block;width:82%;margin-top:7.00px;font-size:12.50px;color:var(--color-text-secondary);line-height:1.7}.content{padding:0 var(--spacing-page-x)}.block{margin-top:var(--spacing-section)}.block-title{display:block;font-size:15.50px;font-weight:600}.block-subtitle{display:block;margin-top:4.00px;font-size:12.00px;color:var(--color-text-tertiary)}.card{margin-top:9.00px;padding:14.00px;background:var(--color-bg-card);border:0.50px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.feature-row,.menu-row,.record-row{display:flex;align-items:center;gap:10.00px;min-height:56.00px;padding:9.00px 0;border-bottom:0.50px solid var(--color-divider)}.feature-row:last-child,.menu-row:last-child,.record-row:last-child{border-bottom:0}.feature-icon{width:36.00px;height:36.00px;display:flex;align-items:center;justify-content:center;flex:none;border-radius:11.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-weight:700}.feature-copy{flex:1;min-width:0}.feature-title{display:block;font-size:14.00px;font-weight:600}.feature-desc,.meta{display:block;margin-top:3.50px;font-size:12.00px;color:var(--color-text-tertiary);line-height:1.55}.arrow{font-size:20.00px;color:var(--color-text-disabled)}.tag{display:inline-flex;margin-right:5.00px;margin-top:5.00px;padding:3.00px 6.50px;border-radius:499.50px;background:var(--color-success-light);color:var(--color-success-strong);font-size:12.00px}.tag.warning{background:var(--color-warning-light);color:var(--color-warning-strong)}.primary-btn,.secondary-btn{height:44.00px;display:flex;align-items:center;justify-content:center;border-radius:22.00px;font-size:14.00px;font-weight:600}.primary-btn{background:var(--gradient-brand-solid);color:var(--color-text-inverse);box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)}.primary-btn.disabled{background:var(--color-bg-muted);color:var(--color-text-tertiary);box-shadow:none}.secondary-btn{background:var(--color-primary-light);color:var(--color-primary-strong)}.fixed-action{position:fixed;left:0;right:0;bottom:0;padding:9.00px var(--spacing-page-x) calc(9.00px + 0px);background:rgba(255,255,255,.96);border-top:0.50px solid var(--color-divider);z-index:100}.field{margin-top:13.00px}.label{display:block;margin-bottom:6.00px;font-size:12.50px;font-weight:600}.input,.select-box,.textarea{width:100%;box-sizing:border-box;background:var(--color-bg-page);border:0.50px solid var(--color-border);border-radius:var(--radius-md);font-size:13.00px}.input,.select-box{height:44.00px;padding:0 12.00px;display:flex;align-items:center}.textarea{min-height:90.00px;padding:11.00px}.notice{margin-top:10.00px;padding:11.00px;border-radius:var(--radius-md);background:var(--color-info-light);color:var(--color-text-secondary);font-size:12.00px;line-height:1.65}.select-box.is-readonly{background:var(--color-bg-subtle);color:var(--color-text-secondary)}.empty-panel{text-align:center;padding:35.00px 15.00px}.empty-symbol{width:48.00px;height:48.00px;margin:auto;display:flex;align-items:center;justify-content:center;border-radius:15.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-size:18.00px;font-weight:700}.empty-title{display:block;margin-top:11.00px;font-size:15.00px;font-weight:600}.article-card{margin-top:9.00px;background:var(--color-bg-card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.article-cover{height:110.00px;padding:12.00px;background:linear-gradient(135deg,var(--color-warning-light),var(--color-warning-light));display:flex;align-items:flex-end}.article-cover text{font-size:21.00px;color:rgba(125,76,63,.52);font-weight:700}.article-body{padding:12.00px}.article-title{display:block;font-size:14.50px;font-weight:600;line-height:1.45}.article-meta{display:block;margin-top:5.00px;font-size:12.00px;color:var(--color-text-tertiary)}.article-content{padding:16.00px;background:var(--color-bg-card);font-size:14.00px;line-height:1.9;color:var(--color-text-secondary)}.article-content .lead{display:block;font-size:15.50px;color:var(--color-text-primary);font-weight:600;margin-bottom:12.00px}.danger-card{background:var(--color-primary-lighter);border-color:var(--color-primary-light)}.danger-card .feature-icon{background:var(--color-warning-light);color:var(--color-warning-strong)}@media(max-width:340px){.hero-title{font-size:18.00px}.hero-desc{width:92%}} + +.service-shell{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:var(--color-bg-page)}.service-content{padding:4.00px 12.00px 18.00px}.service-status{display:flex;align-items:center;justify-content:space-between;margin-top:12.00px;padding:10.00px 12.00px;border-radius:11.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-status__label{color:var(--color-text-tertiary);font-size:12.00px}.service-status__value{padding:3.00px 7.00px;border-radius:9.00px;background:var(--color-success-light);color:var(--color-success-strong);font-size:12.00px;font-weight:600}.service-status__value.disabled{background:var(--color-danger-light);color:var(--color-danger-strong)}.service-topics{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.service-topic{min-height:74.00px;padding:10.00px;border-radius:12.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-topic__icon{display:flex;align-items:center;justify-content:center;width:27.00px;height:27.00px;border-radius:8.50px;background:var(--color-primary-light)}.service-topic__icon image{width:17.00px;height:17.00px}.service-topic__title{display:block;margin-top:6.50px;color:var(--color-text-strong);font-size:12.00px;font-weight:600}.service-topic__desc{display:block;margin-top:3.00px;color:var(--color-text-tertiary);font-size:12.00px;line-height:1.45}.service-actions{display:flex;gap:7.00px}.service-actions .secondary-btn{width:95.00px;flex:none}.service-actions .primary-btn{flex:1}.privacy-note{display:flex;align-items:flex-start;gap:7.00px;margin-top:11.00px;padding:10.00px;border-radius:11.00px;background:var(--color-info-light);color:var(--color-text-tertiary);font-size:12.00px;line-height:1.55}.privacy-note image{width:17.00px;height:17.00px;flex:none} /* ==== miniapp/components/service-hero ==== */ .service-hero { - position: relative; - height: 150.00px; - overflow: hidden; - border-radius: 0 0 16.00px 16.00px; - background: #fff4f7; + position:relative; + height:150.00px; + overflow:hidden; + border-radius:0 0 16.00px 16.00px; + background:var(--color-primary-light); } .service-hero__image, .service-hero__veil { - position: absolute; - inset: 0; - width: 100%; - height: 100%; + position:absolute; + inset:0; + width:100%; + height:100%; } .service-hero__veil { - background: linear-gradient(90deg, rgba(255, 250, 252, 0.98) 0%, rgba(255, 250, 252, 0.82) 38%, rgba(255, 250, 252, 0.08) 70%); + background:linear-gradient(90deg, rgba(255, 250, 252, 0.98) 0%, rgba(255, 250, 252, 0.82) 38%, rgba(255, 250, 252, 0.08) 70%); } .service-hero--night .service-hero__veil { - background: linear-gradient(90deg, rgba(18, 24, 83, 0.92) 0%, rgba(34, 31, 111, 0.64) 42%, rgba(34, 31, 111, 0.08) 72%); + background:linear-gradient(90deg, rgba(18, 24, 83, 0.92) 0%, rgba(34, 31, 111, 0.64) 42%, rgba(34, 31, 111, 0.08) 72%); } .service-hero__content { - position: relative; - z-index: 1; - display: flex; - flex-direction: column; - justify-content: center; - width: 54%; - height: 100%; - padding: 0 18.00px; - box-sizing: border-box; + position:relative; + z-index:1; + display:flex; + flex-direction:column; + justify-content:center; + width:54%; + height:100%; + padding:0 18.00px; + box-sizing:border-box; } .service-hero__eyebrow { - margin-bottom: 5.00px; - color: var(--color-primary); - font-size: 11.00px; - font-weight: 600; - letter-spacing: 1.00px; + margin-bottom:5.00px; + color:var(--color-primary-strong); + font-size:12.00px; + font-weight:600; + letter-spacing:1.00px; } .service-hero__title { - color: #24305e; - font-size: 20.00px; - font-weight: 700; - line-height: 1.28; + color:var(--color-text-strong); + font-size:20.00px; + font-weight:700; + line-height:1.28; } .service-hero__subtitle { - margin-top: 7.00px; - color: #737c96; - font-size: 12.00px; - line-height: 1.55; + margin-top:7.00px; + color:var(--color-text-tertiary); + font-size:12.00px; + line-height:1.55; } .service-hero--night .service-hero__eyebrow, .service-hero--night .service-hero__title, .service-hero--night .service-hero__subtitle { - color: #ffffff; + color:var(--color-text-inverse); } @import "../../styles/service-page.wxss"; /** * 丹阳公益婚恋服务平台 - 全局 Design Token * - * 依据《前端组件库与 Design Token 规范 V1.0》 - * 单位说明:rpx(375.00px = 屏幕宽度),规范 px 值按 2x 映射为 rpx - * 禁止页面层写死颜色/间距/圆角,必须引用 var(--token) + * v2(2026-09-22 设计系统夯实) + * --------------------------------------------------------------- + * 本次修订针对审计发现的系统性问题,逐条给出依据: + * + * 1) 品牌色不能承载文字 → 引入「基础色 / -strong」分级 + * #E96B6B on 白 = 3.10:1,白字 on #E96B6B = 3.10:1,on #FFF3F2 = 2.85:1, + * 三条路径都不满足正文 4.5:1。故: + * --color-primary 仅用于大色块、渐变、光晕、装饰(非文字) + * --color-primary-strong 用于文字、小图标、纯文字链接(5.33:1 ✓) + * --color-primary-solid 实心按钮底(白字 ≥4.5:1 ✓) + * 功能色(success/warning/danger/info)同此分级。 + * + * 2) 次要文字对比度过低 + * 旧 --color-text-tertiary(#777) = 4.48(on 白,勉强)/ #999 实测 2.85 却被用了 71 次。 + * 现将三级文字压到 #646C85 = 5.22:1,占位符保留浅色(占位符非正文)。 + * + * 3) 颜色碎片化 + * 审计前全站 182 种 hex、770 次硬编码(54 种灰、60 种蓝紫、40 种红橙)。 + * 本文件是唯一的颜色事实源;页面层禁止再写 hex,一律 var(--token)。 + * + * 4) 触摸目标 + * 组件库默认按钮只有 40px、小号 28px、"喜欢"按钮 31px。 + * 统一以 --tap-min(44.00px=44px) 为下限,--tap-gap 为最小间距。 + * + * 5) 动效几乎未落地(--motion-* 全站仅 5 次引用) + * 补充 --ease-spring 与 --press-scale,让点击有即时反馈。 + * + * 6) 夜间氛围层缺失(参考图有明显的光晕/星点,代码只有纯渐变) + * 新增 --mini-glow-* / --mini-star / --mini-glass / --mini-hairline。 + * + * 单位说明:rpx(375.00px = 屏幕宽度,0.50px ≈ 0.5px @375pt) + * 旧 token 名全部保留(88 个 wxss 共 909 处引用),只更新取值,避免大范围失效。 */ .wx-page { - /* ============ 品牌主色(规范 §3) ============ */ - --color-primary: #E96B6B; - --color-primary-active: #D95F5F; + /* ============ 品牌主色(分级:色块 / 文字 / 实心按钮) ============ */ + --color-primary: #E96B6B; /* 基础色:渐变、光晕、装饰、非文字图形 */ + --color-primary-strong: #B8434A; /* 文字与小图标(5.33:1 on 白,4.91:1 on 浅粉底) */ + --color-primary-solid: #C24C50; /* 实心按钮底(白字 4.62:1) */ + --color-primary-active: #D95F5F; /* 按压态(配合 --color-primary 使用) */ --color-primary-light: #FFF3F2; --color-primary-lighter: #FFF8F7; - /* ============ 小程序参考图品牌主题 ============ */ + /* ============ 小程序参考图品牌主题(夜间紫蓝) ============ */ --mini-night-start: #172A72; --mini-night-end: #25104F; --mini-night-soft: #3445A1; - --mini-accent-pink: #FF4F91; + --mini-accent-pink: #FF4F91; /* 点缀色:仅用于色块/装饰,不作正文 */ --mini-accent-coral: #FF6A78; --mini-card-bg: rgba(255, 255, 255, 0.98); --mini-text: #1F2744; --mini-muted: #7D839B; --mini-card-radius: 12.00px; - --mini-text-on-night: #FFFFFF; - --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); + --mini-text-on-night: #FFFFFF; /* on 深底 13.04:1 ✓ */ + --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); /* on 深底 ≈8:1 ✓ */ --mini-shadow: 0 8.00px 20.00px rgba(28, 30, 88, 0.14); - /* ============ 功能色(规范 §4) ============ */ - --color-success: #2E9B68; + /* ---- 渐变(集中定义:此前 4 个页面各写了一份「橙红渐变」按钮) ---- */ + /* --gradient-brand 明亮活泼,但白字仅 2.77:1 —— 只能用于无文字的装饰填充。 */ + --gradient-brand: linear-gradient(135deg, #FF6A78 0%, #E96B6B 100%); + /* 承载白字的 CTA 渐变:两端 #C24C50(4.73:1) / #B8434A(5.33:1) 均达标。 */ + --gradient-brand-solid: linear-gradient(135deg, #C24C50 0%, #B8434A 100%); + --gradient-night: linear-gradient(160deg, #172A72 0%, #25104F 100%); + --gradient-night-soft: linear-gradient(160deg, #3445A1 0%, #172A72 100%); + + /* ---- 首页 4×2 入口宫格图标渐变(参考图 2:高饱和圆角砖 + 白色描画图标) ---- + 白图标的对比度判据是**非文本图形 3:1**(WCAG 1.4.11)。渐变是斜向的、图标又跨在 + 两色之间,所以**较亮的一端也必须达标** —— 下表注释给的是 0% 处实算值,100% 更暗只会更高。 + 色相按业务语义固定(不随 tone 名漂移):找对象/婚前辅导=玫瑰粉系、公益红娘/服务站=暖橙系、 + 公益活动=紫罗兰、婚恋咨询=蓝、婚恋课堂=紫、婚恋反诈=绿。 */ + --gradient-entry-rose: linear-gradient(135deg, #F56287 0%, #F34671 100%); /* 3.01:1 / 3.54:1 */ + --gradient-entry-orange: linear-gradient(135deg, #F66A06 0%, #D95E06 100%); /* 3.01:1 / 3.78:1 */ + --gradient-entry-violet: linear-gradient(135deg, #A380F5 0%, #8F64F2 100%); /* 3.02:1 / 3.98:1 */ + --gradient-entry-blue: linear-gradient(135deg, #5195F6 0%, #3484F4 100%); /* 3.01:1 / 3.65:1 */ + --gradient-entry-purple: linear-gradient(135deg, #B27BF0 0%, #A260ED 100%); /* 3.01:1 / 3.87:1 */ + --gradient-entry-pink: linear-gradient(135deg, #F2619E 0%, #F0458C 100%); /* 3.01:1 / 3.54:1 */ + --gradient-entry-green: linear-gradient(135deg, #18A979 0%, #148F66 100%); /* 3.00:1 / 4.08:1 */ + --gradient-entry-amber: linear-gradient(135deg, #E9740C 0%, #CC650B 100%); /* 3.01:1 / 3.86:1 */ + /* 图标砖落影:比 --mini-shadow 更小,避免 4 列宫格里相邻砖块的投影互相压边 */ + --mini-entry-shadow: 0 4.00px 9.00px rgba(28, 30, 88, 0.18); + + /* ---- 夜间氛围层(v2 新增;参考图有光晕与星点,此前完全没有) ---- */ + --mini-glow-coral: rgba(255, 79, 145, 0.40); + --mini-glow-indigo: rgba(94, 124, 255, 0.32); + --mini-glow-soft: rgba(255, 255, 255, 0.10); + --mini-star: rgba(255, 255, 255, 0.70); + --mini-glass: rgba(255, 255, 255, 0.10); /* 深底玻璃面 */ + --mini-glass-strong: rgba(255, 255, 255, 0.16); + --mini-hairline: rgba(255, 255, 255, 0.16); /* 深底分隔线 */ + --mini-glass-success: rgba(90, 226, 184, 0.16); /* 深底上的成功态玻璃面 */ + + /* 星点层:多个小径向渐变叠在夜空渐变之上。用 radial-gradient 而非图片, + 避免额外请求,也便于随主题换色(index 页脚注:装饰层不承载信息)。 */ + --mini-starfield: + radial-gradient(circle at 12% 18%, var(--mini-star) 0, transparent 1.25px), + radial-gradient(circle at 31% 66%, var(--mini-star) 0, transparent 1.00px), + radial-gradient(circle at 57% 12%, var(--mini-star) 0, transparent 1.00px), + radial-gradient(circle at 79% 52%, var(--mini-star) 0, transparent 1.50px), + radial-gradient(circle at 93% 84%, var(--mini-star) 0, transparent 1.00px); + + /* 横幅压暗层:保证任何底图上的白色标题都有足够对比度 */ + --mini-banner-scrim: linear-gradient(90deg, rgba(23, 42, 114, 0.84) 0%, rgba(37, 16, 79, 0.40) 56%, rgba(255, 79, 145, 0.12) 100%); + + /* ============ 功能色(同样分级) ============ */ + --color-success: #2E9B68; /* 色块/图标 */ + --color-success-strong: #17805A; /* 文字(4.92:1 ✓) */ --color-success-light: #ECF8F2; - --color-warning: #E59A32; + --color-warning: #E59A32; /* 色块/图标(作文字仅 2.33:1) */ + --color-warning-strong: #9C5F14; /* 文字(5.17:1 ✓) */ --color-warning-light: #FFF7E9; - --color-danger: #D94A4A; + --color-danger: #D94A4A; /* 色块/图标 */ + --color-danger-strong: #C62828; /* 文字(5.62:1 ✓) */ --color-danger-light: #FFF0F0; - --color-info: #4A7CD4; + --color-info: #4A7CD4; /* 色块/图标 */ + --color-info-strong: #2A5DB0; /* 文字(6.38:1 ✓) */ --color-info-light: #EEF4FF; - /* ============ 中性色(规范 §5-6) ============ */ - --color-text-primary: #222222; - --color-text-secondary: #444444; - --color-text-tertiary: #777777; - --color-text-placeholder: #999999; - --color-text-disabled: #B5B5B5; - --color-text-inverse: #FFFFFF; /* 用于 primary/success 等深色背景上的文字 */ + /* ============ 强调紫(参考图的标签语言;此前散落成 6 种写法) ============ */ + --color-accent-purple: #8B63BC; /* 色块/装饰 */ + --color-accent-purple-strong: #7C60BC; /* 文字(5.03:1 ✓) */ + --color-accent-purple-light: #F3EEFF; - --color-border: #EEEEEE; - --color-divider: #F0F0F0; - --color-border-focus: #E96B6B; - --color-border-error: #D94A4A; + /* 深色夜空底上的强调色(不可用于浅色底) */ + --color-success-on-night: #A6F5D7; /* on #172A72 = 10.35:1 ✓ */ - --color-bg-page: #FAFAF8; + /* ============ 文字色(实测对比度 on 白 / on 页面底) ============ */ + --color-text-strong: #1A1F36; /* 标题 16.24 / 14.90 ✓ */ + --color-text-primary: #2A3050; /* 正文 12.83 / 11.77 ✓ */ + --color-text-secondary: #4A5169; /* 次要正文 7.86 / 7.21 ✓ */ + --color-text-tertiary: #646C85; /* 说明文字 5.22 / 4.79 ✓(旧 #777 为 4.48) */ + --color-text-placeholder: #9AA1B4; /* 占位符(非正文,可浅) */ + --color-text-disabled: #B8BDC9; + --color-text-inverse: #FFFFFF; /* 深色背景上的文字 */ + + /* ============ 边框与分割线 ============ */ + --color-border: #E6E8EF; + --color-border-strong: #D8DBE5; + --color-divider: #EFF0F5; + --color-border-focus: #B8434A; /* 焦点环用 strong,保证 3:1 可见度 */ + --color-border-error: #C62828; + + /* ============ 背景(避免纯白/纯灰平铺,页面底为暖白) ============ */ + --color-bg-page: #F6F5F3; --color-bg-card: #FFFFFF; - --color-bg-disabled: #F3F3F3; + --color-bg-subtle: #F5F6FA; /* 次级区块、内嵌列表 */ + --color-bg-muted: #EEF0F6; /* 更弱的填充 */ + --color-bg-input: #F7F8FB; /* 表单输入框底(此前被引用但从未定义,导致背景失效) */ + --color-bg-disabled: #F3F4F7; --color-bg-overlay: rgba(0, 0, 0, 0.45); - /* ============ 字体(规范 §7-11) ============ */ + /* ============ 字体 ============ */ + /* 小程序无法可靠加载 Web Font(wx.loadFontFace 依赖 HTTPS 白名单且有闪动风险), + 故使用中文系统字栈:iOS 走苹方、Android 走思源/系统黑体。 + 排版辨识度靠字号阶梯与字重建立,而非依赖字体本身。 */ --font-family-cn: -apple-system, "PingFang SC", "Noto Sans SC", "Hiragino Sans GB", "Microsoft YaHei", system-ui, sans-serif; + --font-family-number: "SF Pro Display", -apple-system, "DIN Alternate", "PingFang SC", sans-serif; - --font-size-xs: 12.00px; /* 12px */ - --font-size-sm: 13.00px; /* 13px */ - --font-size-md: 14.00px; /* 14px */ - --font-size-base: 16.00px; /* 16px */ - --font-size-lg: 18.00px; /* 18px */ - --font-size-xl: 20.00px; /* 20px */ - --font-size-2xl: 24.00px; /* 24px */ - --font-size-3xl: 28.00px; /* 28px */ + /* 字号阶梯 —— 正文 16.00px(16px) 起,元信息下限 12.00px(12px) */ + --font-size-micro: 11.00px; /* 11px 仅角标/装饰,禁用于正文 */ + --font-size-xs: 12.00px; /* 12px 元信息下限 */ + --font-size-sm: 13.00px; /* 13px 次要说明 */ + --font-size-md: 14.00px; /* 14px 次要正文 */ + --font-size-base: 16.00px; /* 16px 正文 */ + --font-size-lg: 18.00px; /* 18px 小标题 */ + --font-size-xl: 20.00px; /* 20px 区块标题 */ + --font-size-2xl: 24.00px; /* 24px 页面标题 */ + --font-size-3xl: 28.00px; /* 28px 大标题 */ + --font-size-display: 32.00px; /* 32px Hero */ + /* 字重:只用 4 档。禁止 550/650/750 等非百位值 —— Android 无对应字重会回退, + 导致同一设计在不同机型上粗细不一致(审计发现 30 处)。 */ --font-weight-regular: 400; --font-weight-medium: 500; --font-weight-semibold: 600; @@ -4227,51 +6572,68 @@ --line-height-tight: 1.25; --line-height-normal: 1.5; - --line-height-relaxed: 1.7; + --line-height-relaxed: 1.65; - /* ============ 间距(规范 §12,4px 栅格) ============ */ - --spacing-1: 4.00px; /* 4px */ - --spacing-2: 8.00px; /* 8px */ - --spacing-3: 12.00px; /* 12px */ - --spacing-4: 16.00px; /* 16px */ - --spacing-5: 20.00px; /* 20px */ - --spacing-6: 24.00px; /* 24px */ - --spacing-8: 32.00px; /* 32px */ - --spacing-10: 40.00px; /* 40px */ - --spacing-12: 48.00px; /* 48px */ + --letter-spacing-tight: 0; + --letter-spacing-wide: 0.50px; + --letter-spacing-wider: 1.00px; - --spacing-page-x: 16.00px; /* 页面左右 16px */ - --spacing-section: 24.00px; /* 区块间 24px */ - --spacing-card-inner: 16.00px; /* 卡片内部 16px */ - --spacing-tight: 8.00px; /* 紧密 8px */ + /* ============ 间距(4px 栅格) ============ */ + --spacing-1: 4.00px; + --spacing-2: 8.00px; + --spacing-3: 12.00px; + --spacing-4: 16.00px; + --spacing-5: 20.00px; + --spacing-6: 24.00px; + --spacing-8: 32.00px; + --spacing-10: 40.00px; + --spacing-12: 48.00px; - /* ============ 圆角(规范 §14) ============ */ - --radius-sm: 8.00px; /* 8px */ - --radius-md: 12.00px; /* 12px */ - --radius-lg: 16.00px; /* 16px */ - --radius-xl: 20.00px; /* 20px */ + --spacing-page-x: 16.00px; + --spacing-section: 24.00px; + --spacing-card-inner: 16.00px; + --spacing-tight: 8.00px; + + /* ============ 圆角 ============ */ + --radius-sm: 8.00px; + --radius-md: 12.00px; + --radius-lg: 16.00px; + --radius-xl: 20.00px; + --radius-2xl: 24.00px; --radius-full: 4999.50px; - /* ============ 阴影(规范 §15,极轻) ============ */ - --shadow-card: 0 4.00px 16.00px rgba(0, 0, 0, 0.04); + /* ============ 阴影(统一为一套,此前 30+ 种近似值) ============ */ + --shadow-card: 0 4.00px 14.00px rgba(35, 35, 95, 0.07); + --shadow-raised: 0 6.00px 18.00px rgba(35, 35, 95, 0.10); --shadow-popup: 0 8.00px 32.00px rgba(0, 0, 0, 0.10); + --shadow-night: 0 8.00px 20.00px rgba(28, 30, 88, 0.18); - /* ============ 边框(规范 §16) ============ */ + /* ============ 边框宽度 ============ */ --border-width: 0.50px; + --border-width-strong: 1.00px; - /* ============ 动效(规范 §17) ============ */ + /* ============ 触摸目标(无障碍下限 44×44px) ============ */ + --tap-min: 44.00px; /* 44px 最小可点区域 */ + --tap-comfortable: 48.00px; /* 48px 舒适尺寸:主操作 */ + --tap-gap: 8.00px; /* 8px 相邻目标最小间距 */ + + /* ============ 动效 ============ */ --motion-fast: 120ms; --motion-normal: 200ms; --motion-slow: 300ms; - --ease-standard: ease-out; + --ease-standard: cubic-bezier(0.32, 0.72, 0, 1); + --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1); + --press-scale: 0.97; + --press-opacity: 0.88; - /* ============ 层级 z-index(规范 §90) ============ */ + /* ============ 层级 z-index ============ */ --z-base: 1; --z-sticky: 100; --z-tabbar: 200; --z-dropdown: 500; --z-modal: 1000; --z-toast: 2000; + --z-ambient: 0; /* ============ 页面基础样式 ============ */ background-color: var(--color-bg-page); @@ -4281,7 +6643,10 @@ line-height: var(--line-height-normal); } -/* ============ 通用工具类 ============ */ +/* ========================================================================== + 通用工具类 + ========================================================================== */ + .container { padding: var(--spacing-page-x); } @@ -4295,17 +6660,34 @@ .flex-shrink-0 { flex-shrink: 0; } .wrap { flex-wrap: wrap; } +/* 4 列宫格:用 flex + 百分比宽度实现。 + 注:display:grid 在 WebView 渲染下可用,但 Skyline 不支持,故统一改为 flex 以免疫渲染引擎迁移。*/ +.grid-4 { + display: flex; + flex-wrap: wrap; +} +.grid-4 > .grid-item { + width: 25%; + box-sizing: border-box; +} + +.text-strong { color: var(--color-text-strong); } .text-primary { color: var(--color-text-primary); } .text-secondary { color: var(--color-text-secondary); } .text-tertiary { color: var(--color-text-tertiary); } .text-placeholder { color: var(--color-text-placeholder); } .text-white { color: var(--color-text-inverse); } -.text-brand { color: var(--color-primary); } -.text-success { color: var(--color-success); } -.text-warning { color: var(--color-warning); } -.text-danger { color: var(--color-danger); } -.text-info { color: var(--color-info); } +.text-brand { color: var(--color-primary-strong); } +/* 品牌色作文字只能用 -strong 变体:基础色 #E96B6B 在白底仅 3.10:1。 + 保留 .text-brand-soft 这个类名是为了不破坏既有引用,取值已统一到 -strong, + 如需「更亮的品牌色」请用于背景/图形而非文字。 */ +.text-brand-soft { color: var(--color-primary-strong); } +.text-success { color: var(--color-success-strong); } +.text-warning { color: var(--color-warning-strong); } +.text-danger { color: var(--color-danger-strong); } +.text-info { color: var(--color-info-strong); } +.font-micro { font-size: var(--font-size-micro); } .font-xs { font-size: var(--font-size-xs); } .font-sm { font-size: var(--font-size-sm); } .font-md { font-size: var(--font-size-md); } @@ -4314,6 +6696,7 @@ .font-xl { font-size: var(--font-size-xl); } .font-2xl { font-size: var(--font-size-2xl); } .font-3xl { font-size: var(--font-size-3xl); } +.font-display { font-size: var(--font-size-display); } .font-regular { font-weight: var(--font-weight-regular); } .font-medium { font-weight: var(--font-weight-medium); } @@ -4351,7 +6734,7 @@ padding-bottom: 0px; } -/* 页面卡片基础样式(中低密度留白) */ +/* 页面卡片基础样式 */ .card-base { background: var(--color-bg-card); border-radius: var(--radius-lg); @@ -4365,350 +6748,477 @@ background: var(--color-divider); } -.wx-page{background:var(--color-bg-page)}.service-page{min-height:100vh;padding-bottom:calc(70.00px + 0px)}.hero{padding:22.00px 16.00px 27.00px;background:linear-gradient(140deg,var(--color-primary-lighter),#FFF8EE);position:relative;overflow:hidden}.eyebrow{display:inline-flex;padding:3.50px 7.00px;border-radius:499.50px;background:rgba(255,255,255,.72);color:var(--color-primary);font-size:10.50px}.hero-title{display:block;margin-top:9.00px;font-size:20.00px;font-weight:700;line-height:1.35}.hero-desc{display:block;width:82%;margin-top:7.00px;font-size:12.50px;color:var(--color-text-secondary);line-height:1.7}.content{padding:0 var(--spacing-page-x)}.block{margin-top:var(--spacing-section)}.block-title{display:block;font-size:15.50px;font-weight:650}.block-subtitle{display:block;margin-top:4.00px;font-size:11.50px;color:var(--color-text-tertiary)}.card{margin-top:9.00px;padding:14.00px;background:var(--color-bg-card);border:0.50px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.feature-row,.menu-row,.record-row{display:flex;align-items:center;gap:10.00px;min-height:56.00px;padding:9.00px 0;border-bottom:0.50px solid var(--color-divider)}.feature-row:last-child,.menu-row:last-child,.record-row:last-child{border-bottom:0}.feature-icon{width:36.00px;height:36.00px;display:flex;align-items:center;justify-content:center;flex:none;border-radius:11.00px;background:var(--color-primary-light);color:var(--color-primary);font-weight:700}.feature-copy{flex:1;min-width:0}.feature-title{display:block;font-size:14.00px;font-weight:600}.feature-desc,.meta{display:block;margin-top:3.50px;font-size:11.50px;color:var(--color-text-tertiary);line-height:1.55}.arrow{font-size:20.00px;color:var(--color-text-disabled)}.tag{display:inline-flex;margin-right:5.00px;margin-top:5.00px;padding:3.00px 6.50px;border-radius:499.50px;background:var(--color-success-light);color:var(--color-success);font-size:10.00px}.tag.warning{background:var(--color-warning-light);color:var(--color-warning)}.primary-btn,.secondary-btn{height:44.00px;display:flex;align-items:center;justify-content:center;border-radius:22.00px;font-size:14.00px;font-weight:600}.primary-btn{background:linear-gradient(135deg,var(--mini-accent-coral),var(--mini-accent-pink));color:var(--color-text-inverse);box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)}.primary-btn.disabled{background:#E6E8EF;color:#989DAF;box-shadow:none}.secondary-btn{background:var(--color-primary-light);color:var(--color-primary)}.fixed-action{position:fixed;left:0;right:0;bottom:0;padding:9.00px var(--spacing-page-x) calc(9.00px + 0px);background:rgba(255,255,255,.96);border-top:0.50px solid var(--color-divider);z-index:100}.field{margin-top:13.00px}.label{display:block;margin-bottom:6.00px;font-size:12.50px;font-weight:600}.input,.select-box,.textarea{width:100%;box-sizing:border-box;background:#FCFAF8;border:0.50px solid var(--color-border);border-radius:var(--radius-md);font-size:13.00px}.input,.select-box{height:44.00px;padding:0 12.00px;display:flex;align-items:center}.textarea{min-height:90.00px;padding:11.00px}.notice{margin-top:10.00px;padding:11.00px;border-radius:var(--radius-md);background:#F3F7FC;color:var(--color-text-secondary);font-size:11.50px;line-height:1.65}.empty-panel{text-align:center;padding:35.00px 15.00px}.empty-symbol{width:48.00px;height:48.00px;margin:auto;display:flex;align-items:center;justify-content:center;border-radius:15.00px;background:var(--color-primary-light);color:var(--color-primary);font-size:18.00px;font-weight:700}.empty-title{display:block;margin-top:11.00px;font-size:15.00px;font-weight:600}.article-card{margin-top:9.00px;background:var(--color-bg-card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.article-cover{height:110.00px;padding:12.00px;background:linear-gradient(135deg,#F5E5DE,#F9F1E8);display:flex;align-items:flex-end}.article-cover text{font-size:21.00px;color:rgba(125,76,63,.52);font-weight:700}.article-body{padding:12.00px}.article-title{display:block;font-size:14.50px;font-weight:650;line-height:1.45}.article-meta{display:block;margin-top:5.00px;font-size:11.00px;color:var(--color-text-tertiary)}.article-content{padding:16.00px;background:var(--color-bg-card);font-size:14.00px;line-height:1.9;color:var(--color-text-secondary)}.article-content .lead{display:block;font-size:15.50px;color:var(--color-text-primary);font-weight:600;margin-bottom:12.00px}.danger-card{background:#FFF8F4;border-color:#F5DED2}.danger-card .feature-icon{background:#FFF0EA;color:#C85D43}@media(max-width:340px){.hero-title{font-size:18.00px}.hero-desc{width:92%}} +/* ========================================================================== + 可访问性:只用 token,不用工具类(2026-09-23 修订) + -------------------------------------------------------------------------- + v2 曾在此处新增 .tap-min / .tap-gap / .focusable / .pressable 四个工具类。 + 复检发现全部零引用(等价能力已各自写在组件样式内,例如 button/index.wxss + 直接使用 min-height:var(--tap-min)),且存在两个硬问题: -.service-shell{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:#F4F5FA}.service-content{padding:4.00px 12.00px 18.00px}.service-status{display:flex;align-items:center;justify-content:space-between;margin-top:12.00px;padding:10.00px 12.00px;border-radius:11.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-status__label{color:#7B8198;font-size:10.50px}.service-status__value{padding:3.00px 7.00px;border-radius:9.00px;background:#EAF8F2;color:#329472;font-size:9.50px;font-weight:650}.service-status__value.disabled{background:#FFF0F0;color:#D45A60}.service-topics{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.service-topic{min-height:74.00px;padding:10.00px;border-radius:12.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-topic__icon{display:flex;align-items:center;justify-content:center;width:27.00px;height:27.00px;border-radius:8.50px;background:#FFF0F5}.service-topic__icon image{width:17.00px;height:17.00px}.service-topic__title{display:block;margin-top:6.50px;color:#283056;font-size:12.00px;font-weight:650}.service-topic__desc{display:block;margin-top:3.00px;color:#858A9E;font-size:9.50px;line-height:1.45}.service-actions{display:flex;gap:7.00px}.service-actions .secondary-btn{width:95.00px;flex:none}.service-actions .primary-btn{flex:1}.privacy-note{display:flex;align-items:flex-start;gap:7.00px;margin-top:11.00px;padding:10.00px;border-radius:11.00px;background:#F1F4FF;color:#69718E;font-size:10.00px;line-height:1.55}.privacy-note image{width:17.00px;height:17.00px;flex:none} + 1) `.tap-gap > * + *` 用了通配符与兄弟选择器 —— WXSS 不支持, + wcc 编译期直接报 `error at token '*'`,导致整个小程序编译失败。 + (这是编译错误,不是静默失效,代价最高。) + 2) `.pressable:active` / `.focusable:focus-visible` 的伪类在 view 上 + 不生效(小程序须用 hover-class),属于"写了等于没写"。 + + 故整块移除,保留 token。需要热区/间距时直接引用 token: + min-height: var(--tap-min); → 44.00px = 44px,最小可点区域 + gap: var(--tap-gap); → 8.00px = 8px,相邻目标间距(flex gap) + 【WXSS 禁用清单】星号通配符、兄弟选择器、属性选择器。 + 【注释约束】WXSS 注释**不可嵌套**:内层注释的结束标记会提前终止外层注释, + 其后的文字会被当成真实样式解析,导致编译失败或样式被污染。 + (2026-09-23 实证:本块注释初版即踩此坑。) + ========================================================================== */ + +.wx-page{background:var(--color-bg-page)}.service-page{min-height:100vh;padding-bottom:calc(70.00px + 0px)}.hero{padding:22.00px 16.00px 27.00px;background:linear-gradient(140deg,var(--color-primary-lighter),var(--color-warning-light));position:relative;overflow:hidden}.eyebrow{display:inline-flex;padding:3.50px 7.00px;border-radius:499.50px;background:rgba(255,255,255,.72);color:var(--color-primary-strong);font-size:12.00px}.hero-title{display:block;margin-top:9.00px;font-size:20.00px;font-weight:700;line-height:1.35}.hero-desc{display:block;width:82%;margin-top:7.00px;font-size:12.50px;color:var(--color-text-secondary);line-height:1.7}.content{padding:0 var(--spacing-page-x)}.block{margin-top:var(--spacing-section)}.block-title{display:block;font-size:15.50px;font-weight:600}.block-subtitle{display:block;margin-top:4.00px;font-size:12.00px;color:var(--color-text-tertiary)}.card{margin-top:9.00px;padding:14.00px;background:var(--color-bg-card);border:0.50px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.feature-row,.menu-row,.record-row{display:flex;align-items:center;gap:10.00px;min-height:56.00px;padding:9.00px 0;border-bottom:0.50px solid var(--color-divider)}.feature-row:last-child,.menu-row:last-child,.record-row:last-child{border-bottom:0}.feature-icon{width:36.00px;height:36.00px;display:flex;align-items:center;justify-content:center;flex:none;border-radius:11.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-weight:700}.feature-copy{flex:1;min-width:0}.feature-title{display:block;font-size:14.00px;font-weight:600}.feature-desc,.meta{display:block;margin-top:3.50px;font-size:12.00px;color:var(--color-text-tertiary);line-height:1.55}.arrow{font-size:20.00px;color:var(--color-text-disabled)}.tag{display:inline-flex;margin-right:5.00px;margin-top:5.00px;padding:3.00px 6.50px;border-radius:499.50px;background:var(--color-success-light);color:var(--color-success-strong);font-size:12.00px}.tag.warning{background:var(--color-warning-light);color:var(--color-warning-strong)}.primary-btn,.secondary-btn{height:44.00px;display:flex;align-items:center;justify-content:center;border-radius:22.00px;font-size:14.00px;font-weight:600}.primary-btn{background:var(--gradient-brand-solid);color:var(--color-text-inverse);box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)}.primary-btn.disabled{background:var(--color-bg-muted);color:var(--color-text-tertiary);box-shadow:none}.secondary-btn{background:var(--color-primary-light);color:var(--color-primary-strong)}.fixed-action{position:fixed;left:0;right:0;bottom:0;padding:9.00px var(--spacing-page-x) calc(9.00px + 0px);background:rgba(255,255,255,.96);border-top:0.50px solid var(--color-divider);z-index:100}.field{margin-top:13.00px}.label{display:block;margin-bottom:6.00px;font-size:12.50px;font-weight:600}.input,.select-box,.textarea{width:100%;box-sizing:border-box;background:var(--color-bg-page);border:0.50px solid var(--color-border);border-radius:var(--radius-md);font-size:13.00px}.input,.select-box{height:44.00px;padding:0 12.00px;display:flex;align-items:center}.textarea{min-height:90.00px;padding:11.00px}.notice{margin-top:10.00px;padding:11.00px;border-radius:var(--radius-md);background:var(--color-info-light);color:var(--color-text-secondary);font-size:12.00px;line-height:1.65}.select-box.is-readonly{background:var(--color-bg-subtle);color:var(--color-text-secondary)}.empty-panel{text-align:center;padding:35.00px 15.00px}.empty-symbol{width:48.00px;height:48.00px;margin:auto;display:flex;align-items:center;justify-content:center;border-radius:15.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-size:18.00px;font-weight:700}.empty-title{display:block;margin-top:11.00px;font-size:15.00px;font-weight:600}.article-card{margin-top:9.00px;background:var(--color-bg-card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.article-cover{height:110.00px;padding:12.00px;background:linear-gradient(135deg,var(--color-warning-light),var(--color-warning-light));display:flex;align-items:flex-end}.article-cover text{font-size:21.00px;color:rgba(125,76,63,.52);font-weight:700}.article-body{padding:12.00px}.article-title{display:block;font-size:14.50px;font-weight:600;line-height:1.45}.article-meta{display:block;margin-top:5.00px;font-size:12.00px;color:var(--color-text-tertiary)}.article-content{padding:16.00px;background:var(--color-bg-card);font-size:14.00px;line-height:1.9;color:var(--color-text-secondary)}.article-content .lead{display:block;font-size:15.50px;color:var(--color-text-primary);font-weight:600;margin-bottom:12.00px}.danger-card{background:var(--color-primary-lighter);border-color:var(--color-primary-light)}.danger-card .feature-icon{background:var(--color-warning-light);color:var(--color-warning-strong)}@media(max-width:340px){.hero-title{font-size:18.00px}.hero-desc{width:92%}} + +.service-shell{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:var(--color-bg-page)}.service-content{padding:4.00px 12.00px 18.00px}.service-status{display:flex;align-items:center;justify-content:space-between;margin-top:12.00px;padding:10.00px 12.00px;border-radius:11.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-status__label{color:var(--color-text-tertiary);font-size:12.00px}.service-status__value{padding:3.00px 7.00px;border-radius:9.00px;background:var(--color-success-light);color:var(--color-success-strong);font-size:12.00px;font-weight:600}.service-status__value.disabled{background:var(--color-danger-light);color:var(--color-danger-strong)}.service-topics{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.service-topic{min-height:74.00px;padding:10.00px;border-radius:12.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-topic__icon{display:flex;align-items:center;justify-content:center;width:27.00px;height:27.00px;border-radius:8.50px;background:var(--color-primary-light)}.service-topic__icon image{width:17.00px;height:17.00px}.service-topic__title{display:block;margin-top:6.50px;color:var(--color-text-strong);font-size:12.00px;font-weight:600}.service-topic__desc{display:block;margin-top:3.00px;color:var(--color-text-tertiary);font-size:12.00px;line-height:1.45}.service-actions{display:flex;gap:7.00px}.service-actions .secondary-btn{width:95.00px;flex:none}.service-actions .primary-btn{flex:1}.privacy-note{display:flex;align-items:flex-start;gap:7.00px;margin-top:11.00px;padding:10.00px;border-radius:11.00px;background:var(--color-info-light);color:var(--color-text-tertiary);font-size:12.00px;line-height:1.55}.privacy-note image{width:17.00px;height:17.00px;flex:none} /* ==== miniapp/components/service-hero ==== */ .service-hero { - position: relative; - height: 150.00px; - overflow: hidden; - border-radius: 0 0 16.00px 16.00px; - background: #fff4f7; + position:relative; + height:150.00px; + overflow:hidden; + border-radius:0 0 16.00px 16.00px; + background:var(--color-primary-light); } .service-hero__image, .service-hero__veil { - position: absolute; - inset: 0; - width: 100%; - height: 100%; + position:absolute; + inset:0; + width:100%; + height:100%; } .service-hero__veil { - background: linear-gradient(90deg, rgba(255, 250, 252, 0.98) 0%, rgba(255, 250, 252, 0.82) 38%, rgba(255, 250, 252, 0.08) 70%); + background:linear-gradient(90deg, rgba(255, 250, 252, 0.98) 0%, rgba(255, 250, 252, 0.82) 38%, rgba(255, 250, 252, 0.08) 70%); } .service-hero--night .service-hero__veil { - background: linear-gradient(90deg, rgba(18, 24, 83, 0.92) 0%, rgba(34, 31, 111, 0.64) 42%, rgba(34, 31, 111, 0.08) 72%); + background:linear-gradient(90deg, rgba(18, 24, 83, 0.92) 0%, rgba(34, 31, 111, 0.64) 42%, rgba(34, 31, 111, 0.08) 72%); } .service-hero__content { - position: relative; - z-index: 1; - display: flex; - flex-direction: column; - justify-content: center; - width: 54%; - height: 100%; - padding: 0 18.00px; - box-sizing: border-box; + position:relative; + z-index:1; + display:flex; + flex-direction:column; + justify-content:center; + width:54%; + height:100%; + padding:0 18.00px; + box-sizing:border-box; } .service-hero__eyebrow { - margin-bottom: 5.00px; - color: var(--color-primary); - font-size: 11.00px; - font-weight: 600; - letter-spacing: 1.00px; + margin-bottom:5.00px; + color:var(--color-primary-strong); + font-size:12.00px; + font-weight:600; + letter-spacing:1.00px; } .service-hero__title { - color: #24305e; - font-size: 20.00px; - font-weight: 700; - line-height: 1.28; + color:var(--color-text-strong); + font-size:20.00px; + font-weight:700; + line-height:1.28; } .service-hero__subtitle { - margin-top: 7.00px; - color: #737c96; - font-size: 12.00px; - line-height: 1.55; + margin-top:7.00px; + color:var(--color-text-tertiary); + font-size:12.00px; + line-height:1.55; } .service-hero--night .service-hero__eyebrow, .service-hero--night .service-hero__title, .service-hero--night .service-hero__subtitle { - color: #ffffff; + color:var(--color-text-inverse); } /* ==== miniapp/components/loading ==== */ .ui-loading--block { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: var(--spacing-8) var(--spacing-page-x); + display:flex; + flex-direction:column; + align-items:center; + justify-content:center; + padding:var(--spacing-8) var(--spacing-page-x); } .ui-loading--inline { - display: inline-flex; - align-items: center; + display:inline-flex; + align-items:center; } .ui-loading__spinner { - width: 30.00px; - height: 30.00px; - display: flex; - align-items: center; - justify-content: center; + width:30.00px; + height:30.00px; + display:flex; + align-items:center; + justify-content:center; } .ui-loading__spinner-icon { - width: 24.00px; - height: 24.00px; - animation: ui-loading-spin 0.8s linear infinite; + width:24.00px; + height:24.00px; + animation:ui-loading-spin 0.8s linear infinite; } @keyframes ui-loading-spin { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } + from { transform:rotate(0deg); } + to { transform:rotate(360deg); } } .ui-loading__text { - margin-top: var(--spacing-3); - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); + margin-top:var(--spacing-3); + font-size:var(--font-size-sm); + color:var(--color-text-tertiary); } /* Skeleton */ .ui-loading__skeleton { - width: 100%; + width:100%; } .ui-loading__skeleton-row { - display: flex; - align-items: center; - padding: var(--spacing-3) var(--spacing-page-x); - background: var(--color-bg-card); - border-bottom: 0.50px solid var(--color-divider); + display:flex; + align-items:center; + padding:var(--spacing-3) var(--spacing-page-x); + background:var(--color-bg-card); + border-bottom:0.50px solid var(--color-divider); } .ui-loading__skeleton-avatar { - width: 44.00px; - height: 44.00px; - border-radius: 50%; - background: var(--color-bg-disabled); - margin-right: var(--spacing-3); - flex-shrink: 0; + width:44.00px; + height:44.00px; + border-radius:50%; + background:var(--color-bg-disabled); + margin-right:var(--spacing-3); + flex-shrink:0; } .ui-loading__skeleton-content { - flex: 1; - min-width: 0; + flex:1; + min-width:0; } .ui-loading__skeleton-line { - height: 12.00px; - background: var(--color-bg-disabled); - border-radius: var(--radius-sm); - position: relative; - overflow: hidden; + height:12.00px; + background:var(--color-bg-disabled); + border-radius:var(--radius-sm); + position:relative; + overflow:hidden; } .ui-loading__skeleton-line--title { - width: 40%; - margin-bottom: var(--spacing-2); + width:40%; + margin-bottom:var(--spacing-2); } .ui-loading__skeleton-line--meta { - width: 70%; + width:70%; } /* shimmer */ .ui-loading__skeleton-line::after, .ui-loading__skeleton-avatar::after { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: linear-gradient( + content:''; + position:absolute; + top:0; + left:0; + width:100%; + height:100%; + background:linear-gradient( 90deg, transparent 0%, rgba(255, 255, 255, 0.55) 50%, transparent 100% ); - animation: ui-loading-shimmer 1.4s ease-in-out infinite; + animation:ui-loading-shimmer 1.4s ease-in-out infinite; } @keyframes ui-loading-shimmer { - 0% { transform: translateX(-100%); } - 100% { transform: translateX(100%); } + 0% { transform:translateX(-100%); } + 100% { transform:translateX(100%); } } /* ==== miniapp/components/empty ==== */ .ui-empty { - display: flex; - flex-direction: column; - align-items: center; - padding: var(--spacing-10) var(--spacing-page-x); - text-align: center; + display:flex; + flex-direction:column; + align-items:center; + padding:var(--spacing-10) var(--spacing-page-x); + text-align:center; } .ui-empty__illustration { - width: 80.00px; - height: 80.00px; - border-radius: 50%; - background: var(--color-bg-disabled); - display: flex; - align-items: center; - justify-content: center; - margin-bottom: var(--spacing-4); + width:80.00px; + height:80.00px; + border-radius:50%; + background:var(--color-bg-disabled); + display:flex; + align-items:center; + justify-content:center; + margin-bottom:var(--spacing-4); } .ui-empty__icon { - width: 36.00px; - height: 36.00px; - opacity: 0.72; + width:36.00px; + height:36.00px; + opacity:0.72; } .ui-empty__title { - font-size: var(--font-size-lg); - font-weight: var(--font-weight-medium); - color: var(--color-text-primary); - margin-bottom: var(--spacing-2); + font-size:var(--font-size-lg); + font-weight:var(--font-weight-medium); + color:var(--color-text-primary); + margin-bottom:var(--spacing-2); } .ui-empty__desc { - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); - line-height: var(--line-height-relaxed); - max-width: 240.00px; + font-size:var(--font-size-sm); + color:var(--color-text-tertiary); + line-height:var(--line-height-relaxed); + max-width:240.00px; } .ui-empty__actions { - display: flex; - flex-direction: column; - gap: var(--spacing-2); - margin-top: var(--spacing-6); - width: 100%; - max-width: 240.00px; + display:flex; + flex-direction:column; + gap:var(--spacing-2); + margin-top:var(--spacing-6); + width:100%; + max-width:240.00px; } .ui-empty__action { - display: flex; - align-items: center; - justify-content: center; - height: 40.00px; - border-radius: var(--radius-full); - font-size: var(--font-size-base); - font-weight: var(--font-weight-medium); -} + display:flex; + align-items:center; + justify-content:center; + min-height:var(--tap-min); + border-radius:var(--radius-full); + font-size:var(--font-size-base); + font-weight:var(--font-weight-medium); +min-width:var(--tap-min);} .ui-empty__action--primary { - background: var(--color-primary); - color: #FFFFFF; + background:var(--color-primary-solid); + color:var(--color-text-inverse); } .ui-empty__action--secondary { - background: var(--color-bg-card); - color: var(--color-primary); - border: 0.50px solid var(--color-primary); + background:var(--color-bg-card); + color:var(--color-primary-strong); + border:0.50px solid var(--color-primary); } /* ==== miniapp/components/error-state ==== */ .error-state { - padding: 32.00px 16.00px; - text-align: center; - background: var(--color-bg-card); - border-radius: var(--radius-lg); + padding:32.00px 16.00px; + text-align:center; + background:var(--color-bg-card); + border-radius:var(--radius-lg); } .error-icon { - display: block; - width: 36.00px; - height: 36.00px; - margin: 0 auto 10.00px; + display:block; + width:36.00px; + height:36.00px; + margin:0 auto 10.00px; } .error-title, .error-desc { - display: block; + display:block; } .error-title { - font-size: 15.00px; - font-weight: 600; + font-size:15.00px; + font-weight:600; } .error-desc { - margin-top: 4.00px; - color: var(--color-text-tertiary); - font-size: 12.00px; + margin-top:4.00px; + color:var(--color-text-tertiary); + font-size:12.00px; } .retry-btn { - width: 110.00px; - height: 40.00px; - margin-top: 12.00px; - border: 0; - border-radius: var(--radius-full); - background: var(--color-primary); - color: var(--color-text-inverse); - font-size: 13.00px; - line-height: 40.00px; -} + width:110.00px; + min-height:var(--tap-min); + margin-top:12.00px; + border:0; + border-radius:var(--radius-full); + background:var(--color-primary-solid); + color:var(--color-text-inverse); + font-size:13.00px; + line-height:var(--tap-min); +min-width:var(--tap-min);} .retry-btn::after { - border: 0; + border:0; } @import "../../styles/service-page.wxss"; -.content-page{min-height:100vh;padding-bottom:20.00px;background:#F4F5FA}.content-categories{padding:12.00px 0;white-space:nowrap}.content-category-row{display:inline-flex;gap:6.00px;padding:0 12.00px}.content-category{padding:5.50px 11.00px;border-radius:12.00px;background:#fff;color:#767D96;font-size:10.50px;box-shadow:0 3.00px 9.00px rgba(35,35,95,.05)}.content-category.active{background:linear-gradient(135deg,var(--mini-accent-coral),var(--mini-accent-pink));color:#fff;font-weight:650}.content-list{padding:0 12.00px}.content-card{display:flex;align-items:center;overflow:hidden;min-height:75.00px;margin-bottom:8.00px;border-radius:12.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.content-cover{width:88.00px;height:75.00px;flex:none}.content-card__body{display:flex;flex:1;min-width:0;flex-direction:column;padding:8.00px}.content-card__category{align-self:flex-start;padding:2.00px 5.00px;border-radius:6.00px;background:#FFF0F5;color:var(--mini-accent-pink);font-size:8.50px}.content-card__title{overflow:hidden;margin-top:4.00px;color:#283056;font-size:12.00px;font-weight:650;white-space:nowrap;text-overflow:ellipsis}.content-card__summary{overflow:hidden;margin-top:2.50px;color:#83899F;font-size:9.00px;white-space:nowrap;text-overflow:ellipsis}.content-card__meta{display:flex;gap:9.00px;margin-top:4.50px;color:#9A9EB0;font-size:8.50px}.content-card__arrow{width:12.00px;height:12.00px;margin-right:8.00px;flex:none} +.content-page{min-height:100vh;padding-bottom:20.00px;background:var(--color-bg-page)}.content-categories{padding:12.00px 0;white-space:nowrap}.content-category-row{display:inline-flex;gap:6.00px;padding:0 12.00px}.content-category{padding:5.50px 11.00px;border-radius:12.00px;background:var(--color-bg-card);color:var(--color-text-tertiary);font-size:12.00px;box-shadow:0 3.00px 9.00px rgba(35,35,95,.05)}.content-category.active{background:var(--gradient-brand-solid);color:var(--color-text-inverse);font-weight:600}.content-list{padding:0 12.00px}.content-card{display:flex;align-items:center;overflow:hidden;min-height:75.00px;margin-bottom:8.00px;border-radius:12.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.content-cover{width:88.00px;height:75.00px;flex:none}.content-card__body{display:flex;flex:1;min-width:0;flex-direction:column;padding:8.00px}.content-card__category{align-self:flex-start;padding:2.00px 5.00px;border-radius:6.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-size:12.00px}.content-card__title{overflow:hidden;margin-top:4.00px;color:var(--color-text-strong);font-size:12.00px;font-weight:600;white-space:nowrap;text-overflow:ellipsis}.content-card__summary{overflow:hidden;margin-top:2.50px;color:var(--color-text-tertiary);font-size:12.00px;white-space:nowrap;text-overflow:ellipsis}.content-card__meta{display:flex;gap:9.00px;margin-top:4.50px;color:var(--color-text-tertiary);font-size:12.00px}.content-card__arrow{width:12.00px;height:12.00px;margin-right:8.00px;flex:none} /** * 丹阳公益婚恋服务平台 - 全局 Design Token * - * 依据《前端组件库与 Design Token 规范 V1.0》 - * 单位说明:rpx(375.00px = 屏幕宽度),规范 px 值按 2x 映射为 rpx - * 禁止页面层写死颜色/间距/圆角,必须引用 var(--token) + * v2(2026-09-22 设计系统夯实) + * --------------------------------------------------------------- + * 本次修订针对审计发现的系统性问题,逐条给出依据: + * + * 1) 品牌色不能承载文字 → 引入「基础色 / -strong」分级 + * #E96B6B on 白 = 3.10:1,白字 on #E96B6B = 3.10:1,on #FFF3F2 = 2.85:1, + * 三条路径都不满足正文 4.5:1。故: + * --color-primary 仅用于大色块、渐变、光晕、装饰(非文字) + * --color-primary-strong 用于文字、小图标、纯文字链接(5.33:1 ✓) + * --color-primary-solid 实心按钮底(白字 ≥4.5:1 ✓) + * 功能色(success/warning/danger/info)同此分级。 + * + * 2) 次要文字对比度过低 + * 旧 --color-text-tertiary(#777) = 4.48(on 白,勉强)/ #999 实测 2.85 却被用了 71 次。 + * 现将三级文字压到 #646C85 = 5.22:1,占位符保留浅色(占位符非正文)。 + * + * 3) 颜色碎片化 + * 审计前全站 182 种 hex、770 次硬编码(54 种灰、60 种蓝紫、40 种红橙)。 + * 本文件是唯一的颜色事实源;页面层禁止再写 hex,一律 var(--token)。 + * + * 4) 触摸目标 + * 组件库默认按钮只有 40px、小号 28px、"喜欢"按钮 31px。 + * 统一以 --tap-min(44.00px=44px) 为下限,--tap-gap 为最小间距。 + * + * 5) 动效几乎未落地(--motion-* 全站仅 5 次引用) + * 补充 --ease-spring 与 --press-scale,让点击有即时反馈。 + * + * 6) 夜间氛围层缺失(参考图有明显的光晕/星点,代码只有纯渐变) + * 新增 --mini-glow-* / --mini-star / --mini-glass / --mini-hairline。 + * + * 单位说明:rpx(375.00px = 屏幕宽度,0.50px ≈ 0.5px @375pt) + * 旧 token 名全部保留(88 个 wxss 共 909 处引用),只更新取值,避免大范围失效。 */ .wx-page { - /* ============ 品牌主色(规范 §3) ============ */ - --color-primary: #E96B6B; - --color-primary-active: #D95F5F; + /* ============ 品牌主色(分级:色块 / 文字 / 实心按钮) ============ */ + --color-primary: #E96B6B; /* 基础色:渐变、光晕、装饰、非文字图形 */ + --color-primary-strong: #B8434A; /* 文字与小图标(5.33:1 on 白,4.91:1 on 浅粉底) */ + --color-primary-solid: #C24C50; /* 实心按钮底(白字 4.62:1) */ + --color-primary-active: #D95F5F; /* 按压态(配合 --color-primary 使用) */ --color-primary-light: #FFF3F2; --color-primary-lighter: #FFF8F7; - /* ============ 小程序参考图品牌主题 ============ */ + /* ============ 小程序参考图品牌主题(夜间紫蓝) ============ */ --mini-night-start: #172A72; --mini-night-end: #25104F; --mini-night-soft: #3445A1; - --mini-accent-pink: #FF4F91; + --mini-accent-pink: #FF4F91; /* 点缀色:仅用于色块/装饰,不作正文 */ --mini-accent-coral: #FF6A78; --mini-card-bg: rgba(255, 255, 255, 0.98); --mini-text: #1F2744; --mini-muted: #7D839B; --mini-card-radius: 12.00px; - --mini-text-on-night: #FFFFFF; - --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); + --mini-text-on-night: #FFFFFF; /* on 深底 13.04:1 ✓ */ + --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); /* on 深底 ≈8:1 ✓ */ --mini-shadow: 0 8.00px 20.00px rgba(28, 30, 88, 0.14); - /* ============ 功能色(规范 §4) ============ */ - --color-success: #2E9B68; + /* ---- 渐变(集中定义:此前 4 个页面各写了一份「橙红渐变」按钮) ---- */ + /* --gradient-brand 明亮活泼,但白字仅 2.77:1 —— 只能用于无文字的装饰填充。 */ + --gradient-brand: linear-gradient(135deg, #FF6A78 0%, #E96B6B 100%); + /* 承载白字的 CTA 渐变:两端 #C24C50(4.73:1) / #B8434A(5.33:1) 均达标。 */ + --gradient-brand-solid: linear-gradient(135deg, #C24C50 0%, #B8434A 100%); + --gradient-night: linear-gradient(160deg, #172A72 0%, #25104F 100%); + --gradient-night-soft: linear-gradient(160deg, #3445A1 0%, #172A72 100%); + + /* ---- 首页 4×2 入口宫格图标渐变(参考图 2:高饱和圆角砖 + 白色描画图标) ---- + 白图标的对比度判据是**非文本图形 3:1**(WCAG 1.4.11)。渐变是斜向的、图标又跨在 + 两色之间,所以**较亮的一端也必须达标** —— 下表注释给的是 0% 处实算值,100% 更暗只会更高。 + 色相按业务语义固定(不随 tone 名漂移):找对象/婚前辅导=玫瑰粉系、公益红娘/服务站=暖橙系、 + 公益活动=紫罗兰、婚恋咨询=蓝、婚恋课堂=紫、婚恋反诈=绿。 */ + --gradient-entry-rose: linear-gradient(135deg, #F56287 0%, #F34671 100%); /* 3.01:1 / 3.54:1 */ + --gradient-entry-orange: linear-gradient(135deg, #F66A06 0%, #D95E06 100%); /* 3.01:1 / 3.78:1 */ + --gradient-entry-violet: linear-gradient(135deg, #A380F5 0%, #8F64F2 100%); /* 3.02:1 / 3.98:1 */ + --gradient-entry-blue: linear-gradient(135deg, #5195F6 0%, #3484F4 100%); /* 3.01:1 / 3.65:1 */ + --gradient-entry-purple: linear-gradient(135deg, #B27BF0 0%, #A260ED 100%); /* 3.01:1 / 3.87:1 */ + --gradient-entry-pink: linear-gradient(135deg, #F2619E 0%, #F0458C 100%); /* 3.01:1 / 3.54:1 */ + --gradient-entry-green: linear-gradient(135deg, #18A979 0%, #148F66 100%); /* 3.00:1 / 4.08:1 */ + --gradient-entry-amber: linear-gradient(135deg, #E9740C 0%, #CC650B 100%); /* 3.01:1 / 3.86:1 */ + /* 图标砖落影:比 --mini-shadow 更小,避免 4 列宫格里相邻砖块的投影互相压边 */ + --mini-entry-shadow: 0 4.00px 9.00px rgba(28, 30, 88, 0.18); + + /* ---- 夜间氛围层(v2 新增;参考图有光晕与星点,此前完全没有) ---- */ + --mini-glow-coral: rgba(255, 79, 145, 0.40); + --mini-glow-indigo: rgba(94, 124, 255, 0.32); + --mini-glow-soft: rgba(255, 255, 255, 0.10); + --mini-star: rgba(255, 255, 255, 0.70); + --mini-glass: rgba(255, 255, 255, 0.10); /* 深底玻璃面 */ + --mini-glass-strong: rgba(255, 255, 255, 0.16); + --mini-hairline: rgba(255, 255, 255, 0.16); /* 深底分隔线 */ + --mini-glass-success: rgba(90, 226, 184, 0.16); /* 深底上的成功态玻璃面 */ + + /* 星点层:多个小径向渐变叠在夜空渐变之上。用 radial-gradient 而非图片, + 避免额外请求,也便于随主题换色(index 页脚注:装饰层不承载信息)。 */ + --mini-starfield: + radial-gradient(circle at 12% 18%, var(--mini-star) 0, transparent 1.25px), + radial-gradient(circle at 31% 66%, var(--mini-star) 0, transparent 1.00px), + radial-gradient(circle at 57% 12%, var(--mini-star) 0, transparent 1.00px), + radial-gradient(circle at 79% 52%, var(--mini-star) 0, transparent 1.50px), + radial-gradient(circle at 93% 84%, var(--mini-star) 0, transparent 1.00px); + + /* 横幅压暗层:保证任何底图上的白色标题都有足够对比度 */ + --mini-banner-scrim: linear-gradient(90deg, rgba(23, 42, 114, 0.84) 0%, rgba(37, 16, 79, 0.40) 56%, rgba(255, 79, 145, 0.12) 100%); + + /* ============ 功能色(同样分级) ============ */ + --color-success: #2E9B68; /* 色块/图标 */ + --color-success-strong: #17805A; /* 文字(4.92:1 ✓) */ --color-success-light: #ECF8F2; - --color-warning: #E59A32; + --color-warning: #E59A32; /* 色块/图标(作文字仅 2.33:1) */ + --color-warning-strong: #9C5F14; /* 文字(5.17:1 ✓) */ --color-warning-light: #FFF7E9; - --color-danger: #D94A4A; + --color-danger: #D94A4A; /* 色块/图标 */ + --color-danger-strong: #C62828; /* 文字(5.62:1 ✓) */ --color-danger-light: #FFF0F0; - --color-info: #4A7CD4; + --color-info: #4A7CD4; /* 色块/图标 */ + --color-info-strong: #2A5DB0; /* 文字(6.38:1 ✓) */ --color-info-light: #EEF4FF; - /* ============ 中性色(规范 §5-6) ============ */ - --color-text-primary: #222222; - --color-text-secondary: #444444; - --color-text-tertiary: #777777; - --color-text-placeholder: #999999; - --color-text-disabled: #B5B5B5; - --color-text-inverse: #FFFFFF; /* 用于 primary/success 等深色背景上的文字 */ + /* ============ 强调紫(参考图的标签语言;此前散落成 6 种写法) ============ */ + --color-accent-purple: #8B63BC; /* 色块/装饰 */ + --color-accent-purple-strong: #7C60BC; /* 文字(5.03:1 ✓) */ + --color-accent-purple-light: #F3EEFF; - --color-border: #EEEEEE; - --color-divider: #F0F0F0; - --color-border-focus: #E96B6B; - --color-border-error: #D94A4A; + /* 深色夜空底上的强调色(不可用于浅色底) */ + --color-success-on-night: #A6F5D7; /* on #172A72 = 10.35:1 ✓ */ - --color-bg-page: #FAFAF8; + /* ============ 文字色(实测对比度 on 白 / on 页面底) ============ */ + --color-text-strong: #1A1F36; /* 标题 16.24 / 14.90 ✓ */ + --color-text-primary: #2A3050; /* 正文 12.83 / 11.77 ✓ */ + --color-text-secondary: #4A5169; /* 次要正文 7.86 / 7.21 ✓ */ + --color-text-tertiary: #646C85; /* 说明文字 5.22 / 4.79 ✓(旧 #777 为 4.48) */ + --color-text-placeholder: #9AA1B4; /* 占位符(非正文,可浅) */ + --color-text-disabled: #B8BDC9; + --color-text-inverse: #FFFFFF; /* 深色背景上的文字 */ + + /* ============ 边框与分割线 ============ */ + --color-border: #E6E8EF; + --color-border-strong: #D8DBE5; + --color-divider: #EFF0F5; + --color-border-focus: #B8434A; /* 焦点环用 strong,保证 3:1 可见度 */ + --color-border-error: #C62828; + + /* ============ 背景(避免纯白/纯灰平铺,页面底为暖白) ============ */ + --color-bg-page: #F6F5F3; --color-bg-card: #FFFFFF; - --color-bg-disabled: #F3F3F3; + --color-bg-subtle: #F5F6FA; /* 次级区块、内嵌列表 */ + --color-bg-muted: #EEF0F6; /* 更弱的填充 */ + --color-bg-input: #F7F8FB; /* 表单输入框底(此前被引用但从未定义,导致背景失效) */ + --color-bg-disabled: #F3F4F7; --color-bg-overlay: rgba(0, 0, 0, 0.45); - /* ============ 字体(规范 §7-11) ============ */ + /* ============ 字体 ============ */ + /* 小程序无法可靠加载 Web Font(wx.loadFontFace 依赖 HTTPS 白名单且有闪动风险), + 故使用中文系统字栈:iOS 走苹方、Android 走思源/系统黑体。 + 排版辨识度靠字号阶梯与字重建立,而非依赖字体本身。 */ --font-family-cn: -apple-system, "PingFang SC", "Noto Sans SC", "Hiragino Sans GB", "Microsoft YaHei", system-ui, sans-serif; + --font-family-number: "SF Pro Display", -apple-system, "DIN Alternate", "PingFang SC", sans-serif; - --font-size-xs: 12.00px; /* 12px */ - --font-size-sm: 13.00px; /* 13px */ - --font-size-md: 14.00px; /* 14px */ - --font-size-base: 16.00px; /* 16px */ - --font-size-lg: 18.00px; /* 18px */ - --font-size-xl: 20.00px; /* 20px */ - --font-size-2xl: 24.00px; /* 24px */ - --font-size-3xl: 28.00px; /* 28px */ + /* 字号阶梯 —— 正文 16.00px(16px) 起,元信息下限 12.00px(12px) */ + --font-size-micro: 11.00px; /* 11px 仅角标/装饰,禁用于正文 */ + --font-size-xs: 12.00px; /* 12px 元信息下限 */ + --font-size-sm: 13.00px; /* 13px 次要说明 */ + --font-size-md: 14.00px; /* 14px 次要正文 */ + --font-size-base: 16.00px; /* 16px 正文 */ + --font-size-lg: 18.00px; /* 18px 小标题 */ + --font-size-xl: 20.00px; /* 20px 区块标题 */ + --font-size-2xl: 24.00px; /* 24px 页面标题 */ + --font-size-3xl: 28.00px; /* 28px 大标题 */ + --font-size-display: 32.00px; /* 32px Hero */ + /* 字重:只用 4 档。禁止 550/650/750 等非百位值 —— Android 无对应字重会回退, + 导致同一设计在不同机型上粗细不一致(审计发现 30 处)。 */ --font-weight-regular: 400; --font-weight-medium: 500; --font-weight-semibold: 600; @@ -4716,51 +7226,68 @@ --line-height-tight: 1.25; --line-height-normal: 1.5; - --line-height-relaxed: 1.7; + --line-height-relaxed: 1.65; - /* ============ 间距(规范 §12,4px 栅格) ============ */ - --spacing-1: 4.00px; /* 4px */ - --spacing-2: 8.00px; /* 8px */ - --spacing-3: 12.00px; /* 12px */ - --spacing-4: 16.00px; /* 16px */ - --spacing-5: 20.00px; /* 20px */ - --spacing-6: 24.00px; /* 24px */ - --spacing-8: 32.00px; /* 32px */ - --spacing-10: 40.00px; /* 40px */ - --spacing-12: 48.00px; /* 48px */ + --letter-spacing-tight: 0; + --letter-spacing-wide: 0.50px; + --letter-spacing-wider: 1.00px; - --spacing-page-x: 16.00px; /* 页面左右 16px */ - --spacing-section: 24.00px; /* 区块间 24px */ - --spacing-card-inner: 16.00px; /* 卡片内部 16px */ - --spacing-tight: 8.00px; /* 紧密 8px */ + /* ============ 间距(4px 栅格) ============ */ + --spacing-1: 4.00px; + --spacing-2: 8.00px; + --spacing-3: 12.00px; + --spacing-4: 16.00px; + --spacing-5: 20.00px; + --spacing-6: 24.00px; + --spacing-8: 32.00px; + --spacing-10: 40.00px; + --spacing-12: 48.00px; - /* ============ 圆角(规范 §14) ============ */ - --radius-sm: 8.00px; /* 8px */ - --radius-md: 12.00px; /* 12px */ - --radius-lg: 16.00px; /* 16px */ - --radius-xl: 20.00px; /* 20px */ + --spacing-page-x: 16.00px; + --spacing-section: 24.00px; + --spacing-card-inner: 16.00px; + --spacing-tight: 8.00px; + + /* ============ 圆角 ============ */ + --radius-sm: 8.00px; + --radius-md: 12.00px; + --radius-lg: 16.00px; + --radius-xl: 20.00px; + --radius-2xl: 24.00px; --radius-full: 4999.50px; - /* ============ 阴影(规范 §15,极轻) ============ */ - --shadow-card: 0 4.00px 16.00px rgba(0, 0, 0, 0.04); + /* ============ 阴影(统一为一套,此前 30+ 种近似值) ============ */ + --shadow-card: 0 4.00px 14.00px rgba(35, 35, 95, 0.07); + --shadow-raised: 0 6.00px 18.00px rgba(35, 35, 95, 0.10); --shadow-popup: 0 8.00px 32.00px rgba(0, 0, 0, 0.10); + --shadow-night: 0 8.00px 20.00px rgba(28, 30, 88, 0.18); - /* ============ 边框(规范 §16) ============ */ + /* ============ 边框宽度 ============ */ --border-width: 0.50px; + --border-width-strong: 1.00px; - /* ============ 动效(规范 §17) ============ */ + /* ============ 触摸目标(无障碍下限 44×44px) ============ */ + --tap-min: 44.00px; /* 44px 最小可点区域 */ + --tap-comfortable: 48.00px; /* 48px 舒适尺寸:主操作 */ + --tap-gap: 8.00px; /* 8px 相邻目标最小间距 */ + + /* ============ 动效 ============ */ --motion-fast: 120ms; --motion-normal: 200ms; --motion-slow: 300ms; - --ease-standard: ease-out; + --ease-standard: cubic-bezier(0.32, 0.72, 0, 1); + --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1); + --press-scale: 0.97; + --press-opacity: 0.88; - /* ============ 层级 z-index(规范 §90) ============ */ + /* ============ 层级 z-index ============ */ --z-base: 1; --z-sticky: 100; --z-tabbar: 200; --z-dropdown: 500; --z-modal: 1000; --z-toast: 2000; + --z-ambient: 0; /* ============ 页面基础样式 ============ */ background-color: var(--color-bg-page); @@ -4770,7 +7297,10 @@ line-height: var(--line-height-normal); } -/* ============ 通用工具类 ============ */ +/* ========================================================================== + 通用工具类 + ========================================================================== */ + .container { padding: var(--spacing-page-x); } @@ -4784,17 +7314,34 @@ .flex-shrink-0 { flex-shrink: 0; } .wrap { flex-wrap: wrap; } +/* 4 列宫格:用 flex + 百分比宽度实现。 + 注:display:grid 在 WebView 渲染下可用,但 Skyline 不支持,故统一改为 flex 以免疫渲染引擎迁移。*/ +.grid-4 { + display: flex; + flex-wrap: wrap; +} +.grid-4 > .grid-item { + width: 25%; + box-sizing: border-box; +} + +.text-strong { color: var(--color-text-strong); } .text-primary { color: var(--color-text-primary); } .text-secondary { color: var(--color-text-secondary); } .text-tertiary { color: var(--color-text-tertiary); } .text-placeholder { color: var(--color-text-placeholder); } .text-white { color: var(--color-text-inverse); } -.text-brand { color: var(--color-primary); } -.text-success { color: var(--color-success); } -.text-warning { color: var(--color-warning); } -.text-danger { color: var(--color-danger); } -.text-info { color: var(--color-info); } +.text-brand { color: var(--color-primary-strong); } +/* 品牌色作文字只能用 -strong 变体:基础色 #E96B6B 在白底仅 3.10:1。 + 保留 .text-brand-soft 这个类名是为了不破坏既有引用,取值已统一到 -strong, + 如需「更亮的品牌色」请用于背景/图形而非文字。 */ +.text-brand-soft { color: var(--color-primary-strong); } +.text-success { color: var(--color-success-strong); } +.text-warning { color: var(--color-warning-strong); } +.text-danger { color: var(--color-danger-strong); } +.text-info { color: var(--color-info-strong); } +.font-micro { font-size: var(--font-size-micro); } .font-xs { font-size: var(--font-size-xs); } .font-sm { font-size: var(--font-size-sm); } .font-md { font-size: var(--font-size-md); } @@ -4803,6 +7350,7 @@ .font-xl { font-size: var(--font-size-xl); } .font-2xl { font-size: var(--font-size-2xl); } .font-3xl { font-size: var(--font-size-3xl); } +.font-display { font-size: var(--font-size-display); } .font-regular { font-weight: var(--font-weight-regular); } .font-medium { font-weight: var(--font-weight-medium); } @@ -4840,7 +7388,7 @@ padding-bottom: 0px; } -/* 页面卡片基础样式(中低密度留白) */ +/* 页面卡片基础样式 */ .card-base { background: var(--color-bg-card); border-radius: var(--radius-lg); @@ -4854,148 +7402,275 @@ background: var(--color-divider); } -.wx-page{background:var(--color-bg-page)}.service-page{min-height:100vh;padding-bottom:calc(70.00px + 0px)}.hero{padding:22.00px 16.00px 27.00px;background:linear-gradient(140deg,var(--color-primary-lighter),#FFF8EE);position:relative;overflow:hidden}.eyebrow{display:inline-flex;padding:3.50px 7.00px;border-radius:499.50px;background:rgba(255,255,255,.72);color:var(--color-primary);font-size:10.50px}.hero-title{display:block;margin-top:9.00px;font-size:20.00px;font-weight:700;line-height:1.35}.hero-desc{display:block;width:82%;margin-top:7.00px;font-size:12.50px;color:var(--color-text-secondary);line-height:1.7}.content{padding:0 var(--spacing-page-x)}.block{margin-top:var(--spacing-section)}.block-title{display:block;font-size:15.50px;font-weight:650}.block-subtitle{display:block;margin-top:4.00px;font-size:11.50px;color:var(--color-text-tertiary)}.card{margin-top:9.00px;padding:14.00px;background:var(--color-bg-card);border:0.50px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.feature-row,.menu-row,.record-row{display:flex;align-items:center;gap:10.00px;min-height:56.00px;padding:9.00px 0;border-bottom:0.50px solid var(--color-divider)}.feature-row:last-child,.menu-row:last-child,.record-row:last-child{border-bottom:0}.feature-icon{width:36.00px;height:36.00px;display:flex;align-items:center;justify-content:center;flex:none;border-radius:11.00px;background:var(--color-primary-light);color:var(--color-primary);font-weight:700}.feature-copy{flex:1;min-width:0}.feature-title{display:block;font-size:14.00px;font-weight:600}.feature-desc,.meta{display:block;margin-top:3.50px;font-size:11.50px;color:var(--color-text-tertiary);line-height:1.55}.arrow{font-size:20.00px;color:var(--color-text-disabled)}.tag{display:inline-flex;margin-right:5.00px;margin-top:5.00px;padding:3.00px 6.50px;border-radius:499.50px;background:var(--color-success-light);color:var(--color-success);font-size:10.00px}.tag.warning{background:var(--color-warning-light);color:var(--color-warning)}.primary-btn,.secondary-btn{height:44.00px;display:flex;align-items:center;justify-content:center;border-radius:22.00px;font-size:14.00px;font-weight:600}.primary-btn{background:linear-gradient(135deg,var(--mini-accent-coral),var(--mini-accent-pink));color:var(--color-text-inverse);box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)}.primary-btn.disabled{background:#E6E8EF;color:#989DAF;box-shadow:none}.secondary-btn{background:var(--color-primary-light);color:var(--color-primary)}.fixed-action{position:fixed;left:0;right:0;bottom:0;padding:9.00px var(--spacing-page-x) calc(9.00px + 0px);background:rgba(255,255,255,.96);border-top:0.50px solid var(--color-divider);z-index:100}.field{margin-top:13.00px}.label{display:block;margin-bottom:6.00px;font-size:12.50px;font-weight:600}.input,.select-box,.textarea{width:100%;box-sizing:border-box;background:#FCFAF8;border:0.50px solid var(--color-border);border-radius:var(--radius-md);font-size:13.00px}.input,.select-box{height:44.00px;padding:0 12.00px;display:flex;align-items:center}.textarea{min-height:90.00px;padding:11.00px}.notice{margin-top:10.00px;padding:11.00px;border-radius:var(--radius-md);background:#F3F7FC;color:var(--color-text-secondary);font-size:11.50px;line-height:1.65}.empty-panel{text-align:center;padding:35.00px 15.00px}.empty-symbol{width:48.00px;height:48.00px;margin:auto;display:flex;align-items:center;justify-content:center;border-radius:15.00px;background:var(--color-primary-light);color:var(--color-primary);font-size:18.00px;font-weight:700}.empty-title{display:block;margin-top:11.00px;font-size:15.00px;font-weight:600}.article-card{margin-top:9.00px;background:var(--color-bg-card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.article-cover{height:110.00px;padding:12.00px;background:linear-gradient(135deg,#F5E5DE,#F9F1E8);display:flex;align-items:flex-end}.article-cover text{font-size:21.00px;color:rgba(125,76,63,.52);font-weight:700}.article-body{padding:12.00px}.article-title{display:block;font-size:14.50px;font-weight:650;line-height:1.45}.article-meta{display:block;margin-top:5.00px;font-size:11.00px;color:var(--color-text-tertiary)}.article-content{padding:16.00px;background:var(--color-bg-card);font-size:14.00px;line-height:1.9;color:var(--color-text-secondary)}.article-content .lead{display:block;font-size:15.50px;color:var(--color-text-primary);font-weight:600;margin-bottom:12.00px}.danger-card{background:#FFF8F4;border-color:#F5DED2}.danger-card .feature-icon{background:#FFF0EA;color:#C85D43}@media(max-width:340px){.hero-title{font-size:18.00px}.hero-desc{width:92%}} +/* ========================================================================== + 可访问性:只用 token,不用工具类(2026-09-23 修订) + -------------------------------------------------------------------------- + v2 曾在此处新增 .tap-min / .tap-gap / .focusable / .pressable 四个工具类。 + 复检发现全部零引用(等价能力已各自写在组件样式内,例如 button/index.wxss + 直接使用 min-height:var(--tap-min)),且存在两个硬问题: -.service-shell{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:#F4F5FA}.service-content{padding:4.00px 12.00px 18.00px}.service-status{display:flex;align-items:center;justify-content:space-between;margin-top:12.00px;padding:10.00px 12.00px;border-radius:11.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-status__label{color:#7B8198;font-size:10.50px}.service-status__value{padding:3.00px 7.00px;border-radius:9.00px;background:#EAF8F2;color:#329472;font-size:9.50px;font-weight:650}.service-status__value.disabled{background:#FFF0F0;color:#D45A60}.service-topics{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.service-topic{min-height:74.00px;padding:10.00px;border-radius:12.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-topic__icon{display:flex;align-items:center;justify-content:center;width:27.00px;height:27.00px;border-radius:8.50px;background:#FFF0F5}.service-topic__icon image{width:17.00px;height:17.00px}.service-topic__title{display:block;margin-top:6.50px;color:#283056;font-size:12.00px;font-weight:650}.service-topic__desc{display:block;margin-top:3.00px;color:#858A9E;font-size:9.50px;line-height:1.45}.service-actions{display:flex;gap:7.00px}.service-actions .secondary-btn{width:95.00px;flex:none}.service-actions .primary-btn{flex:1}.privacy-note{display:flex;align-items:flex-start;gap:7.00px;margin-top:11.00px;padding:10.00px;border-radius:11.00px;background:#F1F4FF;color:#69718E;font-size:10.00px;line-height:1.55}.privacy-note image{width:17.00px;height:17.00px;flex:none} + 1) `.tap-gap > * + *` 用了通配符与兄弟选择器 —— WXSS 不支持, + wcc 编译期直接报 `error at token '*'`,导致整个小程序编译失败。 + (这是编译错误,不是静默失效,代价最高。) + 2) `.pressable:active` / `.focusable:focus-visible` 的伪类在 view 上 + 不生效(小程序须用 hover-class),属于"写了等于没写"。 + + 故整块移除,保留 token。需要热区/间距时直接引用 token: + min-height: var(--tap-min); → 44.00px = 44px,最小可点区域 + gap: var(--tap-gap); → 8.00px = 8px,相邻目标间距(flex gap) + 【WXSS 禁用清单】星号通配符、兄弟选择器、属性选择器。 + 【注释约束】WXSS 注释**不可嵌套**:内层注释的结束标记会提前终止外层注释, + 其后的文字会被当成真实样式解析,导致编译失败或样式被污染。 + (2026-09-23 实证:本块注释初版即踩此坑。) + ========================================================================== */ + +.wx-page{background:var(--color-bg-page)}.service-page{min-height:100vh;padding-bottom:calc(70.00px + 0px)}.hero{padding:22.00px 16.00px 27.00px;background:linear-gradient(140deg,var(--color-primary-lighter),var(--color-warning-light));position:relative;overflow:hidden}.eyebrow{display:inline-flex;padding:3.50px 7.00px;border-radius:499.50px;background:rgba(255,255,255,.72);color:var(--color-primary-strong);font-size:12.00px}.hero-title{display:block;margin-top:9.00px;font-size:20.00px;font-weight:700;line-height:1.35}.hero-desc{display:block;width:82%;margin-top:7.00px;font-size:12.50px;color:var(--color-text-secondary);line-height:1.7}.content{padding:0 var(--spacing-page-x)}.block{margin-top:var(--spacing-section)}.block-title{display:block;font-size:15.50px;font-weight:600}.block-subtitle{display:block;margin-top:4.00px;font-size:12.00px;color:var(--color-text-tertiary)}.card{margin-top:9.00px;padding:14.00px;background:var(--color-bg-card);border:0.50px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.feature-row,.menu-row,.record-row{display:flex;align-items:center;gap:10.00px;min-height:56.00px;padding:9.00px 0;border-bottom:0.50px solid var(--color-divider)}.feature-row:last-child,.menu-row:last-child,.record-row:last-child{border-bottom:0}.feature-icon{width:36.00px;height:36.00px;display:flex;align-items:center;justify-content:center;flex:none;border-radius:11.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-weight:700}.feature-copy{flex:1;min-width:0}.feature-title{display:block;font-size:14.00px;font-weight:600}.feature-desc,.meta{display:block;margin-top:3.50px;font-size:12.00px;color:var(--color-text-tertiary);line-height:1.55}.arrow{font-size:20.00px;color:var(--color-text-disabled)}.tag{display:inline-flex;margin-right:5.00px;margin-top:5.00px;padding:3.00px 6.50px;border-radius:499.50px;background:var(--color-success-light);color:var(--color-success-strong);font-size:12.00px}.tag.warning{background:var(--color-warning-light);color:var(--color-warning-strong)}.primary-btn,.secondary-btn{height:44.00px;display:flex;align-items:center;justify-content:center;border-radius:22.00px;font-size:14.00px;font-weight:600}.primary-btn{background:var(--gradient-brand-solid);color:var(--color-text-inverse);box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)}.primary-btn.disabled{background:var(--color-bg-muted);color:var(--color-text-tertiary);box-shadow:none}.secondary-btn{background:var(--color-primary-light);color:var(--color-primary-strong)}.fixed-action{position:fixed;left:0;right:0;bottom:0;padding:9.00px var(--spacing-page-x) calc(9.00px + 0px);background:rgba(255,255,255,.96);border-top:0.50px solid var(--color-divider);z-index:100}.field{margin-top:13.00px}.label{display:block;margin-bottom:6.00px;font-size:12.50px;font-weight:600}.input,.select-box,.textarea{width:100%;box-sizing:border-box;background:var(--color-bg-page);border:0.50px solid var(--color-border);border-radius:var(--radius-md);font-size:13.00px}.input,.select-box{height:44.00px;padding:0 12.00px;display:flex;align-items:center}.textarea{min-height:90.00px;padding:11.00px}.notice{margin-top:10.00px;padding:11.00px;border-radius:var(--radius-md);background:var(--color-info-light);color:var(--color-text-secondary);font-size:12.00px;line-height:1.65}.select-box.is-readonly{background:var(--color-bg-subtle);color:var(--color-text-secondary)}.empty-panel{text-align:center;padding:35.00px 15.00px}.empty-symbol{width:48.00px;height:48.00px;margin:auto;display:flex;align-items:center;justify-content:center;border-radius:15.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-size:18.00px;font-weight:700}.empty-title{display:block;margin-top:11.00px;font-size:15.00px;font-weight:600}.article-card{margin-top:9.00px;background:var(--color-bg-card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.article-cover{height:110.00px;padding:12.00px;background:linear-gradient(135deg,var(--color-warning-light),var(--color-warning-light));display:flex;align-items:flex-end}.article-cover text{font-size:21.00px;color:rgba(125,76,63,.52);font-weight:700}.article-body{padding:12.00px}.article-title{display:block;font-size:14.50px;font-weight:600;line-height:1.45}.article-meta{display:block;margin-top:5.00px;font-size:12.00px;color:var(--color-text-tertiary)}.article-content{padding:16.00px;background:var(--color-bg-card);font-size:14.00px;line-height:1.9;color:var(--color-text-secondary)}.article-content .lead{display:block;font-size:15.50px;color:var(--color-text-primary);font-weight:600;margin-bottom:12.00px}.danger-card{background:var(--color-primary-lighter);border-color:var(--color-primary-light)}.danger-card .feature-icon{background:var(--color-warning-light);color:var(--color-warning-strong)}@media(max-width:340px){.hero-title{font-size:18.00px}.hero-desc{width:92%}} + +.service-shell{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:var(--color-bg-page)}.service-content{padding:4.00px 12.00px 18.00px}.service-status{display:flex;align-items:center;justify-content:space-between;margin-top:12.00px;padding:10.00px 12.00px;border-radius:11.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-status__label{color:var(--color-text-tertiary);font-size:12.00px}.service-status__value{padding:3.00px 7.00px;border-radius:9.00px;background:var(--color-success-light);color:var(--color-success-strong);font-size:12.00px;font-weight:600}.service-status__value.disabled{background:var(--color-danger-light);color:var(--color-danger-strong)}.service-topics{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.service-topic{min-height:74.00px;padding:10.00px;border-radius:12.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-topic__icon{display:flex;align-items:center;justify-content:center;width:27.00px;height:27.00px;border-radius:8.50px;background:var(--color-primary-light)}.service-topic__icon image{width:17.00px;height:17.00px}.service-topic__title{display:block;margin-top:6.50px;color:var(--color-text-strong);font-size:12.00px;font-weight:600}.service-topic__desc{display:block;margin-top:3.00px;color:var(--color-text-tertiary);font-size:12.00px;line-height:1.45}.service-actions{display:flex;gap:7.00px}.service-actions .secondary-btn{width:95.00px;flex:none}.service-actions .primary-btn{flex:1}.privacy-note{display:flex;align-items:flex-start;gap:7.00px;margin-top:11.00px;padding:10.00px;border-radius:11.00px;background:var(--color-info-light);color:var(--color-text-tertiary);font-size:12.00px;line-height:1.55}.privacy-note image{width:17.00px;height:17.00px;flex:none} /* ==== miniapp/components/service-hero ==== */ .service-hero { - position: relative; - height: 150.00px; - overflow: hidden; - border-radius: 0 0 16.00px 16.00px; - background: #fff4f7; + position:relative; + height:150.00px; + overflow:hidden; + border-radius:0 0 16.00px 16.00px; + background:var(--color-primary-light); } .service-hero__image, .service-hero__veil { - position: absolute; - inset: 0; - width: 100%; - height: 100%; + position:absolute; + inset:0; + width:100%; + height:100%; } .service-hero__veil { - background: linear-gradient(90deg, rgba(255, 250, 252, 0.98) 0%, rgba(255, 250, 252, 0.82) 38%, rgba(255, 250, 252, 0.08) 70%); + background:linear-gradient(90deg, rgba(255, 250, 252, 0.98) 0%, rgba(255, 250, 252, 0.82) 38%, rgba(255, 250, 252, 0.08) 70%); } .service-hero--night .service-hero__veil { - background: linear-gradient(90deg, rgba(18, 24, 83, 0.92) 0%, rgba(34, 31, 111, 0.64) 42%, rgba(34, 31, 111, 0.08) 72%); + background:linear-gradient(90deg, rgba(18, 24, 83, 0.92) 0%, rgba(34, 31, 111, 0.64) 42%, rgba(34, 31, 111, 0.08) 72%); } .service-hero__content { - position: relative; - z-index: 1; - display: flex; - flex-direction: column; - justify-content: center; - width: 54%; - height: 100%; - padding: 0 18.00px; - box-sizing: border-box; + position:relative; + z-index:1; + display:flex; + flex-direction:column; + justify-content:center; + width:54%; + height:100%; + padding:0 18.00px; + box-sizing:border-box; } .service-hero__eyebrow { - margin-bottom: 5.00px; - color: var(--color-primary); - font-size: 11.00px; - font-weight: 600; - letter-spacing: 1.00px; + margin-bottom:5.00px; + color:var(--color-primary-strong); + font-size:12.00px; + font-weight:600; + letter-spacing:1.00px; } .service-hero__title { - color: #24305e; - font-size: 20.00px; - font-weight: 700; - line-height: 1.28; + color:var(--color-text-strong); + font-size:20.00px; + font-weight:700; + line-height:1.28; } .service-hero__subtitle { - margin-top: 7.00px; - color: #737c96; - font-size: 12.00px; - line-height: 1.55; + margin-top:7.00px; + color:var(--color-text-tertiary); + font-size:12.00px; + line-height:1.55; } .service-hero--night .service-hero__eyebrow, .service-hero--night .service-hero__title, .service-hero--night .service-hero__subtitle { - color: #ffffff; + color:var(--color-text-inverse); } @import "../../styles/service-page.wxss"; -.risk-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.risk-card{display:flex;min-height:87.00px;flex-direction:column;padding:10.00px;border:0.50px solid #F7DCE2;border-radius:12.00px;background:#FFF9FA}.risk-card image{width:21.00px;height:21.00px}.risk-title{margin-top:5.00px;color:#9E4054;font-size:11.50px;font-weight:650}.risk-desc{margin-top:3.50px;color:#846F78;font-size:9.00px;line-height:1.5}.safety-steps{overflow:hidden;margin-top:9.00px;border-radius:12.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.safety-step{display:flex;align-items:center;gap:8.00px;min-height:52.00px;padding:8.00px 10.00px;border-bottom:0.50px solid #EFF0F5}.safety-step:last-child{border-bottom:0}.safety-step>image{width:24.00px;height:24.00px;flex:none}.safety-step>view{display:flex;flex:1;flex-direction:column}.safety-step view text:first-child{color:#303654;font-size:11.50px;font-weight:650}.safety-step view text:last-child{margin-top:2.50px;color:#858A9E;font-size:9.50px;line-height:1.45} +.risk-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.risk-card{display:flex;min-height:87.00px;flex-direction:column;padding:10.00px;border:0.50px solid var(--color-primary-light);border-radius:12.00px;background:var(--color-bg-page)}.risk-card image{width:21.00px;height:21.00px}.risk-title{margin-top:5.00px;color:var(--color-primary-strong);font-size:12.00px;font-weight:600}.risk-desc{margin-top:3.50px;color:var(--color-text-tertiary);font-size:12.00px;line-height:1.5}.safety-steps{overflow:hidden;margin-top:9.00px;border-radius:12.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.safety-step{display:flex;align-items:center;gap:8.00px;min-height:52.00px;padding:8.00px 10.00px;border-bottom:0.50px solid var(--color-divider)}.safety-step:last-child{border-bottom:0}.safety-step>image{width:24.00px;height:24.00px;flex:none}.safety-step>view{display:flex;flex:1;flex-direction:column}.safety-step view text:first-child{color:var(--color-text-strong);font-size:12.00px;font-weight:600}.safety-step view text:last-child{margin-top:2.50px;color:var(--color-text-tertiary);font-size:12.00px;line-height:1.45} /** * 丹阳公益婚恋服务平台 - 全局 Design Token * - * 依据《前端组件库与 Design Token 规范 V1.0》 - * 单位说明:rpx(375.00px = 屏幕宽度),规范 px 值按 2x 映射为 rpx - * 禁止页面层写死颜色/间距/圆角,必须引用 var(--token) + * v2(2026-09-22 设计系统夯实) + * --------------------------------------------------------------- + * 本次修订针对审计发现的系统性问题,逐条给出依据: + * + * 1) 品牌色不能承载文字 → 引入「基础色 / -strong」分级 + * #E96B6B on 白 = 3.10:1,白字 on #E96B6B = 3.10:1,on #FFF3F2 = 2.85:1, + * 三条路径都不满足正文 4.5:1。故: + * --color-primary 仅用于大色块、渐变、光晕、装饰(非文字) + * --color-primary-strong 用于文字、小图标、纯文字链接(5.33:1 ✓) + * --color-primary-solid 实心按钮底(白字 ≥4.5:1 ✓) + * 功能色(success/warning/danger/info)同此分级。 + * + * 2) 次要文字对比度过低 + * 旧 --color-text-tertiary(#777) = 4.48(on 白,勉强)/ #999 实测 2.85 却被用了 71 次。 + * 现将三级文字压到 #646C85 = 5.22:1,占位符保留浅色(占位符非正文)。 + * + * 3) 颜色碎片化 + * 审计前全站 182 种 hex、770 次硬编码(54 种灰、60 种蓝紫、40 种红橙)。 + * 本文件是唯一的颜色事实源;页面层禁止再写 hex,一律 var(--token)。 + * + * 4) 触摸目标 + * 组件库默认按钮只有 40px、小号 28px、"喜欢"按钮 31px。 + * 统一以 --tap-min(44.00px=44px) 为下限,--tap-gap 为最小间距。 + * + * 5) 动效几乎未落地(--motion-* 全站仅 5 次引用) + * 补充 --ease-spring 与 --press-scale,让点击有即时反馈。 + * + * 6) 夜间氛围层缺失(参考图有明显的光晕/星点,代码只有纯渐变) + * 新增 --mini-glow-* / --mini-star / --mini-glass / --mini-hairline。 + * + * 单位说明:rpx(375.00px = 屏幕宽度,0.50px ≈ 0.5px @375pt) + * 旧 token 名全部保留(88 个 wxss 共 909 处引用),只更新取值,避免大范围失效。 */ .wx-page { - /* ============ 品牌主色(规范 §3) ============ */ - --color-primary: #E96B6B; - --color-primary-active: #D95F5F; + /* ============ 品牌主色(分级:色块 / 文字 / 实心按钮) ============ */ + --color-primary: #E96B6B; /* 基础色:渐变、光晕、装饰、非文字图形 */ + --color-primary-strong: #B8434A; /* 文字与小图标(5.33:1 on 白,4.91:1 on 浅粉底) */ + --color-primary-solid: #C24C50; /* 实心按钮底(白字 4.62:1) */ + --color-primary-active: #D95F5F; /* 按压态(配合 --color-primary 使用) */ --color-primary-light: #FFF3F2; --color-primary-lighter: #FFF8F7; - /* ============ 小程序参考图品牌主题 ============ */ + /* ============ 小程序参考图品牌主题(夜间紫蓝) ============ */ --mini-night-start: #172A72; --mini-night-end: #25104F; --mini-night-soft: #3445A1; - --mini-accent-pink: #FF4F91; + --mini-accent-pink: #FF4F91; /* 点缀色:仅用于色块/装饰,不作正文 */ --mini-accent-coral: #FF6A78; --mini-card-bg: rgba(255, 255, 255, 0.98); --mini-text: #1F2744; --mini-muted: #7D839B; --mini-card-radius: 12.00px; - --mini-text-on-night: #FFFFFF; - --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); + --mini-text-on-night: #FFFFFF; /* on 深底 13.04:1 ✓ */ + --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); /* on 深底 ≈8:1 ✓ */ --mini-shadow: 0 8.00px 20.00px rgba(28, 30, 88, 0.14); - /* ============ 功能色(规范 §4) ============ */ - --color-success: #2E9B68; + /* ---- 渐变(集中定义:此前 4 个页面各写了一份「橙红渐变」按钮) ---- */ + /* --gradient-brand 明亮活泼,但白字仅 2.77:1 —— 只能用于无文字的装饰填充。 */ + --gradient-brand: linear-gradient(135deg, #FF6A78 0%, #E96B6B 100%); + /* 承载白字的 CTA 渐变:两端 #C24C50(4.73:1) / #B8434A(5.33:1) 均达标。 */ + --gradient-brand-solid: linear-gradient(135deg, #C24C50 0%, #B8434A 100%); + --gradient-night: linear-gradient(160deg, #172A72 0%, #25104F 100%); + --gradient-night-soft: linear-gradient(160deg, #3445A1 0%, #172A72 100%); + + /* ---- 首页 4×2 入口宫格图标渐变(参考图 2:高饱和圆角砖 + 白色描画图标) ---- + 白图标的对比度判据是**非文本图形 3:1**(WCAG 1.4.11)。渐变是斜向的、图标又跨在 + 两色之间,所以**较亮的一端也必须达标** —— 下表注释给的是 0% 处实算值,100% 更暗只会更高。 + 色相按业务语义固定(不随 tone 名漂移):找对象/婚前辅导=玫瑰粉系、公益红娘/服务站=暖橙系、 + 公益活动=紫罗兰、婚恋咨询=蓝、婚恋课堂=紫、婚恋反诈=绿。 */ + --gradient-entry-rose: linear-gradient(135deg, #F56287 0%, #F34671 100%); /* 3.01:1 / 3.54:1 */ + --gradient-entry-orange: linear-gradient(135deg, #F66A06 0%, #D95E06 100%); /* 3.01:1 / 3.78:1 */ + --gradient-entry-violet: linear-gradient(135deg, #A380F5 0%, #8F64F2 100%); /* 3.02:1 / 3.98:1 */ + --gradient-entry-blue: linear-gradient(135deg, #5195F6 0%, #3484F4 100%); /* 3.01:1 / 3.65:1 */ + --gradient-entry-purple: linear-gradient(135deg, #B27BF0 0%, #A260ED 100%); /* 3.01:1 / 3.87:1 */ + --gradient-entry-pink: linear-gradient(135deg, #F2619E 0%, #F0458C 100%); /* 3.01:1 / 3.54:1 */ + --gradient-entry-green: linear-gradient(135deg, #18A979 0%, #148F66 100%); /* 3.00:1 / 4.08:1 */ + --gradient-entry-amber: linear-gradient(135deg, #E9740C 0%, #CC650B 100%); /* 3.01:1 / 3.86:1 */ + /* 图标砖落影:比 --mini-shadow 更小,避免 4 列宫格里相邻砖块的投影互相压边 */ + --mini-entry-shadow: 0 4.00px 9.00px rgba(28, 30, 88, 0.18); + + /* ---- 夜间氛围层(v2 新增;参考图有光晕与星点,此前完全没有) ---- */ + --mini-glow-coral: rgba(255, 79, 145, 0.40); + --mini-glow-indigo: rgba(94, 124, 255, 0.32); + --mini-glow-soft: rgba(255, 255, 255, 0.10); + --mini-star: rgba(255, 255, 255, 0.70); + --mini-glass: rgba(255, 255, 255, 0.10); /* 深底玻璃面 */ + --mini-glass-strong: rgba(255, 255, 255, 0.16); + --mini-hairline: rgba(255, 255, 255, 0.16); /* 深底分隔线 */ + --mini-glass-success: rgba(90, 226, 184, 0.16); /* 深底上的成功态玻璃面 */ + + /* 星点层:多个小径向渐变叠在夜空渐变之上。用 radial-gradient 而非图片, + 避免额外请求,也便于随主题换色(index 页脚注:装饰层不承载信息)。 */ + --mini-starfield: + radial-gradient(circle at 12% 18%, var(--mini-star) 0, transparent 1.25px), + radial-gradient(circle at 31% 66%, var(--mini-star) 0, transparent 1.00px), + radial-gradient(circle at 57% 12%, var(--mini-star) 0, transparent 1.00px), + radial-gradient(circle at 79% 52%, var(--mini-star) 0, transparent 1.50px), + radial-gradient(circle at 93% 84%, var(--mini-star) 0, transparent 1.00px); + + /* 横幅压暗层:保证任何底图上的白色标题都有足够对比度 */ + --mini-banner-scrim: linear-gradient(90deg, rgba(23, 42, 114, 0.84) 0%, rgba(37, 16, 79, 0.40) 56%, rgba(255, 79, 145, 0.12) 100%); + + /* ============ 功能色(同样分级) ============ */ + --color-success: #2E9B68; /* 色块/图标 */ + --color-success-strong: #17805A; /* 文字(4.92:1 ✓) */ --color-success-light: #ECF8F2; - --color-warning: #E59A32; + --color-warning: #E59A32; /* 色块/图标(作文字仅 2.33:1) */ + --color-warning-strong: #9C5F14; /* 文字(5.17:1 ✓) */ --color-warning-light: #FFF7E9; - --color-danger: #D94A4A; + --color-danger: #D94A4A; /* 色块/图标 */ + --color-danger-strong: #C62828; /* 文字(5.62:1 ✓) */ --color-danger-light: #FFF0F0; - --color-info: #4A7CD4; + --color-info: #4A7CD4; /* 色块/图标 */ + --color-info-strong: #2A5DB0; /* 文字(6.38:1 ✓) */ --color-info-light: #EEF4FF; - /* ============ 中性色(规范 §5-6) ============ */ - --color-text-primary: #222222; - --color-text-secondary: #444444; - --color-text-tertiary: #777777; - --color-text-placeholder: #999999; - --color-text-disabled: #B5B5B5; - --color-text-inverse: #FFFFFF; /* 用于 primary/success 等深色背景上的文字 */ + /* ============ 强调紫(参考图的标签语言;此前散落成 6 种写法) ============ */ + --color-accent-purple: #8B63BC; /* 色块/装饰 */ + --color-accent-purple-strong: #7C60BC; /* 文字(5.03:1 ✓) */ + --color-accent-purple-light: #F3EEFF; - --color-border: #EEEEEE; - --color-divider: #F0F0F0; - --color-border-focus: #E96B6B; - --color-border-error: #D94A4A; + /* 深色夜空底上的强调色(不可用于浅色底) */ + --color-success-on-night: #A6F5D7; /* on #172A72 = 10.35:1 ✓ */ - --color-bg-page: #FAFAF8; + /* ============ 文字色(实测对比度 on 白 / on 页面底) ============ */ + --color-text-strong: #1A1F36; /* 标题 16.24 / 14.90 ✓ */ + --color-text-primary: #2A3050; /* 正文 12.83 / 11.77 ✓ */ + --color-text-secondary: #4A5169; /* 次要正文 7.86 / 7.21 ✓ */ + --color-text-tertiary: #646C85; /* 说明文字 5.22 / 4.79 ✓(旧 #777 为 4.48) */ + --color-text-placeholder: #9AA1B4; /* 占位符(非正文,可浅) */ + --color-text-disabled: #B8BDC9; + --color-text-inverse: #FFFFFF; /* 深色背景上的文字 */ + + /* ============ 边框与分割线 ============ */ + --color-border: #E6E8EF; + --color-border-strong: #D8DBE5; + --color-divider: #EFF0F5; + --color-border-focus: #B8434A; /* 焦点环用 strong,保证 3:1 可见度 */ + --color-border-error: #C62828; + + /* ============ 背景(避免纯白/纯灰平铺,页面底为暖白) ============ */ + --color-bg-page: #F6F5F3; --color-bg-card: #FFFFFF; - --color-bg-disabled: #F3F3F3; + --color-bg-subtle: #F5F6FA; /* 次级区块、内嵌列表 */ + --color-bg-muted: #EEF0F6; /* 更弱的填充 */ + --color-bg-input: #F7F8FB; /* 表单输入框底(此前被引用但从未定义,导致背景失效) */ + --color-bg-disabled: #F3F4F7; --color-bg-overlay: rgba(0, 0, 0, 0.45); - /* ============ 字体(规范 §7-11) ============ */ + /* ============ 字体 ============ */ + /* 小程序无法可靠加载 Web Font(wx.loadFontFace 依赖 HTTPS 白名单且有闪动风险), + 故使用中文系统字栈:iOS 走苹方、Android 走思源/系统黑体。 + 排版辨识度靠字号阶梯与字重建立,而非依赖字体本身。 */ --font-family-cn: -apple-system, "PingFang SC", "Noto Sans SC", "Hiragino Sans GB", "Microsoft YaHei", system-ui, sans-serif; + --font-family-number: "SF Pro Display", -apple-system, "DIN Alternate", "PingFang SC", sans-serif; - --font-size-xs: 12.00px; /* 12px */ - --font-size-sm: 13.00px; /* 13px */ - --font-size-md: 14.00px; /* 14px */ - --font-size-base: 16.00px; /* 16px */ - --font-size-lg: 18.00px; /* 18px */ - --font-size-xl: 20.00px; /* 20px */ - --font-size-2xl: 24.00px; /* 24px */ - --font-size-3xl: 28.00px; /* 28px */ + /* 字号阶梯 —— 正文 16.00px(16px) 起,元信息下限 12.00px(12px) */ + --font-size-micro: 11.00px; /* 11px 仅角标/装饰,禁用于正文 */ + --font-size-xs: 12.00px; /* 12px 元信息下限 */ + --font-size-sm: 13.00px; /* 13px 次要说明 */ + --font-size-md: 14.00px; /* 14px 次要正文 */ + --font-size-base: 16.00px; /* 16px 正文 */ + --font-size-lg: 18.00px; /* 18px 小标题 */ + --font-size-xl: 20.00px; /* 20px 区块标题 */ + --font-size-2xl: 24.00px; /* 24px 页面标题 */ + --font-size-3xl: 28.00px; /* 28px 大标题 */ + --font-size-display: 32.00px; /* 32px Hero */ + /* 字重:只用 4 档。禁止 550/650/750 等非百位值 —— Android 无对应字重会回退, + 导致同一设计在不同机型上粗细不一致(审计发现 30 处)。 */ --font-weight-regular: 400; --font-weight-medium: 500; --font-weight-semibold: 600; @@ -5003,51 +7678,68 @@ --line-height-tight: 1.25; --line-height-normal: 1.5; - --line-height-relaxed: 1.7; + --line-height-relaxed: 1.65; - /* ============ 间距(规范 §12,4px 栅格) ============ */ - --spacing-1: 4.00px; /* 4px */ - --spacing-2: 8.00px; /* 8px */ - --spacing-3: 12.00px; /* 12px */ - --spacing-4: 16.00px; /* 16px */ - --spacing-5: 20.00px; /* 20px */ - --spacing-6: 24.00px; /* 24px */ - --spacing-8: 32.00px; /* 32px */ - --spacing-10: 40.00px; /* 40px */ - --spacing-12: 48.00px; /* 48px */ + --letter-spacing-tight: 0; + --letter-spacing-wide: 0.50px; + --letter-spacing-wider: 1.00px; - --spacing-page-x: 16.00px; /* 页面左右 16px */ - --spacing-section: 24.00px; /* 区块间 24px */ - --spacing-card-inner: 16.00px; /* 卡片内部 16px */ - --spacing-tight: 8.00px; /* 紧密 8px */ + /* ============ 间距(4px 栅格) ============ */ + --spacing-1: 4.00px; + --spacing-2: 8.00px; + --spacing-3: 12.00px; + --spacing-4: 16.00px; + --spacing-5: 20.00px; + --spacing-6: 24.00px; + --spacing-8: 32.00px; + --spacing-10: 40.00px; + --spacing-12: 48.00px; - /* ============ 圆角(规范 §14) ============ */ - --radius-sm: 8.00px; /* 8px */ - --radius-md: 12.00px; /* 12px */ - --radius-lg: 16.00px; /* 16px */ - --radius-xl: 20.00px; /* 20px */ + --spacing-page-x: 16.00px; + --spacing-section: 24.00px; + --spacing-card-inner: 16.00px; + --spacing-tight: 8.00px; + + /* ============ 圆角 ============ */ + --radius-sm: 8.00px; + --radius-md: 12.00px; + --radius-lg: 16.00px; + --radius-xl: 20.00px; + --radius-2xl: 24.00px; --radius-full: 4999.50px; - /* ============ 阴影(规范 §15,极轻) ============ */ - --shadow-card: 0 4.00px 16.00px rgba(0, 0, 0, 0.04); + /* ============ 阴影(统一为一套,此前 30+ 种近似值) ============ */ + --shadow-card: 0 4.00px 14.00px rgba(35, 35, 95, 0.07); + --shadow-raised: 0 6.00px 18.00px rgba(35, 35, 95, 0.10); --shadow-popup: 0 8.00px 32.00px rgba(0, 0, 0, 0.10); + --shadow-night: 0 8.00px 20.00px rgba(28, 30, 88, 0.18); - /* ============ 边框(规范 §16) ============ */ + /* ============ 边框宽度 ============ */ --border-width: 0.50px; + --border-width-strong: 1.00px; - /* ============ 动效(规范 §17) ============ */ + /* ============ 触摸目标(无障碍下限 44×44px) ============ */ + --tap-min: 44.00px; /* 44px 最小可点区域 */ + --tap-comfortable: 48.00px; /* 48px 舒适尺寸:主操作 */ + --tap-gap: 8.00px; /* 8px 相邻目标最小间距 */ + + /* ============ 动效 ============ */ --motion-fast: 120ms; --motion-normal: 200ms; --motion-slow: 300ms; - --ease-standard: ease-out; + --ease-standard: cubic-bezier(0.32, 0.72, 0, 1); + --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1); + --press-scale: 0.97; + --press-opacity: 0.88; - /* ============ 层级 z-index(规范 §90) ============ */ + /* ============ 层级 z-index ============ */ --z-base: 1; --z-sticky: 100; --z-tabbar: 200; --z-dropdown: 500; --z-modal: 1000; --z-toast: 2000; + --z-ambient: 0; /* ============ 页面基础样式 ============ */ background-color: var(--color-bg-page); @@ -5057,7 +7749,10 @@ line-height: var(--line-height-normal); } -/* ============ 通用工具类 ============ */ +/* ========================================================================== + 通用工具类 + ========================================================================== */ + .container { padding: var(--spacing-page-x); } @@ -5071,17 +7766,34 @@ .flex-shrink-0 { flex-shrink: 0; } .wrap { flex-wrap: wrap; } +/* 4 列宫格:用 flex + 百分比宽度实现。 + 注:display:grid 在 WebView 渲染下可用,但 Skyline 不支持,故统一改为 flex 以免疫渲染引擎迁移。*/ +.grid-4 { + display: flex; + flex-wrap: wrap; +} +.grid-4 > .grid-item { + width: 25%; + box-sizing: border-box; +} + +.text-strong { color: var(--color-text-strong); } .text-primary { color: var(--color-text-primary); } .text-secondary { color: var(--color-text-secondary); } .text-tertiary { color: var(--color-text-tertiary); } .text-placeholder { color: var(--color-text-placeholder); } .text-white { color: var(--color-text-inverse); } -.text-brand { color: var(--color-primary); } -.text-success { color: var(--color-success); } -.text-warning { color: var(--color-warning); } -.text-danger { color: var(--color-danger); } -.text-info { color: var(--color-info); } +.text-brand { color: var(--color-primary-strong); } +/* 品牌色作文字只能用 -strong 变体:基础色 #E96B6B 在白底仅 3.10:1。 + 保留 .text-brand-soft 这个类名是为了不破坏既有引用,取值已统一到 -strong, + 如需「更亮的品牌色」请用于背景/图形而非文字。 */ +.text-brand-soft { color: var(--color-primary-strong); } +.text-success { color: var(--color-success-strong); } +.text-warning { color: var(--color-warning-strong); } +.text-danger { color: var(--color-danger-strong); } +.text-info { color: var(--color-info-strong); } +.font-micro { font-size: var(--font-size-micro); } .font-xs { font-size: var(--font-size-xs); } .font-sm { font-size: var(--font-size-sm); } .font-md { font-size: var(--font-size-md); } @@ -5090,6 +7802,7 @@ .font-xl { font-size: var(--font-size-xl); } .font-2xl { font-size: var(--font-size-2xl); } .font-3xl { font-size: var(--font-size-3xl); } +.font-display { font-size: var(--font-size-display); } .font-regular { font-weight: var(--font-weight-regular); } .font-medium { font-weight: var(--font-weight-medium); } @@ -5127,7 +7840,7 @@ padding-bottom: 0px; } -/* 页面卡片基础样式(中低密度留白) */ +/* 页面卡片基础样式 */ .card-base { background: var(--color-bg-card); border-radius: var(--radius-lg); @@ -5141,280 +7854,309 @@ background: var(--color-divider); } -.wx-page{background:var(--color-bg-page)}.service-page{min-height:100vh;padding-bottom:calc(70.00px + 0px)}.hero{padding:22.00px 16.00px 27.00px;background:linear-gradient(140deg,var(--color-primary-lighter),#FFF8EE);position:relative;overflow:hidden}.eyebrow{display:inline-flex;padding:3.50px 7.00px;border-radius:499.50px;background:rgba(255,255,255,.72);color:var(--color-primary);font-size:10.50px}.hero-title{display:block;margin-top:9.00px;font-size:20.00px;font-weight:700;line-height:1.35}.hero-desc{display:block;width:82%;margin-top:7.00px;font-size:12.50px;color:var(--color-text-secondary);line-height:1.7}.content{padding:0 var(--spacing-page-x)}.block{margin-top:var(--spacing-section)}.block-title{display:block;font-size:15.50px;font-weight:650}.block-subtitle{display:block;margin-top:4.00px;font-size:11.50px;color:var(--color-text-tertiary)}.card{margin-top:9.00px;padding:14.00px;background:var(--color-bg-card);border:0.50px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.feature-row,.menu-row,.record-row{display:flex;align-items:center;gap:10.00px;min-height:56.00px;padding:9.00px 0;border-bottom:0.50px solid var(--color-divider)}.feature-row:last-child,.menu-row:last-child,.record-row:last-child{border-bottom:0}.feature-icon{width:36.00px;height:36.00px;display:flex;align-items:center;justify-content:center;flex:none;border-radius:11.00px;background:var(--color-primary-light);color:var(--color-primary);font-weight:700}.feature-copy{flex:1;min-width:0}.feature-title{display:block;font-size:14.00px;font-weight:600}.feature-desc,.meta{display:block;margin-top:3.50px;font-size:11.50px;color:var(--color-text-tertiary);line-height:1.55}.arrow{font-size:20.00px;color:var(--color-text-disabled)}.tag{display:inline-flex;margin-right:5.00px;margin-top:5.00px;padding:3.00px 6.50px;border-radius:499.50px;background:var(--color-success-light);color:var(--color-success);font-size:10.00px}.tag.warning{background:var(--color-warning-light);color:var(--color-warning)}.primary-btn,.secondary-btn{height:44.00px;display:flex;align-items:center;justify-content:center;border-radius:22.00px;font-size:14.00px;font-weight:600}.primary-btn{background:linear-gradient(135deg,var(--mini-accent-coral),var(--mini-accent-pink));color:var(--color-text-inverse);box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)}.primary-btn.disabled{background:#E6E8EF;color:#989DAF;box-shadow:none}.secondary-btn{background:var(--color-primary-light);color:var(--color-primary)}.fixed-action{position:fixed;left:0;right:0;bottom:0;padding:9.00px var(--spacing-page-x) calc(9.00px + 0px);background:rgba(255,255,255,.96);border-top:0.50px solid var(--color-divider);z-index:100}.field{margin-top:13.00px}.label{display:block;margin-bottom:6.00px;font-size:12.50px;font-weight:600}.input,.select-box,.textarea{width:100%;box-sizing:border-box;background:#FCFAF8;border:0.50px solid var(--color-border);border-radius:var(--radius-md);font-size:13.00px}.input,.select-box{height:44.00px;padding:0 12.00px;display:flex;align-items:center}.textarea{min-height:90.00px;padding:11.00px}.notice{margin-top:10.00px;padding:11.00px;border-radius:var(--radius-md);background:#F3F7FC;color:var(--color-text-secondary);font-size:11.50px;line-height:1.65}.empty-panel{text-align:center;padding:35.00px 15.00px}.empty-symbol{width:48.00px;height:48.00px;margin:auto;display:flex;align-items:center;justify-content:center;border-radius:15.00px;background:var(--color-primary-light);color:var(--color-primary);font-size:18.00px;font-weight:700}.empty-title{display:block;margin-top:11.00px;font-size:15.00px;font-weight:600}.article-card{margin-top:9.00px;background:var(--color-bg-card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.article-cover{height:110.00px;padding:12.00px;background:linear-gradient(135deg,#F5E5DE,#F9F1E8);display:flex;align-items:flex-end}.article-cover text{font-size:21.00px;color:rgba(125,76,63,.52);font-weight:700}.article-body{padding:12.00px}.article-title{display:block;font-size:14.50px;font-weight:650;line-height:1.45}.article-meta{display:block;margin-top:5.00px;font-size:11.00px;color:var(--color-text-tertiary)}.article-content{padding:16.00px;background:var(--color-bg-card);font-size:14.00px;line-height:1.9;color:var(--color-text-secondary)}.article-content .lead{display:block;font-size:15.50px;color:var(--color-text-primary);font-weight:600;margin-bottom:12.00px}.danger-card{background:#FFF8F4;border-color:#F5DED2}.danger-card .feature-icon{background:#FFF0EA;color:#C85D43}@media(max-width:340px){.hero-title{font-size:18.00px}.hero-desc{width:92%}} +/* ========================================================================== + 可访问性:只用 token,不用工具类(2026-09-23 修订) + -------------------------------------------------------------------------- + v2 曾在此处新增 .tap-min / .tap-gap / .focusable / .pressable 四个工具类。 + 复检发现全部零引用(等价能力已各自写在组件样式内,例如 button/index.wxss + 直接使用 min-height:var(--tap-min)),且存在两个硬问题: -.service-shell{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:#F4F5FA}.service-content{padding:4.00px 12.00px 18.00px}.service-status{display:flex;align-items:center;justify-content:space-between;margin-top:12.00px;padding:10.00px 12.00px;border-radius:11.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-status__label{color:#7B8198;font-size:10.50px}.service-status__value{padding:3.00px 7.00px;border-radius:9.00px;background:#EAF8F2;color:#329472;font-size:9.50px;font-weight:650}.service-status__value.disabled{background:#FFF0F0;color:#D45A60}.service-topics{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.service-topic{min-height:74.00px;padding:10.00px;border-radius:12.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-topic__icon{display:flex;align-items:center;justify-content:center;width:27.00px;height:27.00px;border-radius:8.50px;background:#FFF0F5}.service-topic__icon image{width:17.00px;height:17.00px}.service-topic__title{display:block;margin-top:6.50px;color:#283056;font-size:12.00px;font-weight:650}.service-topic__desc{display:block;margin-top:3.00px;color:#858A9E;font-size:9.50px;line-height:1.45}.service-actions{display:flex;gap:7.00px}.service-actions .secondary-btn{width:95.00px;flex:none}.service-actions .primary-btn{flex:1}.privacy-note{display:flex;align-items:flex-start;gap:7.00px;margin-top:11.00px;padding:10.00px;border-radius:11.00px;background:#F1F4FF;color:#69718E;font-size:10.00px;line-height:1.55}.privacy-note image{width:17.00px;height:17.00px;flex:none} + 1) `.tap-gap > * + *` 用了通配符与兄弟选择器 —— WXSS 不支持, + wcc 编译期直接报 `error at token '*'`,导致整个小程序编译失败。 + (这是编译错误,不是静默失效,代价最高。) + 2) `.pressable:active` / `.focusable:focus-visible` 的伪类在 view 上 + 不生效(小程序须用 hover-class),属于"写了等于没写"。 + + 故整块移除,保留 token。需要热区/间距时直接引用 token: + min-height: var(--tap-min); → 44.00px = 44px,最小可点区域 + gap: var(--tap-gap); → 8.00px = 8px,相邻目标间距(flex gap) + 【WXSS 禁用清单】星号通配符、兄弟选择器、属性选择器。 + 【注释约束】WXSS 注释**不可嵌套**:内层注释的结束标记会提前终止外层注释, + 其后的文字会被当成真实样式解析,导致编译失败或样式被污染。 + (2026-09-23 实证:本块注释初版即踩此坑。) + ========================================================================== */ + +.wx-page{background:var(--color-bg-page)}.service-page{min-height:100vh;padding-bottom:calc(70.00px + 0px)}.hero{padding:22.00px 16.00px 27.00px;background:linear-gradient(140deg,var(--color-primary-lighter),var(--color-warning-light));position:relative;overflow:hidden}.eyebrow{display:inline-flex;padding:3.50px 7.00px;border-radius:499.50px;background:rgba(255,255,255,.72);color:var(--color-primary-strong);font-size:12.00px}.hero-title{display:block;margin-top:9.00px;font-size:20.00px;font-weight:700;line-height:1.35}.hero-desc{display:block;width:82%;margin-top:7.00px;font-size:12.50px;color:var(--color-text-secondary);line-height:1.7}.content{padding:0 var(--spacing-page-x)}.block{margin-top:var(--spacing-section)}.block-title{display:block;font-size:15.50px;font-weight:600}.block-subtitle{display:block;margin-top:4.00px;font-size:12.00px;color:var(--color-text-tertiary)}.card{margin-top:9.00px;padding:14.00px;background:var(--color-bg-card);border:0.50px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}.feature-row,.menu-row,.record-row{display:flex;align-items:center;gap:10.00px;min-height:56.00px;padding:9.00px 0;border-bottom:0.50px solid var(--color-divider)}.feature-row:last-child,.menu-row:last-child,.record-row:last-child{border-bottom:0}.feature-icon{width:36.00px;height:36.00px;display:flex;align-items:center;justify-content:center;flex:none;border-radius:11.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-weight:700}.feature-copy{flex:1;min-width:0}.feature-title{display:block;font-size:14.00px;font-weight:600}.feature-desc,.meta{display:block;margin-top:3.50px;font-size:12.00px;color:var(--color-text-tertiary);line-height:1.55}.arrow{font-size:20.00px;color:var(--color-text-disabled)}.tag{display:inline-flex;margin-right:5.00px;margin-top:5.00px;padding:3.00px 6.50px;border-radius:499.50px;background:var(--color-success-light);color:var(--color-success-strong);font-size:12.00px}.tag.warning{background:var(--color-warning-light);color:var(--color-warning-strong)}.primary-btn,.secondary-btn{height:44.00px;display:flex;align-items:center;justify-content:center;border-radius:22.00px;font-size:14.00px;font-weight:600}.primary-btn{background:var(--gradient-brand-solid);color:var(--color-text-inverse);box-shadow:0 5.00px 12.00px rgba(255,92,130,.22)}.primary-btn.disabled{background:var(--color-bg-muted);color:var(--color-text-tertiary);box-shadow:none}.secondary-btn{background:var(--color-primary-light);color:var(--color-primary-strong)}.fixed-action{position:fixed;left:0;right:0;bottom:0;padding:9.00px var(--spacing-page-x) calc(9.00px + 0px);background:rgba(255,255,255,.96);border-top:0.50px solid var(--color-divider);z-index:100}.field{margin-top:13.00px}.label{display:block;margin-bottom:6.00px;font-size:12.50px;font-weight:600}.input,.select-box,.textarea{width:100%;box-sizing:border-box;background:var(--color-bg-page);border:0.50px solid var(--color-border);border-radius:var(--radius-md);font-size:13.00px}.input,.select-box{height:44.00px;padding:0 12.00px;display:flex;align-items:center}.textarea{min-height:90.00px;padding:11.00px}.notice{margin-top:10.00px;padding:11.00px;border-radius:var(--radius-md);background:var(--color-info-light);color:var(--color-text-secondary);font-size:12.00px;line-height:1.65}.select-box.is-readonly{background:var(--color-bg-subtle);color:var(--color-text-secondary)}.empty-panel{text-align:center;padding:35.00px 15.00px}.empty-symbol{width:48.00px;height:48.00px;margin:auto;display:flex;align-items:center;justify-content:center;border-radius:15.00px;background:var(--color-primary-light);color:var(--color-primary-strong);font-size:18.00px;font-weight:700}.empty-title{display:block;margin-top:11.00px;font-size:15.00px;font-weight:600}.article-card{margin-top:9.00px;background:var(--color-bg-card);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-card)}.article-cover{height:110.00px;padding:12.00px;background:linear-gradient(135deg,var(--color-warning-light),var(--color-warning-light));display:flex;align-items:flex-end}.article-cover text{font-size:21.00px;color:rgba(125,76,63,.52);font-weight:700}.article-body{padding:12.00px}.article-title{display:block;font-size:14.50px;font-weight:600;line-height:1.45}.article-meta{display:block;margin-top:5.00px;font-size:12.00px;color:var(--color-text-tertiary)}.article-content{padding:16.00px;background:var(--color-bg-card);font-size:14.00px;line-height:1.9;color:var(--color-text-secondary)}.article-content .lead{display:block;font-size:15.50px;color:var(--color-text-primary);font-weight:600;margin-bottom:12.00px}.danger-card{background:var(--color-primary-lighter);border-color:var(--color-primary-light)}.danger-card .feature-icon{background:var(--color-warning-light);color:var(--color-warning-strong)}@media(max-width:340px){.hero-title{font-size:18.00px}.hero-desc{width:92%}} + +.service-shell{min-height:100vh;padding-bottom:calc(68.00px + 0px);background:var(--color-bg-page)}.service-content{padding:4.00px 12.00px 18.00px}.service-status{display:flex;align-items:center;justify-content:space-between;margin-top:12.00px;padding:10.00px 12.00px;border-radius:11.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-status__label{color:var(--color-text-tertiary);font-size:12.00px}.service-status__value{padding:3.00px 7.00px;border-radius:9.00px;background:var(--color-success-light);color:var(--color-success-strong);font-size:12.00px;font-weight:600}.service-status__value.disabled{background:var(--color-danger-light);color:var(--color-danger-strong)}.service-topics{display:grid;grid-template-columns:repeat(2,1fr);gap:8.00px;margin-top:9.00px}.service-topic{min-height:74.00px;padding:10.00px;border-radius:12.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.service-topic__icon{display:flex;align-items:center;justify-content:center;width:27.00px;height:27.00px;border-radius:8.50px;background:var(--color-primary-light)}.service-topic__icon image{width:17.00px;height:17.00px}.service-topic__title{display:block;margin-top:6.50px;color:var(--color-text-strong);font-size:12.00px;font-weight:600}.service-topic__desc{display:block;margin-top:3.00px;color:var(--color-text-tertiary);font-size:12.00px;line-height:1.45}.service-actions{display:flex;gap:7.00px}.service-actions .secondary-btn{width:95.00px;flex:none}.service-actions .primary-btn{flex:1}.privacy-note{display:flex;align-items:flex-start;gap:7.00px;margin-top:11.00px;padding:10.00px;border-radius:11.00px;background:var(--color-info-light);color:var(--color-text-tertiary);font-size:12.00px;line-height:1.55}.privacy-note image{width:17.00px;height:17.00px;flex:none} /* ==== miniapp/components/service-hero ==== */ .service-hero { - position: relative; - height: 150.00px; - overflow: hidden; - border-radius: 0 0 16.00px 16.00px; - background: #fff4f7; + position:relative; + height:150.00px; + overflow:hidden; + border-radius:0 0 16.00px 16.00px; + background:var(--color-primary-light); } .service-hero__image, .service-hero__veil { - position: absolute; - inset: 0; - width: 100%; - height: 100%; + position:absolute; + inset:0; + width:100%; + height:100%; } .service-hero__veil { - background: linear-gradient(90deg, rgba(255, 250, 252, 0.98) 0%, rgba(255, 250, 252, 0.82) 38%, rgba(255, 250, 252, 0.08) 70%); + background:linear-gradient(90deg, rgba(255, 250, 252, 0.98) 0%, rgba(255, 250, 252, 0.82) 38%, rgba(255, 250, 252, 0.08) 70%); } .service-hero--night .service-hero__veil { - background: linear-gradient(90deg, rgba(18, 24, 83, 0.92) 0%, rgba(34, 31, 111, 0.64) 42%, rgba(34, 31, 111, 0.08) 72%); + background:linear-gradient(90deg, rgba(18, 24, 83, 0.92) 0%, rgba(34, 31, 111, 0.64) 42%, rgba(34, 31, 111, 0.08) 72%); } .service-hero__content { - position: relative; - z-index: 1; - display: flex; - flex-direction: column; - justify-content: center; - width: 54%; - height: 100%; - padding: 0 18.00px; - box-sizing: border-box; + position:relative; + z-index:1; + display:flex; + flex-direction:column; + justify-content:center; + width:54%; + height:100%; + padding:0 18.00px; + box-sizing:border-box; } .service-hero__eyebrow { - margin-bottom: 5.00px; - color: var(--color-primary); - font-size: 11.00px; - font-weight: 600; - letter-spacing: 1.00px; + margin-bottom:5.00px; + color:var(--color-primary-strong); + font-size:12.00px; + font-weight:600; + letter-spacing:1.00px; } .service-hero__title { - color: #24305e; - font-size: 20.00px; - font-weight: 700; - line-height: 1.28; + color:var(--color-text-strong); + font-size:20.00px; + font-weight:700; + line-height:1.28; } .service-hero__subtitle { - margin-top: 7.00px; - color: #737c96; - font-size: 12.00px; - line-height: 1.55; + margin-top:7.00px; + color:var(--color-text-tertiary); + font-size:12.00px; + line-height:1.55; } .service-hero--night .service-hero__eyebrow, .service-hero--night .service-hero__title, .service-hero--night .service-hero__subtitle { - color: #ffffff; + color:var(--color-text-inverse); } /* ==== miniapp/components/loading ==== */ .ui-loading--block { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: var(--spacing-8) var(--spacing-page-x); + display:flex; + flex-direction:column; + align-items:center; + justify-content:center; + padding:var(--spacing-8) var(--spacing-page-x); } .ui-loading--inline { - display: inline-flex; - align-items: center; + display:inline-flex; + align-items:center; } .ui-loading__spinner { - width: 30.00px; - height: 30.00px; - display: flex; - align-items: center; - justify-content: center; + width:30.00px; + height:30.00px; + display:flex; + align-items:center; + justify-content:center; } .ui-loading__spinner-icon { - width: 24.00px; - height: 24.00px; - animation: ui-loading-spin 0.8s linear infinite; + width:24.00px; + height:24.00px; + animation:ui-loading-spin 0.8s linear infinite; } @keyframes ui-loading-spin { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } + from { transform:rotate(0deg); } + to { transform:rotate(360deg); } } .ui-loading__text { - margin-top: var(--spacing-3); - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); + margin-top:var(--spacing-3); + font-size:var(--font-size-sm); + color:var(--color-text-tertiary); } /* Skeleton */ .ui-loading__skeleton { - width: 100%; + width:100%; } .ui-loading__skeleton-row { - display: flex; - align-items: center; - padding: var(--spacing-3) var(--spacing-page-x); - background: var(--color-bg-card); - border-bottom: 0.50px solid var(--color-divider); + display:flex; + align-items:center; + padding:var(--spacing-3) var(--spacing-page-x); + background:var(--color-bg-card); + border-bottom:0.50px solid var(--color-divider); } .ui-loading__skeleton-avatar { - width: 44.00px; - height: 44.00px; - border-radius: 50%; - background: var(--color-bg-disabled); - margin-right: var(--spacing-3); - flex-shrink: 0; + width:44.00px; + height:44.00px; + border-radius:50%; + background:var(--color-bg-disabled); + margin-right:var(--spacing-3); + flex-shrink:0; } .ui-loading__skeleton-content { - flex: 1; - min-width: 0; + flex:1; + min-width:0; } .ui-loading__skeleton-line { - height: 12.00px; - background: var(--color-bg-disabled); - border-radius: var(--radius-sm); - position: relative; - overflow: hidden; + height:12.00px; + background:var(--color-bg-disabled); + border-radius:var(--radius-sm); + position:relative; + overflow:hidden; } .ui-loading__skeleton-line--title { - width: 40%; - margin-bottom: var(--spacing-2); + width:40%; + margin-bottom:var(--spacing-2); } .ui-loading__skeleton-line--meta { - width: 70%; + width:70%; } /* shimmer */ .ui-loading__skeleton-line::after, .ui-loading__skeleton-avatar::after { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: linear-gradient( + content:''; + position:absolute; + top:0; + left:0; + width:100%; + height:100%; + background:linear-gradient( 90deg, transparent 0%, rgba(255, 255, 255, 0.55) 50%, transparent 100% ); - animation: ui-loading-shimmer 1.4s ease-in-out infinite; + animation:ui-loading-shimmer 1.4s ease-in-out infinite; } @keyframes ui-loading-shimmer { - 0% { transform: translateX(-100%); } - 100% { transform: translateX(100%); } + 0% { transform:translateX(-100%); } + 100% { transform:translateX(100%); } } /* ==== miniapp/components/empty ==== */ .ui-empty { - display: flex; - flex-direction: column; - align-items: center; - padding: var(--spacing-10) var(--spacing-page-x); - text-align: center; + display:flex; + flex-direction:column; + align-items:center; + padding:var(--spacing-10) var(--spacing-page-x); + text-align:center; } .ui-empty__illustration { - width: 80.00px; - height: 80.00px; - border-radius: 50%; - background: var(--color-bg-disabled); - display: flex; - align-items: center; - justify-content: center; - margin-bottom: var(--spacing-4); + width:80.00px; + height:80.00px; + border-radius:50%; + background:var(--color-bg-disabled); + display:flex; + align-items:center; + justify-content:center; + margin-bottom:var(--spacing-4); } .ui-empty__icon { - width: 36.00px; - height: 36.00px; - opacity: 0.72; + width:36.00px; + height:36.00px; + opacity:0.72; } .ui-empty__title { - font-size: var(--font-size-lg); - font-weight: var(--font-weight-medium); - color: var(--color-text-primary); - margin-bottom: var(--spacing-2); + font-size:var(--font-size-lg); + font-weight:var(--font-weight-medium); + color:var(--color-text-primary); + margin-bottom:var(--spacing-2); } .ui-empty__desc { - font-size: var(--font-size-sm); - color: var(--color-text-tertiary); - line-height: var(--line-height-relaxed); - max-width: 240.00px; + font-size:var(--font-size-sm); + color:var(--color-text-tertiary); + line-height:var(--line-height-relaxed); + max-width:240.00px; } .ui-empty__actions { - display: flex; - flex-direction: column; - gap: var(--spacing-2); - margin-top: var(--spacing-6); - width: 100%; - max-width: 240.00px; + display:flex; + flex-direction:column; + gap:var(--spacing-2); + margin-top:var(--spacing-6); + width:100%; + max-width:240.00px; } .ui-empty__action { - display: flex; - align-items: center; - justify-content: center; - height: 40.00px; - border-radius: var(--radius-full); - font-size: var(--font-size-base); - font-weight: var(--font-weight-medium); -} + display:flex; + align-items:center; + justify-content:center; + min-height:var(--tap-min); + border-radius:var(--radius-full); + font-size:var(--font-size-base); + font-weight:var(--font-weight-medium); +min-width:var(--tap-min);} .ui-empty__action--primary { - background: var(--color-primary); - color: #FFFFFF; + background:var(--color-primary-solid); + color:var(--color-text-inverse); } .ui-empty__action--secondary { - background: var(--color-bg-card); - color: var(--color-primary); - border: 0.50px solid var(--color-primary); + background:var(--color-bg-card); + color:var(--color-primary-strong); + border:0.50px solid var(--color-primary); } /* ==== miniapp/components/error-state ==== */ .error-state { - padding: 32.00px 16.00px; - text-align: center; - background: var(--color-bg-card); - border-radius: var(--radius-lg); + padding:32.00px 16.00px; + text-align:center; + background:var(--color-bg-card); + border-radius:var(--radius-lg); } .error-icon { - display: block; - width: 36.00px; - height: 36.00px; - margin: 0 auto 10.00px; + display:block; + width:36.00px; + height:36.00px; + margin:0 auto 10.00px; } .error-title, .error-desc { - display: block; + display:block; } .error-title { - font-size: 15.00px; - font-weight: 600; + font-size:15.00px; + font-weight:600; } .error-desc { - margin-top: 4.00px; - color: var(--color-text-tertiary); - font-size: 12.00px; + margin-top:4.00px; + color:var(--color-text-tertiary); + font-size:12.00px; } .retry-btn { - width: 110.00px; - height: 40.00px; - margin-top: 12.00px; - border: 0; - border-radius: var(--radius-full); - background: var(--color-primary); - color: var(--color-text-inverse); - font-size: 13.00px; - line-height: 40.00px; -} + width:110.00px; + min-height:var(--tap-min); + margin-top:12.00px; + border:0; + border-radius:var(--radius-full); + background:var(--color-primary-solid); + color:var(--color-text-inverse); + font-size:13.00px; + line-height:var(--tap-min); +min-width:var(--tap-min);} .retry-btn::after { - border: 0; + border:0; } @import "../../styles/service-page.wxss"; -.station-name-card{display:flex;align-items:center;gap:9.00px;margin-top:12.00px;padding:12.00px;border-radius:13.00px;background:linear-gradient(135deg,#F1FFFA,#FFF7F9);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.station-name-card>image{width:33.00px;height:33.00px}.station-name-card>view{display:flex;flex:1;flex-direction:column}.station-name{color:#283056;font-size:13.50px;font-weight:700}.station-short-name{margin-top:3.00px;color:#7E859B;font-size:9.50px}.station-info-card{overflow:hidden;margin-top:9.00px;border-radius:13.00px;background:#fff;box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.station-info-row{display:flex;align-items:center;gap:8.00px;min-height:52.00px;padding:7.00px 10.00px;border-bottom:0.50px solid #EFF0F5}.station-info-row:last-child{border-bottom:0}.station-info-row>image:first-child{width:21.00px;height:21.00px;flex:none}.station-info-row>view{display:flex;flex:1;flex-direction:column}.station-info-label{color:#303654;font-size:11.00px;font-weight:650}.station-info-value{margin-top:2.50px;color:#858A9E;font-size:9.50px;line-height:1.45}.station-info-row .station-arrow{width:12.00px;height:12.00px}.station-services{display:grid;grid-template-columns:repeat(2,1fr);gap:7.00px;margin-top:9.00px}.station-service{display:flex;align-items:center;gap:6.00px;min-height:37.00px;padding:6.00px 8.00px;border-radius:10.00px;background:#fff;color:#505874;font-size:10.00px;box-shadow:0 3.00px 10.00px rgba(35,35,95,.05)}.station-service image{width:17.00px;height:17.00px}.map-button{display:flex;align-items:center;justify-content:center;gap:5.00px;height:39.00px;margin-top:10.00px;border:0.50px solid #E5E7F0;border-radius:19.50px;background:#fff;color:#53607F;font-size:11.00px}.map-button image{width:17.00px;height:17.00px} +.station-name-card{display:flex;align-items:center;gap:9.00px;margin-top:12.00px;padding:12.00px;border-radius:13.00px;background:linear-gradient(135deg,var(--color-success-light),var(--color-primary-light));box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.station-name-card>image{width:33.00px;height:33.00px}.station-name-card>view{display:flex;flex:1;flex-direction:column}.station-name{color:var(--color-text-strong);font-size:13.50px;font-weight:700}.station-short-name{margin-top:3.00px;color:var(--color-text-tertiary);font-size:12.00px}.station-info-card{overflow:hidden;margin-top:9.00px;border-radius:13.00px;background:var(--color-bg-card);box-shadow:0 4.00px 13.00px rgba(35,35,95,.06)}.station-info-row{display:flex;align-items:center;gap:8.00px;min-height:52.00px;padding:7.00px 10.00px;border-bottom:0.50px solid var(--color-divider)}.station-info-row:last-child{border-bottom:0}.station-info-row>image:first-child{width:21.00px;height:21.00px;flex:none}.station-info-row>view{display:flex;flex:1;flex-direction:column}.station-info-label{color:var(--color-text-strong);font-size:12.00px;font-weight:600}.station-info-value{margin-top:2.50px;color:var(--color-text-tertiary);font-size:12.00px;line-height:1.45}.station-info-row .station-arrow{width:12.00px;height:12.00px}.station-services{display:grid;grid-template-columns:repeat(2,1fr);gap:7.00px;margin-top:9.00px}.station-service{display:flex;align-items:center;gap:6.00px;min-height:37.00px;padding:6.00px 8.00px;border-radius:10.00px;background:var(--color-bg-card);color:var(--color-text-secondary);font-size:12.00px;box-shadow:0 3.00px 10.00px rgba(35,35,95,.05)}.station-service image{width:17.00px;height:17.00px}.map-button{display:flex;align-items:center;justify-content:center;gap:5.00px;min-height:var(--tap-min);margin-top:10.00px;border:0.50px solid var(--color-border);border-radius:19.50px;background:var(--color-bg-card);color:var(--color-text-secondary);font-size:12.00px;min-width:var(--tap-min);}.map-button image{width:17.00px;height:17.00px} +/* 临时公告:仅当服务端返回「已发布且未过期」公告时渲染 */ +.station-announcements{display:flex;flex-direction:column;gap:7.00px;margin-top:9.00px} +.station-announcement{padding:9.00px 10.00px;border-radius:10.00px;background:linear-gradient(135deg,var(--color-warning-light),var(--color-primary-light));box-shadow:0 3.00px 10.00px rgba(35,35,95,.05)} +.station-announcement-head{display:flex;align-items:center;gap:5.00px} +.station-announcement-dot{width:6.00px;height:6.00px;flex:none;border-radius:50%;background:var(--color-warning)} +.station-announcement-title{color:var(--color-warning-strong);font-size:12.00px;font-weight:700} +.station-announcement-body{display:block;margin-top:4.00px;color:var(--color-warning-strong);font-size:12.00px;line-height:1.5} @@ -5422,7 +8164,7 @@
@@ -5431,7 +8173,7 @@
- +
善缘丹阳 公益婚恋服务平台 @@ -5452,7 +8194,7 @@
-
- +
+
王女士28岁
-
丹阳 · 163cm · 本科
-
教育
同城年龄相近兴趣重合
+
丹阳 · 163cm
+
同城年龄相近兴趣重合
-
- +
+
陈先生31岁
-
丹阳 · 176cm · 硕士
-
制造业
同城择偶条件匹配
+
丹阳 · 176cm
+
同城择偶条件匹配
-
+ +
+
善缘公益服务 需要时,我们在这里陪伴你
-
公益红娘一对一由公益红娘协助梳理择偶条件,推荐更合适的人选。了解服务
婚恋咨询面对关系困惑,可预约专业咨询师谈谈。预约咨询
暂无待推荐的公益服务
+
+
+
+ +
+ 公益红娘一对一 + 了解服务 +
+ +
+ 婚恋咨询 + 预约咨询 +
+
暂无待推荐的公益服务
+
@@ -5543,16 +8317,16 @@
全部活动 - +
-
公益活动丹阳青年公益联谊会丹阳市文化中心
公益活动婚恋反诈公益讲堂善缘服务站·云阳街道
近期暂无可报名活动
+
公益活动丹阳青年公益联谊会丹阳市文化中心
公益活动婚恋反诈公益讲堂善缘服务站·云阳街道
近期暂无可报名活动
善缘服务站 就在身边的公益婚恋服务阵地
-
善缘服务站(云阳街道)云阳街道服务站
资料核验红娘咨询活动报名
查看线下公益服务阵地
+
善缘服务站(云阳街道)云阳街道服务站
资料核验红娘咨询活动报名
查看线下公益服务阵地
@@ -5560,15 +8334,28 @@ 学习成长,收获更好的自己
更多内容 - +
-
暂无新内容,稍后再来看看
+
暂无新内容,稍后再来看看
-
善缘安全提醒实名认证和人工审核可以提高信息真实性,交往过程中仍请谨慎涉及借款、投资和个人隐私。查看婚恋反诈指南
+ +
+
+
+ +
+ 善缘安全提醒 +
+
+ 实名认证和人工审核可以提高信息真实性,交往过程中仍请谨慎涉及借款、投资和个人隐私。 + 查看婚恋反诈指南 +
+
+
- +
首页首页
找对象找对象
消息消息
活动活动
我的我的