Files
FeedLite/assets/style.css
T
laoyang 0ebf250c76 去掉内容区与顶栏重复的标题行和我要反馈按钮;简介移到顶栏标题下灰色小字
用户:上面已有标题和「我要反馈」,下面又出现一次,完全重复。
「下面这一行不要了…把那个软件简介放在最上面『同步日历反馈系统』下面那个位置,
  用个灰色的。我要反馈按钮也不要了,其他内容开始往前提,更简洁。」

改法:
- index.php 删掉整个 page-head 行(软件图标+名字 / 简介 / 我要反馈大按钮)
  → 列表内容直接从筛选器开始,上提一整行(实测内容起始 y=109)
- 顶栏品牌位改成两行:
    行1 图标 + 「XX 反馈系统」(软件主题色 17px)
    行2 一句话简介(software.note,灰色 #6b7280,12.5px,移动端 11.5px)
- 简介左对齐到标题文字(padding-left 41px = 图标 32 + gap 9),不是贴图标左边
- 顶栏高度从固定 66px 改为 min-height + padding,两行也放得下(实测 67px)

⚠️ 「我要反馈」按钮去掉了 hide-sm:
   列表页那个大按钮删掉后,顶栏这个是全站唯一入口,
   如果手机上隐藏掉,手机端就没有提交入口了。

清理 .page-sw-id 死样式。
验证:桌面/手机下简介都在标题下方、颜色灰色、内容区无重复、我要反馈只 1 个且两宽度都可见;
8 个路由全部 200;详情页顶栏同样显示简介。
2026-11-03 15:05:37 +08:00

899 lines
42 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* FeedLite · 轻反馈 —— 简洁、克制的基础视觉基调 */
:root{
--fg:#1f2329; --muted:#6b7280; --line:#e5e7eb; --line-strong:#d7dbe0;
--bg:#f5f6f8; --card:#ffffff; --brand:#0057B8; --brand-600:#004a9e; --brand-soft:#e8f0f9;
/* 顶栏品牌图标:与官网首页同一枚应用图标(内联,离线预览也能显示) */
--icon-mark:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAADsOAAA7DgHMtqGDAAADj0lEQVR4nO1b205TQRTdGB/UB78B0BdfRNA3NUT/QPHMHIgaP0BeMPqoog8mJqDyCfoBImJnDuCFyEWhIGiUegONimkFodYEaqpj9qEEwZbS0zOXXlaykqZNO2uvM9M9Z8/ZABkhysBy9gLhl4Dwh0B5CAj7CZQLo4iaCJtwNRLWDITVZI4tY+CMAOGvtQfnnSGwnWNuLFmBBnYAZU8NCMAvDoLlVGwseCtwAAgLGyDaZ7IZsJ3D6wdP+CEg7Jd+sdIYBytQm+bKOxVAecQAkfJngsV3rolelBXYms/EgdV/jJRTA0SpJeF1K1c/v1OdRwPYxFL8dtc+7WJ00Q5U4/S/rF2INrKLkNzeiqIkYfcBCHujXYg+hgAoixkgRBNZDHL5gU22IxraxsXdkYiYnlsUid9/hGzgGDhWRzAi6tvGXQ05mQAev1jZ2CtGp6JCN0Ymo64WpQZUNvaKSDQuTEE4GhcVXk0AD9PehCu/FsH3UW/LAbL8Aq55U2HfGJNvQOdoRJiKO8GwfAO+zi0KU/Hl+6J8AxIKUp1XoDbpBqTCp9kFsftsf/aDe2TVuX7xeXYhpRYtBrR0TikLfpmt9z6YY8DQu3mx5XiXsuC3nuh2054xBiBwe9rzYkZ0P5dLHGO9P2JtBpiCkgG0NANEQaTBbSe7xdWOyfxYAi2S0uD2Uz35YcCQpDRoXRvLDwNkpMEnb+c9bbu1GWAKSgbQ0gwQUpdAIsW69JoGNzc4oq71mW+32Epuh6dT7MNzTYNY2fUDeIss3YCOYMTXNIjV3NhCwhcDbg8pKInVpymKekmDj17O+hY8gl5XUBTdZDu+TVk/MayqLA7JgxE8jDAFqKX8tKKDEfhn7aaryqi+8p5PhWgOBiwvBzyMwHo8lqRVHY7iWO3DYXfNazscBQ88cyuUMcCmmyFlekC1Acgr7env8fEz1XpA+YDJ88WP31bq+vga39OhBbQMmtwG72p67BJf69IB2gY2haBbgG4C5T+0i9BFwqNQlI/JrnpclrIHxf6gZLN2Ifp4Hg2oKd4ZwKuSzRI8VHzBs1crDRPYWqZbkGragSNrWmb4oHZRysj6/u8lpKy8aJqmsC8yTc9grdtapl2kNMaBsoMZeged/QXbOIl9kRuC5fYQDhRQ8H3uEs8OArvJ6tztovYAckh1lB2FnGEHqt0GI9w6uoaY2GXCYkvt86iRXwDL2bOR0P4Cy8Hrhv+SooQAAAAASUVORK5CYII=");
--ok:#0f9d58; --ok-soft:#e9f7ef; --warn:#b7791f; --warn-soft:#fff8e6;
--danger:#d93025; --danger-soft:#fdecea; --shadow:0 1px 3px rgba(16,24,40,.06);
}
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
margin:0; background:var(--bg); color:var(--fg);
font-family:-apple-system,BlinkMacSystemFont,"HarmonyOS Sans SC","HarmonyOS Sans","PingFang SC","Helvetica Neue","Microsoft YaHei",sans-serif;
font-size:15.5px; line-height:1.75; letter-spacing:.01em;
}
.wrap{max-width:880px; margin:0 auto; padding:0 16px}
a{color:var(--brand); text-decoration:none}
a:hover{text-decoration:underline}
h1{font-size:23px; margin:0 0 8px; font-weight:700}
h2{font-size:17px; margin:0 0 12px; font-weight:700}
p{margin:8px 0}
.muted{color:var(--muted)}
.small{font-size:13px}
.dot{color:var(--line-strong); padding:0 2px}
/* ---------- 顶栏(与官网首页同一套导航样式) / 页脚 ---------- */
.topbar{
position:sticky; top:0; z-index:20;
background:rgba(255,255,255,.82);
backdrop-filter:saturate(180%) blur(14px);
-webkit-backdrop-filter:saturate(180%) blur(14px);
border-bottom:1px solid var(--line);
/* 软件抽屉是 absolute + top:100%,需要它来做定位参照,否则会跑到页面最上面 */
}
.topbar .wrap{display:flex; align-items:center; gap:14px; min-height:66px; padding-top:9px; padding-bottom:9px; position:relative; box-sizing:border-box}
/* 顶栏品牌位:两行结构
* 行1 = 图标 + 「XX 反馈系统」(软件主题色,17px)
* 行2 = 一句话简介(灰色 12.5px),只在有 note 时出现
* 🔴 用户 2026-11-03:简介从内容区挪到这里,用灰色。
* 内容区那一行(标题+简介+我要反馈)与新顶栏完全重复,已删除。 */
.topbar .brand-mini{display:flex; flex-direction:column; align-items:flex-start; gap:1px; font-weight:700; font-size:17px; color:var(--fg); min-width:0; line-height:1.25}
.topbar .brand-mini:hover{text-decoration:none; color:var(--fg)}
.topbar .brand-mini-row{display:flex; align-items:center; gap:10px; min-width:0}
.topbar .brand-mini-note{
font-size:12.5px; font-weight:400; color:var(--muted);
line-height:1.35; max-width:520px;
overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
/* 与标题文字左对齐:让简介从图标右侧开始,而不是贴到图标左侧 */
padding-left:41px;
}
/* 顶栏里的软件标识:17px 字 + 32px 图标 ——
* 比「选择软件」标签(13.5px)大两号,又不至于压过内容区标题。 */
.topbar .brand-mini .sw-badge{gap:9px}
.topbar .brand-mini .sw-badge-nm{font-size:17px; font-weight:700; letter-spacing:.2px}
@media (max-width:560px){
.topbar .wrap{min-height:60px; padding-top:8px; padding-bottom:8px}
.topbar .brand-mini .sw-badge-nm{font-size:15.5px}
.topbar .brand-mini .sw-badge-img{width:26px !important; height:26px !important}
.topbar .brand-mini .sw-badge{gap:7px}
.topbar .brand-mini-note{font-size:11.5px; padding-left:33px; max-width:60vw}
}
/* ---------- 右上角三横线按钮 + 下拉菜单 ---------- */
.sw-toggle{
flex:none; width:38px; height:38px; padding:0; margin-left:2px;
display:inline-flex; flex-direction:column; align-items:center; justify-content:center; gap:4px;
background:transparent; border:0; border-radius:9px;
cursor:pointer;
}
.sw-toggle span{
display:block; width:18px; height:2px; border-radius:2px;
background:var(--fg);
}
.sw-toggle:hover{background:var(--brand-soft)}
.sw-toggle[aria-expanded="true"]{background:var(--brand-soft)}
/* ---------- 软件下拉菜单(右上角三横线) ----------
* 参考家书 FamilyBook 顶栏那个 popup 的做法:**内容多高就多高的小浮窗**,
* 紧贴按钮下方、宽度由内容撑开,不是铺满整屏的面板,也不加遮罩。
* 用户 2026-11-03:「不用做那么复杂,就是点了之后拉下来一个很窄的框,
* 把所有的内容都铺在上面就可以了」。
*
* ⚠️ 用过两版都不对:
* ① 宽屏横排 / 窄屏竖排两套 —— 手机上和正文撞在一起
* ② 整幅 absolute 面板 + 遮罩 —— 太重了,像侧边栏而不是下拉菜单
* 现在只有这一种形态:小浮窗,贴按钮右侧对齐。 */
.sw-panel{
position:absolute; top:calc(100% - 4px); right:12px;
z-index:60;
min-width:172px; max-width:min(280px, calc(100vw - 24px));
padding:6px;
background:var(--card);
border:1px solid var(--line);
border-radius:12px;
box-shadow:0 10px 28px -8px rgba(20,30,50,.28), 0 2px 6px rgba(20,30,50,.08);
max-height:calc(100vh - 90px);
overflow:auto;
}
/* 菜单里不再需要「选择软件」这个标题 —— 按钮本身已经说明用途 */
.sw-panel-hd{display:none}
.sw-panel .wrap{padding:0; max-width:none}
/* 一条一行,竖排 */
.sw-panel-list{display:flex; flex-direction:column; gap:1px}
.sw-item{
display:flex; align-items:center; gap:8px;
padding:8px 10px; border-radius:8px; color:var(--fg);
font-size:14px; white-space:nowrap;
border:0;
}
.sw-item:hover{background:var(--brand-soft); text-decoration:none; color:var(--fg)}
.sw-item.on{background:var(--brand-soft)}
.sw-item.on .sw-badge-nm{font-weight:700}
.sw-item .sw-badge{gap:7px}
.sw-item .sw-badge-nm{font-size:14px; font-weight:500}
.sw-item .sw-badge-img{width:18px !important; height:18px !important}
/* 「当前」标记缩成一个小圆点,别在窄框里占地方 */
.sw-item-cur{
margin-left:auto;
width:6px; height:6px; flex:none; border-radius:50%;
background:var(--brand);
font-size:0; line-height:0; overflow:hidden; text-indent:-999px;
}
.topbar .brand-text{overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.topbar .logo-mark{
width:30px; height:30px; flex:none; display:block; border-radius:8px;
background-image:var(--icon-mark); background-size:cover; background-position:center;
box-shadow:var(--shadow);
}
.topbar .spacer{flex:1}
.topbar .navlink{color:var(--muted); font-size:14.5px; padding:8px 10px; border-radius:8px; white-space:nowrap}
.topbar .navlink:hover{color:var(--brand); background:var(--brand-soft); text-decoration:none}
.topbar .btn-mini{
flex:none; font-size:14.5px; font-weight:600; color:#fff; background:var(--brand);
padding:9px 18px; border-radius:999px; white-space:nowrap;
box-shadow:0 4px 14px -4px rgba(0,87,184,.55);
}
.topbar .btn-mini:hover{background:var(--brand-600); color:#fff; text-decoration:none}
.hide-sm{display:inline-block}
@media (max-width:640px){
.hide-sm{display:none}
.topbar .wrap{gap:10px}
.topbar .brand-mini{font-size:15.5px; gap:9px}
.topbar .logo-mark{width:28px; height:28px}
}
main.wrap{padding-top:24px; padding-bottom:40px; min-height:60vh}
.foot{border-top:1px solid var(--line); background:var(--card); padding:22px 0 34px; margin-top:40px}
.foot p{margin:4px 0; text-align:center; font-size:13px; color:var(--muted)}
.foot a{color:var(--muted); text-decoration:underline}
/* 版权句 + 管理后台入口:同一行居中,窄屏自动换行 */
.foot-line{display:flex; flex-wrap:wrap; align-items:center; justify-content:center; gap:0 6px}
.foot-line .dot{padding:0}
/* ---------- 按钮 ---------- */
.btn{
display:inline-block; border:1px solid var(--line-strong); background:var(--card);
color:var(--fg); border-radius:9px; padding:8px 16px; font-size:14.5px;
cursor:pointer; line-height:1.4; font-family:inherit;
}
.btn:hover{border-color:var(--brand); color:var(--brand); text-decoration:none}
.btn.primary{background:var(--brand); border-color:var(--brand); color:#fff; font-weight:600}
.btn.primary:hover{background:var(--brand-600); color:#fff}
/* ---------- 页头 ---------- */
.page-head{display:flex; align-items:flex-start; gap:16px; margin:6px 0 18px}
.page-head .btn{margin-left:auto; flex:none; margin-top:4px}
/* ---------- 首页:轻反馈介绍页 ----------
* 用户 2026-11-03:首页不列问题,只做介绍 + 指路。
* 因为访客总是从某个软件过来的,他要的是「怎么进自己那个软件的反馈」,
* 而不是看别人的问题列表。 */
.home{max-width:820px; margin:0 auto; padding:8px 0 40px}
.home-hero{text-align:center; padding:26px 0 30px}
.home-hero h1{
font-size:30px; line-height:1.3; margin:0 0 12px;
letter-spacing:-.4px;
}
.home-lead{
font-size:15.5px; line-height:1.75; color:var(--muted);
margin:0 auto; max-width:600px;
}
.home-feats{
display:grid; grid-template-columns:repeat(2, minmax(0,1fr));
gap:12px; margin:0 0 34px;
}
@media (max-width:600px){ .home-feats{grid-template-columns:1fr} }
.home-feat{
background:var(--card); border:1px solid var(--line);
border-radius:12px; padding:16px 18px;
}
.home-feat-ic{font-size:20px; line-height:1; margin-bottom:8px}
.home-feat h3{margin:0 0 6px; font-size:15px; font-weight:700}
.home-feat p{margin:0; font-size:13.5px; line-height:1.7; color:var(--muted)}
.home-enter{
background:var(--card); border:1px solid var(--line);
border-radius:14px; padding:22px 24px;
}
.home-enter h2{margin:0 0 10px; font-size:17px}
.home-enter-tip{
font-size:14px; color:var(--muted); line-height:1.8; margin:0 0 16px;
display:flex; align-items:center; flex-wrap:wrap; gap:6px;
}
.home-enter-tip b{color:var(--fg); font-weight:600}
/* 小号三横线示意,让「右上角那个设置按钮」有具体形象可对照 */
.home-menu-demo{
display:inline-flex; flex-direction:column; justify-content:center; gap:2.5px;
width:22px; height:22px; padding:4px; box-sizing:border-box;
border:1px solid var(--line-strong); border-radius:6px;
background:var(--bg, #f6f8fb);
}
.home-menu-demo i{display:block; width:100%; height:1.5px; background:var(--fg); border-radius:2px}
.home-sw-list{display:flex; flex-direction:column; gap:8px}
.home-sw{
display:flex; align-items:center; gap:12px;
padding:11px 14px; border-radius:11px;
border:1px solid var(--line); background:var(--card);
color:var(--fg);
}
.home-sw:hover{
text-decoration:none; color:var(--fg);
border-color:var(--swc); background:var(--bg, #f6f8fb);
}
.home-sw-ic{
width:36px; height:36px; flex:none; border-radius:9px;
display:flex; align-items:center; justify-content:center;
font-size:22px; line-height:1;
}
.home-sw-ic img{width:36px; height:36px; object-fit:contain; display:block}
.home-sw-nm{font-size:15px; font-weight:600; color:var(--swc)}
.home-sw-go{margin-left:auto; font-size:13px; color:var(--muted); flex:none}
.home-sw:hover .home-sw-go{color:var(--swc)}
.home-enter-alt{margin:12px 0 0}
.page-head h1{margin-bottom:4px}
.page-head .muted{font-size:14px; margin:0}
/* ---------- 后台处理按钮栏 ---------- */
.act-bar{
margin:0 0 18px; padding:14px 16px;
background:var(--card); border:1px solid var(--line); border-radius:12px;
}
.act-bar-title{
font-size:12.5px; font-weight:700; letter-spacing:.5px;
color:var(--muted); text-transform:uppercase; margin-bottom:10px;
}
.act-bar-body{display:flex; flex-wrap:wrap; gap:8px; align-items:center}
.act-inline{display:inline}
.act-btn{white-space:nowrap}
.act-btn.is-cur{
opacity:.55; cursor:default;
box-shadow:none;
}
.act-btn.ok{border-color:#b7dfc2; color:#1e7b3c}
.act-btn.ok:hover:not(:disabled){background:#f0f9f2}
.act-btn.warn{border-color:#f0dfae; color:#8a6a15}
.act-btn.warn:hover:not(:disabled){background:#fff9ec}
.act-state.on{
display:inline-block; padding:6px 12px; border-radius:99px;
font-size:12.5px; font-weight:600;
background:#f0f9f2; color:#1e7b3c; border:1px solid #b7dfc2;
}
.act-hint{
margin-left:auto; font-size:12.5px; color:var(--muted);
}
@media (max-width:560px){
.act-hint{margin-left:0; flex-basis:100%}
}
.act-note{
margin-top:14px; padding-top:14px; border-top:1px dashed var(--line);
}
/* ---------- 软件标识:图标 + 名字(多软件区分的主视觉) ----------
* 🔴 一律不要背景色:图标本身就是一张图/一个 emoji,再垫一个色块会糊在一起,
* 反而看不清。直接「图标 + 文字」并排是识别度最高的做法。
* 邮件模板里有等价的 table 写法,两边观感要对得上。 */
.sw-badge{display:inline-flex; align-items:center; gap:7px; min-width:0; vertical-align:middle}
.sw-badge-ic{
display:inline-flex; align-items:center; justify-content:center;
flex:none; line-height:1; letter-spacing:0;
background:none; border:0; box-shadow:none;
}
.sw-badge-nm{
font-weight:600; font-size:14px; color:var(--fg);
overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.sw-badge-sm .sw-badge-nm{font-size:14px}
.sw-badge-md .sw-badge-nm{font-size:16px; font-weight:600}
/* 内容区:只是软件标识,字号刻意小于顶栏标题(17px),
* 避免「上面的字比下面的小」这种主次颠倒。颜色同样跟随软件主题色。 */
.sw-badge-lg .sw-badge-nm{font-size:15px; font-weight:600; color:var(--swc, var(--fg))}
/* 顶栏主标题:比「选择软件」标签(13.5px)大两号 = 17px,且大于内容区的 15px。
* 颜色跟随软件主题色(--swc 由 PHP 内联写到 .brand-mini 上),
* 让「同步日历」「密码生成器」这些标题一眼可辨。 */
.sw-badge-brand .sw-badge-nm{font-size:17px; font-weight:700; letter-spacing:.2px; color:var(--swc, var(--fg))}
/* 页头副行:图标 + 软件名 */
/* (已删).page-sw-id —— 内容区那行软件标识已移除,
* 软件名与简介统一由顶栏承担,避免与顶栏标题重复。 */
/* 提交页顶部的软件上下文条:同样无背景色,只留一行轻分隔 */
.sw-context{
display:flex; align-items:center; gap:10px; flex-wrap:wrap;
margin:0 0 16px; padding:0 0 12px; border-bottom:1px solid var(--line);
}
.sw-context .sw-badge-nm{color:var(--fg)}
/* 后台软件编辑:图标快选 */
.icon-presets{display:flex; gap:4px; flex-wrap:wrap; margin-top:8px}
.icon-preset{
width:34px; height:34px; border:1px solid var(--line-strong); border-radius:9px;
background:var(--card); cursor:pointer; font-size:17px; line-height:1; padding:0;
display:inline-flex; align-items:center; justify-content:center;
}
.icon-preset:hover{border-color:var(--brand); background:var(--brand-soft)}
/* ---------- 软件图标(上传图片) ---------- */
/* 图标图片:外框与字符版完全一致,换图不会让布局跳动 */
/* 图标图片:不留背景、不加圆角底衬,直接贴图 */
.sw-badge-img{
display:inline-block; object-fit:contain; flex:none;
background:none; border:0; box-shadow:none;
}
.chip.on .sw-badge-img{box-shadow:0 0 0 1px rgba(255,255,255,.5)}
/* 后台图标上传行 */
.icon-up{display:flex; align-items:flex-start; gap:14px; flex-wrap:wrap; margin-top:6px}
.icon-prev{
width:56px; height:56px; flex:none; border-radius:12px; overflow:hidden;
border:1px solid var(--line); background:var(--card);
display:flex; align-items:center; justify-content:center;
}
.icon-prev img{width:100%; height:100%; object-fit:cover; display:block}
.icon-prev-ph{
width:100%; height:100%; display:flex; align-items:center; justify-content:center;
color:#fff; font-size:24px; font-weight:600;
}
.icon-up-main{flex:1; min-width:220px; display:flex; flex-direction:column}
.icon-up-main input[type=file]{font-size:13.5px; max-width:100%}
/* chip 里也不用白底反色了 —— 图标本来就没有底色 */
.chip.on .sw-badge-nm{color:#fff}
.chip .sw-badge-ic{background:none !important; color:inherit !important; box-shadow:none}
/* ---------- 主题色选择器 ---------- */
.sw-dot{
display:inline-block; width:10px; height:10px; border-radius:50%;
flex:none; margin-right:2px; vertical-align:middle;
box-shadow:0 0 0 1px rgba(0,0,0,.12);
}
.color-row{display:flex; align-items:center; gap:10px; flex-wrap:wrap}
.color-input{
width:46px; height:34px; padding:2px; border:1px solid var(--line-strong);
border-radius:9px; background:var(--card); cursor:pointer; flex:none;
}
.color-presets{display:flex; gap:6px; flex-wrap:wrap}
.color-preset{
width:26px; height:26px; border-radius:50%; border:2px solid transparent;
cursor:pointer; padding:0; flex:none; transition:transform .12s;
}
.color-preset:hover{transform:scale(1.12)}
.color-preset.on{border-color:var(--fg); box-shadow:0 0 0 2px var(--card) inset}
/* ---------- 邮件测试 ---------- */
.mail-test{
display:flex; flex-wrap:wrap; align-items:center; gap:10px;
padding:12px 14px; margin:6px 0 16px;
background:var(--card); border:1px dashed var(--line); border-radius:11px;
}
.mail-test input[type=email]{
flex:1 1 220px; min-width:180px;
border:1px solid var(--line-strong); border-radius:9px; padding:8px 10px;
font-size:14px; background:var(--card); color:var(--fg); font-family:inherit;
}
.mail-test-out{flex:1 1 100%; font-size:13px; line-height:1.6}
.mail-test-out.ok{color:var(--ok)}
.mail-test-out.err{color:#c9302c}
/* RAM 角色探测结果 */
.role-ok{
padding:8px 11px; border-radius:9px; font-size:13.5px;
background:var(--ok-soft, #eef8f0); border:1px solid #cfe8d5;
}
.role-warn{
padding:8px 11px; border-radius:9px; font-size:13.5px;
background:#fff8e6; border:1px solid #f0e0b0; color:#8a6d1f;
}
/* ---------- 表单就地校验的错误提示 ---------- */
.field.has-error > input,
.field.has-error > textarea,
.field.has-error > select,
.field.has-error .chips{
border-color:#d9534f !important;
box-shadow:0 0 0 3px rgba(217,83,79,.12) !important;
}
.field-error{
display:block; margin-top:6px; font-style:normal;
font-size:12.5px; color:#c9302c; line-height:1.5;
}
.field-error::before{content:"⚠ "; font-style:normal}
/* ---------- 后台:软件 / 分类 / 状态 ---------- */
.card-list{display:flex; flex-direction:column; gap:8px; margin-bottom:16px}
.tax-row{
display:flex; align-items:flex-start; gap:12px; flex-wrap:wrap;
padding:12px 14px; background:var(--card); border:1px solid var(--line);
border-radius:11px;
}
.tax-row.on{border-color:var(--brand); box-shadow:0 0 0 1px var(--brand) inset}
.tax-row.off{opacity:.62}
.tax-main{flex:1 1 320px; min-width:0}
.tax-name{font-weight:600; font-size:15.5px; text-decoration:none; color:var(--fg)}
.tax-name:hover{color:var(--brand)}
.tax-name.plain{font-weight:600}
.tax-slug{
display:inline-block; margin-left:8px; font-size:12px; color:var(--muted);
font-family:ui-monospace,Consolas,monospace;
}
.tax-meta{margin-left:10px; font-size:12.5px; color:var(--muted)}
.tax-note{margin-top:5px; font-size:13px; color:var(--muted); line-height:1.5}
.tax-acts{display:flex; flex-wrap:wrap; gap:6px; align-items:center}
.inline-form{display:inline}
.btn.sm{padding:5px 11px; font-size:13px; border-radius:8px}
.btn.danger{border-color:#e0b4b4; color:#b4242c}
.btn.danger:hover{background:#fdf2f2; border-color:#b4242c}
.tax-form-box{
margin:18px 0 8px; border:1px solid var(--line); border-radius:11px;
background:var(--card); overflow:hidden;
}
.tax-form-box>summary{
cursor:pointer; padding:12px 14px; font-weight:600; font-size:14.5px;
background:var(--bg-soft, #f7f8fa); user-select:none;
}
.tax-form-box>summary:hover{color:var(--brand)}
.tax-form-box[open]>summary{border-bottom:1px solid var(--line)}
.sm-form{padding:14px; margin:0}
.sm-form .field{margin-bottom:10px}
/* ---------- 软件切换(一级) ---------- */
.software-bar{
display:flex; flex-wrap:wrap; align-items:center; gap:8px;
margin-bottom:14px; padding-bottom:14px; border-bottom:1px solid var(--line);
}
.software-bar .sw-label{font-size:13.5px; color:var(--muted); font-weight:600}
.software-bar .chips{margin-bottom:0}
/* ---------- 筛选(二级:分类 / 状态) ---------- */
.filters{margin-bottom:16px}
.chips{display:flex; flex-wrap:wrap; gap:8px; margin-bottom:12px}
.chip{
padding:5px 13px; border-radius:999px; background:var(--card);
border:1px solid var(--line); font-size:13.5px; color:var(--fg);
}
.chip:hover{border-color:var(--brand); color:var(--brand); text-decoration:none}
.chip.on{background:var(--brand); border-color:var(--brand); color:#fff; font-weight:600}
.filter-row{display:flex; flex-wrap:wrap; gap:8px}
.filter-row select,.filter-row input[type=search]{
border:1px solid var(--line-strong); border-radius:9px; padding:8px 10px;
font-size:14px; background:var(--card); color:var(--fg); font-family:inherit;
}
.filter-row input[type=search]{flex:1; min-width:160px}
/* ---------- 列表 ---------- */
.list{display:flex; flex-direction:column; gap:12px}
.item{
display:block; background:var(--card); border:1px solid var(--line);
border-radius:13px; padding:15px 17px; box-shadow:var(--shadow); color:inherit;
}
.item:hover{border-color:var(--brand); text-decoration:none; box-shadow:0 3px 12px rgba(0,87,184,.10)}
/* 列表项:
* 行1 = 标题(顶头、单独一行)
* 行2 = 分类 / 状态 标签
* 行3 = 摘要、缩略图、作者信息
*
* 🔴 用户 2026-11-03:标签别放在标题前面。
* 以前 badges 和标题挤在同一个 flex 行里,标签占掉左边一大截,
* 标题被推到右边、长度不够就换行,很难看。
* 现在标题独占一行、从左边缘开始,标签另起一行。 */
/* ⚠️ .item-top 仍被 admin.php 的三处内部列表使用(后台待审核 / 详情头 / 操作日志)。
* 前台列表已改用 .item-head + .item-tags(标题独占一行),这里保留供后台用。 */
.item-top{display:flex; align-items:center; flex-wrap:wrap; gap:8px}
.item-head{display:flex; align-items:flex-start; gap:8px}
.item-title{font-weight:600; font-size:16px; flex:1; min-width:0; line-height:1.45; word-break:break-word}
.item-tags{display:flex; flex-wrap:wrap; align-items:center; gap:6px; margin-top:7px}
.item-ex{color:var(--muted); font-size:14px; margin:8px 0 8px; word-break:break-word}
.item-meta{display:flex; flex-wrap:wrap; align-items:center; gap:6px; font-size:13px; color:var(--muted)}
.item-meta .who{color:#3a424d; font-weight:600}
/* 带 token 回复时展示只读身份(昵称 + 邮箱) */
.reply-identity{
display:flex; align-items:center; flex-wrap:wrap; gap:8px;
padding:9px 12px; border-radius:9px;
background:var(--bg, #f6f8fb); border:1px solid var(--line);
font-size:14px;
}
.reply-identity-nm{font-weight:600; color:var(--fg)}
.reply-identity-mail{
color:var(--muted); font-size:13px;
padding:1px 8px; border-radius:99px; background:var(--card);
border:1px solid var(--line);
}
/* 提交人凭 token 看自己未公开反馈时的提示条 */
.owner-note{
display:flex; flex-direction:column; gap:4px;
margin:0 0 16px; padding:12px 14px;
background:var(--warn-soft, #fff8e6);
border:1px solid #f0d9a8; border-left:3px solid #d99b1f;
border-radius:10px; font-size:13.5px; line-height:1.65;
color:#6b5313;
}
.owner-note b{font-size:14px; color:#5a4610}
/* ---------- 后台「待审核」列表 ----------
* 列表式:一屏能看多条,右侧固定一个「通过并公开」。
* 详情/关闭说明留在管理页里填,列表页不塞表单。 */
.plist{display:flex; flex-direction:column; gap:10px}
.prow{
display:flex; align-items:flex-start; gap:16px;
background:var(--card); border:1px solid var(--line);
border-radius:12px; padding:13px 16px;
}
.prow:hover{border-color:var(--line-strong)}
.prow-main{flex:1; min-width:0}
.prow-top{display:flex; align-items:center; flex-wrap:wrap; gap:8px}
.prow-title{
font-weight:600; font-size:15.5px; color:var(--fg);
flex:1; min-width:160px; word-break:break-word;
}
.prow-title:hover{color:var(--brand); text-decoration:underline}
.prow-ex{
color:var(--muted); font-size:13.5px; margin:6px 0;
word-break:break-word; display:-webkit-box; -webkit-line-clamp:2;
-webkit-box-orient:vertical; overflow:hidden;
}
.prow-meta{display:flex; flex-wrap:wrap; align-items:center; gap:6px; font-size:12.5px; color:var(--muted)}
.prow-meta .who{color:#3a424d; font-weight:600}
.prow-act{flex:none; padding-top:2px}
.prow-act .btn{white-space:nowrap}
@media (max-width:600px){
.prow{flex-direction:column; gap:10px}
.prow-act{align-self:flex-start}
}
/* 问题编号:便于按 id 逐条跟进与引用 */
.item-id{
flex:none; font-size:12.5px; font-weight:600; color:var(--muted);
font-variant-numeric:tabular-nums; letter-spacing:.02em;
border:1px solid var(--line); border-radius:6px; padding:0 7px; line-height:1.9;
}
/* ---------- 徽标 ---------- */
.badge{
display:inline-block; font-size:12px; line-height:1.6; padding:1px 9px;
border-radius:999px; background:var(--brand-soft); color:var(--brand);
font-weight:600; white-space:nowrap;
}
.badge.st{background:#f1f3f5; color:#5b636e}
.badge.st-open{background:var(--warn-soft); color:var(--warn)}
/* 「未公开」= 还没审过,用中性灰,不要和「已关闭」混淆 */
.badge.st-hidden{background:#eef0f3; color:#6b7684}
.badge.st-doing{background:var(--brand-soft); color:var(--brand)}
.badge.st-resolved{background:var(--ok-soft); color:var(--ok)}
.badge.st-closed{background:#f1f3f5; color:#8a929c}
.badge.official{background:var(--brand); color:#fff}
/* 软件徽章:比分类更"重",一眼看出属于哪个软件 */
/* 软件徽标:每个软件用自己的主题色 + 图标,方便一眼区分是哪个软件。
* 颜色由 PHP 内联写入(--swc / --swc-soft),这里只管形态。 */
.badge.sw{
display:inline-flex; align-items:center; gap:5px;
background:var(--swc-soft, #eef2f8); color:var(--swc, #2b4a74);
border:1px solid var(--swc-line, #cfdcee); font-weight:600;
padding:1px 9px 1px 6px;
}
.badge.sw .badge-sw-ic{
display:inline-flex; align-items:center; justify-content:center;
width:15px; height:15px; flex:none; line-height:1;
}
.badge.sw .badge-sw-ic img{width:15px; height:15px; display:block; object-fit:contain}
.badge.sw .badge-sw-nm{white-space:nowrap}
.badge.st-wontfix{background:#f6eef0; color:#a13c53}
/* ---------- 分页 ---------- */
.pager{display:flex; align-items:center; gap:12px; margin:22px 0 0; justify-content:center}
.pager-info{font-size:13.5px; color:var(--muted)}
/* ---------- 空态 ---------- */
.empty{
background:var(--card); border:1px dashed var(--line-strong); border-radius:13px;
padding:34px 20px; text-align:center; color:var(--muted);
}
.empty.small{padding:20px}
/* ---------- 面包屑 ---------- */
.crumbs{margin:4px 0 14px; font-size:14px}
/* ---------- 主题 / 回复 ---------- */
.subject{background:var(--card); border:1px solid var(--line); border-radius:14px; padding:20px 22px; box-shadow:var(--shadow)}
/* 详情页三段:标题(顶头独占一行)→ 标签行 → 作者信息行。
* 🔴 用户 2026-11-03:软件名/分类/状态这三个标签原来在标题前面,
* 把标题挤到右边去了。现在标题在最上面顶头,标签另起一行放下面。 */
.subject-head{display:flex; align-items:flex-start; gap:10px}
.subject-title{font-size:21px; margin:0; flex:1; min-width:0; line-height:1.4; word-break:break-word}
.subject-tags{display:flex; flex-wrap:wrap; align-items:center; gap:7px; margin:10px 0 0}
.subject-body{margin-top:14px; white-space:normal; word-break:break-word; line-height:1.85}
.subject-body br{content:""}
.replies{margin-top:22px}
.reply{
background:var(--card); border:1px solid var(--line); border-left:3px solid var(--line-strong);
border-radius:11px; padding:13px 16px; margin-bottom:11px;
}
.reply.admin{border-left-color:var(--brand); background:linear-gradient(180deg,var(--brand-soft),var(--card) 42%)}
.reply-head{display:flex; align-items:center; gap:8px; font-size:13px; color:var(--muted); margin-bottom:6px}
.reply-head .who{font-weight:600; color:#3a424d; font-size:14px}
.reply-body{word-break:break-word; line-height:1.8}
/* ---------- 表单 ---------- */
/* 提交页容器。
* 🔴 原来只有 max-width:640px,**没有居中** —— 在 880px 的内容区里,
* 表单贴左边、右侧空出 240px 白,看起来像"页面缺了一块"。
* 用户 2026-11-03 指出这一点。现在:加 margin 居中,宽度放到 720px,
* 既不至于像正文那么宽(长行难读),也不会显得抠掉一块。 */
.narrow{max-width:720px; margin-left:auto; margin-right:auto}
/* ---------- 提交成功页 ----------
* 用户 2026-11-03:提交完不要跳走,要给回执 + 凭据 + 后续去处。 */
.submitted{
background:var(--card); border:1px solid var(--line);
border-radius:16px; padding:30px 32px 26px; margin-top:14px;
box-shadow:var(--shadow);
text-align:center;
}
.submitted-ok{
width:52px; height:52px; margin:0 auto 14px; border-radius:50%;
background:var(--ok-soft, #e8f6ee); color:var(--ok, #16794a);
font-size:26px; line-height:52px; font-weight:700;
}
.submitted h1{font-size:22px; margin:0 0 10px}
.submitted-lead{
font-size:14px; line-height:1.75; color:var(--muted);
margin:0 auto 20px; max-width:520px;
}
.submitted-lead b{color:var(--fg)}
/* 凭据框:要显眼但不能吓人 —— 用中性浅底 + 等宽字,看起来像"码" */
.token-box{
text-align:left; margin:0 0 22px; padding:15px 16px;
background:var(--bg, #f6f8fb); border:1px solid var(--line);
border-radius:11px;
}
.token-box-hd{
font-size:12.5px; font-weight:700; color:var(--muted);
letter-spacing:.3px; margin-bottom:8px;
}
.token-code{
font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size:14px; font-weight:600; color:var(--fg);
padding:10px 12px; background:var(--card);
border:1px dashed var(--line-strong); border-radius:8px;
word-break:break-all; user-select:all; line-height:1.5;
}
.token-box-tip{
font-size:12.5px; line-height:1.7; color:var(--muted); margin:10px 0 0;
}
.token-box-warn{
font-size:12.5px; line-height:1.7; color:#8a5a10; margin:8px 0 0;
padding:7px 10px; background:#fff8e6; border-radius:6px;
}
.submitted-next{
font-size:13px; color:var(--muted); margin:0 0 10px; text-align:left;
}
.submitted-actions{
display:flex; flex-wrap:wrap; gap:8px; justify-content:flex-start;
margin:0 0 22px;
}
/* (已删)submitted-others / submitted-sw ——
* 成功页不再列其他软件的入口,跨软件只有顶栏三横线菜单一个入口。 */
.submitted-credit{
margin:18px 0 0; padding-top:16px; border-top:1px solid var(--line);
font-size:12.5px; color:var(--muted); text-align:left;
word-break:break-all;
}
@media (max-width:600px){
.submitted{padding:24px 18px 20px}
.submitted-actions .btn{flex:1 1 auto; text-align:center}
}
.card-form{background:var(--card); border:1px solid var(--line); border-radius:14px; padding:20px 22px; box-shadow:var(--shadow); margin-top:14px}
.field{display:block; margin-bottom:16px}
.field > span{display:block; font-size:14px; font-weight:600; margin-bottom:6px}
.field .req{color:var(--danger)}
.field .hint{font-style:normal; font-weight:400; font-size:12.5px; color:var(--muted); margin-left:6px}
.field input[type=text],.field input[type=email],.field input[type=tel],
.field input[type=password],.field textarea,.field select{
width:100%; border:1px solid var(--line-strong); border-radius:9px;
padding:9px 12px; font-size:15px; font-family:inherit; background:var(--card);
color:var(--fg); line-height:1.6;
}
.field textarea{resize:vertical; min-height:110px}
.field input:focus,.field textarea:focus,.field select:focus{
outline:none; border-color:var(--brand); box-shadow:0 0 0 3px var(--brand-soft);
}
.row2{display:grid; grid-template-columns:1fr 1fr; gap:14px}
@media (max-width:560px){ .row2{grid-template-columns:1fr} }
.captcha{margin:18px 0 0; padding:14px 16px; background:#fafbfc; border:1px solid var(--line); border-radius:11px}
.captcha .field{margin-bottom:0}
.captcha-line{display:flex; align-items:center; gap:10px; flex-wrap:wrap}
.captcha-line .c-q{
flex:1; min-width:200px; font-weight:600; color:var(--brand);
background:var(--brand-soft); border-radius:8px; padding:8px 12px;
}
.captcha-line input{flex:none; width:110px}
.captcha-line .reload{font-size:13.5px; white-space:nowrap}
.form-actions{margin-top:20px}
.form-actions .btn{padding:10px 26px; font-size:15px}
.admin-status{margin-bottom:16px}
/* 蜜罐字段:对用户不可见,但保留在 DOM 中诱捕机器人 */
.hp-field{position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden}
/* ---------- 提示条 ---------- */
.flash{border-radius:10px; padding:11px 15px; font-size:14px; margin:0 0 16px}
.flash.error{background:var(--danger-soft); border:1px solid #f6c6c1; color:#9c2b21}
.flash.ok{background:var(--ok-soft); border:1px solid #bfe5cd; color:#0b6b3d}
/* ---------- 附件上传(浏览器直传 OSS) ---------- */
.uploader-box{
margin:18px 0 0; padding:14px 16px; background:#fafbfc;
border:1px solid var(--line); border-radius:11px;
}
.uploader{border-radius:10px; transition:background .15s, box-shadow .15s}
.uploader + .uploader{margin-top:14px; padding-top:14px; border-top:1px dashed var(--line)}
.uploader.dragging{background:var(--brand-soft); box-shadow:0 0 0 2px var(--brand) inset}
.up-head{display:flex; align-items:center; gap:10px; flex-wrap:wrap}
.up-title{font-size:14px; font-weight:600}
.up-head .btn{margin-left:auto; padding:6px 14px; font-size:13.5px; flex:none}
.up-file{display:none}
.up-list{display:flex; flex-wrap:wrap; gap:9px; margin-top:10px}
.up-list:empty{display:none}
.up-item{
position:relative; display:flex; gap:10px; align-items:center; width:100%;
padding:8px 10px; border:1px solid var(--line); border-radius:10px; background:var(--card);
}
.up-thumb{
width:52px; height:52px; flex:none; border-radius:8px; overflow:hidden; background:#eef1f4;
display:flex; align-items:center; justify-content:center;
}
.up-thumb img{width:100%; height:100%; object-fit:cover; display:block}
.up-thumb-video{font-size:10px; font-weight:700; color:var(--muted); letter-spacing:.08em}
.up-info{flex:1; min-width:0}
.up-name{font-size:13.5px; font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.up-state{font-size:12.5px; color:var(--muted); word-break:break-word}
.up-bar{height:4px; border-radius:2px; background:#e6eaee; overflow:hidden; margin-top:5px}
.up-bar i{display:block; height:100%; width:0; background:var(--brand); transition:width .2s}
.up-item.done .up-bar{display:none}
.up-item.fail{border-color:#f6c6c1; background:var(--danger-soft)}
.up-item.fail .up-state{color:var(--danger)}
.up-del{
flex:none; border:1px solid var(--line-strong); background:var(--card); color:var(--muted);
border-radius:7px; padding:5px 10px; font-size:12.5px; cursor:pointer; font-family:inherit;
}
.up-del:hover{border-color:var(--danger); color:var(--danger)}
.up-del:disabled{opacity:.45; cursor:default}
/* ---------- 附件展示 ---------- */
/* align-items:flex-start —— 否则同行里有视频(多了标题栏)时,图片盒子会被拉伸,底部留白 */
.atts{display:flex; flex-wrap:wrap; align-items:flex-start; gap:10px; margin-top:14px}
.atts .att{
margin:0; max-width:100%; border:1px solid var(--line); border-radius:11px;
overflow:hidden; background:var(--card);
}
.atts .att-image img{display:block; width:220px; height:auto; max-height:200px; object-fit:cover}
.atts.compact .att-image img{width:150px; max-height:140px}
.atts .att-video{flex:1 1 320px; max-width:440px}
.atts .att-video video{display:block; width:100%; max-height:330px; background:#000}
.att-video-ph{
width:360px; max-width:100%; height:200px; background:#11161c; color:#8b97a5;
display:flex; align-items:center; justify-content:center; font-size:13px;
}
.atts figcaption{
display:flex; gap:8px; align-items:center; padding:6px 9px; font-size:12px; color:var(--muted);
}
.atts .att-name{overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.atts .att-size{margin-left:auto; flex:none}
.thumbs{display:flex; gap:8px; margin:0 0 8px}
.thumbs img{
width:78px; height:78px; object-fit:cover; display:block;
border-radius:9px; border:1px solid var(--line);
}
.att-tag{color:var(--brand); font-weight:600}
/* ---------- 附件灯箱(点击放大 + 左右切换) ---------- */
.atts .att-image .att-lb{display:block; line-height:0; cursor:zoom-in}
.atts .att-image .att-lb:focus-visible{outline:2px solid var(--brand); outline-offset:2px}
.att-zoom{
flex:none; border:1px solid var(--line-strong); background:var(--card); color:var(--muted);
border-radius:6px; padding:2px 9px; font-size:12px; line-height:1.6; cursor:pointer; font-family:inherit;
}
.att-zoom:hover{border-color:var(--brand); color:var(--brand)}
html.lb-open,body.lb-open{overflow:hidden}
.lb{
position:fixed; inset:0; z-index:1000; background:rgba(12,14,17,.94);
display:flex; flex-direction:column; animation:lb-in .16s ease-out;
}
.lb[hidden]{display:none}
@keyframes lb-in{from{opacity:0} to{opacity:1}}
.lb-stage{flex:1; min-height:0; position:relative}
.lb-media{
position:absolute; inset:0; z-index:1; padding:48px 62px;
display:flex; align-items:center; justify-content:center;
}
.lb-media img,.lb-media video{
display:block; max-width:100%; max-height:100%; border-radius:6px;
box-shadow:0 10px 44px rgba(0,0,0,.55);
}
.lb-media video{background:#000; width:auto}
.lb-media.loading::after{
content:''; position:absolute; width:26px; height:26px; border-radius:50%;
border:3px solid rgba(255,255,255,.26); border-top-color:#fff;
animation:lb-spin .8s linear infinite;
}
@keyframes lb-spin{to{transform:rotate(360deg)}}
.lb-nav{
position:absolute; top:50%; transform:translateY(-50%); z-index:2;
width:46px; height:46px; padding:0 0 3px; border:0; border-radius:50%; cursor:pointer;
background:rgba(255,255,255,.14); color:#fff; font-size:26px; line-height:1;
display:flex; align-items:center; justify-content:center; font-family:inherit;
}
.lb-nav:hover{background:rgba(255,255,255,.32)}
.lb-nav[hidden]{display:none}
.lb-prev{left:14px}
.lb-next{right:14px}
.lb-x{
position:absolute; top:14px; right:14px; z-index:3;
width:40px; height:40px; border:0; border-radius:50%; cursor:pointer;
background:rgba(255,255,255,.14); color:#fff; font-size:17px; font-family:inherit;
}
.lb-x:hover{background:rgba(255,255,255,.32)}
.lb-bar{
flex:none; display:flex; align-items:center; gap:10px; flex-wrap:wrap;
padding:10px 18px 16px; color:#e9edf2; font-size:13.5px;
}
.lb-name{font-weight:600; max-width:58vw; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.lb-meta{color:#9aa4b0; white-space:nowrap}
.lb-orig{margin-left:auto; color:#9ec5ff; white-space:nowrap}
.lb-orig[hidden]{display:none}
@media (max-width:560px){
.lb-media{padding:40px 10px}
.lb-nav{width:38px; height:38px; font-size:22px}
.lb-prev{left:6px} .lb-next{right:6px}
.lb-name{max-width:44vw}
}
/* ---------- 深色模式 ---------- */
@media (prefers-color-scheme: dark){
:root{
--fg:#e6e8eb; --muted:#9aa2ad; --line:#2c3138; --line-strong:#3a4149;
--bg:#15181c; --card:#1c2024; --brand:#5aa2ff; --brand-soft:#1e2a3d;
--ok:#4ec98a; --ok-soft:#16301f; --warn:#e2b559; --warn-soft:#2a2517;
--danger:#ff8a80; --danger-soft:#33191a; --shadow:0 1px 3px rgba(0,0,0,.35);
}
.item-meta .who,.reply-head .who{color:#cfd4da}
.field > span{color:#e6e8eb}
.captcha{background:#21262b}
.uploader-box{background:#21262b}
.up-thumb{background:#2c3138}
.up-bar{background:#2c3138}
.up-item.fail{border-color:#5a2a2a}
.badge.st{background:#242a30; color:#a8b0ba}
.badge.st-closed{background:#242a30; color:#8a929c}
.topbar{background:rgba(21,24,28,.82)}
.topbar .navlink:hover{background:var(--brand-soft)}
.btn:hover{border-color:var(--brand)}
.reply.admin{background:linear-gradient(180deg,var(--brand-soft),var(--card) 42%)}
.flash.error{background:var(--danger-soft); border-color:#5a2a2a; color:#ffb4ab}
.flash.ok{background:var(--ok-soft); border-color:#26503a; color:#9fe3bd}
}
/* ---- 管理后台 ---- */
.tabs{display:flex; flex-wrap:wrap; gap:8px; margin:16px 0 4px; border-bottom:1px solid var(--line); padding-bottom:10px}
.tab{padding:7px 14px; border-radius:999px; font-size:14px; color:var(--muted); background:var(--card); border:1px solid var(--line)}
.tab:hover{color:var(--brand); border-color:var(--brand)}
.tab.on{background:var(--brand); border-color:var(--brand); color:#fff}
.grid2{display:grid; grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); gap:12px 16px; margin:12px 0}
.grid2 .field{margin:0}
.check{display:flex; align-items:center; gap:8px; font-size:14px; color:var(--muted); margin:8px 0}
.check input{width:16px; height:16px}
.btn.danger{border-color:#e08b84; color:#c0392b}
.btn.danger:hover{background:#fdecea}
.filters{display:flex; flex-wrap:wrap; gap:8px; margin:18px 0 4px}
.filters input[type=text]{flex:1 1 220px; min-width:180px}
.filters select{max-width:160px}
@media (max-width:640px){
.grid2{grid-template-columns:1fr}
.filters input[type=text],.filters select{width:100%; max-width:none}
}