/* ===========================================================================
   后台统一样式（宿主级）
   ---------------------------------------------------------------------------
   所有产品的后台都套在这一层里，所以**样式只在这里定义一次**：
   产品自己的 CSS 不需要（也不应该）再写按钮/卡片/表格长什么样。

   两层结构：
     一、设计令牌（:root 变量）—— 配色、圆角、间距、字号、阴影都在这里
     二、组件（按钮/卡片/表格/表单/标签/空状态…）—— 只用令牌，不写死颜色

   改主题色只要改 --primary（后台「可视化装修」会覆盖它），整套跟着变。
   =========================================================================== */

/* ─────────── 一、设计令牌 ─────────── */
:root {
    --primary: #2f6bff;
    --primary-hover: #1f57e6;
    --primary-weak: #eef3ff;
    --primary-line: #c7d7f8;

    --text: #1c1f26;
    --text-sub: #4b5563;
    --muted: #6b7280;
    --line: #e8eaef;
    --line-soft: #f1f3f7;
    --bg: #f5f6f9;
    --surface: #ffffff;

    --ok: #12805c;
    --ok-bg: #e8f6f0;
    --warn: #b26a00;
    --warn-bg: #fff8e6;
    --danger: #c0392b;
    --danger-bg: #fdeceb;
    --info: #1a4bd0;
    --info-bg: #eef4ff;

    --radius: 10px;
    --radius-lg: 14px;
    --gap: 16px;
    --shadow-sm: 0 1px 2px rgba(16, 24, 40, .04);
    --shadow: 0 2px 12px rgba(16, 24, 40, .06);

    --sidebar-bg: #14161d;
    --sidebar-line: #262a34;
    --sidebar-text: #c3c8d4;
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-family: -apple-system, "Segoe UI", "Microsoft YaHei", system-ui, sans-serif;
    font-size: 14px;
    line-height: 1.65;
}

a { color: var(--primary); text-decoration: none; }
a:hover { text-decoration: underline; }
.muted { color: var(--muted); }
.small { font-size: 13px; }
.mono { font-family: ui-monospace, Consolas, monospace; font-size: 13px; }
.required { color: #e5484d; }

/* ─────────── 二、骨架：侧边栏 + 主区 ─────────── */
.shell { display: flex; min-height: 100vh; }

.sidebar {
    width: 224px; flex-shrink: 0;
    background: var(--sidebar-bg); color: var(--sidebar-text);
    display: flex; flex-direction: column;
    padding: 20px 12px 14px;
    position: sticky; top: 0; height: 100vh;
}
.brand {
    font-size: 16px; font-weight: 700; color: #fff;
    padding: 0 10px 18px; margin-bottom: 8px;
    border-bottom: 1px solid var(--sidebar-line);
    display: flex; align-items: center; gap: 10px;
}
/* 品牌前面那个小方块：没有 logo 图时也有个"标志物"，比纯文字像样 */
.brand::before {
    content: ""; width: 26px; height: 26px; border-radius: 8px;
    background: linear-gradient(135deg, var(--primary), #7aa2ff);
    flex: 0 0 auto;
}
.sidebar nav { display: flex; flex-direction: column; flex: 1; gap: 2px; overflow-y: auto; }
.sidebar nav a {
    padding: 9px 12px; border-radius: 8px;
    color: var(--sidebar-text); font-size: 13.5px;
    transition: background .15s, color .15s;
}
.sidebar nav a:hover { background: #1e222c; color: #fff; text-decoration: none; }
/*
 * 当前项：**不要整块主色**。
 *
 * 深色侧边栏上铺一块亮蓝太跳，看着像"这里是个按钮"而不是"我在这个页面"，
 * 而且客户的品牌色要是大红/大绿会更刺眼（客户反馈："侧边栏颜色搭配有问题"）。
 * 企业级常见的做法是"低调底色 + 左侧一条主色竖条"，任何主题色都好看。
 */
.sidebar nav a.on {
    background: #232735; color: #fff; font-weight: 600;
    box-shadow: inset 3px 0 0 var(--primary);
}

/* 分组标题（"我的应用""系统"这种小字） */
.nav-group {
    padding: 14px 12px 6px;
    font-size: 11px; letter-spacing: .5px;
    /*
     * 深色侧边栏上的小字**不能太暗**：#666d7d 在 #14161d 上对比度只有 3 左右，
     * 客户看图的第一句话就是"这个字看不清"（截图里"我的应用"几乎是隐形的）。
     * 换成 #9aa3b5（对比度约 7），小字也读得清。
     */
    color: #9aa3b5; text-transform: uppercase;
    font-weight: 600;
}

/*
 * 分组之间的分隔线。
 *
 * 客户截图反馈的原话：「应该把这个区分开来和应用，要不然别人以为这都是应用了」——
 * 侧边栏里"我的应用首页 / 微信登录 / 账号设置"紧贴在最后一个应用名下面，
 * 看着就像那个应用自己的子菜单。
 * 现在每组之间有一条浅色横线 + 一个分组标题（"我的应用" / "账号与设置"），
 * 谁是谁一目了然。
 */
.nav-sep {
    height: 1px; margin: 12px 12px 2px;
    background: #262b36;
    flex: 0 0 auto;
}

/* 侧边栏里的次要链接（"全部应用（12）→"这种） */
.sidebar nav a.sub {
    padding: 7px 12px 7px 16px;
    font-size: 12.5px; color: #9aa3b5;
}
.sidebar nav a.sub:hover { color: #fff; }

.sidebar-foot {
    padding: 12px 12px 0; margin-top: 8px;
    border-top: 1px solid var(--sidebar-line);
    display: flex; flex-direction: column; gap: 4px;
}
.sidebar-foot a { color: #b6bdcb; font-size: 13px; }
.sidebar-foot a:hover { color: #fff; text-decoration: none; }

/*
 * 深色侧边栏里所有 .muted 都要提亮。
 *
 * .muted 是给**白色内容区**定的（#6b7280），放到深色侧边栏上就糊了 ——
 * 底部的账号名"测试1"、"管理会员"这类字就是这么变得看不清的。
 */
.sidebar .muted, .sidebar-foot .muted, .sidebar .small { color: #9aa3b5; }

.main { flex: 1; padding: 24px 28px 64px; min-width: 0; }
.page-head {
    margin-bottom: 18px;
    display: flex; align-items: center; justify-content: space-between;
    gap: 16px; flex-wrap: wrap;
}
.page-head h1 { font-size: 21px; margin: 0; font-weight: 700; letter-spacing: .3px; }

/*
 * 应用自己的功能菜单（只在该应用的页面里出现）
 *
 * **要和页面内的切换标签（.tabs）明显区分开**，否则客户面对上下两排一模一样的
 * 胶囊，分不清哪个是"换应用功能"、哪个是"换本页子页签"（客户反馈"来回切换有问题"）。
 * 这里用"下划线式"页签：应用菜单是灰字+主色下划线，页面内切换是胶囊。
 */
.app-tabs {
    display: flex; flex-wrap: wrap; gap: 2px;
    margin-bottom: 18px;
    border-bottom: 1px solid var(--line);
}
.app-tabs a {
    padding: 10px 14px; border-radius: 0; border: 0;
    border-bottom: 2px solid transparent;
    background: transparent; color: var(--text-sub); font-size: 13.5px;
    transition: color .15s, border-color .15s;
}
.app-tabs a:hover { color: var(--primary); text-decoration: none; }
.app-tabs a.on {
    background: transparent; color: var(--primary);
    font-weight: 600; border-bottom-color: var(--primary);
}
/*
 * 大产品的功能菜单（简单商城 70 多项）只显示前 11 项，剩下的收进这个下拉。
 * 用原生 <details>：不用 JS、键盘也能用、点外面不会莫名关掉。
 */
.app-tabs-more { position: relative; margin-left: auto; }
.app-tabs-more > summary {
    list-style: none; cursor: pointer;
    padding: 10px 14px; font-size: 13.5px; color: var(--text-sub);
    border-bottom: 2px solid transparent; user-select: none;
}
.app-tabs-more > summary::-webkit-details-marker { display: none; }
.app-tabs-more > summary::after { content: " ▾"; color: var(--muted); }
.app-tabs-more[open] > summary { color: var(--primary); border-bottom-color: var(--primary); font-weight: 600; }
.app-tabs-more-list {
    position: absolute; right: 0; top: 100%; z-index: 20;
    min-width: 240px; max-height: 60vh; overflow: auto;
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--radius); box-shadow: var(--shadow);
    padding: 8px; display: flex; flex-direction: column;
}
.app-tabs-more-list a {
    padding: 8px 10px; border-radius: 8px; font-size: 13px;
    color: var(--text-sub);
}
.app-tabs-more-list a:hover { background: #f6f8fb; text-decoration: none; color: var(--text); }
        .app-tabs-more-list a.on { background: var(--primary-weak); color: var(--primary); font-weight: 600; }

        /*
         * 功能入口的**两级菜单**（2026-10-04 企业级标准）
         *
         * 一级 = 分类（Core\AdminMenu 的七类：业务处理 / 收款与价格 / 用户与权限 / 内容与文案 /
         * 接口与对接 / 系统设置 / 客户端发布），二级 = 这一类里这个应用自己的页面。
         * 每一类就是一个 <details> 下拉，所以菜单再多也不会铺满一屏；
         * 当前页所在的那一类带 .on（默认 open），客户一眼知道自己在哪一类里。
         *
         * 注意：原来的 .app-tabs-more 是"全部功能"那个**靠右**的单个下拉（margin-left:auto），
         * 分组之后是并排好几个，必须把这个靠右去掉。
         */
        .app-tabs-groups .app-tabs-more { margin-left: 0; }
        .app-tabs-more.on > summary {
            color: var(--primary); font-weight: 600; border-bottom-color: var(--primary);
        }

/* ─────────── 三、提示条 ─────────── */
.flash {
    padding: 11px 16px; border-radius: var(--radius);
    margin-bottom: 18px; font-size: 13.5px;
    border: 1px solid transparent;
}
.flash-info { background: var(--info-bg); color: var(--info); border-color: #d6e2ff; }
.flash-success { background: var(--ok-bg); color: var(--ok); border-color: #cdeade; }
.flash-error { background: var(--danger-bg); color: var(--danger); border-color: #f6d7d3; }
.flash-warning { background: var(--warn-bg); color: var(--warn); border-color: #f6e2b8; }

/* ─────────── 四、卡片与指标 ─────────── */
.card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    padding: 20px 22px; margin-bottom: var(--gap);
    box-shadow: var(--shadow-sm);
}
.card h2 {
    font-size: 16px; margin: 0 0 16px; padding-bottom: 12px;
    border-bottom: 1px solid var(--line-soft);
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
}

.stats {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 14px; margin-bottom: var(--gap);
}
.stat {
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--radius-lg); padding: 18px 20px;
    box-shadow: var(--shadow-sm);
}
.stat-label { font-size: 13px; color: var(--muted); margin-bottom: 6px; }
.stat-value { font-size: 26px; font-weight: 700; letter-spacing: .5px; }
.stat-hint { font-size: 12px; color: var(--muted); margin-top: 4px; }

.badge-ok { color: var(--ok); }
.badge-warn { color: var(--warn); }
.badge-bad { color: var(--danger); }

/* ─────────── 五、按钮 ─────────── */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    min-height: 34px; padding: 0 15px;
    border: 1px solid var(--line); border-radius: var(--radius);
    background: var(--surface); color: var(--text);
    font-size: 13px; font-family: inherit; line-height: 1.5;
    cursor: pointer; text-decoration: none; white-space: nowrap;
    transition: all .15s;
}
.btn:hover { border-color: #c9ccd4; text-decoration: none; }
.btn-primary { background: var(--primary); border-color: var(--primary); color: #fff; }
.btn-primary:hover { background: var(--primary-hover); border-color: var(--primary-hover); }
.btn-danger { color: var(--danger); border-color: #f0c8c3; background: var(--surface); }
.btn-danger:hover { background: var(--danger-bg); }
.btn-sm { min-height: 28px; padding: 0 11px; font-size: 12px; border-radius: 8px; }
.btn-block { display: flex; width: 100%; }

/* ─────────── 六、工具条 / 搜索 ─────────── */
/*
 * 工具条：**一律左对齐**，右侧那组操作靠 `.actions { margin-left:auto }` 顶到右边。
 *
 * 为什么不用 justify-content: space-between：产品把"切换标签"也放进 .toolbar 里
 * （财务的 提现审核/充值记录/余额流水、内容管理的 消息公告/幻灯片/常见问题/意见反馈…）。
 * space-between 会把这几个标签**拉散到整行**：一个贴左、一个贴右、中间两个悬浮 ——
 * 客户一眼就看出"布局有问题"。左对齐之后，两种用法都正常：
 *   搜索 + 操作      → 搜索在左，操作在右
 *   一排切换标签     → 老老实实从左边排过去
 */
.toolbar {
    display: flex; align-items: center; justify-content: flex-start;
    gap: 12px; flex-wrap: wrap; margin-bottom: var(--gap);
}
.toolbar > .actions, .toolbar > .right, .toolbar .push-right { margin-left: auto; }
.search { display: flex; gap: 8px; align-items: center; }
.search input { width: 220px; margin: 0; }
.actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* 切换标签条（**切换就用它，别拿 .btn 当标签** —— 那会变成一排大按钮） */
.tabs { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: var(--gap); }
.tabs a {
    padding: 8px 16px; border-radius: 999px;
    border: 1px solid var(--line); background: #f7f9fc;
    color: var(--text-sub); font-size: 13px; line-height: 1.5;
}
.tabs a:hover { border-color: var(--primary-line); color: var(--primary); text-decoration: none; }
.tabs a.on, .tabs a.active {
    background: var(--primary); border-color: var(--primary); color: #fff; font-weight: 600;
}

/* ─────────── 七、表格 ─────────── */
.table { width: 100%; border-collapse: collapse; }
.table th, .table td { padding: 12px; border-bottom: 1px solid var(--line-soft); text-align: left; }
.table th { background: #fafbfc; color: var(--muted); font-weight: 500; font-size: 13px; }
.table tbody tr:hover { background: #fbfcfe; }
.table tr:last-child td { border-bottom: none; }
/* 表格最后一列"操作"：靠右、不折行（行内一排按钮挤成两行很难看） */
.table th.actions, .table td.actions { text-align: right; white-space: nowrap; }

/* ─────────── 八、表单 ─────────── */
label { display: block; margin-bottom: 16px; font-size: 14px; color: var(--text-sub); }
input[type=text], input[type=password], input[type=number], input[type=tel], select, textarea {
    display: block; width: 100%; margin-top: 6px; padding: 9px 12px;
    border: 1px solid var(--line); border-radius: var(--radius);
    font-size: 14px; font-family: inherit; color: var(--text); background: #fff;
    transition: border-color .15s, box-shadow .15s;
}
input:focus, select:focus, textarea:focus {
    outline: none; border-color: var(--primary);
    box-shadow: 0 0 0 3px rgba(47, 107, 255, .12);
}
textarea { min-height: 90px; resize: vertical; }
/*
 * 表单底部操作条：**靠右下**，上面一条浅线把"填写区"和"操作区"分开。
 * 以前是左对齐、没有分隔线，一长串设置项滚到底之后，客户找不到"保存"在哪。
 */
.form-actions {
    display: flex; gap: 10px; flex-wrap: wrap;
    align-items: center; justify-content: flex-end;
    margin-top: 20px; padding-top: 16px;
}
.form-actions:not(:first-child) { border-top: 1px solid var(--line-soft); }
.form-actions .left, .form-actions .push-left { margin-right: auto; }
/* 单独一张"操作卡"里用：不要上边距和分隔线（卡片本身已经把它隔开了） */
.form-actions.bare { margin-top: 0; padding-top: 0; border-top: 0; }
.inline { display: inline; }

/*
 * ── 表单页标准骨架（客户定的第 2 条） ────────────────────────────────────
 *
 * 客户原话：「表单页（设置/等级/内容…）：卡片里**两栏栅格**（label 左、控件右，
 * 控件宽度受限不拉满），操作按钮固定在**右下**」。
 *
 * 为什么原来难看：表单一整列铺满 1600px 的屏幕，输入框从屏幕这头拉到那头，
 * 客户说"这些输入框显示的都很小""这么小这么丑"——其实是**太宽**，字显得小。
 *
 * 用法（照抄，一层 div 一行设置项）：
 *
 *   <div class="form-page">
 *     <div class="form-lines">
 *       <label for="x">网站名称</label>
 *       <div class="field">
 *         <input id="x" name="x" value="…">
 *         <span class="hint">显示在浏览器标题栏</span>
 *       </div>
 *
 *       <label for="y">联系电话</label>
 *       <div class="field"><input id="y" name="y"></div>
 *     </div>
 *     <div class="form-actions"><button class="btn btn-primary">保存</button></div>
 *   </div>
 *
 * 注意：**不要**再叫 `.form-grid` —— 那个名字已经被 sys101/102/300/302 用来做
 * "卡片并排"了，两个意思抢一个类名，谁后加载谁赢，就是"每个应用长得都不一样"的根源。
 */
.form-page { max-width: 880px; }
.form-lines {
    display: grid; grid-template-columns: 150px minmax(0, 1fr);
    gap: 14px 20px; align-items: start;
}
.form-lines > label {
    margin: 0; padding-top: 10px; text-align: right;
    color: var(--text-sub); font-size: 13.5px;
}
.form-lines .field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.form-lines .field > label { margin: 0; }
.form-lines .hint { font-size: 12px; color: var(--muted); line-height: 1.6; }
.form-lines input, .form-lines select, .form-lines textarea { margin-top: 0; max-width: 520px; }
.form-lines input[type=checkbox], .form-lines input[type=radio] { width: auto; margin: 0; }
.form-lines .full, .form-lines > .full { grid-column: 1 / -1; }
@media (max-width: 640px) {
    .form-lines { grid-template-columns: 1fr; }
    .form-lines > label { text-align: left; padding-top: 0; }
    .form-lines input, .form-lines select, .form-lines textarea { max-width: none; }
}

/*
 * ── 详情页标准骨架（客户定的第 3 条） ───────────────────────────────────
 *
 * 「上面信息卡（dl.kv）、下面标签页 + 列表」：左边主内容、右边一列状态/操作。
 * 窄屏自动收成一列。类名叫 `.detail-layout` 而不是 `.detail-grid` ——
 * sys302 已经有一个 `.detail-grid`（自动分栏），不抢它的名字。
 */
.detail-layout {
    display: grid; grid-template-columns: minmax(0, 1fr) 320px;
    gap: var(--gap); align-items: start;
}
@media (max-width: 980px) { .detail-layout { grid-template-columns: 1fr; } }

/*
 * ── 老写法兼容：<label>标签<控件></label> 也排成"标签左、控件右" ──────────
 *
 * 13 个产品里有 130 多个后台页面是"标签在上、控件在下"的写法
 * （sys311 的 label.f、sys202/sys101/sys201… 的裸 label）。逐个改代码要动上百个文件，
 * 用 CSS 就能统一：把 label 变成两栏栅格 —— **文字是匿名文本节点，会自动占第一格**，
 * 控件是第二个元素，落在第二格。
 *
 * 排除三种情况：
 *   · `.inline` / `.field`：产品自己的横排或竖排写法，别抢
 *   · label 里含 checkbox / radio：那是"勾选框 + 说明"，不是设置项
 *   · **产品自己的多栏卡片栅格**（`grid-2` / `grid2` / `form-grid` / `field-grid` /
 *     `grid-3` / `grid-4` …，统一按 class 里带 "grid" 排除）：那里每格只有 300~400px 宽，
 *     再切成两栏会把标签挤成两行、控件压成一条缝（sys311 的系统设置就是这么被我试出来的）
 * 浏览器不支持 :has() 时整条选择器作废 —— 退回原来的样子，不会比现在更糟。
 */
.main form > label:not(.inline):not(.field):not(:has(input[type=checkbox])):not(:has(input[type=radio])),
.main form > div:not([class*="grid"]) > label:not(.inline):not(.field):not(:has(input[type=checkbox])):not(:has(input[type=radio])) {
    display: grid; grid-template-columns: 150px minmax(0, 1fr);
    column-gap: 20px; row-gap: 6px; align-items: baseline;
    margin-bottom: 16px;
}
/* 控件和说明文字都进右列（第一行是"标签 + 控件"，说明文字自动落到下一行右边） */
.main form > label > input, .main form > label > select, .main form > label > textarea,
.main form > label > .hint, .main form > label > .muted, .main form > label > small,
.main form > div > label > input, .main form > div > label > select, .main form > div > label > textarea,
.main form > div > label > .hint, .main form > div > label > .muted, .main form > div > label > small {
    grid-column: 2;
}
.main form > label > input:not([type=checkbox]):not([type=radio]),
.main form > label > select,
.main form > div > label > input:not([type=checkbox]):not([type=radio]),
.main form > div > label > select { margin-top: 0; }
@media (max-width: 720px) {
    .main form > label:not(.inline):not(.field),
    .main form > div:not([class*="grid"]) > label:not(.inline):not(.field) {
        grid-template-columns: 1fr; row-gap: 4px;
    }
    .main form > label > input, .main form > label > select, .main form > label > textarea,
    .main form > div > label > input, .main form > div > label > select, .main form > div > label > textarea {
        grid-column: 1;
    }
}

/*
 * 详情列表：<dl class="kv"><dt>…</dt><dd>…</dd></dl>
 *
 * **必须写 dl.kv，不能只写 .kv**：产品里排表单用的是 `<table class="kv">`，
 * 只写 .kv 的话表格也会套上 display:grid —— 表格当场塌掉，里面的输入框
 * 被压成几十像素的小方块、标签挤成竖排文字（客户截图反馈过：
 * "你没发现这些输入框显示的都很小吗"）。教训：通用类一定要带上元素限定。
 */
dl.kv { display: grid; grid-template-columns: 140px 1fr; gap: 10px 16px; margin: 0; }
dl.kv dt { color: var(--muted); font-size: 13px; }
dl.kv dd { margin: 0; }

/* 表单用 <table class="kv"> 写的那些页面：标签列窄一点、控件铺开 */
table.kv { display: table; width: 100%; border-collapse: collapse; }
table.kv tr { border-bottom: 1px solid var(--line-soft); }
table.kv tr:last-child { border-bottom: 0; }
table.kv > tbody > tr > td { padding: 10px 12px 10px 0; vertical-align: top; }
table.kv > tbody > tr > td:first-child { width: 140px; color: var(--muted); font-size: 13px; }
table.kv input:not([type=checkbox]):not([type=radio]),
table.kv textarea, table.kv select { width: 100%; box-sizing: border-box; }
/*
 * 但**单行**控件别拉满整屏：1360 宽的屏幕上一条输入框拉 1100px，字看着就很小，
 * 客户的原话是"这些输入框显示的都很小"。560px 封顶，和 .form-lines 一致；
 * 多行 textarea（填须知、JSON 那种）保持整宽，那是真的要地方。
 */
table.kv input:not([type=checkbox]):not([type=radio]),
table.kv select { max-width: 560px; }
table.kv textarea { min-height: 100px; }

/* 表单里的按钮不要通栏（.btn-block 是显式要通栏的，不在此列） */
form .btn:not(.btn-block) { width: auto; }

/* ─────────── 九、空状态 ─────────── */
.empty {
    text-align: center; color: var(--muted);
    padding: 48px 20px; font-size: 13.5px;
}
.empty::before {
    content: "🗂"; display: block; font-size: 40px; margin-bottom: 10px; opacity: .5;
}

/* ─────────── 十、登录页 ─────────── */
/*
 * 登录页：中间一张正经的登录卡。
 *
 * 原来只有 .login-body 居中，里面的表单没有宽度约束 —— 结果内容缩成中间一小条，
 * 四周一大片空白（客户反馈："这就是你的统一外观吗？这么小这么丑"）。
 * 现在给它一个 400px 的卡片：白底、圆角、阴影，输入框 44px 高，按钮通栏。
 */
.login-body {
    display: grid; place-items: center;
    min-height: 100vh; margin: 0;
    background:
        radial-gradient(1000px 500px at 50% -10%, rgba(47, 107, 255, .12), transparent 70%),
        var(--bg);
}
.login-box {
    width: min(400px, calc(100vw - 40px));
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 18px;
    padding: 34px 32px 26px;
    box-shadow: 0 12px 40px rgba(16, 24, 40, .10);
}
.login-box h1 {
    font-size: 24px; margin: 0 0 6px; letter-spacing: .5px;
    display: flex; align-items: center; gap: 10px;
}
/* 标题前那个品牌小方块 */
.login-box h1::before {
    content: ""; width: 30px; height: 30px; border-radius: 9px;
    background: linear-gradient(135deg, var(--primary), #7aa2ff);
    flex: 0 0 auto;
}
.login-box > p.muted { margin: 0 0 22px; font-size: 13px; }
.login-box label { margin-bottom: 14px; }
.login-box input {
    height: 44px; padding: 0 14px; font-size: 15px;
    border-radius: 10px; background: #fbfcfd;
}
.login-box input:focus { background: #fff; }
.login-box .btn-block { height: 44px; font-size: 15px; margin-top: 6px; }

/*
 * 程序目录的「排序价格栏」——和官网首页那条一模一样
 *
 *   [综合] [免费] [最新] [价格]   ¥ 最低 - ¥ 最高   [搜程序名 / 关键词]   [确定]
 *
 * 客户 2026-10-02 给的样式：他在官网首页看到这条，要求客户后台的程序目录也用同一条。
 * 里面的 .market-sort-item 就是 .app-tabs a 那套观感（选中时底部一条蓝线）。
 */
.market-sort {
    display: flex; align-items: center; flex-wrap: wrap; gap: 10px 14px;
    padding: 4px 0 12px; margin: 0 0 12px; border-bottom: 1px solid var(--line);
}
.market-sort-item {
    font-size: 14px; color: var(--text-sub); padding: 4px 2px;
    border-bottom: 2px solid transparent;
}
.market-sort-item:hover { color: var(--primary); text-decoration: none; }
.market-sort-item.on { color: var(--primary); font-weight: 700; border-bottom-color: var(--primary); }

.market-sort-form { display: flex; align-items: center; gap: 6px; margin: 0; flex-wrap: wrap; }
.market-sort .market-sort-form .market-price-ipt {
    display: inline-flex; align-items: center; gap: 4px;
    border: 1px solid var(--line); border-radius: 8px; padding: 0 8px; background: #fff;
    font-size: 13px; color: var(--muted); height: 34px;
}
/*
 * ⚠️ 必须显式写 display / width / margin：
 *   宿主 app.css 上面有一条 `input[type=number] { display:block; width:100%; margin-top:6px }`
 *   （后台表单的统一规则）。不覆盖的话，价格框会变成一个占满整行的大输入框 ——
 *   客户 2026-10-02 截图反馈的"这 UI 太丑了"就是这个。
 */
.market-sort .market-sort-form .market-price-ipt input {
    display: inline-block; width: 66px; min-width: 0; margin: 0; padding: 0;
    border: 0; outline: none; font: inherit; font-size: 13px; color: var(--text);
    background: transparent; box-shadow: none;
}
.market-sort .market-sort-form .market-price-sep { color: var(--muted); }
.market-sort .market-sort-form .market-kw-ipt {
    display: inline-block; width: auto; min-width: 200px; margin: 0;
    font: inherit; font-size: 13px; color: var(--text);
    border: 1px solid var(--line); border-radius: 8px; padding: 0 10px; height: 34px;
}
.market-sort .market-sort-form .market-kw-ipt:focus,
.market-sort .market-sort-form .market-price-ipt:focus-within { border-color: var(--primary); box-shadow: none; }
.market-sort .market-sort-submit {
    font: inherit; font-size: 13px; font-weight: 600; color: #fff; background: var(--primary);
    border: 0; border-radius: 8px; padding: 0 16px; height: 34px; width: auto; min-width: 0;
    cursor: pointer;
}
.market-sort .market-sort-submit:hover { background: var(--primary-hover); }

@media (max-width: 720px) {
    .market-sort-form { width: 100%; }
    .market-sort-form .market-kw-ipt { min-width: 0; flex: 1; }
}
