@charset "UTF-8";
/* ==========================================================================
   999wk.cn · Stitch 设计系统落地样式
   来源：stitch_ui_整理版 / DESIGN.md（Modern EdTech Clean, Material Design 3）
   目标：替代 cdn.tailwindcss.com 与 fonts.googleapis.com，不依赖任何外网资源
   --------------------------------------------------------------------------
   规则：
     · Token 命名沿用 M3 语义名，值逐字取自 DESIGN.md frontmatter
     · 品牌色 --primary 取 DESIGN.md 正文标注的 "definitive brand anchor" #5B5BD6
       （与线上 2026-09-23 覆盖层一致）；#4241BC 保留为 M3 的 --m3-primary 角色色
     · 图标沿用站内已有的 iconify + mdi-local，不引入 Material Symbols 字体
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. 字体：自托管可变字体，Latin 子集 27KB（原来指向 fonts.googleapis.com，
      国内不可达）。CJK 走系统字体链，不额外下载。
   -------------------------------------------------------------------------- */
@font-face {
    font-family: 'Plus Jakarta Sans';
    font-style: normal;
    font-weight: 200 800;
    font-display: swap;
    src: url('/front/assets/fonts/plus-jakarta-sans-latin.woff2') format('woff2');
}

/* --------------------------------------------------------------------------
   2. Design Tokens
   -------------------------------------------------------------------------- */
:root {
    /* ---- 2.1 M3 色彩角色（DESIGN.md frontmatter 逐字对应）---- */
    --m3-surface: #f9f9ff;
    --m3-surface-dim: #d1daf4;
    --m3-surface-bright: #f9f9ff;
    --m3-surface-container-lowest: #ffffff;
    --m3-surface-container-low: #f1f3ff;
    --m3-surface-container: #e9edff;
    --m3-surface-container-high: #e1e8ff;
    --m3-surface-container-highest: #d9e2fc;
    --m3-on-surface: #121b2e;
    --m3-on-surface-variant: #464553;
    --m3-inverse-surface: #273044;
    --m3-inverse-on-surface: #edf0ff;
    --m3-outline: #777585;
    --m3-outline-variant: #c7c4d6;
    --m3-surface-tint: #4e4ec9;
    --m3-primary: #4241bc;
    --m3-on-primary: #ffffff;
    --m3-primary-container: #5b5bd6;
    --m3-on-primary-container: #edeaff;
    --m3-secondary: #5a4cc3;
    --m3-tertiary: #005d53;
    --m3-tertiary-container: #00786c;
    --m3-on-tertiary-container: #92ffed;
    --m3-error: #ba1a1a;
    --m3-on-error: #ffffff;
    --m3-error-container: #ffdad6;
    --m3-on-error-container: #93000a;
    --m3-primary-fixed: #e2dfff;
    --m3-primary-fixed-dim: #c1c1ff;
    --m3-on-primary-fixed: #0a006b;
    --m3-on-primary-fixed-variant: #3533b0;
    --m3-secondary-fixed: #e4dfff;
    --m3-on-secondary-fixed-variant: #4231aa;
    --m3-tertiary-fixed: #71f8e4;
    --m3-tertiary-fixed-dim: #4fdbc8;
    --m3-on-tertiary-fixed-variant: #005048;
    --m3-background: #f9f9ff;
    --m3-on-background: #121b2e;

    /* ---- 2.2 品牌色（DESIGN.md「Colors」正文）---- */
    --primary: #5B5BD6;          /* Brand Primary —— 主 CTA / 关键交互 */
    --primary-press: #4945C4;    /* Hover / Active */
    --primary-soft: #EEEDFD;     /* Primary Soft —— 次级标签 / 选中态底 */
    --primary-soft-press: #E0DDFB;
    --secondary: #7C6FE8;        /* Brand Secondary —— 插图 / 徽标 */
    --accent: #14B8A6;           /* Accent Mint —— 课程高亮 / 完成度 */

    /* ---- 2.3 语义色 ----
       注意：品牌紫与 --m3-tertiary(#005d53 深绿) 是两个体系。
       设计稿里「运行正常」绿点用的是 Tailwind tertiary，落地时统一用 --success，
       避免深绿在浅底上对比不足。 */
    --success: #12B76A;
    --warning: #F79009;
    --danger: #EF4444;

    /* ---- 2.4 文字 / 描边 ---- */
    --ink: #172033;
    --ink-2: #667085;
    --ink-3: #98A2B3;
    --line: #E7EAF2;
    --divider: #F0F1F5;

    /* ---- 2.5 字体族 ----
       ChillRound（寒蝉半圆体，OFL-1.1，自托管）放最前：中文和拉丁都走它，
       整页统一的圆润观感。它只覆盖 GB2312 + 常用符号，生僻字自动落到后面的
       系统字体 —— 所以系统字体链一个都不能删。
       Plus Jakarta Sans 退居第二，仅当 ChillRound 没加载出来时兜底拉丁。 */
    --font-display:  'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont,
        'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Noto Sans SC',
        'Helvetica Neue', Arial, sans-serif;
    --font-body:  -apple-system, BlinkMacSystemFont, 'PingFang SC',
        'Hiragino Sans GB', 'Microsoft YaHei', 'Noto Sans SC',
        'Helvetica Neue', Arial, sans-serif;

    /* ---- 2.6 字阶（DESIGN.md typography）---- */
    --fs-headline-xl: 36px;      --lh-headline-xl: 44px;
    --fs-headline-xl-m: 28px;    --lh-headline-xl-m: 36px;
    --fs-headline-lg: 28px;      --lh-headline-lg: 36px;
    --fs-headline-lg-m: 22px;    --lh-headline-lg-m: 30px;
    --fs-headline-md: 20px;      --lh-headline-md: 28px;
    --fs-headline-sm: 18px;      --lh-headline-sm: 26px;
    --fs-body-lg: 16px;          --lh-body-lg: 24px;
    --fs-body-md: 14px;          --lh-body-md: 20px;
    --fs-body-sm: 12px;          --lh-body-sm: 18px;
    --fs-label-lg: 14px;         --lh-label-lg: 20px;
    --fs-label-md: 12px;         --lh-label-md: 16px;
    --fs-label-sm: 11px;         --lh-label-sm: 14px;

    /* ---- 2.7 圆角（按组件视觉权重递增）---- */
    --r-xs: 8px;
    --r-sm: 12px;
    --r-md: 16px;
    --r-lg: 20px;
    --r-full: 999px;

    /* ---- 2.8 间距（8px 基准 + 4px 半步）---- */
    --sp-xs: 4px;
    --sp-sm: 8px;
    --sp-md: 12px;
    --sp-lg: 16px;
    --sp-xl: 24px;
    --gutter: 16px;
    --margin: 16px;

    /* ---- 2.9 阴影（DESIGN.md「Elevation & Depth」5 级）---- */
    --e0: none;
    --e1: 0 2px 10px rgba(16, 24, 40, .05);
    --e2: 0 10px 28px rgba(16, 24, 40, .09);
    --e3: 0 20px 40px rgba(16, 24, 40, .12);
    --e4: 0 4px 16px rgba(16, 24, 40, .08);

    /* ---- 2.10 语义别名层 ----
       组件样式只允许引用这一层。换肤 = 只覆盖这一层的值 + 极少数「口味」规则，
       不需要改任何组件声明。2026-09-23 为「换款式」需求引入。 */
    /* 注意：这里的字面值不能写成本变量自身。
       2026-09-23 踩过坑：用 replace_all 把组件里的 #1F2937 换成 var(--fg) 时，
       连这一行的定义 `--fg: #1F2937` 也被替换，变成 `--fg: var(--fg)` 自引用循环，
       整条变量失效。改动这一层后务必回头看这几行。 */
    --fg: #1F2937;
    --fg-2: #6B7280;
    --fg-3: #9CA3AF;
    --grip: #D1D5DB;
    --surface: #FFFFFF;
    --surface-2: var(--m3-surface-container-low);
    --on-brand: #FFFFFF;
    --brand: var(--primary);
    --brand-press: var(--primary-press);
    --brand-soft: var(--primary-soft);
    --brand-soft-fg: #4338CA;
    --brand-glow: rgba(91, 91, 214, .15);
    --warning-soft: #FFFAF2;
    --warning-fg: #7A4B08;
    --danger-fg: var(--m3-error);

    /* 控件专用：卡片描边可以很淡，但复选框边框 / 进度条轨道必须看得见。
       深色主题下两者差别很大，所以单独开 token。 */
    --ctl-line: var(--line);
    --track: var(--divider);

    /* 页面底色与「极光」背景层：浅色主题下极光为空 */
    --page-bg: var(--m3-surface);
    --aurora: none;

    /* 安全区 */
    --safe-top: env(safe-area-inset-top, 0px);
    --safe-bottom: env(safe-area-inset-bottom, 0px);
}

@media (min-width: 768px) {
    :root {
        --gutter: 20px;
        --margin: 24px;
    }
}
@media (min-width: 1025px) {
    :root {
        --gutter: 24px;
        --margin: 40px;
    }
}

/* --------------------------------------------------------------------------
   3. 基础
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; background: #f9f9ff; }

body.stitch {
    margin: 0;
    /* 极光直接作为 body 的背景图层。
       不能放 body::before + z-index:-1 —— 那样会被 body 自身的实色背景盖住，
       实测极光完全不显示。 */
    background-color: var(--page-bg);
    background-image: var(--aurora);
    background-attachment: fixed;
    background-repeat: no-repeat;
    color: var(--ink);
    font-family: var(--font-body);
    font-size: var(--fs-body-md);
    line-height: var(--lh-body-md);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    min-height: 100dvh;
}

/* 注意：这里必须用 :where() 把特异性压到 0。
   若写成 `.stitch button {...}`（特异性 0,1,1），会反过来盖掉
   `.pf-btn`（0,1,0）这类单类组件规则，导致按钮底色全部失效。
   2026-09-23 已在 390px 实测确认过这个问题。 */
:where(.stitch) :where(a) { color: inherit; text-decoration: none; }
:where(.stitch) :where(button) {
    font: inherit;
    cursor: pointer;
    border: 0;
    background: none;
    color: inherit;
}

/* hidden 属性必须能压住组件自身的 display:flex。
   UA 样式表里的 [hidden]{display:none} 特异性低于任何作者类规则，
   所以 .sheet-alert / .sync 这类 display:flex 的元素加了 hidden 也会照常显示。
   2026-09-23 实测踩过：超时提示条和进度条在所有状态下都露出来了。 */
[hidden] { display: none !important; }

/* 等宽数字：价格 / 订单号 / 进度 */
.num, .price, .pf-pct {
    font-family: var(--font-display);
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
}

.no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
.no-scrollbar::-webkit-scrollbar { display: none; }

.wrap {
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    padding-left: var(--margin);
    padding-right: var(--margin);
}

/* 焦点可见性（设计系统未定义，按 M3 补） */
.stitch :focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* --------------------------------------------------------------------------
   4. 顶部品牌栏
   -------------------------------------------------------------------------- */
.shell-head {
    position: sticky;
    top: 0;
    z-index: 50;
    background: rgba(249, 249, 255, .85);
    -webkit-backdrop-filter: blur(20px) saturate(180%);
    backdrop-filter: blur(20px) saturate(180%);
    border-bottom: 1px solid var(--line);
    padding-top: var(--safe-top);
}
.shell-head-in {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-sm);
    min-height: 56px;
}
.shell-brand { display: flex; align-items: center; gap: var(--sp-sm); min-width: 0; }
.shell-logo {
    width: 36px; height: 36px;
    border-radius: var(--r-sm);
    background: var(--primary-soft);
    object-fit: contain;
    flex: 0 0 auto;
}
.shell-name {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--fs-headline-sm);
    line-height: 1.2;
    font-weight: 700;
    color: var(--ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.shell-slogan {
    font-size: var(--fs-label-sm);
    line-height: var(--lh-label-sm);
    color: var(--ink-2);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.shell-actions { display: flex; align-items: center; gap: var(--sp-xs); flex: 0 0 auto; }
.shell-iconbtn {
    width: 44px; height: 44px;
    display: flex; align-items: center; justify-content: center;
    border-radius: var(--r-sm);
    color: var(--ink-2);
    font-size: 22px;
    transition: color .18s, background-color .18s, transform .18s;
}
.shell-iconbtn:hover { color: var(--primary); background: var(--m3-surface-container-high); }
.shell-iconbtn:active { transform: scale(.9); }

/* --------------------------------------------------------------------------
   5. 信任胶囊行
   -------------------------------------------------------------------------- */
.trust-row {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--sp-xs);
    padding-top: var(--sp-md);
}
.trust-pill {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 3px;
    padding: 6px 2px;
    border-radius: var(--r-full);
    background: var(--m3-surface-container-low);
    color: var(--m3-tertiary);
    font-size: 10.5px;
    line-height: var(--lh-label-sm);
    white-space: nowrap;
    min-width: 0;
}
.trust-pill i { font-size: 15px; flex: 0 0 auto; }
.trust-pill span {
    color: var(--ink);
    overflow: hidden;
    text-overflow: ellipsis;
}

/* --------------------------------------------------------------------------
   6. 搜索区
   -------------------------------------------------------------------------- */
.searchbar { margin: var(--sp-md) 0; display: flex; flex-direction: column; gap: var(--sp-sm); }
.search-box {
    position: relative;
    display: flex;
    align-items: center;
    height: 48px;
    padding: 4px 5px 4px 13px;
    background: var(--m3-surface-container-lowest);
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    transition: border-color .18s, box-shadow .18s;
}
.search-box:focus-within {
    border-color: var(--primary);
    box-shadow: 0 0 0 3px rgba(91, 91, 214, .15);
}
.search-box > i { font-size: 20px; color: var(--m3-outline); flex: 0 0 auto; pointer-events: none; }
.search-input {
    flex: 1 1 auto;
    min-width: 0;
    height: 100%;
    padding: 0 var(--sp-sm);
    border: 0;
    outline: 0;
    background: transparent;
    color: var(--ink);
    font-size: 16px; /* 16px 以下 iOS 会自动放大页面 */
    font-family: var(--font-body);
}
.search-input::placeholder { color: var(--m3-outline-variant); }
.search-clear {
    width: 28px; height: 28px;
    display: none;
    align-items: center; justify-content: center;
    border-radius: var(--r-full);
    color: var(--m3-outline-variant);
    font-size: 16px;
}
.search-clear.on { display: flex; }
.search-btn {
    height: 38px;
    padding: 0 15px;
    border-radius: 10px;
    background: var(--primary);
    color: var(--on-brand);
    font-size: 13px;
    font-weight: 500;
    flex: 0 0 auto;
    transition: background-color .18s, transform .18s;
}
.search-btn:hover { background: var(--primary-press); }
.search-btn:active { transform: scale(.95); }

.hot-tags {
    display: flex;
    align-items: center;
    gap: var(--sp-xs);
    overflow-x: auto;
    padding-bottom: 2px;
}
.hot-label { font-size: var(--fs-label-sm); color: var(--m3-outline); flex: 0 0 auto; }
.hot-tag {
    padding: 4px 10px;
    border-radius: var(--r-full);
    background: var(--m3-surface-container-low);
    color: var(--m3-on-surface-variant);
    font-size: var(--fs-label-sm);
    white-space: nowrap;
    flex: 0 0 auto;
    transition: color .18s, background-color .18s, transform .18s;
}
.hot-tag:hover { color: var(--primary); }
.hot-tag:active { transform: scale(.95); }

/* --------------------------------------------------------------------------
   7. 防走丢客服卡（琥珀色警示）
   -------------------------------------------------------------------------- */
.kf-card {
    position: relative;
    border-radius: var(--r-md);
    padding: 1px;
    background: linear-gradient(90deg, #f59e0b, #d97706, #ea580c);
    box-shadow: var(--e1);
    margin-bottom: var(--sp-md);
    transition: box-shadow .2s;
}
.kf-card:hover { box-shadow: var(--e4); }
.kf-card-in {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-sm);
    padding: 8px 12px;
    border-radius: 15px;
    background: rgba(255, 255, 255, .95);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
}
.kf-left { display: flex; align-items: center; gap: 10px; min-width: 0; flex: 1 1 auto; }
.kf-ico-wrap { position: relative; display: flex; align-items: center; justify-content: center; flex: 0 0 auto; }
.kf-ico {
    width: 32px; height: 32px;
    border-radius: var(--r-sm);
    background: linear-gradient(135deg, #f59e0b, #ea580c);
    color: var(--on-brand);
    display: flex; align-items: center; justify-content: center;
    font-size: 18px;
}
.kf-dot {
    position: absolute; top: -2px; right: -2px;
    width: 10px; height: 10px;
    border-radius: var(--r-full);
    background: #10b981;
    border: 1px solid var(--surface);
}
.kf-meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; min-width: 0; }
.kf-title { font-size: 13px; font-weight: 700; color: var(--ink); white-space: nowrap; }
.kf-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: 6px;
    background: #fffbeb;
    border: 1px solid rgba(245, 158, 11, .2);
    font-family: var(--font-display);
    font-size: 12px;
    font-weight: 700;
    color: #92400e;
    letter-spacing: .02em;
}
.kf-badge i { font-size: 13px; color: #d97706; }
.kf-copy {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: var(--sp-xs);
    padding: 6px 12px;
    border-radius: var(--r-sm);
    background: linear-gradient(90deg, #d97706, #ea580c);
    color: var(--on-brand);
    font-size: 12px;
    font-weight: 600;
    box-shadow: var(--e1);
    transition: filter .18s, transform .18s;
}
.kf-copy:hover { filter: brightness(.92); }
.kf-copy:active { transform: scale(.95); }
.kf-copy i { font-size: 14px; }

/* --------------------------------------------------------------------------
   8. 区块标题
   -------------------------------------------------------------------------- */
.sec-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-sm);
    margin: var(--sp-lg) 0 10px;
}
.sec-title {
    display: flex;
    align-items: center;
    gap: var(--sp-sm);
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--fs-headline-lg-m);
    line-height: var(--lh-headline-lg-m);
    font-weight: 700;
    letter-spacing: -.2px;
    color: var(--ink);
}
.sec-title::after {
    content: "";
    width: 8px; height: 8px;
    border-radius: var(--r-full);
    background: var(--m3-tertiary);
    flex: 0 0 auto;
}
.sec-count { font-size: var(--fs-label-sm); color: var(--m3-outline); flex: 0 0 auto; }

/* 分类过滤 Tabs（设计稿此处容器为空，按 M3 chip 规范补全） */
.tabs {
    display: flex;
    align-items: center;
    gap: var(--sp-sm);
    overflow-x: auto;
    padding-bottom: 2px;
    margin-bottom: 10px;
}
.tab {
    height: 32px;
    padding: 0 14px;
    border-radius: var(--r-full);
    background: var(--surface);
    border: 1px solid var(--line);
    color: var(--ink-2);
    font-size: var(--fs-label-md);
    font-weight: 500;
    white-space: nowrap;
    flex: 0 0 auto;
    transition: all .18s;
}
.tab[aria-selected="true"] {
    background: var(--primary-soft);
    border-color: var(--primary);
    color: var(--primary);
    font-weight: 600;
}

/* --------------------------------------------------------------------------
   9. 平台卡片
   -------------------------------------------------------------------------- */
.pf-list { display: flex; flex-direction: column; gap: var(--sp-md); }

.pf-card {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-md);
    padding: 14px;
    background: var(--m3-surface-container-lowest);
    border: 1px solid rgba(199, 196, 214, .2);
    border-radius: var(--r-md);
    box-shadow: var(--e1);
    transition: box-shadow .2s, transform .2s;
}
.pf-card:hover { box-shadow: var(--e2); }
.pf-card:active { transform: scale(.99); }

.pf-main { display: flex; align-items: center; gap: 14px; min-width: 0; flex: 1 1 auto; }

.pf-ico {
    width: 56px; height: 56px;
    border-radius: var(--r-md);
    display: flex; align-items: center; justify-content: center;
    font-size: 30px;
    flex: 0 0 auto;
    box-shadow: inset 0 1px 2px rgba(255, 255, 255, .8);
    border: 1px solid transparent;
}
.pf-ico.tone-violet  { background: linear-gradient(135deg, #e2dfff, rgba(91,91,214,.2)); color: var(--primary); border-color: rgba(91,91,214,.1); }
.pf-ico.tone-indigo  { background: linear-gradient(135deg, #e0e7ff, #eef2ff); color: #4f46e5; border-color: rgba(99,102,241,.1); }
.pf-ico.tone-emerald { background: linear-gradient(135deg, #d1fae5, #f0fdfa); color: #0d9488; border-color: rgba(20,184,166,.1); }
.pf-ico.tone-sky     { background: linear-gradient(135deg, #e0f2fe, #eff6ff); color: #2563eb; border-color: rgba(59,130,246,.1); }
.pf-ico.tone-purple  { background: linear-gradient(135deg, #ede9fe, #faf5ff); color: #9333ea; border-color: rgba(168,85,247,.1); }
.pf-ico.tone-amber   { background: linear-gradient(135deg, #fef3c7, #fff7ed); color: #d97706; border-color: rgba(245,158,11,.1); }
.pf-ico.tone-rose    { background: linear-gradient(135deg, #ffe4e6, #fdf2f8); color: #e11d48; border-color: rgba(244,63,94,.1); }
.pf-ico.tone-slate   { background: var(--m3-surface-container-high); color: var(--m3-outline); border-color: rgba(199,196,214,.3); }

.pf-info { display: flex; flex-direction: column; gap: var(--sp-xs); min-width: 0; }
.pf-name-row { display: flex; align-items: center; gap: var(--sp-sm); flex-wrap: wrap; }
.pf-name {
    margin: 0;
    font-family: var(--font-display);
    font-size: 16px;
    line-height: 22px;
    font-weight: 700;
    letter-spacing: -.2px;
    color: var(--ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.pf-badge {
    padding: 2px 6px;
    border-radius: var(--r-full);
    font-size: var(--fs-label-sm);
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
}
.pf-badge.t-primary  { background: rgba(91,91,214,.1); color: var(--primary); }
.pf-badge.t-secondary{ background: var(--m3-secondary-fixed); color: var(--m3-on-secondary-fixed-variant); }
.pf-badge.t-tertiary { background: rgba(113,248,228,.6); color: var(--m3-on-tertiary-fixed-variant); }
.pf-badge.t-muted    { background: var(--m3-surface-container); color: var(--m3-outline); font-weight: 500; }
.pf-badge.t-amber    { background: #fef3c7; color: #92400e; }
.pf-badge.t-rose     { background: #ffe4e6; color: #be123c; }
.pf-badge.t-purple   { background: #f3e8ff; color: #7e22ce; }
.pf-badge.t-slate    { background: var(--m3-surface-container-high); color: var(--ink-2); }

.pf-sub {
    margin: 0;
    font-size: 13px;
    line-height: 1.35;
    color: var(--m3-on-surface-variant);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.pf-right {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 6px;
    flex: 0 0 auto;
}
.pf-status {
    display: flex;
    align-items: center;
    gap: var(--sp-xs);
    font-size: 11px;
    font-weight: 500;
    color: var(--success);
}
.pf-status::before {
    content: "";
    width: 6px; height: 6px;
    border-radius: var(--r-full);
    background: var(--success);
    flex: 0 0 auto;
}
.pf-status.is-down { color: var(--m3-outline); }
.pf-status.is-down::before { background: var(--m3-outline-variant); }

.pf-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-xs);
    padding: 6px 14px;
    border-radius: var(--r-sm);
    background: var(--primary);
    color: var(--on-brand);
    font-size: 13px;
    font-weight: 500;
    box-shadow: var(--e1);
    transition: background-color .18s, transform .18s;
    white-space: nowrap;
}
.pf-btn:hover { background: var(--m3-primary-container); }
.pf-btn:active { transform: scale(.95); }
.pf-btn i { font-size: 15px; }

/* 维护中 / 停用 */
.pf-card.is-disabled {
    background: rgba(255, 255, 255, .8);
    opacity: .85;
}
.pf-card.is-disabled .pf-name { color: rgba(18, 27, 46, .7); }
.pf-card.is-disabled .pf-sub { color: var(--m3-outline); }
.pf-btn.is-disabled {
    background: var(--m3-surface-container);
    color: var(--m3-outline);
    cursor: not-allowed;
    box-shadow: none;
}
.pf-btn.is-disabled:hover { background: var(--m3-surface-container); }
.pf-btn.is-disabled:active { transform: none; }

/* --------------------------------------------------------------------------
   10. 空状态
   -------------------------------------------------------------------------- */
.empty-state {
    display: none;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 40px var(--sp-lg);
    background: var(--m3-surface-container-lowest);
    border-radius: var(--r-sm);
    text-align: center;
}
.empty-state.on { display: flex; }
.empty-state > i { font-size: 48px; color: var(--m3-outline-variant); margin-bottom: var(--sp-sm); }
.empty-title {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--fs-headline-sm);
    line-height: var(--lh-headline-sm);
    font-weight: 600;
    color: var(--ink);
}
.empty-sub { margin: 4px 0 0; font-size: var(--fs-body-sm); line-height: var(--lh-body-sm); color: var(--m3-outline); }
.empty-btn {
    margin-top: var(--sp-lg);
    padding: 8px var(--sp-lg);
    border-radius: var(--r-xs);
    background: var(--primary);
    color: var(--on-brand);
    font-size: var(--fs-label-md);
    font-weight: 500;
}

/* --------------------------------------------------------------------------
   11. 底部导航
   -------------------------------------------------------------------------- */
.tabbar {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 50;
    display: flex;
    justify-content: center;
    padding: 0 var(--sp-lg);
    margin-bottom: var(--sp-md);
    padding-bottom: var(--safe-bottom);
    pointer-events: none;
}
.tabbar-in {
    pointer-events: auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    max-width: 28rem;
    padding: 8px 12px;
    border-radius: var(--r-full);
    background: linear-gradient(135deg, rgba(255,255,255,.78) 0%, rgba(249,249,255,.58) 100%);
    -webkit-backdrop-filter: blur(28px) saturate(190%);
    backdrop-filter: blur(28px) saturate(190%);
    border: 1px solid rgba(255,255,255,.88);
    box-shadow: inset 0 1px 1.5px 0 rgba(255,255,255,.95),
                0 12px 36px -6px rgba(66,65,188,.16),
                0 4px 14px rgba(0,0,0,.05);
}
.tb-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    flex: 1 1 0;
    min-width: 0;
    padding: 6px 4px;
    border-radius: var(--r-full);
    color: var(--m3-on-surface-variant);
    transition: color .2s, background-color .3s, transform .2s;
}
.tb-item i { font-size: 22px; line-height: 1; opacity: .85; }
.tb-txt {
    margin-top: 2px;
    font-size: 11px;
    font-weight: 500;
    letter-spacing: -.2px;
    white-space: nowrap;
}
.tb-item:active { transform: scale(.95); }
.tb-item.on {
    color: var(--primary);
    background: radial-gradient(circle, rgba(66,65,188,.14) 0%, rgba(91,91,214,.08) 100%);
    box-shadow: inset 0 1px 1px rgba(255,255,255,.6);
}
.tb-item.on i { opacity: 1; font-weight: 600; }
.tb-item.on .tb-txt { font-weight: 700; }

/* 给底部导航让出空间 */
.has-tabbar { padding-bottom: 92px; }

/* ==========================================================================
   12. 底部抽屉（bottom sheet）
   来源：stitch_ui 查课流程（_1 加载中 / _2 默认 / _3 校验失败 /
         _4 超时重试 / _5 不支持查课）
   已按实现决策调整：
     · 加载态去掉假的「68%」，改为不确定进度条 + 分阶段文案
       （后端 getWk 是一次阻塞请求，没有真实进度事件）
     · 移除「忘记密码?」入口 —— 那是学校教务系统的密码，平台无权也不能重置
   ========================================================================== */
.sheet-mask {
    position: fixed;
    inset: 0;
    z-index: 40;
    background: rgba(0, 0, 0, .55);
    opacity: 0;
    visibility: hidden;
    transition: opacity .28s, visibility .28s;
}
.sheet-mask.on { opacity: 1; visibility: visible; }

.sheet {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 50;
    margin: 0 auto;
    width: 100%;
    max-width: 430px;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    pointer-events: none;
    transform: translateY(100%);
    transition: transform .28s cubic-bezier(.16, 1, .3, 1);
}
.sheet.on { transform: translateY(0); }

.sheet-panel {
    pointer-events: auto;
    position: relative;
    display: flex;
    flex-direction: column;
    width: 100%;
    max-height: 85vh;
    overflow: hidden;
    background: var(--m3-surface-container-lowest);
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    box-shadow: 0 -8px 30px rgba(16, 24, 40, .15);
}

.sheet-grip-row {
    position: relative;
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 10px 0 4px;
}
.sheet-grip { width: 40px; height: 4px; border-radius: var(--r-full); background: var(--grip); }
.sheet-close {
    position: absolute;
    right: 16px;
    top: 10px;
    width: 32px;
    height: 32px;
    border-radius: var(--r-full);
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--m3-surface-container-low);
    color: var(--m3-on-surface-variant);
    font-size: 18px;
    transition: background-color .15s, color .15s;
}
.sheet-close:hover { background: var(--m3-surface-container); color: var(--ink); }

.sheet-body {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 8px 20px 16px;
    display: flex;
    flex-direction: column;
    gap: var(--sp-lg);
}

.sheet-head { display: flex; flex-direction: column; gap: 4px; padding-right: 24px; }
.sheet-title {
    margin: 0;
    font-family: var(--font-display);
    font-size: 20px;
    line-height: 28px;
    font-weight: 600;
    color: var(--fg);
}
.sheet-sub {
    margin: 0;
    font-size: 13px;
    line-height: 18px;
    color: var(--fg-2);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* 加密说明条 */
.sec-banner {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 12px;
    background: var(--primary-soft);
    border-radius: var(--r-sm);
}
.sec-banner > i { font-size: 20px; color: var(--primary); flex: 0 0 auto; margin-top: 2px; }
.sec-banner p { margin: 0; font-size: 12px; line-height: 18px; color: var(--brand-soft-fg); }

/* --------------------------------------------------------------------------
   12.1 表单
   -------------------------------------------------------------------------- */
.field { display: flex; flex-direction: column; gap: 6px; }
.field-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-sm);
}
.field-label {
    display: flex;
    align-items: center;
    gap: 2px;
    font-size: var(--fs-label-lg);
    line-height: var(--lh-label-lg);
    color: var(--fg);
}
.field-req { color: var(--m3-error); font-weight: 700; font-size: 14px; }
.field-opt {
    font-size: 11px;
    line-height: 14px;
    font-weight: 500;
    color: var(--fg-3);
    background: var(--m3-surface-container-low);
    padding: 2px 8px;
    border-radius: var(--r-full);
}

.field-box { position: relative; display: flex; align-items: center; }
.field-ico {
    position: absolute;
    left: 12px;
    font-size: 20px;
    color: var(--fg-3);
    pointer-events: none;
    transition: color .15s;
}
.field-input {
    width: 100%;
    height: 44px;
    padding: 0 12px 0 40px;
    border: 0;
    outline: 0;
    border-radius: var(--r-sm);
    background: var(--m3-surface-container-lowest);
    color: var(--fg);
    font-family: var(--font-body);
    font-size: var(--fs-body-md);
    box-shadow: inset 0 0 0 1px var(--line);
    transition: box-shadow .15s, background-color .15s;
}
.field-input::placeholder { color: var(--fg-3); }
.field-input:focus {
    box-shadow: inset 0 0 0 1.5px var(--primary), 0 0 0 3px var(--primary-soft);
    background: var(--m3-surface-bright);
}
.field-box.has-eye .field-input { padding-right: 40px; }
.field-eye {
    position: absolute;
    right: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 4px;
    border-radius: 6px;
    color: var(--fg-3);
    font-size: 20px;
    transition: color .15s;
}
.field-eye:hover { color: var(--ink); }

/* 错误态（_3 校验失败） */
.field.is-error .field-input {
    box-shadow: inset 0 0 0 1.5px var(--danger), 0 0 0 3px rgba(239, 68, 68, .15);
}
.field.is-error .field-ico { color: var(--danger); }
.field-err {
    display: none;
    align-items: center;
    gap: 4px;
    font-size: 12px;
    line-height: 18px;
    color: var(--m3-error);
}
.field.is-error .field-err { display: flex; }

/* 只读行（_1 同步中：表单降级为展示） */
.field-ro {
    position: relative;
    display: flex;
    align-items: center;
    height: 44px;
    padding: 0 12px;
    border-radius: var(--r-sm);
    background: var(--m3-surface-container-low);
    box-shadow: inset 0 1px 2px rgba(16, 24, 40, .05);
    color: var(--m3-outline);
    font-size: var(--fs-body-md);
}
.field-ro > i:first-child { font-size: 20px; color: rgba(119, 117, 133, .7); margin-right: 8px; flex: 0 0 auto; }
.field-ro .ro-val {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.field-ro .ro-val.is-pwd { letter-spacing: .18em; }
.field-ro .ro-lock { font-size: 18px; color: rgba(119, 117, 133, .5); flex: 0 0 auto; }
.field-ro.is-masked .ro-val { letter-spacing: .05em; }

.sheet-trust {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 4px 0;
    color: var(--m3-on-surface-variant);
    opacity: .8;
    font-size: 11px;
    line-height: 14px;
}
.sheet-trust i { font-size: 14px; }

/* --------------------------------------------------------------------------
   12.2 同步中：不确定进度条 + 分阶段文案
   -------------------------------------------------------------------------- */
.sync {
    display: flex;
    flex-direction: column;
    gap: var(--sp-sm);
    padding: 12px;
    background: var(--m3-surface-container-low);
    border-radius: var(--r-sm);
}
.sync-top { display: flex; align-items: center; gap: var(--sp-sm); }
.sync-dot { position: relative; width: 10px; height: 10px; flex: 0 0 auto; }
.sync-dot::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: var(--r-full);
    background: var(--primary);
    opacity: .75;
    animation: sync-ping 1.4s cubic-bezier(0, 0, .2, 1) infinite;
}
.sync-dot::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: var(--r-full);
    background: var(--primary);
}
@keyframes sync-ping {
    75%, 100% { transform: scale(2.4); opacity: 0; }
}
.sync-text {
    font-size: var(--fs-label-sm);
    line-height: var(--lh-label-sm);
    color: var(--m3-on-surface-variant);
    flex: 1 1 auto;
    min-width: 0;
}
.sync-track {
    height: 4px;
    border-radius: var(--r-full);
    background: var(--m3-surface-container-high);
    overflow: hidden;
}
.sync-bar {
    height: 100%;
    width: 40%;
    border-radius: var(--r-full);
    background: var(--primary);
    animation: sync-indet 1.5s ease-in-out infinite;
}
@keyframes sync-indet {
    0%   { transform: translateX(-110%); }
    100% { transform: translateX(260%); }
}
.sync.is-slow .sync-bar { background: var(--warning); }
.sync.is-slow .sync-dot::before,
.sync.is-slow .sync-dot::after { background: var(--warning); }

/* 超时提示条（_4） */
.sheet-alert {
    display: flex;
    align-items: flex-start;
    gap: var(--sp-sm);
    padding: 8px 12px;
    border-radius: var(--r-sm);
    background: var(--warning-soft);
    box-shadow: inset 0 0 0 1px rgba(247, 144, 9, .3);
    font-size: 12px;
    line-height: 18px;
    color: var(--warning-fg);
}
.sheet-alert > i { font-size: 16px; color: var(--warning); flex: 0 0 auto; margin-top: 1px; }

/* --------------------------------------------------------------------------
   12.3 吸底操作区
   -------------------------------------------------------------------------- */
.sheet-dock {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    gap: var(--sp-sm);
    padding: 12px 16px calc(24px + var(--safe-bottom));
    background: rgba(255, 255, 255, .95);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
    box-shadow: 0 -4px 20px rgba(16, 24, 40, .06);
}
.btn-primary {
    width: 100%;
    height: 48px;
    border-radius: var(--r-sm);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-sm);
    background: var(--primary);
    color: var(--on-brand);
    font-family: var(--font-display);
    font-size: var(--fs-headline-sm);
    font-weight: 600;
    box-shadow: var(--e1);
    transition: background-color .15s, transform .15s;
}
.btn-primary:hover { background: var(--primary-press); }
.btn-primary:active { transform: scale(.985); }
.btn-primary i { font-size: 20px; }
.btn-primary[disabled],
.btn-primary.is-busy {
    background: rgba(91, 91, 214, .8);
    cursor: not-allowed;
    transform: none;
}
.btn-primary.is-ghosted {
    background: var(--m3-surface-container);
    color: var(--m3-outline);
    cursor: not-allowed;
    box-shadow: none;
}
.btn-outline {
    width: 100%;
    height: 44px;
    border-radius: var(--r-sm);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-sm);
    background: var(--surface);
    color: var(--primary);
    font-family: var(--font-display);
    font-size: var(--fs-label-lg);
    font-weight: 600;
    box-shadow: inset 0 0 0 1px var(--primary);
    transition: background-color .15s, transform .15s;
}
.btn-outline:hover { background: var(--primary-soft); }
.btn-outline:active { transform: scale(.985); }
.btn-outline i { font-size: 20px; }
.btn-outline.is-soft {
    box-shadow: inset 0 0 0 1px var(--line);
    color: var(--ink);
}
.btn-outline.is-soft:hover { background: var(--m3-surface-container-low); }
.sheet-hint {
    text-align: center;
    font-size: 11px;
    line-height: 14px;
    color: var(--fg-2);
}

@keyframes spin { to { transform: rotate(360deg); } }
.is-spinning { display: inline-flex; animation: spin 1s linear infinite; }

/* --------------------------------------------------------------------------
   12.4 空态（_5 不支持查课 / 查不到课程）
   -------------------------------------------------------------------------- */
.empty-block {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-md);
    padding: var(--sp-xl) 0;
    text-align: center;
}
.empty-block > .e-ico {
    width: 64px;
    height: 64px;
    border-radius: var(--r-full);
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--m3-surface-container-low);
    color: var(--m3-outline-variant);
    font-size: 34px;
}
.empty-block .e-title {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--fs-headline-sm);
    line-height: var(--lh-headline-sm);
    font-weight: 600;
    color: var(--fg);
}
.empty-block .e-sub {
    margin: 0;
    font-size: 13px;
    line-height: 20px;
    color: var(--fg-2);
    max-width: 280px;
}
.chip-soft {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 10px;
    border-radius: var(--r-full);
    background: var(--m3-surface-container-low);
    font-size: 11px;
    line-height: 14px;
    color: var(--m3-on-surface-variant);
}
.chip-soft i { font-size: 14px; }
.kf-hours {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    font-size: 11px;
    line-height: 14px;
    color: var(--fg-2);
}
.kf-hours::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: var(--r-full);
    background: var(--success);
    flex: 0 0 auto;
}

/* ==========================================================================
   13. 查课与选课页（全页面版）
   来源：stitch_ui «查课与选课» 导出。
   相对原稿的调整（均已按后端真实契约核对）：
     · 「教师: XXX」→ 删除，getWk 不返回教师
     · 「进度: 0/16 章节」→ 改为百分比进度条，上游 process 是 "45%" 而非章节数
     · 「必修通识/选修素养」课程分类标签 → 删除，无课程级分类
     · 明文密码 value、QA 状态切换条、alert() 演示逻辑 → 全部剔除
   ========================================================================== */

/* 13.1 页面顶栏 */
.page-head {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 50;
    background: color-mix(in srgb, var(--surface) 80%, transparent);
    -webkit-backdrop-filter: blur(20px) saturate(180%);
    backdrop-filter: blur(20px) saturate(180%);
    border-bottom: 1px solid var(--line);
    padding-top: var(--safe-top);
}
.page-head-in {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-sm);
    height: 56px;
    max-width: 430px;
    margin: 0 auto;
    padding: 0 var(--margin);
}
.page-head-btn {
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--r-sm);
    color: var(--fg);
    font-size: 24px;
    flex: 0 0 auto;
    transition: color .15s, background-color .15s;
}
.page-head-btn:hover { color: var(--brand); background: var(--surface-2); }
.page-title {
    flex: 1 1 auto;
    margin: 0;
    text-align: center;
    font-family: var(--font-display);
    font-size: var(--fs-headline-sm);
    line-height: var(--lh-headline-sm);
    font-weight: 600;
    color: var(--fg);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.page-avatar {
    width: 32px;
    height: 32px;
    border-radius: var(--r-full);
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--brand);
    color: var(--on-brand);
    font-size: 18px;
    flex: 0 0 auto;
}

/* 13.2 通用卡片 */
.card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    box-shadow: var(--e1);
    padding: var(--sp-md);
}
.card + .card { margin-top: var(--sp-md); }
.card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-sm);
}
.card-title {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--fs-headline-sm);
    line-height: var(--lh-headline-sm);
    font-weight: 600;
    color: var(--fg);
}

/* 13.3 服务摘要卡 */
.svc-main { display: flex; align-items: center; gap: var(--sp-sm); min-width: 0; }
.svc-ico {
    width: 40px;
    height: 40px;
    border-radius: var(--r-sm);
    background: var(--brand-soft);
    color: var(--brand-soft-fg);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 22px;
    flex: 0 0 auto;
}
.svc-name-row { display: flex; align-items: center; gap: var(--sp-xs); flex-wrap: wrap; }
.svc-name {
    font-family: var(--font-display);
    font-size: var(--fs-headline-sm);
    line-height: var(--lh-headline-sm);
    font-weight: 600;
    color: var(--fg);
}
.svc-price { margin: 2px 0 0; font-size: var(--fs-body-sm); line-height: var(--lh-body-sm); color: var(--fg-2); }
.svc-price b { color: var(--brand); font-weight: 600; }
.svc-toggle {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 4px 8px;
    border-radius: var(--r-xs);
    background: var(--surface-2);
    color: var(--fg-2);
    font-size: var(--fs-label-sm);
    flex: 0 0 auto;
}
.svc-toggle i { font-size: 16px; transition: transform .2s; }
.svc-toggle.on i { transform: rotate(180deg); }
.svc-detail {
    margin-top: var(--sp-sm);
    padding: var(--sp-sm);
    border-radius: var(--r-xs);
    background: var(--surface-2);
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.svc-detail div { display: flex; align-items: flex-start; gap: 6px; font-size: var(--fs-body-sm); line-height: var(--lh-body-sm); color: var(--fg-2); }
.svc-detail i { font-size: 16px; color: var(--brand); flex: 0 0 auto; margin-top: 1px; }

/* 13.4 账号摘要条 */
.acct-bar { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-sm); }
.acct-left { display: flex; align-items: center; gap: var(--sp-sm); min-width: 0; }
.acct-ico {
    width: 32px; height: 32px;
    border-radius: var(--r-xs);
    background: var(--surface-2);
    color: var(--brand);
    display: flex; align-items: center; justify-content: center;
    font-size: 18px; flex: 0 0 auto;
}
.acct-name { font-size: var(--fs-label-md); line-height: var(--lh-label-md); font-weight: 600; color: var(--fg); }
.acct-sub { font-size: var(--fs-label-sm); line-height: var(--lh-label-sm); color: var(--fg-2); }
.btn-ghost {
    padding: 6px 12px;
    border-radius: var(--r-xs);
    background: var(--surface-2);
    color: var(--brand);
    font-size: var(--fs-label-sm);
    font-weight: 600;
    flex: 0 0 auto;
    transition: background-color .15s, transform .15s;
}
.btn-ghost:hover { background: var(--brand-soft); }
.btn-ghost:active { transform: scale(.97); }

/* 13.5 状态视图（未查询 / 查询中 / 无课程） */
.state-view {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 40px var(--sp-lg);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    box-shadow: var(--e1);
}
.state-ico {
    width: 48px; height: 48px;
    border-radius: var(--r-full);
    background: var(--surface-2);
    color: var(--brand);
    display: flex; align-items: center; justify-content: center;
    font-size: 26px;
    margin-bottom: var(--sp-sm);
}
.state-title {
    margin: 0 0 4px;
    font-family: var(--font-display);
    font-size: var(--fs-headline-sm);
    line-height: var(--lh-headline-sm);
    font-weight: 600;
    color: var(--fg);
}
.state-sub {
    margin: 0;
    max-width: 260px;
    font-size: var(--fs-body-sm);
    line-height: var(--lh-body-sm);
    color: var(--fg-2);
}

/* 13.6 表单错误条 */
.form-err {
    display: flex;
    align-items: center;
    gap: var(--sp-sm);
    padding: var(--sp-sm);
    border-radius: var(--r-xs);
    background: var(--m3-error-container);
    color: var(--m3-on-error-container);
    font-size: var(--fs-body-sm);
    line-height: var(--lh-body-sm);
    margin-bottom: var(--sp-md);
}
.form-err i { font-size: 18px; flex: 0 0 auto; }

/* 13.7 选课列表 */
.pick-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-sm);
    margin-bottom: var(--sp-sm);
}
.pick-title { margin: 0; font-family: var(--font-display); font-size: var(--fs-headline-sm); line-height: var(--lh-headline-sm); font-weight: 600; color: var(--fg); }
.pick-stat { margin: 2px 0 0; font-size: var(--fs-label-sm); line-height: var(--lh-label-sm); color: var(--fg-2); }
.pick-stat b { color: var(--brand); font-weight: 700; }

.pick-filter { position: relative; display: flex; align-items: center; margin-bottom: var(--sp-sm); }
.pick-filter > i { position: absolute; left: 12px; font-size: 18px; color: var(--fg-3); pointer-events: none; }
.pick-filter input {
    width: 100%;
    height: 40px;
    padding: 0 12px 0 36px;
    border: 0;
    outline: 0;
    border-radius: var(--r-sm);
    background: var(--surface);
    color: var(--fg);
    font-family: var(--font-body);
    font-size: var(--fs-body-sm);
    box-shadow: inset 0 0 0 1px var(--line);
}
.pick-filter input::placeholder { color: var(--fg-3); }
.pick-filter input:focus { box-shadow: inset 0 0 0 1.5px var(--brand), 0 0 0 3px var(--brand-glow); }

.pick-list { display: flex; flex-direction: column; gap: var(--sp-sm); }

.course {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--sp-sm);
    padding: var(--sp-md);
    border-radius: var(--r-sm);
    background: var(--surface);
    border: 1px solid var(--line);
    cursor: pointer;
    transition: background-color .18s, border-color .18s, transform .18s;
}
.course:active { transform: scale(.995); }
.course.on {
    border-color: var(--brand);
    background: color-mix(in srgb, var(--brand-soft) 55%, var(--surface));
}
.course-left { display: flex; align-items: flex-start; gap: var(--sp-sm); min-width: 0; flex: 1 1 auto; }
.course-body { min-width: 0; }

/* 复选框 */
.cbox {
    width: 20px; height: 20px;
    margin-top: 2px;
    border-radius: 6px;
    background: transparent;
    box-shadow: inset 0 0 0 1.5px var(--ctl-line);
    display: flex; align-items: center; justify-content: center;
    color: transparent;
    font-size: 15px;
    flex: 0 0 auto;
    transition: background-color .15s, box-shadow .15s, color .15s;
}
.course.on .cbox {
    background: var(--brand);
    box-shadow: none;
    color: var(--on-brand);
}
.course-name {
    display: block;
    font-family: var(--font-display);
    font-size: var(--fs-headline-sm);
    line-height: var(--lh-headline-sm);
    font-weight: 600;
    color: var(--fg);
    overflow-wrap: anywhere;
}
.course-meta {
    margin: 3px 0 0;
    font-size: var(--fs-body-sm);
    line-height: var(--lh-body-sm);
    color: var(--fg-2);
    overflow-wrap: anywhere;
}
.course-prog { display: flex; align-items: center; gap: 6px; margin-top: 6px; }
.prog-track {
    width: 72px; height: 4px;
    border-radius: var(--r-full);
    background: var(--track);
    overflow: hidden;
    flex: 0 0 auto;
}
.prog-fill {
    height: 100%;
    border-radius: var(--r-full);
    background: var(--accent);
}
.course-pct {
    font-family: var(--font-display);
    font-variant-numeric: tabular-nums;
    font-size: var(--fs-label-sm);
    color: var(--fg-2);
}
.course-pct.is-unknown { color: var(--fg-3); }
.course-right { text-align: right; flex: 0 0 auto; padding-left: var(--sp-xs); }
.course-price {
    font-family: var(--font-display);
    font-variant-numeric: tabular-nums;
    font-size: var(--fs-headline-sm);
    font-weight: 600;
    color: var(--brand);
}
.course.is-done { opacity: .6; }
.course.is-done .cbox { cursor: not-allowed; }

/* 标签胶囊 */
.tag {
    display: inline-block;
    padding: 2px 6px;
    border-radius: var(--r-xs);
    background: var(--surface-2);
    color: var(--fg-2);
    font-size: 10px;
    line-height: 12px;
    font-weight: 500;
    white-space: nowrap;
}
.tag.is-mint { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent); }

/* 13.8 吸底结算栏 */
.checkout {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 40;
    background: color-mix(in srgb, var(--surface) 92%, transparent);
    -webkit-backdrop-filter: blur(16px);
    backdrop-filter: blur(16px);
    border-top: 1px solid var(--line);
    padding-bottom: var(--safe-bottom);
}
.checkout-in {
    max-width: 430px;
    margin: 0 auto;
    height: 64px;
    padding: 0 var(--margin);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-sm);
}
.checkout-count { font-size: 10px; line-height: 12px; color: var(--fg-2); }
.checkout-count b { color: var(--fg); font-weight: 600; }
.checkout-total { display: flex; align-items: baseline; gap: 4px; }
.checkout-total > span { font-size: var(--fs-label-sm); color: var(--fg-2); }
.checkout-total > b {
    font-family: var(--font-display);
    font-variant-numeric: tabular-nums;
    font-size: var(--fs-headline-md);
    font-weight: 600;
    color: var(--brand);
}
.checkout-btn {
    height: 44px;
    padding: 0 22px;
    border-radius: var(--r-sm);
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: var(--brand);
    color: var(--on-brand);
    font-family: var(--font-display);
    font-size: var(--fs-label-md);
    font-weight: 600;
    box-shadow: var(--e1);
    transition: background-color .15s, transform .15s;
}
.checkout-btn:hover { background: var(--brand-press); }
.checkout-btn:active { transform: scale(.98); }
.checkout-btn i { font-size: 18px; }
.checkout-btn[disabled] {
    background: var(--surface-2);
    color: var(--fg-3);
    cursor: not-allowed;
    box-shadow: none;
}
.checkout-btn[disabled]:hover { background: var(--surface-2); }

/* 页面主体：给固定顶栏与吸底栏留出空间 */
.page-body {
    max-width: 430px;
    margin: 0 auto;
    padding: calc(56px + var(--safe-top) + var(--sp-md)) var(--margin) calc(88px + var(--safe-bottom));
}
