/* ==========================================================================
   韵加速用户中心 —— 手写样式表
   取代 ant-design-vue（打包后 1.6MB JS + 13KB CSS）。

   结构：
     1. 设计令牌        —— 色板 / 圆角 / 间距 / 阴影 / 动效
     2. 基础与背景      —— 分层渐变 + 噪点 + 暗角（不再依赖大图壁纸）
     3. 玻璃层          —— 三层阴影 + 渐变描边 + 顶部高光
     4. 排版与原子类
     5. 布局            —— 顶栏 / 侧栏 / 抽屉 / 页脚
     6. 组件            —— 卡片 / 按钮 / 输入 / 开关 / 单选 / 标签 / 标签页 / 弹窗 / 提示
     7. 页面            —— 首页 / 续费 / 帮助 / 独立出口
     8. 响应式与暗色
   ========================================================================== */

/* ------------------------------------------------------------------ 1. 令牌 */

:root {
    /* 主色与语义色 */
    --blue:   #007AFF;
    --blue-d: #0062cc;
    --green:  #34C759;
    --red:    #FF3B30;
    --amber:  #f59e0b;
    --purple: #722ed1;

    /* 文字 */
    --ink:    #1d1d1f;
    --ink-2:  #3a3a3f;
    --muted:  #86868b;
    --muted-2:#a1a1aa;

    /* 线与面 */
    --line:      rgba(0, 0, 0, .06);
    --line-2:    rgba(0, 0, 0, .04);
    --surface:   rgba(0, 0, 0, .03);

    /* 玻璃 */
    --glass-bg:  rgba(255, 255, 255, .46);
    --glass-bg-hi: rgba(255, 255, 255, .62);
    --glass-brd: rgba(255, 255, 255, .72);
    --blur:      20px;
    --sat:       180%;

    /* 圆角 */
    --r-xl: 22px;
    --r-lg: 16px;
    --r-md: 12px;
    --r-sm: 8px;
    --r-pill: 999px;

    /* 间距（8pt 栅格） */
    --sp-1: 8px;
    --sp-2: 16px;
    --sp-3: 24px;
    --sp-4: 32px;
    --sp-5: 48px;

    /* 阴影：贴地近影 + 中距扩散 + 内高光 */
    --sh-1: 0 1px 2px rgba(16, 24, 40, .04),
            0 4px 12px rgba(16, 24, 40, .05);
    --sh-2: 0 2px 4px rgba(16, 24, 40, .05),
            0 12px 28px rgba(16, 24, 40, .09);
    --sh-3: 0 4px 8px rgba(16, 24, 40, .06),
            0 24px 56px rgba(16, 24, 40, .14);
    --sh-inset: inset 0 1px 0 rgba(255, 255, 255, .8);

    /* 动效 */
    --ease: cubic-bezier(.25, .8, .25, 1);
    --ease-pop: cubic-bezier(.175, .885, .32, 1.275);
    --dur: 200ms;
    --dur-fast: 130ms;

    --focus: 0 0 0 3px rgba(0, 122, 255, .28);
}

/* ------------------------------------------------------------- 2. 基础与背景 */

*, *::before, *::after { box-sizing: border-box; }

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

/*
 * 必须放在最前面。
 *
 * hidden 属性是靠浏览器默认样式 [hidden]{display:none} 生效的，而它的优先级
 * 与类选择器相同（都是 0,1,0）—— 只要本文件里给同一个元素写了 display
 * （例如 .modal-scrim{display:flex}、.overlay{display:flex}），
 * 后出现的规则就会赢，hidden 直接失效。
 *
 * 后果正是：弹窗、遮罩一进页面就全部显示出来，而且点关闭按钮也关不掉
 * （JS 确实执行了 hidden=true，只是视觉上没有任何变化，看起来就像按钮点不动）。
 */
[hidden] { display: none !important; }


body {
    margin: 0;
    min-width: 320px;
    min-height: 100vh;
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI",
                 Roboto, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", Arial, sans-serif;
    font-size: 15px;
    line-height: 1.6;
    color: var(--ink);
    background-color: #f2f5f8;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    font-synthesis: none;
    text-rendering: optimizeLegibility;
}

/*
 * 背景自下而上四层：
 *   .bg          照片壁纸（assets/bg.webp）
 *   .aurora      柔和光斑
 *   .grain       极细噪点
 *   body::after  暗角
 *
 * 历史：迁移时一度把照片换成纯 CSS 光斑（不占带宽、缩放不损失）。
 * 但毛玻璃在照片上才看得出效果 —— 这张图高频细节多（云、方块、花），
 * backdrop-filter 有东西可糊；纯渐变色糊出来几乎是平的，玻璃看着像塑料。
 *
 * 光斑保留，但默认调得很淡：它原本是用来**替代**照片的，
 * 照片回来了它就不该抢戏（左上那团蓝正好压在照片的太阳上）。
 * 用 --aurora-alpha 控制，0 就是完全关掉。
 */
.aurora {
    position: fixed;
    inset: -20vmax;
    z-index: -2;
    pointer-events: none;
    opacity: var(--aurora-alpha);
    background:
        radial-gradient(48vmax 36vmax at 10% 4%, rgba(63, 133, 214, .17), transparent 62%),
        radial-gradient(46vmax 38vmax at 92% 88%, rgba(75, 146, 155, .12), transparent 62%);
    filter: blur(10px) saturate(120%);
    animation: drift 44s var(--ease) infinite alternate;
}

/* ------------------------------------------------ 2b. 背景照片与三个旋钮 */

/*
 * 这张照片**不做任何整体处理**：不模糊、不调亮度、不压白纱。
 *
 * 原因：任何一层半透明叠加都会拉低照片对比度，观感上就是"糊"和"灰"。
 * 尤其是一层白色薄纱压上去，整张图会明显发白，看起来像失焦。
 * 所以这里只留下裁剪位置一个旋钮。
 *
 *   --bg-position   照片裁剪位置。构图敏感：太阳在左上角，默认 center 时
 *                   它会落在顶栏和侧栏后面，可能把 logo 冲淡。
 *                   画面往下走调 "center 65%"，往上调 "center 20%"
 *   --bg-scrim      照片上的薄纱，默认完全透明。只在页脚之类"直接压在
 *                   背景上的文字"读不清时才需要，调成 rgba(242,245,248,.25)
 *   --aurora-alpha  原来的光斑。名字里的"光斑"当初就是用来**替代**这张照片的，
 *                   照片回来了它就没必要，默认 0（关闭）
 */
:root {
    --bg-image:     none;
    --bg-position:  center;
    --bg-scrim:     transparent;
    --aurora-alpha: 1;          /* 无照片时，光斑是主角 */
}

/* ------------------------------------------------ 2c. 主题预设（背景） */

/*
 * 主题切换改的就是这里。data-theme 写在 <html> 上：
 * 服务端按 cookie 渲染（首屏不闪），<head> 里的内联脚本把 auto 解析成实际明暗。
 *
 *   auto / light / dark   纯 CSS 光斑，没有照片 —— 迁移后的原始样子
 *   grass                 背景照片
 *
 * 照片主题原有三个（cloud 云海 / castle 城堡 / grass 草原），
 * 后来只留 grass：同一张照片挪三个裁剪位置，观感差别很小，
 * 主题菜单却白白长了三条。要换构图改下面那个 --bg-position 就行。
 */
:root[data-theme="grass"] {
    --bg-image:     url('/assets/bg.webp');
    --aurora-alpha: 0;          /* 有照片时让光斑退场，别跟照片抢戏 */
    --bg-position:  32% 96%;    /* 草地与 Steve（画面下方） */
}

/*
 * 照片放在独立的 fixed 层，而不是写在 body 的 background 上。
 * 原因：body { background-attachment: fixed } 在 iOS Safari 上不生效，
 * 会被当成 scroll，cover 于是按**整页高度**拉伸，画面会糊成一大块。
 * 固定层 + background-size: cover 在所有浏览器上表现一致。
 */
.bg {
    position: fixed;
    inset: 0;
    z-index: -3;                 /* 比 aurora(-2) 再低一层 */
    pointer-events: none;
    background-image: var(--bg-image);
    background-position: var(--bg-position);
    background-size: cover;
    background-repeat: no-repeat;
}

/*
 * 薄纱层，默认全透明。
 *
 * 注意：**不要**给 .bg 加 filter —— 哪怕 brightness(1) 这种恒等变换也不行。
 * 元素一旦有 filter，浏览器就得把它先单独栅格化成一个图层再合成，
 * 而在部分浏览器 / 高分屏上这一层的栅格化分辨率会掉，照片看上去就发虚。
 * 要调明暗请改 --bg-scrim：那只是一层普通叠加，不触发额外栅格化。
 */
.bg::after {
    content: '';
    position: absolute;
    inset: 0;
    background: var(--bg-scrim);
}

/* 噪点：压掉渐变的塑料感，做出磨砂纸的质感 */
.grain {
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    opacity: .34;
    mix-blend-mode: soft-light;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* 暗角：让视线聚焦到中间内容 */
body::after {
    content: '';
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background: radial-gradient(120% 90% at 50% 40%, transparent 55%, rgba(16, 24, 40, .07));
}

@keyframes drift {
    0%   { transform: translate3d(0, 0, 0) scale(1); }
    50%  { transform: translate3d(2%, -2%, 0) scale(1.06); }
    100% { transform: translate3d(-2%, 2%, 0) scale(1.03); }
}

/* ---------------------------------------------------------------- 3. 玻璃层 */

/*
 * 玻璃质感由四层叠出来：
 *   backdrop-filter 模糊+提饱和  → 底下的光斑透上来
 *   半透明白底                   → 决定"厚度"
 *   1px 亮边（渐变伪元素）       → 模拟玻璃切边的高光
 *   三层阴影 + 顶部内高光        → 离地感
 */
.glass {
    position: relative;
    background: var(--glass-bg);
    -webkit-backdrop-filter: blur(var(--blur)) saturate(var(--sat));
    backdrop-filter: blur(var(--blur)) saturate(var(--sat));
    border-radius: var(--r-lg);
    box-shadow: var(--sh-1), var(--sh-inset);
}

.glass::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    padding: 1px;
    background: linear-gradient(160deg,
                rgba(255, 255, 255, .95),
                rgba(255, 255, 255, .28) 42%,
                rgba(255, 255, 255, .55));
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    mask-composite: exclude;
    pointer-events: none;
}

/* 交互式玻璃（卡片）：hover 轻微上浮并加强阴影 */
.card {
    border-radius: var(--r-lg);
    transition: box-shadow var(--dur) var(--ease);
    overflow: hidden;
}

.card:hover {
    box-shadow: var(--sh-2), var(--sh-inset);
}

/* ------------------------------------------------------------ 4. 排版与原子 */

h1, h2, h3 { margin: 0; font-weight: 600; color: var(--ink); line-height: 1.3; }
p { margin: 0; }

.page-title {
    font-size: 34px;
    font-weight: 700;
    letter-spacing: -.5px;
    margin-bottom: var(--sp-3);
}

.card-head h2,
.card-header-title {
    font-size: 15px;
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 6px;
}

.card-head h2 .muted { font-weight: 400; }

/* 数字类内容用等宽 + tabular-nums，避免跳动、便于核对 */
.mono {
    font-family: "SF Mono", "JetBrains Mono", ui-monospace, Consolas, "Courier New", monospace;
    font-variant-numeric: tabular-nums;
    letter-spacing: -.2px;
}

.xl { font-size: 22px; font-weight: 600; letter-spacing: -.3px; }
.lg { font-size: 18px; }
.sm { font-size: 13px; }
.xs { font-size: 12px; }

.muted    { color: var(--muted); }
.accent   { color: var(--blue); font-weight: 600; }
.center   { text-align: center; }
.center-text { text-align: center; }
.mx-auto  { margin-left: auto; margin-right: auto; }
.grow     { flex: 1 1 auto; min-width: 0; }
.wrap     { flex-wrap: wrap; }

.mt-2 { margin-top: var(--sp-2); }
.mt-3 { margin-top: var(--sp-3); }
.mt-4 { margin-top: var(--sp-4); }
.mb-3 { margin-bottom: var(--sp-3); }
.mb-4 { margin-bottom: var(--sp-4); }

.ico-blue  { color: var(--blue); }
.ico-green { color: var(--green); }
.ico-red   { color: var(--red); }
.ico-amber { color: var(--amber); }

.stack   { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.stack-2 { display: flex; flex-direction: column; gap: var(--sp-1); }
.stack-3 { display: flex; flex-direction: column; gap: var(--sp-3); }

.row-inline  { display: flex; align-items: center; }
.row-between { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); }
.row-end     { display: flex; justify-content: flex-end; }
.gap-2 { gap: var(--sp-2); }
.gap-3 { gap: var(--sp-3); }

.divider {
    height: 1px;
    border: 0;
    margin: var(--sp-2) 0;
    background: var(--line-2);
}

.empty {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-1);
    padding: var(--sp-3);
    border-radius: var(--r-md);
    background: var(--surface);
    color: var(--muted);
    font-size: 14px;
}

/* ---------------------------------------------------------------- 5. 布局 */

.app {
    max-width: 1440px;
    margin: 0 auto;
    padding: 0 var(--sp-2);
    padding-top: env(safe-area-inset-top, 0px);
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

.topbar {
    position: relative;
    z-index: 40;
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    height: 64px;
    padding: 0 var(--sp-3);
    margin-bottom: var(--sp-2);
    border-radius: 0 0 var(--r-lg) var(--r-lg);
}

.brand { display: flex; align-items: center; margin-right: auto; }
.brand img { display: block; height: 32px; width: auto; }

/*
 * 顶栏 logo 的两个版本，按**实际生效的明暗**切换。
 *
 *   .logo-light  logo.png    深色字 —— 浅底上用
 *   .logo-dark   logo-w.png  白色字 —— 深底上用
 *
 * 为什么用 data-scheme 而不是 data-theme：auto 和草原主题都跟随系统，
 * 真正决定"背景是深是浅"的是 scheme；用 theme 判断的话，
 * 系统是深色而主题是 auto 时会选错图（白字压在白玻璃上）。
 *
 * 两张图都在文档里、由 CSS 切换，而不是 JS 换 src ——
 * 换 src 的那一瞬新图还没下载完，logo 会先空一下再出现。
 *
 * 特异性说明：上面那条 .brand img 是 (0,1,1)，所以这两条必须写到
 * (0,2,0) 以上才压得住它，不能只写 .logo-dark。
 */
.brand .logo-dark { display: none; }
:root[data-scheme="dark"] .brand .logo-light { display: none; }
:root[data-scheme="dark"] .brand .logo-dark  { display: block; }

.topbar-right { display: flex; align-items: center; gap: var(--sp-1); }

.shell { display: flex; gap: var(--sp-3); flex: 1; align-items: flex-start; }

.sidebar {
    width: 240px;
    flex: 0 0 240px;
    padding: var(--sp-2) var(--sp-2) var(--sp-3);
    position: sticky;
    top: var(--sp-2);
}

.nav { display: flex; flex-direction: column; gap: 4px; padding: 0 var(--sp-1); }

.nav-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 11px 14px;
    border-radius: var(--r-md);
    color: var(--ink-2);
    text-decoration: none;
    font-size: 14px;
    font-weight: 500;
    transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease),
                transform var(--dur-fast) var(--ease);
}

.nav-item:hover { background: rgba(255, 255, 255, .58); transform: translateX(2px); }
.nav-item:active { transform: translateX(2px) scale(.985); }

.nav-item.is-active {
    background: var(--blue);
    color: #fff;
    box-shadow: 0 6px 16px rgba(0, 122, 255, .28);
}

.main { flex: 1 1 auto; min-width: 0; padding: 0 var(--sp-2) var(--sp-4); }

.footer {
    padding: var(--sp-3) 0 calc(var(--sp-3) + env(safe-area-inset-bottom, 0px));
    text-align: center;
    color: var(--muted-2);
    font-size: 13px;
}

/* 移动端抽屉 */
.drawer-scrim {
    position: fixed;
    inset: 0;
    z-index: 60;
    background: rgba(16, 24, 40, .28);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
    animation: fade var(--dur) var(--ease);
}

.drawer {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 61;
    width: 280px;
    max-width: 84vw;
    padding: var(--sp-2);
    border-radius: 0 var(--r-xl) var(--r-xl) 0;
    transform: translateX(-104%);
    transition: transform 260ms var(--ease);
    overflow-y: auto;
}

.drawer.is-open { transform: translateX(0); }

.drawer-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 72px;
    padding: 0 var(--sp-1);
}

/* ---------------------------------------------------------------- 6. 组件 */

/* ---- 卡片 ---- */

/*
 * 少数卡片里放了向下展开的下拉菜单（首页的出口选择）。
 * .card{overflow:hidden} 会把浮在卡片外的菜单裁掉，菜单项一多就点不到，
 * 这类卡片显式放开裁剪 —— 它内部没有需要被圆角裁掉的内容，放开是安全的。
 */
.card-menu-overflow { overflow: visible; }

.card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-2);
    min-height: 48px;
    padding: 0 var(--sp-3);
    border-bottom: 1px solid var(--line-2);
}

.card-body { padding: var(--sp-3); }

.grid {
    display: grid;
    grid-template-columns: repeat(24, 1fr);
    gap: var(--sp-3);
}

.span-8  { grid-column: span 8; }
.span-16 { grid-column: span 16; }
.span-24 { grid-column: span 24; }

/* ---- 图标容器 ---- */
.icon-badge {
    width: 56px;
    height: 56px;
    flex: 0 0 56px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 15px;
    background: rgba(0, 122, 255, .1);
    color: var(--blue);
}

/* ---- 按钮 ---- */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 9px 18px;
    border: 1px solid transparent;
    border-radius: var(--r-md);
    background: rgba(255, 255, 255, .72);
    color: var(--ink);
    font-family: inherit;
    font-size: 14px;
    font-weight: 500;
    line-height: 1.4;
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: transform var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease),
                background var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease);
}

.btn:hover   { background: rgba(255, 255, 255, .92); box-shadow: var(--sh-1); }
.btn:active  { transform: scale(.975); }
.btn:disabled,
.btn[disabled] { opacity: .48; cursor: not-allowed; transform: none; box-shadow: none; }

.btn-primary {
    background: var(--blue);
    color: #fff;
    box-shadow: 0 4px 12px rgba(0, 122, 255, .26);
}
.btn-primary:hover { background: var(--blue-d); box-shadow: 0 6px 18px rgba(0, 122, 255, .34); }

.btn-ghost { background: transparent; border-color: var(--line); }
.btn-ghost:hover { background: rgba(255, 255, 255, .6); }

.btn-plain {
    background: var(--surface);
    border-color: transparent;
    box-shadow: none;
    justify-content: space-between;
    font-weight: 500;
}
.btn-plain:hover { background: rgba(0, 0, 0, .05); box-shadow: none; }

.btn-danger-ghost {
    background: rgba(255, 59, 48, .08);
    color: var(--red);
    border-color: rgba(255, 59, 48, .22);
}
.btn-danger-ghost:hover { background: rgba(255, 59, 48, .14); }

.btn-block { width: 100%; }
.btn-lg    { padding: 13px 22px; font-size: 15px; }
.btn-sm    { padding: 6px 12px; font-size: 13px; }
.btn-round { border-radius: var(--r-pill); }

.icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    border: 0;
    border-radius: var(--r-sm);
    background: transparent;
    color: var(--muted);
    cursor: pointer;
    transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.icon-btn:hover { background: rgba(0, 0, 0, .05); color: var(--ink); }

.btn-row { display: flex; align-items: center; gap: var(--sp-1); flex-wrap: wrap; }

/* ---- 表单 ---- */

/*
 * 输入框用固定高度而不是上下 padding：这样和并排的按钮天然对齐，
 * 也避免"图标绝对定位 + padding-left 被后来的规则覆盖"导致图标压住文字。
 */
.input {
    width: 100%;
    height: 46px;
    padding: 0 14px;
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    background: rgba(255, 255, 255, .66);
    color: var(--ink);
    font-family: inherit;
    font-size: 14px;
    line-height: 1.2;
    transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease),
                background var(--dur-fast) var(--ease);
}

.input::placeholder { color: var(--muted-2); }

.input:hover:not(:disabled) { border-color: rgba(0, 0, 0, .13); }

.input:focus {
    outline: none;
    border-color: rgba(0, 122, 255, .55);
    background: #fff;
    box-shadow: var(--focus);
}

.input:disabled { background: rgba(0, 0, 0, .04); color: var(--muted); cursor: not-allowed; }

.field { display: block; margin-bottom: var(--sp-2); }

.field-label {
    display: block;
    margin-bottom: 7px;
    font-size: 13px;
    font-weight: 500;
    color: var(--ink-2);
}

/* 输入框 + 左侧图标 */
.input-wrap { position: relative; display: block; }

.input-wrap .input { padding-left: 42px; }

.input-wrap .input-ico {
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    align-items: center;
    color: var(--muted-2);
    pointer-events: none;
}

/* 输入框 + 右侧按钮并排（短信 / 邮箱验证码） */
.input-row { display: flex; gap: var(--sp-1); align-items: stretch; }
.input-row > .input,
.input-row > .input-wrap { flex: 1 1 auto; min-width: 0; }

.input-row > .btn {
    flex: 0 0 auto;
    height: 46px;
    min-width: 112px;   /* 固定最小宽度，"60s" 倒计时不会让按钮忽宽忽窄 */
}

.hint { min-height: 18px; margin-top: 4px; font-size: 12px; color: var(--muted); }

/* 开关 */
.switch { display: inline-flex; align-items: center; gap: var(--sp-1); cursor: pointer; user-select: none; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }

.switch-track {
    position: relative;
    width: 46px;
    height: 26px;
    border-radius: var(--r-pill);
    background: rgba(0, 0, 0, .16);
    transition: background var(--dur) var(--ease);
    flex: 0 0 auto;
}

.switch-thumb {
    position: absolute;
    top: 3px;
    left: 3px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .25);
    transition: transform var(--dur) var(--ease);
}

.switch input:checked + .switch-track { background: var(--blue); }
.switch input:checked + .switch-track .switch-thumb { transform: translateX(20px); }
.switch input:focus-visible + .switch-track { box-shadow: var(--focus); }

.switch-label { font-size: 13px; font-weight: 500; color: var(--ink-2); min-width: 32px; }

/* 复选框 */
.checkbox {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    font-size: 14px;
    line-height: 1.55;
    color: var(--ink-2);
    cursor: pointer;
}

.checkbox input {
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
    margin: 3px 0 0;
    accent-color: var(--blue);
    cursor: pointer;
}

/* 单选按钮组 */
.radio-group { display: flex; width: 100%; }

.radio-pill { flex: 1; }
.radio-pill input { position: absolute; opacity: 0; width: 0; height: 0; }

.radio-pill span {
    display: block;
    padding: 8px 4px;
    text-align: center;
    font-size: 13px;
    color: var(--ink-2);
    background: rgba(255, 255, 255, .55);
    border: 1px solid var(--line);
    border-left-width: 0;
    cursor: pointer;
    transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

.radio-pill:first-child span { border-left-width: 1px; border-radius: var(--r-sm) 0 0 var(--r-sm); }
.radio-pill:last-child span  { border-radius: 0 var(--r-sm) var(--r-sm) 0; }

.radio-pill input:checked + span {
    background: var(--blue);
    border-color: var(--blue);
    color: #fff;
    font-weight: 600;
}

.radio-pill input:focus-visible + span { box-shadow: var(--focus); }

/* 标签 */
.tag {
    display: inline-flex;
    align-items: center;
    padding: 3px 12px;
    border-radius: var(--r-pill);
    font-size: 13px;
    font-weight: 600;
    background: rgba(0, 0, 0, .06);
    color: var(--ink-2);
}

.tag[style*="--tag"] { background: color-mix(in srgb, var(--tag) 16%, transparent); color: var(--tag); }

.tag-blue   { background: rgba(0, 122, 255, .12); color: var(--blue); }
.tag-orange { background: rgba(245, 158, 11, .14); color: #b45309; }
.tag-red    { background: rgba(255, 59, 48, .12); color: var(--red); }
.tag-default{ background: rgba(0, 0, 0, .06); color: var(--muted); }

/* 标签页 */
.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--line); margin-bottom: var(--sp-2); }

.tab {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 10px 18px;
    border: 0;
    border-bottom: 2px solid transparent;
    background: transparent;
    color: var(--muted);
    font-family: inherit;
    font-size: 14px;
    cursor: pointer;
    transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}

.tab:hover { color: var(--blue); }
.tab.is-active { color: var(--blue); border-bottom-color: var(--blue); font-weight: 500; }

.tab-panel { min-height: 100px; }

.log-row {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    padding: 10px 12px;
    border-radius: var(--r-sm);
    transition: background var(--dur-fast) var(--ease);
}
.log-row:hover { background: rgba(0, 0, 0, .025); }
.log-row .mono.sm { min-width: 150px; }

/* 下拉菜单 */
.dropdown { position: relative; }

.dropdown-menu {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    min-width: 240px;
    padding: var(--sp-1);
    display: none;
    animation: pop var(--dur) var(--ease);
    z-index: 60;
}

.dropdown-menu.glass { box-shadow: var(--sh-3), var(--sh-inset); }

.dropdown.is-open .dropdown-menu { display: block; }

/*
 * 出口选择：菜单和按钮同宽，向下展开。
 * 原实现用的是 a-dropdown 默认方向（向下），并且菜单渲染在 body 层不会被卡片裁剪；
 * 这里不用 portal，改成让承载卡片放开 overflow（见 .card-menu-overflow）。
 */
.dropdown-block .dropdown-menu { left: 0; right: auto; width: 100%; }

.menu-row {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 10px 12px;
    border: 0;
    border-radius: var(--r-sm);
    background: transparent;
    color: var(--ink-2);
    font-family: inherit;
    font-size: 14px;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
    transition: background var(--dur-fast) var(--ease);
}
.menu-row:hover { background: rgba(0, 0, 0, .05); }

.menu-static { cursor: default; color: var(--muted); }
.menu-static:hover { background: transparent; }
.menu-danger { color: var(--red); }
.menu-danger:hover { background: rgba(255, 59, 48, .08); }

.menu-uid { flex-direction: column; align-items: flex-start; gap: 2px; }
.menu-label { font-size: 12px; color: var(--muted); }

.menu-divider { height: 1px; margin: 6px 4px; background: var(--line); }

.exit-option { flex-direction: column; align-items: flex-start; gap: 2px; }

/* 用户胶囊 */
.user-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 14px;
    border: 1px solid var(--glass-brd);
    border-radius: var(--r-pill);
    background: rgba(255, 255, 255, .46);
    color: var(--ink);
    font-family: inherit;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    transition: background var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.user-chip:hover { background: rgba(255, 255, 255, .82); box-shadow: var(--sh-1); }

.avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--blue);
    color: #fff;
}

.user-name { max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chev { color: var(--muted); }

/* 弹窗 */
.modal-scrim {
    position: fixed;
    inset: 0;
    z-index: 80;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--sp-2);
    background: rgba(16, 24, 40, .3);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    animation: fade var(--dur) var(--ease);
}

/*
 * 不压黑页面的遮罩（绑定手机号用）。
 *
 * 遮罩层本身还在 —— 它仍然负责"点空白处关闭"这件交互，只是不上色、也不做背景模糊，
 * 背后的页面保持原亮度。用户是**主动**点开这张表单来办事的，
 * 没有理由让整个页面陪它变暗。
 *
 * 确认框（#confirm-modal）继续用带色遮罩：那一类弹窗需要打断用户，
 * 观感上本来就该"压住"页面。两种遮罩的差别是有意的，不是漏改。
 */
.modal-scrim.is-plain {
    background: none;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
}

.modal {
    width: 440px;
    max-width: 100%;
    max-height: 88vh;
    overflow-y: auto;
    box-shadow: var(--sh-3), var(--sh-inset);
    animation: pop 240ms var(--ease);
}

.modal-sm { width: 380px; }

.modal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--sp-2) var(--sp-3);
    border-bottom: 1px solid var(--line-2);
}
.modal-head h3 { font-size: 16px; }

.modal-body { padding: var(--sp-3); }

.modal-foot {
    display: flex;
    justify-content: flex-end;
    gap: var(--sp-1);
    padding: var(--sp-2) var(--sp-3);
    border-top: 1px solid var(--line-2);
}

/* 轻提示 */
.toast-host {
    position: fixed;
    top: calc(16px + env(safe-area-inset-top, 0px));
    left: 50%;
    transform: translateX(-50%);
    z-index: 100;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    pointer-events: none;
}

/* 腾讯云验证码的挂载点
 *
 * 这个库是**内联渲染**的：构造时传 DOM 参数，它就把节点插到该容器的文档流位置，
 * 自己不会弹浮层（这个版本不传 DOM、只传 appId 会直接抛
 * "parameter ... passed incorrectly"）。所以**容器放在哪，验证码就出现在哪**。
 *
 * 现在它挂在绑定表单内部（#bindphone-modal 的 modal-body 里）。弹窗本身是
 * max-height:88vh + overflow-y:auto，验证码天然落在可见区域内 ——
 * 既不会跑到屏幕外，也不需要任何定位技巧，而且就长在"获取验证码"按钮下方。
 *
 * 历史：它一度挂在 body 末尾、靠 position:fixed 钉在视口正中。那是在
 * "容器在文档最后 → 页面一长就渲染到屏幕外"这个前提下的补救，
 * 代价是验证码浮在弹窗上方、和表单脱节。容器移进表单后，补救就不再需要。
 *
 * 这里只剩一件事：**没有验证码时不占位**。
 * 用 :empty 判定，所以 layout 里那行 HTML 必须写成 <div id="captcha-host"></div>，
 * 中间不能有空白字符 —— 有空白的文本节点就不算 empty，会白白撑出一段空隙。
 */
#captcha-host { margin-top: var(--sp-2); }
#captcha-host:empty { display: none; }

.toast {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 18px;
    border-radius: var(--r-pill);
    background: rgba(29, 29, 31, .9);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
    color: #fff;
    font-size: 14px;
    box-shadow: var(--sh-2);
    animation: toast-in 240ms var(--ease);
}

.toast.is-out { animation: toast-out 200ms var(--ease) forwards; }
.toast-ok  { background: rgba(28, 128, 60, .94); }
.toast-err { background: rgba(190, 40, 32, .94); }

@keyframes toast-in  { from { opacity: 0; transform: translateY(-12px) scale(.96); } to { opacity: 1; transform: none; } }
@keyframes toast-out { to { opacity: 0; transform: translateY(-10px) scale(.96); } }

/* 页头提示条 */
.notice {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: var(--sp-3);
    padding: 14px var(--sp-3);
    font-size: 14px;
    border-radius: var(--r-md);
}
.notice-warn { color: #8a5a00; background: rgba(255, 250, 230, .82); }
.notice-ok   { color: #1c6b39; background: rgba(232, 250, 238, .82); }

/* 加载骨架 */
.skeleton {
    border-radius: var(--r-sm);
    background: linear-gradient(100deg,
        rgba(0, 0, 0, .05) 30%, rgba(0, 0, 0, .09) 50%, rgba(0, 0, 0, .05) 70%);
    background-size: 220% 100%;
    animation: shimmer 1.3s linear infinite;
}

@keyframes shimmer { from { background-position: 140% 0; } to { background-position: -40% 0; } }

.spin { animation: spin 1s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

@keyframes pop { from { opacity: 0; transform: translateY(8px) scale(.97); } to { opacity: 1; transform: none; } }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }

/* -------------------------------------------------------------- 7. 页面 */

/* ---- 首页 ---- */

/*
 * 注意：这个 tooltip 类叫 .hint-icon，不要叫 .help。
 * .help 已经是帮助页的根容器，两个同权重规则撞在一起时，
 * 这里的 display:inline-flex 会作用到帮助页根节点上，把整页压成一行。
 */
.hint-icon { display: inline-flex; color: var(--muted); cursor: help; }

.id-box {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 16px;
    border: 1px solid var(--line-2);
    border-radius: var(--r-md);
    background: var(--surface);
}

.line-status {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-2);
    border: 1px solid rgba(0, 122, 255, .13);
    margin: 0 0 14px;
    padding: 9px 11px;
    border-radius: 12px;
    background: rgba(0, 122, 255, .045);
}

.premium { position: relative; }

/* 遮罩：未解锁 / 已隐藏前缀 */
.overlay {
    position: absolute;
    inset: 0;
    z-index: 10;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: inherit;
    background: rgba(255, 255, 255, .38);
    -webkit-backdrop-filter: blur(14px) saturate(150%);
    backdrop-filter: blur(14px) saturate(150%);
}

.overlay-inner { display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center; padding: var(--sp-2); }

/*
 * 遮罩还在的时候，把前缀输入框里的文字**彻底藏掉**。
 *
 * 背景：遮罩只有 38% 白纱 + 14px 模糊，底下的真实前缀仍会透出一团灰影。
 * 这张卡的立意就是"前缀已安全隐藏"（.input:disabled 的取色是 --muted，中灰），
 * 透出个影子等于没藏住。
 *
 * 为什么是 transparent 而不是白色：
 *   浅色下两者**观感完全一致** —— 中灰字压在 38% 白纱上，换成白就是看不见。
 *   但深色下不一样：文字取色仍是 --muted(#9a9aa2)，而遮罩是 rgba(20,22,27,.5) 的**深**纱。
 *   在深色背景上把字改成白色，只会比原来**更显眼** —— 等于把"藏"改成了"高亮"。
 *   transparent 两个主题下都是真隐形。
 *
 * 用 :has() 直接跟着遮罩的状态走，而不是另加一个 class 让 JS 去同步：
 *   · 非 PRO：遮罩永远在，文字永远藏着
 *   · PRO：点"修改前缀"后 JS 给遮罩加 hidden，:not([hidden]) 不再匹配，颜色自动撤销
 * 这样"遮住了没有"只有一个真相来源（遮罩的 hidden），
 * 不会出现"遮罩揭了、字还隐着"这种两处状态不同步的 bug。
 *
 * :has() 是 Chrome 105 / Safari 15.4 / Firefox 121 起支持。老浏览器上整条规则被丢弃，
 * 退回到"透出一团灰影"的现状，不会更糟。
 */
.card:has(> .overlay:not([hidden])) #prefix-input { color: transparent; }

.inform { color: var(--ink-2); font-size: 14px; }

/* 线路胶囊 */
.pill-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }

.pill {
    position: relative;
    display: flex;
    align-items: center;
    gap: 10px;
    border: 1px solid var(--line);
    background: rgba(255, 255, 255, .6);
    color: var(--ink);
    font-family: inherit;
    font-weight: 500;
    text-align: left;
    cursor: pointer;
    overflow: hidden;
    height: 44px;
    padding: 0 14px;
    border-radius: 12px;
    font-size: 14px;
    transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease), box-shadow var(--dur) var(--ease), transform var(--dur-fast) var(--ease);
}


.pill-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.dot { width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto; }
.dot-on  { background: var(--green); box-shadow: 0 0 8px rgba(52, 199, 89, .55); position: relative; }
.dot-off { background: var(--red); }

.pill-check { display: inline-flex; animation: pop-in 300ms var(--ease-pop); }

@keyframes pop-in { from { transform: scale(.4); opacity: 0; } to { transform: scale(1); opacity: 1; } }

/* ---- 续费 ---- */
.renew { max-width: 1180px; margin: 0 auto; }

.plan-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); align-items: stretch; gap: 16px; }

.plan {
    display: flex;
    flex-direction: column;
    width: auto;
    min-width: 0;
    max-width: 100%;
    padding: var(--sp-3);
    border: 1px solid var(--line);
    transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
                border-color var(--dur) var(--ease);
}

.plan:hover { transform: translateY(-4px); box-shadow: var(--sh-3), var(--sh-inset); position: relative; z-index: 1; }

.plan-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); padding-bottom: var(--sp-2); }
.plan-head h3 { font-size: 18px; }

.accent-ip  .plan-head h3 { color: #358e39; }

/* 卡片选中态（对应原 selectCard：点击卡片高亮当前选择的套餐） */
.accent-ip.is-selected {
    border-color: rgba(0, 180, 50, .55);
    box-shadow: 0 0 0 2px rgba(0, 152, 0, .18), var(--sh-2), var(--sh-inset);
}

.tag-vip { background: #1890ff; color: #fff; }
.tag-pro { background: var(--purple); color: #fff; }
.tag-ip  { background: #3daa24; color: #fff; }

.plan-price { text-align: center; padding: var(--sp-2) 0; }
.amount { font-size: 28px; font-weight: 700; letter-spacing: -.5px; }

.benefits { list-style: none; margin: 0 0 var(--sp-2); padding: 0; }
.benefits li { display: flex; align-items: flex-start; gap: 8px; margin-bottom: 14px; color: var(--ink-2); }
.benefits li .ico-green, .benefits li .ico-red, .benefits li .ico-amber { margin-top: 3px; flex: 0 0 auto; }

.benefit-title { font-weight: 500; line-height: 1.45; font-size: 14px; }
.benefit-desc  { font-size: 12px; color: var(--muted); line-height: 1.5; margin-top: 2px; }

.coupon-link {
    align-self: flex-end;
    padding: 2px 0;
    border: 0;
    background: none;
    color: var(--muted);
    font-family: inherit;
    font-size: 13px;
    cursor: pointer;
}
.coupon-link:hover { color: var(--blue); }

.plan .radio-group { margin: var(--sp-2) 0; }
.buy-btn { margin-top: auto; }

.accent-ip .buy-btn { background: rgba(0, 133, 18, .98); box-shadow: 0 4px 12px rgba(0, 152, 0, .24); }
.accent-ip .buy-btn:hover { background: rgb(0, 152, 0); }

/* ---- 帮助 ---- */
.help { display: block; max-width: 1000px; margin: 0 auto; }
.help-hero img { width: 100%; padding: 10px 3px; border-radius: var(--r-lg); }

.faq-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-2) var(--sp-3); }
.faq .card-body { color: #666; }

/* ---- 独立出口 ---- */
.info-row { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); padding: 8px 0; }

.steps { display: flex; align-items: center; justify-content: center; }

.step-dot {
    width: 32px;
    height: 32px;
    flex: 0 0 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(0, 0, 0, .06);
    color: var(--muted);
    font-size: 14px;
    font-weight: 600;
    transition: all var(--dur) var(--ease);
}

.step-dot.active { background: var(--blue); color: #fff; box-shadow: 0 4px 12px rgba(0, 122, 255, .3); }
.step-dot.done   { background: var(--green); color: #fff; box-shadow: 0 4px 12px rgba(52, 199, 89, .3); }

/* 已完成的步骤显示对勾而不是数字，由 CSS 完成以便 JS 只切换 class */
.step-dot.done span { display: none; }
.step-dot.done::after { content: '✓'; font-size: 15px; font-weight: 700; }

.step-line { width: 60px; height: 2px; background: rgba(0, 0, 0, .08); transition: background var(--dur) var(--ease); }
.step-line.active { background: var(--blue); }

.step-labels { display: flex; justify-content: center; margin-top: 10px; }
.step-labels span { flex: 1; max-width: 140px; text-align: center; font-size: 13px; color: var(--muted); }
.step-labels span.active { color: var(--blue); font-weight: 500; }

.step-body { animation: pop 260ms var(--ease); }
.step-box { padding: var(--sp-2); border-radius: var(--r-md); }

.box-warn { background: rgba(255, 149, 0, .05); border: 1px solid rgba(255, 149, 0, .14); }
.box-info { background: rgba(0, 122, 255, .04); border: 1px solid rgba(0, 122, 255, .12); }
.box-ok   { background: rgba(52, 199, 89, .05); border: 1px solid rgba(52, 199, 89, .16); }

.email-box {
    padding: 14px;
    margin-bottom: var(--sp-2);
    border-radius: var(--r-md);
    background: var(--surface);
    text-align: center;
    font-size: 20px;
    font-weight: 600;
    letter-spacing: .5px;
}

.link {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 0;
    border: 0;
    background: none;
    color: var(--blue);
    font-family: inherit;
    font-size: 13px;
    text-decoration: none;
    cursor: pointer;
}
.link:hover { text-decoration: underline; }

/* 「重新发送验证码」发送期间会 disable，要看得出来 */
.link:disabled { opacity: .45; cursor: not-allowed; text-decoration: none; }

/* 居中的块级包裹：.link 是 inline-flex，把 .center 写在它身上不会居中 */
.link-center { display: block; text-align: center; }

.center-page { display: flex; align-items: center; justify-content: center; min-height: 60vh; padding: var(--sp-3); }

/* ------------------------------------------------------ 8. 响应式与暗色 */

.only-mobile  { display: none; }
.only-desktop { display: block; }

/*
 * 两个断点管的不是同一件事，顺序是「**先收导航，再收排版**」。
 *
 *   1199px   侧栏 → 汉堡菜单。导航这一列放不下了，但内容区因此**宽出来** 264px，
 *            所以这一档只收导航，列不动。
 *   900px    内容列 → 竖排（24 列塌成一列，所有 span 占满）。
 *
 * 900 这个数是算出来的，不是拍的：有侧栏时 1199px 视口的主内容区 ≈ 903px，
 * 现有设计本来就是按这个宽度调的（跨度 8 的卡片 ≈ 288px 是它在容忍的下限）。
 * 侧栏让位之后，同样的 903px 要到 900px 视口才出现 ——
 * 所以把竖排推到这里，等于**保持那一列的最小宽度不变**，而不是把内容压得更窄。
 * 两者原来挤在同一个断点，才会出现"导航刚一收起来，排版也跟着塌"。
 */
@media (max-width: 1199px) {
    .only-mobile  { display: block; }
    .only-desktop { display: none !important; }
    .main { padding: 0 0 var(--sp-3); }
}

@media (max-width: 900px) {
    .grid { grid-template-columns: minmax(0, 1fr); }
    .span-8, .span-16, .span-24 { grid-column: 1 / -1; }
    .faq-grid { grid-template-columns: 1fr; }
}

@media (max-width: 700px) {
    body { font-size: 14px; }
    .page-title { font-size: 26px; }
    .pill-grid { grid-template-columns: 1fr; }
    .app { padding: 0 var(--sp-2); }
    .topbar { padding: 0 var(--sp-2); height: 58px; }
    .user-name { max-width: 72px; }
    .plan { width: 100%; padding: 20px; }
    .step-line { width: 32px; }
    .log-row { flex-wrap: wrap; }
    .log-row .mono.sm { min-width: auto; }
}

/* 无障碍：尊重系统的"减少动态效果" */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
    }
    .aurora { animation: none; }
    .card:hover, .pill:hover, .plan:hover, .nav-item:hover { transform: none; }
}

/* 键盘可达性：所有可聚焦元素都有可见焦点环 */
:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.btn:focus-visible, .icon-btn:focus-visible, .input:focus-visible { outline: none; }
.btn:focus-visible { box-shadow: var(--focus); }

/* 暗色模式：跟随系统。玻璃层换成深色令牌，保证对比度 */
/* --------------------------------------------------------------------------
   Dashboard refinement: restrained signal palette, crisp controls, clear layers
   -------------------------------------------------------------------------- */

/* Menus live above neighboring glass cards; the header and an open outlet card
   each get their own intentional layer instead of relying on large menu z-indexes. */
.card-menu-overflow.is-menu-open { position: relative; z-index: 35; }

/* PRO membership pass */
.membership-card {
    min-height: 188px;
    overflow: hidden;
    align-self: start;
    transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.membership-card .card-head { min-height: 44px; }
.membership-state {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    color: var(--muted);
    font-size: 11px;
    letter-spacing: .04em;
    text-transform: uppercase;
}
.membership-state i {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: #34c759;
    box-shadow: 0 0 0 3px rgba(52, 199, 89, .13);
    position: relative;
}
.membership-plan { display: flex; align-items: center; gap: 12px; min-width: 0; }
.membership-icon {
    width: 44px;
    height: 44px;
    flex: 0 0 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid rgba(0, 122, 255, .12);
    border-radius: 13px;
    background: rgba(0, 122, 255, .08);
    color: var(--blue);
}
.membership-name { display: flex; flex-direction: column; min-width: 0; gap: 2px; }
.membership-name strong { font-size: 20px; line-height: 1.2; letter-spacing: -.35px; }
.membership-eyebrow {
    color: var(--muted);
    font-size: 9px;
    font-weight: 700;
    letter-spacing: .14em;
}
.membership-number {
    margin-left: auto;
    color: rgba(0, 0, 0, .08);
    font: 600 48px/1 "SF Mono", "JetBrains Mono", ui-monospace, Consolas, monospace;
    letter-spacing: -.08em;
}
.membership-rule { height: 1px; margin: 17px 0 12px; background: var(--line); }
.membership-expiry { display: flex; align-items: flex-end; justify-content: space-between; gap: 8px; }
.membership-expiry > div { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.membership-expiry > div > span { color: var(--muted); font-size: 11px; }
.membership-expiry strong { font-size: 13px; font-weight: 600; }
.membership-access { color: var(--muted-2); font-size: 9px; letter-spacing: .12em; white-space: nowrap; }

.membership-vip.glass {
    color: #edf5ff;
    border: 1px solid rgba(92, 161, 239, .34);
    background:
        radial-gradient(24rem 14rem at 100% 0%, rgba(35, 122, 220, .18), transparent 68%),
        linear-gradient(rgba(111, 168, 229, .035) 1px, transparent 1px),
        linear-gradient(90deg, rgba(111, 168, 229, .035) 1px, transparent 1px),
        linear-gradient(128deg, #0a1423 0%, #111e31 62%, #0b1524 100%);
    background-size: auto, 26px 26px, 26px 26px, auto;
    box-shadow: 0 14px 34px rgba(7, 19, 36, .2), inset 0 1px 0 rgba(179, 214, 255, .1);
}
.membership-vip.glass::before {
    background: linear-gradient(150deg, rgba(143, 197, 255, .58), rgba(255, 255, 255, .04) 45%, rgba(47, 108, 174, .22));
}
.membership-vip .card-head { border-color: rgba(146, 192, 241, .13); }
.membership-vip .card-head h2 { color: #eaf3ff; }
.membership-vip .membership-state { color: #aec5df; }
.membership-vip .membership-icon {
    color: #88c7ff;
    border-color: rgba(105, 177, 247, .28);
    background: rgba(31, 116, 198, .17);
}
.membership-vip .membership-eyebrow { color: #84b7e7; }
.membership-vip .membership-name strong { color: #fff; }
.membership-vip .membership-number { color: rgba(112, 180, 250, .13); }
.membership-vip .membership-rule { background: rgba(148, 193, 240, .16); }
.membership-vip .membership-expiry > div > span { color: #adbed2; }
.membership-vip .membership-expiry strong { color: #f4f8ff; }
.membership-vip .membership-access { color: #83bfff; }

.membership-pro.glass {
    color: #f5f0e4;
    border: 1px solid rgba(201, 166, 99, .4);
    background:
        radial-gradient(25rem 14rem at 100% 0%, rgba(151, 111, 40, .17), transparent 68%),
        linear-gradient(128deg, #12110e 0%, #1c1913 62%, #17140f 100%);
    box-shadow: 0 14px 34px rgba(24, 19, 10, .2), inset 0 1px 0 rgba(250, 225, 170, .1);
}
.membership-pro.glass::before {
    background: linear-gradient(150deg, rgba(239, 207, 139, .66), rgba(255, 255, 255, .035) 45%, rgba(167, 125, 53, .28));
}
.membership-pro .card-head { border-color: rgba(220, 187, 122, .16); }
.membership-pro .card-head h2 { color: #f5ebd4; }
.membership-pro .membership-state { color: #c7b892; }
.membership-pro .membership-icon {
    color: #e5c783;
    border-color: rgba(221, 186, 111, .3);
    background: rgba(157, 117, 46, .16);
}
.membership-pro .membership-eyebrow { color: #d3b775; }
.membership-pro .membership-name strong { color: #fffaf0; }
.membership-pro .membership-number { color: rgba(232, 198, 124, .14); }
.membership-pro .membership-rule { background: rgba(221, 189, 126, .2); }
.membership-pro .membership-expiry > div > span { color: #c4b99e; }
.membership-pro .membership-expiry strong { color: #fff5dd; }
.membership-pro .membership-access { color: #d8bc7c; }

/* The endpoint box is separated from the outlet selector and its controls are
   compact icon affordances rather than a large blue slab. */
.line-status > .row-inline { flex: 1 1 auto; min-width: 0; flex-wrap: wrap; gap: 8px 11px; }
.line-status .mono { overflow-wrap: anywhere; font-size: 13px; }
.dropdown-block > .btn { min-height: 40px; padding: 7px 12px; border-radius: 11px; font-size: 13px; }

/* Smaller, more architectural node controls: less capsule, more console. */
.route-selector-card { align-self: start; }
.pill:hover {
    box-shadow: 0 6px 16px rgba(0, 0, 0, .07);
    transform: none;
    background: rgba(255, 255, 255, .88);
}
.pill.is-active {
    color: #0759a8;
    border-color: rgba(0, 122, 255, .28);
    background: rgba(0, 122, 255, .09);
    box-shadow: inset 0 0 0 1px rgba(0, 122, 255, .06);
}
.pill.is-active .dot-on { box-shadow: 0 0 0 3px rgba(52, 199, 89, .12); }

/* Full-viewport route transaction state. Above dialogs, below no content layer. */
.route-loading {
    position: fixed;
    inset: 0;
    z-index: 120;
    display: grid;
    place-items: center;
    padding: 24px;
    background: rgba(239, 243, 248, .78);
    -webkit-backdrop-filter: blur(12px) saturate(120%);
    backdrop-filter: blur(12px) saturate(120%);
    animation: fade 180ms ease-out;
}
.route-loading-panel {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: min(340px, 100%);
    padding: 34px 28px 30px;
    border: 1px solid rgba(255, 255, 255, .82);
    border-radius: 20px;
    background: rgba(255, 255, 255, .78);
    box-shadow: 0 20px 60px rgba(25, 42, 68, .15), inset 0 1px 0 #fff;
    text-align: center;
}
.route-loader-mark { position: relative; width: 52px; height: 52px; margin-bottom: 20px; }
.route-loader-mark::before,
.route-loader-mark::after,
.route-loader-mark span {
    position: absolute;
    inset: 0;
    border: 1px solid rgba(0, 122, 255, .18);
    border-radius: 50%;
    content: '';
}
.route-loader-mark::before { border-top-color: #0878df; border-right-color: #0878df; animation: spin 1s linear infinite; }
.route-loader-mark::after { inset: 7px; border-bottom-color: #566f98; border-left-color: #566f98; animation: spin 1.6s linear infinite reverse; }
.route-loader-mark span { inset: 19px; border: 0; background: #0878df; box-shadow: 0 0 16px rgba(0, 122, 255, .45); }
.route-loading-eyebrow { margin-bottom: 7px; color: #50739b; font-size: 9px; font-weight: 700; letter-spacing: .2em; }
.route-loading-panel h2 { margin-bottom: 5px; font-size: 19px; letter-spacing: -.02em; }
.route-loading-panel > p:last-child { color: #7c8798; font-size: 13px; }
body.is-route-loading { overflow: hidden; }

@media (max-width: 700px) {
    .membership-card { min-height: 0; }
    .membership-number { font-size: 40px; }
    .membership-rule { margin-top: 14px; }
    .line-status { align-items: flex-start; }
    .line-status > .row-inline { align-items: flex-start; flex-direction: column; gap: 2px; }
    .line-status .btn-row { flex: 0 0 auto; gap: 3px; }
    .line-status .icon-btn { width: 30px; height: 30px; }
    .pill { height: 42px; }
    .route-loading-panel { padding: 30px 20px 26px; }
}

@media (prefers-reduced-motion: reduce) {
    .route-loader-mark::before, .route-loader-mark::after { animation: none; }
}


/* --------------------------------------------------------------------------
   Tier identity and editorial details
   -------------------------------------------------------------------------- */
.dashboard-heading {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 20px;
    margin-bottom: var(--sp-3);
}
.dashboard-heading .page-title { margin: 5px 0 0; }
.dashboard-heading .page-title > span { color: var(--muted); font-size: .68em; font-weight: 500; letter-spacing: -.03em; }
.dashboard-eyebrow {
    display: flex;
    align-items: center;
    gap: 9px;
    color: #68798d;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: .16em;
}
.dashboard-eyebrow i { width: 18px; height: 1px; background: #8ba4bd; }
.dashboard-index { display: flex; align-items: center; gap: 10px; padding-bottom: 8px; color: #8995a3; font-size: 9px; letter-spacing: .15em; }
.dashboard-index b { padding-left: 10px; border-left: 1px solid rgba(90, 111, 133, .32); color: #35465a; font: 600 13px/1 "SF Mono", ui-monospace, Consolas, monospace; }
.card-head-meta { display: inline-flex; align-items: center; gap: 7px; color: var(--muted-2); font-size: 9px; font-weight: 700; letter-spacing: .13em; white-space: nowrap; margin-left: auto; }
.card-head-meta i { width: 6px; height: 6px; border-radius: 50%; background: #4f9ce0; box-shadow: 0 0 0 3px rgba(79, 156, 224, .1); }

/* Plan chooser uses the same identity as the active membership card. */
.renew-eyebrow { margin: 4px 0 5px; color: #718196; font-size: 9px; font-weight: 700; letter-spacing: .2em; }
.accent-vip.glass {
    color: #eaf2fb;
    border-color: rgba(94, 159, 232, .3);
    background:
        radial-gradient(23rem 15rem at 100% 0%, rgba(30, 111, 203, .2), transparent 68%),
        linear-gradient(rgba(111, 168, 229, .03) 1px, transparent 1px),
        linear-gradient(90deg, rgba(111, 168, 229, .03) 1px, transparent 1px),
        linear-gradient(135deg, #0b1524 0%, #111e30 62%, #0b1422 100%);
    background-size: auto, 28px 28px, 28px 28px, auto;
    box-shadow: 0 12px 30px rgba(7, 20, 38, .17), inset 0 1px 0 rgba(169, 209, 255, .09);
}
.accent-vip.glass::before { background: linear-gradient(150deg, rgba(143, 197, 255, .5), rgba(255, 255, 255, .03) 45%, rgba(47, 108, 174, .2)); }
.accent-pro.glass {
    color: #f4efdf;
    border-color: rgba(196, 159, 87, .4);
    background:
        radial-gradient(24rem 16rem at 100% 0%, rgba(148, 106, 37, .18), transparent 68%),
        linear-gradient(135deg, #12110e 0%, #1b1812 62%, #15120d 100%);
    box-shadow: 0 12px 30px rgba(24, 19, 10, .18), inset 0 1px 0 rgba(248, 222, 163, .09);
}
.accent-pro.glass::before { background: linear-gradient(150deg, rgba(239, 207, 139, .6), rgba(255, 255, 255, .025) 45%, rgba(167, 125, 53, .24)); }
.accent-vip .plan-head h3 { color: #a9d8ff; }
.accent-pro .plan-head h3 { color: #ecd39c; }
.accent-vip .plan-price .amount { color: #f4f8ff; }
.accent-pro .plan-price .amount { color: #fff5dc; }
.accent-vip .plan-price .muted { color: #9cb1c8; }
.accent-pro .plan-price .muted { color: #c1b69b; }
.accent-vip .benefits li, .accent-vip .benefit-title { color: #dce9f7; }
.accent-vip .benefit-desc { color: #9aadc2; }
.accent-pro .benefits li, .accent-pro .benefit-title { color: #eee5d1; }
.accent-pro .benefit-desc { color: #b7ad98; }
.accent-vip .divider, .accent-pro .divider { background: rgba(255, 255, 255, .12); }
.accent-vip .coupon-link { color: #91bde7; }
.accent-vip .coupon-link:hover { color: #d4ecff; }
.accent-pro .coupon-link { color: #c5ae7a; }
.accent-pro .coupon-link:hover { color: #f0dcae; }
.accent-vip .tag-vip { color: #c8e6ff; border: 1px solid rgba(120, 184, 244, .3); background: rgba(51, 125, 194, .18); }
.accent-pro .tag-pro { color: #e5c985; border: 1px solid rgba(211, 175, 102, .3); background: rgba(151, 112, 42, .16); }
.accent-vip.is-selected { border-color: rgba(106, 182, 255, .76); box-shadow: 0 0 0 1px rgba(106, 182, 255, .24), 0 18px 42px rgba(8, 27, 51, .24); }
.accent-pro.is-selected { border-color: rgba(221, 183, 106, .8); box-shadow: 0 0 0 1px rgba(221, 183, 106, .25), 0 18px 42px rgba(34, 26, 12, .24); }
.accent-vip .radio-pill span { color: #c0d2e5; border-color: rgba(170, 201, 233, .18); background: rgba(255, 255, 255, .045); }
.accent-vip .radio-pill input:checked + span { color: #071421; border-color: #84caff; background: #8bcfff; }
.accent-pro .radio-pill span { color: #d4c9b1; border-color: rgba(221, 194, 140, .2); background: rgba(255, 255, 255, .04); }
.accent-pro .radio-pill input:checked + span { color: #21190b; border-color: #e0bd70; background: #dfbd73; }
.accent-vip .buy-btn { color: #071421; border: 0; background: linear-gradient(100deg, #80c8ff, #52a6ee); box-shadow: 0 5px 18px rgba(47, 139, 218, .25); }
.accent-vip .buy-btn:hover { background: linear-gradient(100deg, #a0d7ff, #70baff); }
.accent-pro .buy-btn { color: #20190d; border: 0; background: linear-gradient(105deg, #e4c77f, #bf9650); box-shadow: 0 5px 18px rgba(173, 132, 57, .2); }
.accent-pro .buy-btn:hover { background: linear-gradient(105deg, #f0d99c, #d0aa63); }

/* State labels, pointer feedback and a restrained network pulse. */
.pill:not(:disabled):hover { transform: translateY(-1px); border-color: rgba(48, 126, 201, .32); box-shadow: 0 6px 15px rgba(27, 70, 111, .08); }
.pill:active { transform: translateY(0) scale(.99); }
.pill-meta { flex: 0 0 auto; color: #6f879b; font-size: 10px; letter-spacing: .02em; }
.pill.is-active .pill-meta { color: #3978ae; }
.pill-meta.is-offline { color: #b77a63; }
.dot-on::after { position: absolute; inset: -3px; border: 1px solid rgba(52, 199, 89, .45); border-radius: 50%; content: ''; animation: signal-pulse 2.8s ease-out infinite; }
@keyframes signal-pulse { 0% { transform: scale(.65); opacity: .55; } 75%, 100% { transform: scale(1.45); opacity: 0; } }

@media (max-width: 700px) {
    .dashboard-index { display: none; }
    .dashboard-heading { margin-bottom: 20px; }
    .dashboard-eyebrow { font-size: 8px; letter-spacing: .13em; }
    .card-head-meta { font-size: 8px; }
    .pill-meta { font-size: 9px; }
}
@media (prefers-reduced-motion: reduce) {
    .dot-on::after { animation: none; }
    .pill:not(:disabled):hover { transform: none; }
}


/* Tier finishes and tactile feedback */
.membership-card .membership-icon { transition: transform 240ms var(--ease), box-shadow 240ms var(--ease); }
.membership-card:hover .membership-icon { transform: translateY(-1px) rotate(-3deg); }
.membership-state i::after {
    position: absolute;
    inset: -3px;
    border: 1px solid rgba(52, 199, 89, .42);
    border-radius: 50%;
    content: '';
    animation: signal-pulse 2.8s ease-out infinite;
}
.membership-lite .membership-icon {
    color: #75869a;
    border-color: rgba(117, 134, 154, .18);
    background: rgba(117, 134, 154, .08);
}
.membership-lite:hover { border-color: rgba(117, 134, 154, .28); }
.membership-vip:hover {
    border-color: rgba(118, 186, 255, .58);
    box-shadow: 0 17px 38px rgba(7, 28, 54, .26), inset 0 1px 0 rgba(185, 221, 255, .13);
}
.membership-vip:hover .membership-icon { box-shadow: 0 0 20px rgba(68, 151, 230, .2); }
.membership-pro:hover {
    border-color: rgba(227, 190, 112, .65);
    box-shadow: 0 17px 38px rgba(31, 24, 13, .27), inset 0 1px 0 rgba(250, 225, 170, .14);
}
.membership-pro:hover .membership-icon { box-shadow: 0 0 20px rgba(199, 153, 67, .18); }

/* Three plans now share one rhythm on desktop; the shorter add-on keeps its own natural height. */
.plan.accent-ip { align-self: start; }
@media (max-width: 1000px) {
    .plan-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .plan:last-child { grid-column: 1 / -1; width: min(370px, 100%); justify-self: center; }
}
@media (max-width: 700px) {
    .plan-grid { grid-template-columns: minmax(0, 1fr); }
    .plan:last-child { grid-column: auto; width: auto; justify-self: stretch; }
}
@media (prefers-reduced-motion: reduce) {
    .membership-card .membership-icon { transition: none; }
    .membership-state i::after { animation: none; }
}


/* --------------------------------------------------------------------------
   暗色主题（唯一的一份）

   暗色的触发条件只有一个：<html> 上有 data-scheme="dark"。
   这个属性由 layout.php 头部的内联脚本在**首屏绘制前**同步设置：
   显式选了浅色/暗色就用选的那个，否则跟随系统偏好（matchMedia）。

   这里**不再有** @media (prefers-color-scheme: dark) 块。原来有，
   但媒体查询无法感知"用户显式选了浅色"，于是系统是暗色时显式选浅色不生效。
   两份规则并存还会带来同步问题，所以合并成一份、由属性统一驱动。

   代价：关闭 JS 的访客只有浅色模式。这个取舍是有意的 ——
   站点的主要交互（线路切换、验证码、支付）本来就需要 JS。

   为什么用 :where()：它的特异性贡献恒为 0，所以这里每条规则的特异性
   与原来媒体查询里的原规则**完全相同**，层叠行为不会因为这次改动而变化。
   直接写成 [data-scheme="dark"] .btn 会多一个属性选择器、特异性变高，
   就会压过一些原本能压住它的规则 —— 那是个很隐蔽的回归。

   :root 是例外：它必须真的调高特异性（:root[data-scheme="dark"]，0-2-0）
   才能压过上面那条基础 :root（0-1-0）。
   -------------------------------------------------------------------------- */

:root[data-scheme="dark"] {
        --ink:     #f2f2f7;
        --ink-2:   #d8d8dd;
        --muted:   #9a9aa2;
        --muted-2: #7c7c85;
        --line:    rgba(255, 255, 255, .10);
        --line-2:  rgba(255, 255, 255, .07);
        --surface: rgba(255, 255, 255, .06);
        --glass-bg:    rgba(28, 30, 36, .58);
        --glass-bg-hi: rgba(38, 40, 48, .72);
        --glass-brd:   rgba(255, 255, 255, .14);
        --sh-1: 0 1px 2px rgba(0, 0, 0, .3), 0 4px 12px rgba(0, 0, 0, .26);
        --sh-2: 0 2px 4px rgba(0, 0, 0, .32), 0 12px 28px rgba(0, 0, 0, .36);
        --sh-3: 0 4px 8px rgba(0, 0, 0, .36), 0 24px 56px rgba(0, 0, 0, .48);
        --sh-inset: inset 0 1px 0 rgba(255, 255, 255, .10);
        /* 暗色模式下照片必须压暗：原图非常亮（大面积天空 + 左上太阳），
           配深色玻璃会刺眼到读不了字。
           用深色薄纱而不是 filter: brightness()，理由同上 —— 避免额外栅格化。 */
        --bg-scrim: rgba(12, 16, 23, .62);
}
:where([data-scheme="dark"]) body { background-color: #14161b; }
:where([data-scheme="dark"]) .aurora {
        background:
            radial-gradient(48vmax 36vmax at 10% 4%, rgba(42, 110, 181, .2), transparent 62%),
            radial-gradient(46vmax 38vmax at 92% 88%, rgba(81, 116, 139, .12), transparent 62%);
}
:where([data-scheme="dark"]) body::after { background: radial-gradient(120% 90% at 50% 40%, transparent 50%, rgba(0, 0, 0, .34)); }
:where([data-scheme="dark"]) .grain { opacity: .22; }
:where([data-scheme="dark"]) .glass::before {
        background: linear-gradient(160deg,
            rgba(255, 255, 255, .22), rgba(255, 255, 255, .05) 45%, rgba(255, 255, 255, .12));
}
:where([data-scheme="dark"]) .btn { background: rgba(255, 255, 255, .10); color: var(--ink); }
:where([data-scheme="dark"]) .btn:hover { background: rgba(255, 255, 255, .16); }
:where([data-scheme="dark"]) .btn-ghost { background: transparent; border-color: var(--line); }
:where([data-scheme="dark"]) .btn-plain { background: rgba(255, 255, 255, .07); }
:where([data-scheme="dark"]) .btn-plain:hover { background: rgba(255, 255, 255, .12); }
:where([data-scheme="dark"]) .nav-item:hover { background: rgba(255, 255, 255, .10); }
:where([data-scheme="dark"]) .user-chip { background: rgba(255, 255, 255, .10); }
:where([data-scheme="dark"]) .user-chip:hover { background: rgba(255, 255, 255, .16); }
:where([data-scheme="dark"]) .input { background: rgba(255, 255, 255, .08); color: var(--ink); }
:where([data-scheme="dark"]) .input:focus { background: rgba(255, 255, 255, .12); }
:where([data-scheme="dark"]) .input:disabled { background: rgba(255, 255, 255, .04); }
:where([data-scheme="dark"]) .pill { background: rgba(255, 255, 255, .07); }
:where([data-scheme="dark"]) .pill:hover { background: rgba(255, 255, 255, .13); }
:where([data-scheme="dark"]) .radio-pill span { background: rgba(255, 255, 255, .07); }
:where([data-scheme="dark"]) .overlay { background: rgba(20, 22, 27, .5); }
:where([data-scheme="dark"]) .notice-warn { color: #f5d08a; background: rgba(90, 70, 20, .38); }
:where([data-scheme="dark"]) .notice-ok { color: #9ee0b4; background: rgba(20, 70, 40, .38); }
:where([data-scheme="dark"]) .email-box { background: rgba(255, 255, 255, .06); }
:where([data-scheme="dark"]) .faq .card-body { color: var(--ink-2); }
:where([data-scheme="dark"]) .skeleton {
        background: linear-gradient(100deg,
            rgba(255, 255, 255, .05) 30%, rgba(255, 255, 255, .11) 50%, rgba(255, 255, 255, .05) 70%);
        background-size: 220% 100%;
}

:where([data-scheme="dark"]) .pill.is-active { color: #b9dcff; border-color: rgba(87, 164, 255, .38); background: rgba(31, 113, 194, .22); }
:where([data-scheme="dark"]) .pill.is-active:hover { background: rgba(31, 113, 194, .28); }
:where([data-scheme="dark"]) .route-loading { background: rgba(12, 16, 23, .72); }
:where([data-scheme="dark"]) .route-loading-panel { border-color: rgba(255, 255, 255, .12); background: rgba(28, 32, 41, .88); box-shadow: 0 20px 60px rgba(0, 0, 0, .48), inset 0 1px 0 rgba(255, 255, 255, .08); }
:where([data-scheme="dark"]) .route-loading-eyebrow { color: #8fb8e5; }
:where([data-scheme="dark"]) .route-loading-panel > p:last-child { color: #a2a9b7; }

:where([data-scheme="dark"]) .membership-lite .membership-number { color: rgba(255, 255, 255, .1); }
:where([data-scheme="dark"]) .dashboard-eyebrow { color: #96a5b6; }
:where([data-scheme="dark"]) .dashboard-index b { color: #d0dae5; }
:where([data-scheme="dark"]) .pill-meta { color: #9bb1c8; }
:where([data-scheme="dark"]) .pill.is-active .pill-meta { color: #b8d9f5; }



/* --------------------------------------------------------------------------
   侧栏分节标签
   -------------------------------------------------------------------------- */

/*
 * 侧栏不再放 logo —— 顶栏已经有了，重复放一个是冗余。
 * 原来 logo 占的 88px 换成这个标签，用与 .dashboard-eyebrow 同一套语言
 * （大写、宽字距、极小字号），让"这一列是导航"有明确的起点。
 */
.sidebar-label {
    display: flex;
    align-items: center;
    gap: 9px;
    margin: 0 0 var(--sp-2);
    padding: 5px var(--sp-1) 0;
    color: #68798d;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: .16em;
    text-transform: uppercase;
}

.sidebar-label > i {
    flex: 1 1 auto;
    height: 1px;
    background: var(--line);
}

/* 抽屉头部：标签占满剩余宽度，关闭按钮靠右 */
.drawer-head .sidebar-label {
    flex: 1 1 auto;
    margin-bottom: 0;
    padding-top: 0;
}

/*
 * 暗色变体。
 *
 * 这里原本还有一个取值相同的 @media (prefers-color-scheme: dark) 块，
 * 是当初统一暗色驱动方式时漏掉的一处。它与上面的基础规则特异性相同（都是 0,1,0）
 * 却排在后面，于是"系统是深色、而用户**显式选了浅色**"时它会照样命中 ——
 * 给深色背景用的浅灰压在浅色背景上，这一行标签几乎看不见。
 * 媒体查询感知不到"用户显式选了浅色"，所以暗色只能由 data-scheme 驱动。
 */
:root[data-scheme="dark"] .sidebar-label { color: #96a5b6; }


/* --------------------------------------------------------------------------
   主题切换菜单
   -------------------------------------------------------------------------- */

.theme-menu { min-width: 172px; }

.theme-option {
    position: relative;
    /* 没有选中态时右侧的勾是隐藏的，但位置要一直留着，避免切换时文字抖动 */
    justify-content: flex-start;
}

.theme-option > .grow { text-align: left; }

.theme-tick {
    display: inline-flex;
    margin-left: auto;
    color: var(--blue);
    opacity: 0;
    transition: opacity var(--dur-fast) var(--ease);
}

.theme-option.is-active {
    color: var(--blue);
    font-weight: 600;
}

.theme-option.is-active .theme-tick { opacity: 1; }

/* 顶栏那个调色板按钮：打开时给它一个按下态，跟用户菜单一致 */
#theme-dropdown.is-open > .icon-btn {
    background: rgba(0, 0, 0, .05);
    color: var(--ink);
}
:root[data-scheme="dark"] #theme-dropdown.is-open > .icon-btn {
    background: rgba(255, 255, 255, .12);
}

/* --------------------------------------------------------------------------
   图标按钮：尺寸与材质
   -------------------------------------------------------------------------- */

/*
 * 根因：icon() 不传 size 时生成的是 <svg viewBox="0 0 24 24">，**没有 width/height**，
 * 而本文件里没有任何给 svg 定尺寸的规则。于是图标会撑满整个按钮、
 * 笔画直接贴到边框上 —— 这是这些按钮看起来又挤又糙的原因。
 *
 * 在 CSS 里统一内缩，而不是去改 5 处 PHP 调用：前者漏不掉，后者随时会被忘。
 */
.icon-btn svg {
    width: 18px;
    height: 18px;
}

/*
 * 顶栏的主题按钮：与右侧用户胶囊用同一套材质（细描边 + 半透明白底 + 胶囊圆角）。
 * 原来是裸图标（透明、灰色）漂在玻璃条上，跟旁边那颗精致的胶囊不像一家人。
 */
#theme-dropdown > .icon-btn {
    width: 34px;
    height: 34px;
    border: 1px solid var(--glass-brd);
    border-radius: var(--r-pill);
    background: rgba(255, 255, 255, .46);
    color: var(--ink-2);
}

#theme-dropdown > .icon-btn:hover {
    background: rgba(255, 255, 255, .86);
    color: var(--ink);
    box-shadow: var(--sh-1);
}

#theme-dropdown > .icon-btn svg {
    width: 17px;
    height: 17px;
}

/*
 * 线路入口右侧的两个操作（显示/隐藏、复制）：合成**一组**。
 * 原来是两个各自带边框的小方块，套在已经带边框的 .line-status 里 ——
 * 盒中盒，视觉上很碎。现在去掉各自的边框，共用一个胶囊外壳。
 */
.line-status .btn-row {
    flex: 0 0 auto;
    gap: 2px;
    padding: 3px;
    border-radius: var(--r-pill);
    background: rgba(255, 255, 255, .62);
    box-shadow: inset 0 0 0 1px var(--line);
}

.line-status .icon-btn {
    width: 28px;
    height: 28px;
    border: 0;
    border-radius: var(--r-pill);
    background: transparent;
    color: var(--muted);
}

.line-status .icon-btn svg {
    width: 16px;
    height: 16px;
}

.line-status .icon-btn:hover {
    background: rgba(0, 122, 255, .12);
    color: var(--blue);
}

/* 眼睛按钮的两态图标：默认"眼睛"，地址露出来之后换成"眼睛带斜杠" */
#line-toggle > span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

#line-toggle .ico-eye-off { display: none; }
#line-toggle.is-on .ico-eye { display: none; }
#line-toggle.is-on .ico-eye-off { display: inline-flex; }

/* ---------------------------------------------------------------- 暗色 */

/*
 * 这一节的规则写在暗色块**之后**，同特异性下后者胜，
 * 所以这里必须把暗色变体一并写全，否则会把暗色样式盖掉。
 */
:where([data-scheme="dark"]) #theme-dropdown > .icon-btn {
    background: rgba(255, 255, 255, .10);
    border-color: rgba(255, 255, 255, .14);
    color: var(--ink-2);
}

:where([data-scheme="dark"]) #theme-dropdown > .icon-btn:hover {
    background: rgba(255, 255, 255, .16);
    color: var(--ink);
}

:where([data-scheme="dark"]) .line-status .btn-row {
    background: rgba(255, 255, 255, .07);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .10);
}

:where([data-scheme="dark"]) .line-status .icon-btn {
    background: transparent;
    color: #9bb1c8;
}

:where([data-scheme="dark"]) .line-status .icon-btn:hover {
    background: rgba(255, 255, 255, .13);
    color: #b9dcff;
}