P0 致命修复: - 首页表单中段灰色不可见文字: hero-note(#e8edf7) 改为显式 #475569 可读色 - 首页上传区域空白虚线框: 补图标+说明+格式支持+CTA文案 - 结账页顶部裸 HTML class="wrap">: 缺少 <main 标签导致 P0 CTA层级: - 首页双CTA: "直接做完整规划"从 btn-primary 改为 btn-secondary 形成层级 P1 信任感: - 结账页补退款政策+支付方式+支付安全三栏 - 结账页删除 3 张冗余 trust-strip 卡片(原 6 张→2 张 form-proof) - 结账页补"考试省份"必填星号 P1 定价页统一: - CTA 文案统一: "选择付费审核"/"支付并启动方案生成"/"选择深度辅导" - 价格单位统一: /次 /单 → 全部 /份 P1 导航对比度: - global-nav-link 从 #b8c8e4 提亮到 #d8e4f8 (WCAG AA 4.5:1) 验证: pytest 1303 passed, ruff All checks passed
371 lines
7.3 KiB
CSS
371 lines
7.3 KiB
CSS
:root {
|
||
--portal-bg: #f3f7fb;
|
||
--portal-surface: #ffffff;
|
||
--portal-surface-soft: #f7fbff;
|
||
--portal-border: #d7e3f1;
|
||
--portal-text: #142235;
|
||
--portal-muted: #5b6b88;
|
||
--portal-primary: #1f6feb;
|
||
--portal-primary-dark: #194fb6;
|
||
--portal-primary-soft: rgba(31, 111, 235, 0.12);
|
||
--portal-success: #0f766e;
|
||
--portal-success-soft: #dff7f1;
|
||
--portal-warning: #8a5a00;
|
||
--portal-warning-soft: #fff7e6;
|
||
--portal-shadow: 0 18px 42px rgba(20, 34, 53, 0.08);
|
||
--portal-radius-xl: 24px;
|
||
--portal-radius-lg: 18px;
|
||
--portal-radius-md: 14px;
|
||
}
|
||
|
||
* {
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
body {
|
||
color: var(--portal-text);
|
||
}
|
||
|
||
a {
|
||
color: var(--portal-primary);
|
||
}
|
||
|
||
a:hover {
|
||
color: var(--portal-primary-dark);
|
||
}
|
||
|
||
.portal-panel {
|
||
background: var(--portal-surface);
|
||
border: 1px solid var(--portal-border);
|
||
border-radius: var(--portal-radius-xl);
|
||
box-shadow: var(--portal-shadow);
|
||
}
|
||
|
||
.portal-eyebrow {
|
||
display: inline-flex;
|
||
padding: 6px 10px;
|
||
border-radius: 999px;
|
||
background: var(--portal-success-soft);
|
||
color: var(--portal-success);
|
||
font-size: 12px;
|
||
font-weight: 700;
|
||
letter-spacing: 0.04em;
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
.portal-muted {
|
||
color: var(--portal-muted);
|
||
}
|
||
|
||
.portal-button,
|
||
.portal-button-secondary {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
min-height: 46px;
|
||
padding: 0 18px;
|
||
border-radius: var(--portal-radius-md);
|
||
text-decoration: none;
|
||
font-weight: 700;
|
||
border: none;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.portal-button {
|
||
background: var(--portal-primary);
|
||
color: #fff;
|
||
}
|
||
|
||
.portal-button:hover {
|
||
background: var(--portal-primary-dark);
|
||
color: #fff;
|
||
}
|
||
|
||
.portal-button-secondary {
|
||
background: #edf3ff;
|
||
color: var(--portal-primary-dark);
|
||
}
|
||
|
||
.portal-button-secondary:hover {
|
||
background: #dfeaff;
|
||
color: var(--portal-primary-dark);
|
||
}
|
||
|
||
.portal-field input,
|
||
.portal-field textarea,
|
||
.portal-field select {
|
||
width: 100%;
|
||
padding: 12px;
|
||
border-radius: 12px;
|
||
border: 1px solid #cfd7e6;
|
||
font-size: 14px;
|
||
background: #fff;
|
||
color: var(--portal-text);
|
||
}
|
||
|
||
.portal-field input:focus,
|
||
.portal-field textarea:focus,
|
||
.portal-field select:focus {
|
||
outline: none;
|
||
border-color: var(--portal-primary);
|
||
box-shadow: 0 0 0 4px var(--portal-primary-soft);
|
||
}
|
||
|
||
.portal-helper {
|
||
color: var(--portal-muted);
|
||
font-size: 12px;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.portal-notice {
|
||
padding: 16px 18px;
|
||
border-radius: 16px;
|
||
background: var(--portal-warning-soft);
|
||
border: 1px solid #f4d39b;
|
||
color: var(--portal-warning);
|
||
line-height: 1.7;
|
||
}
|
||
|
||
.portal-status-grid {
|
||
display: grid;
|
||
gap: 12px;
|
||
}
|
||
|
||
.portal-status-item {
|
||
padding: 14px 16px;
|
||
border-radius: 16px;
|
||
background: var(--portal-surface-soft);
|
||
border: 1px solid var(--portal-border);
|
||
}
|
||
|
||
.global-nav {
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 100;
|
||
background: rgba(14,26,43,.92);
|
||
backdrop-filter: blur(12px);
|
||
border-bottom: 1px solid rgba(255,255,255,.08);
|
||
padding: 12px 20px;
|
||
}
|
||
|
||
.global-nav-inner {
|
||
max-width: 1180px;
|
||
margin: 0 auto;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
gap: 16px;
|
||
}
|
||
|
||
.global-nav-brand {
|
||
font-size: 18px;
|
||
font-weight: 700;
|
||
color: #fff;
|
||
text-decoration: none;
|
||
}
|
||
|
||
.global-nav-links {
|
||
display: flex;
|
||
gap: 20px;
|
||
align-items: center;
|
||
}
|
||
|
||
.global-nav-link {
|
||
color: #d8e4f8;
|
||
text-decoration: none;
|
||
font-size: 14px;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.global-nav-link:hover {
|
||
color: #fff;
|
||
}
|
||
|
||
a:focus-visible,
|
||
button:focus-visible,
|
||
input:focus-visible,
|
||
select:focus-visible,
|
||
textarea:focus-visible {
|
||
outline: 2px solid var(--portal-primary);
|
||
outline-offset: 2px;
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.global-nav {
|
||
padding: 10px 14px;
|
||
}
|
||
.global-nav-brand {
|
||
font-size: 16px;
|
||
}
|
||
.global-nav-links {
|
||
gap: 12px;
|
||
}
|
||
.global-nav-link {
|
||
font-size: 13px;
|
||
}
|
||
}
|
||
|
||
/* ============================================================
|
||
通用状态组件库(2026-06-26 第一阶段 P1-2)
|
||
覆盖:loading / skeleton / empty / error / toast / spinner
|
||
所有用户端页面可直接 <div class="state-..."> 引用。
|
||
============================================================ */
|
||
|
||
/* —— Loading 容器 —— */
|
||
.state-loading {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 12px;
|
||
padding: 36px 18px;
|
||
text-align: center;
|
||
color: #5b6b88;
|
||
background: #f8fbff;
|
||
border: 1px solid #d7e3f1;
|
||
border-radius: 16px;
|
||
}
|
||
.state-loading__spinner {
|
||
width: 28px;
|
||
height: 28px;
|
||
border: 3px solid #dbe7f5;
|
||
border-top-color: #1f6feb;
|
||
border-radius: 50%;
|
||
animation: state-spin 0.9s linear infinite;
|
||
}
|
||
.state-loading__text {
|
||
font-size: 14px;
|
||
line-height: 1.6;
|
||
margin: 0;
|
||
}
|
||
@keyframes state-spin {
|
||
to { transform: rotate(360deg); }
|
||
}
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.state-loading__spinner {
|
||
animation-duration: 2.5s;
|
||
}
|
||
}
|
||
|
||
/* —— Skeleton 占位(首屏数据未到时用)—— */
|
||
.state-skeleton {
|
||
display: block;
|
||
padding: 18px;
|
||
background: #f4f7fb;
|
||
border: 1px solid #e1e8f3;
|
||
border-radius: 14px;
|
||
}
|
||
.state-skeleton__line {
|
||
display: block;
|
||
height: 14px;
|
||
margin: 10px 0;
|
||
border-radius: 7px;
|
||
background: linear-gradient(90deg, #e6ecf5 0%, #f3f6fb 50%, #e6ecf5 100%);
|
||
background-size: 200% 100%;
|
||
animation: state-shimmer 1.4s ease-in-out infinite;
|
||
}
|
||
.state-skeleton__line--short { width: 38%; }
|
||
.state-skeleton__line--mid { width: 64%; }
|
||
.state-skeleton__line--long { width: 90%; }
|
||
@keyframes state-shimmer {
|
||
0% { background-position: 200% 0; }
|
||
100% { background-position: -200% 0; }
|
||
}
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.state-skeleton__line {
|
||
animation: none;
|
||
background: #e6ecf5;
|
||
}
|
||
}
|
||
|
||
/* —— Empty 空状态 —— */
|
||
.state-empty {
|
||
padding: 28px 20px;
|
||
border-radius: 16px;
|
||
background: #f8fbff;
|
||
border: 1px solid #d7e3f1;
|
||
color: #5b6b88;
|
||
text-align: center;
|
||
}
|
||
.state-empty__title {
|
||
margin: 0 0 6px;
|
||
font-size: 16px;
|
||
font-weight: 700;
|
||
color: #2c3e5b;
|
||
}
|
||
.state-empty__hint {
|
||
margin: 0;
|
||
font-size: 13px;
|
||
line-height: 1.7;
|
||
}
|
||
|
||
/* —— Error 错误状态 —— */
|
||
.state-error {
|
||
padding: 20px 18px;
|
||
border-radius: 14px;
|
||
background: #fff5f5;
|
||
border: 1px solid #f5c2c7;
|
||
color: #b42318;
|
||
}
|
||
.state-error__title {
|
||
margin: 0 0 6px;
|
||
font-size: 15px;
|
||
font-weight: 700;
|
||
}
|
||
.state-error__hint {
|
||
margin: 0;
|
||
font-size: 13px;
|
||
line-height: 1.7;
|
||
color: #8a1f15;
|
||
}
|
||
.state-error a {
|
||
color: #b42318;
|
||
text-decoration: underline;
|
||
}
|
||
|
||
/* —— Toast(全局,aria-live=polite)—— */
|
||
.state-toast-stack {
|
||
position: fixed;
|
||
left: 50%;
|
||
bottom: 24px;
|
||
transform: translateX(-50%);
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
z-index: 9999;
|
||
pointer-events: none;
|
||
}
|
||
.state-toast {
|
||
pointer-events: auto;
|
||
min-width: 220px;
|
||
max-width: 90vw;
|
||
padding: 10px 14px;
|
||
border-radius: 10px;
|
||
background: rgba(20, 34, 53, .92);
|
||
color: #fff;
|
||
font-size: 13px;
|
||
line-height: 1.5;
|
||
box-shadow: 0 12px 30px rgba(20, 34, 53, .18);
|
||
opacity: 0;
|
||
transform: translateY(8px);
|
||
transition: opacity .2s ease, transform .2s ease;
|
||
}
|
||
.state-toast--visible {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
.state-toast--success { background: #1f7a4d; }
|
||
.state-toast--error { background: #b42318; }
|
||
.state-toast--info { background: #1f6feb; }
|
||
|
||
/* —— 工具类:sr-only(可访问性配套)—— */
|
||
.state-sr-only {
|
||
position: absolute;
|
||
width: 1px; height: 1px;
|
||
padding: 0; margin: -1px;
|
||
overflow: hidden;
|
||
clip: rect(0, 0, 0, 0);
|
||
white-space: nowrap;
|
||
border: 0;
|
||
}
|