/* ==========================================================================
   后台样式
   规则（刻意约束，不要随手打破）：
     · 唯一的实心重色是黑色 —— 主按钮、强调小卡片
     · 图表只用灰度，不上彩色
     · 绿色只给「涨幅」和「已启用」，红色只给「危险操作」和「跌幅」
     · 线性图标，不用 emoji
     · 白卡片 + 极浅灰边框，阴影几乎为零；卡片内嵌浅灰小块
     · 大数字撑视觉重量，标签一律小号灰字
   ========================================================================== */

:root {
  --bg:        #F6F7F7;
  --card:      #FFFFFF;
  --sunk:      #F4F5F5;   /* 卡片内嵌的浅灰小块 */
  --line:      #ECEDED;   /* 卡片边框 */
  --line-2:    #E3E5E5;   /* 输入框、描边按钮 */
  --hair:      #F1F2F2;   /* 表格行分隔 */
  --ink:       #17181A;
  --ink-2:     #55595E;
  --gray:      #6B7075;
  --gray-2:    #9AA0A6;
  --gray-3:    #B4B9BD;
  --green:     #17A34A;
  --green-bg:  #F0F8F3;
  --green-ln:  #D8EAE0;
  --red:       #DC2626;
  --red-bg:    #FEF2F2;
  --red-ln:    #FBD5D5;
  --amber:     #B45309;
  --amber-bg:  #FFFBEB;
  --amber-ln:  #FDE68A;
  --r:         8px;
  --r-lg:      11px;
  --sans:      -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
               "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
  --mono:      ui-monospace, "Cascadia Code", Consolas, "SF Mono", Menlo, monospace;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

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

body {
  background: var(--bg);
  color: var(--ink);
  font: 400 13px/1.55 var(--sans);
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }
svg { display: block; flex-shrink: 0; }

/* ============================ 布局骨架 ============================ */

.shell { display: flex; min-height: 100vh; }

.sidebar {
  width: 208px;
  flex-shrink: 0;
  background: var(--card);
  border-right: 1px solid var(--line);
  padding: 15px 11px;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.brand { display: flex; align-items: center; gap: 9px; padding: 4px 7px 17px; }
.brand .logo {
  width: 26px; height: 26px; border-radius: 7px; background: var(--ink);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.brand .name {
  font-weight: 600; font-size: 14.5px; letter-spacing: -.012em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.nav-group { margin-bottom: 3px; }
.nav-label {
  font-size: 10.5px; color: var(--gray-2); padding: 12px 8px 5px;
  letter-spacing: .03em;
}
.nav-item {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 9px; border-radius: var(--r);
  color: var(--ink-2); font-size: 13px; margin-bottom: 1px;
  transition: background .12s, color .12s;
}
.nav-item:hover { background: var(--sunk); color: var(--ink); }
.nav-item.active { background: var(--hair); color: var(--ink); font-weight: 500; }
.nav-item .chev { margin-left: auto; color: var(--gray-3); font-size: 11px; }
.nav-item .badge {
  margin-left: auto; font-size: 11px; color: var(--gray-2);
  font-variant-numeric: tabular-nums;
}

.nav-sub { padding: 1px 0 5px 34px; }
.nav-sub a {
  display: block; padding: 5px 0; font-size: 12.5px; color: var(--gray);
}
.nav-sub a:hover { color: var(--ink); }
.nav-sub a.active { color: var(--ink); font-weight: 500; }

.side-foot { margin-top: auto; padding-top: 14px; border-top: 1px solid var(--hair); }
.side-user { display: flex; align-items: center; gap: 9px; padding: 6px 7px; border-radius: var(--r); }
.side-user:hover { background: var(--sunk); }
.side-user .av {
  width: 26px; height: 26px; border-radius: 50%; background: var(--sunk);
  color: var(--gray); display: flex; align-items: center; justify-content: center;
  font-weight: 600; font-size: 11.5px; flex-shrink: 0;
}
.side-user .who { min-width: 0; flex: 1; }
.side-user .who .n { font-size: 12.5px; font-weight: 500; overflow: hidden;
                     white-space: nowrap; text-overflow: ellipsis; }
.side-user .who .r { font-size: 11px; color: var(--gray-2); }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
/* 不设 max-width —— 内容跟着窗口铺满，宽屏右边不留空白 */
.main-inner { flex: 1; width: 100%; min-width: 0; padding: 15px 18px 12px; }

/* ============================ 页头 ============================ */

.page-head {
  display: flex; justify-content: space-between; align-items: flex-end;
  gap: 14px; margin-bottom: 14px; flex-wrap: wrap;
}
.page-head h1 { font-size: 18px; font-weight: 600; letter-spacing: -.02em; }
.page-head .sub { color: var(--gray); font-size: 12.5px; margin-top: 2px; }
.page-head .tools { display: flex; gap: 9px; align-items: center; flex-wrap: wrap; }

/* ============================ 按钮 ============================ */

.btn {
  display: inline-flex; align-items: center; gap: 6px; justify-content: center;
  border: 0; border-radius: var(--r); padding: 8px 14px;
  font: 500 13px/1 var(--sans); cursor: pointer; white-space: nowrap;
  transition: background .13s, border-color .13s, color .13s;
}
.btn-primary { background: var(--ink); color: #fff; }
.btn-primary:hover { background: #000; }
.btn-light {
  background: var(--card); color: var(--ink); border: 1px solid var(--line-2);
}
.btn-light:hover { border-color: var(--gray-3); }
.btn-ghost { background: transparent; color: var(--ink-2); border: 1px solid var(--line-2); }
.btn-ghost:hover { background: var(--sunk); color: var(--ink); }
.btn-danger { background: var(--card); color: var(--red); border: 1px solid var(--red-ln); }
.btn-danger:hover { background: var(--red-bg); }
.btn-sm { padding: 5px 10px; font-size: 12px; border-radius: 7px; }
.btn[disabled] { opacity: .5; cursor: not-allowed; }
.btn-row { display: flex; gap: 9px; margin-top: 15px; flex-wrap: wrap; }

/* ============================ 卡片 ============================ */

.card {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 16px 17px; margin-bottom: 12px;
}
.card.flush { padding: 0; overflow: hidden; }
.card-head {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 12px; padding: 15px 17px 11px;
}
.card-head.bordered { border-bottom: 1px solid var(--hair); }
.card-title { font-weight: 600; font-size: 14.5px; letter-spacing: -.01em; }
.card-sub { color: var(--gray); font-size: 12px; margin-top: 2px; }
.card > h2 {
  font-size: 14.5px; font-weight: 600; letter-spacing: -.01em;
  margin-bottom: 14px; padding-bottom: 11px; border-bottom: 1px solid var(--hair);
}

.row { display: flex; gap: 11px; margin-bottom: 11px; align-items: stretch; flex-wrap: wrap; }
.row > * { margin-bottom: 0; }
.grow { flex: 1 1 320px; min-width: 0; }

/* 小号统计卡：一行挤不下时自动分摊宽度 */
.col-stat { flex: 1 1 108px; min-width: 100px; }

/* 主内容 + 窄侧栏的两列布局。
   用 Grid 而不是 flex —— flex 表达不了「同排时侧栏保持窄、独占一行时铺满」，
   Grid 的 minmax 两种情况都对。 */
.row-split {
  display: grid;
  gap: 11px;
  margin-bottom: 11px;
  grid-template-columns: minmax(0, 1fr) minmax(250px, 330px);
  align-items: stretch;
}
.row-split.narrow-first {
  grid-template-columns: minmax(250px, 330px) minmax(0, 1fr);
}
/* IP 排行那一列比默认侧栏宽一点：里面要放 IP 地址（14 个字符）
   和地区名，250px 会把地址挤断行 */
.row-split.wide-second {
  grid-template-columns: minmax(0, 1fr) minmax(260px, 380px);
}
/* 三段并排（首页：数据洞察 | 模块列表 | IP 榜）。
   minmax 的第二个值放得比前面宽，是因为 IP 榜里要放地址和地区。 */
.row-split.three {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr) minmax(250px, 340px);
}
/* 「数据洞察」那张卡改成纵向 flex：它旁边的 IP 榜有 10 行、更高，
   Grid 会把这张短的拉长。内部用 flex 排列，底部的说明才有东西可推
   （.insight-foot 的 margin-top:auto 需要父元素是 flex 容器才生效）。 */
.row-split.three > .card:first-child {
  display: flex;
  flex-direction: column;
}
.row-split > * { margin-bottom: 0; min-width: 0; }

/* 窄屏：三段并排会挤成一条条，直接落成一列。
   放在 920px 之前的两档 —— 三列比两列更早需要落列。 */
@media (max-width: 1180px) {
  .row-split.three {
    grid-template-columns: minmax(0, 1fr) minmax(250px, 340px);
  }
  /* 落到两列时，把「数据洞察」整段铺满第一行：
     它是四个小方块，本来就适合横着放 */
  .row-split.three > .card:first-child {
    grid-column: 1 / -1;
  }
}

@media (max-width: 920px) {
  .row-split, .row-split.narrow-first, .row-split.wide-second, .row-split.three {
    grid-template-columns: minmax(0, 1fr);
  }
  .row-split.three > .card:first-child { grid-column: auto; }
}

/* ---------- IP 排行榜 ---------- */

/* 数据洞察的六宫格。用 auto-fit 而不是写死 1fr 1fr：
   卡片窄的时候自动落成一列，不会把"手机 / 平板"这种四五个字的值挤断行 */
.insight-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 9px;
  padding: 0 16px 14px;
}

/* 撑住卡片底部的一句话。旁边 IP 榜有 10 行、比这张卡高，
   Grid 会把短的那张拉长 —— 与其留一块空白，不如让这句话
   贴到底部，中间的空隙看着像是刻意的留白 */
.insight-foot {
  margin-top: auto;
  padding: 12px 16px 15px;
  border-top: 1px solid var(--hair);
  color: var(--gray-2);
  font-size: 11.5px;
  line-height: 1.6;
}

.ip-rank { padding: 2px 16px 12px; }

.ip-row { margin-bottom: 12px; }
.ip-row:last-child { margin-bottom: 4px; }

.ip-head {
  display: flex; align-items: baseline; gap: 8px;
  font-size: 12.5px; margin-bottom: 4px;
}
.ip-head .ix { color: var(--gray-2); font-size: 11.5px; width: 10px; flex-shrink: 0; }
.ip-head .addr {
  flex: 1; min-width: 0; font-family: var(--mono); font-size: 12px;
  /* IP 不该被折行 —— 折了就看不出是一个地址了 */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ip-head .n {
  font-weight: 600; font-size: 12.5px; font-variant-numeric: tabular-nums;
  color: var(--ink-2); flex-shrink: 0;
}

.ip-bar { height: 5px; background: var(--sunk); border-radius: 3px; overflow: hidden; }
.ip-bar i { display: block; height: 100%; background: #2B2C2F; border-radius: 3px; }

.ip-region { color: var(--gray-2); font-size: 11px; margin-top: 3px; }

/* 内嵌浅灰小块 */
.sunk { background: var(--sunk); border-radius: var(--r); padding: 11px 13px; }
.sunk .l { font-size: 11px; color: var(--gray); }
.sunk .v { font-weight: 600; font-size: 15px; margin-top: 4px; letter-spacing: -.01em; }

/* 黑色强调小卡片 —— 全站只用在一两处 */
.blackcard {
  background: var(--ink); color: #fff; border-radius: var(--r-lg);
  padding: 13px 16px;
  flex: 1 1 130px; min-width: 122px;
  display: flex; flex-direction: column; justify-content: center;
}
.blackcard .l { font-size: 10.5px; color: #9EA3A7; }
.blackcard .v { font-size: 17px; font-weight: 700; margin: 3px 0; letter-spacing: -.02em; }
.blackcard .s { font-size: 10px; color: #9EA3A7; }

/* ============================ KPI ============================ */

.kpi { flex: 1; min-width: 150px; padding: 14px 16px; }
.kpi .l { font-size: 12px; color: var(--gray); }
.kpi .v {
  font-size: 27px; font-weight: 700; letter-spacing: -.028em;
  margin: 5px 0 4px; font-variant-numeric: tabular-nums;
}
.kpi .v .unit { font-size: 14px; font-weight: 500; margin-left: 3px; }
.kpi .d { font-size: 11.5px; color: var(--gray); }
.kpi .d.up { color: var(--green); }
.kpi .d.down { color: var(--red); }
.kpi.hl { background: var(--green-bg); border-color: var(--green-ln); }

/* ============================ 问候卡 ============================ */

.greet { display: flex; align-items: center; gap: 15px; padding: 16px 18px; }
.greet .av {
  width: 44px; height: 44px; border-radius: 50%; background: var(--sunk);
  color: var(--gray); display: flex; align-items: center; justify-content: center;
  font-weight: 600; font-size: 16px; flex-shrink: 0;
}
.greet .hi {
  font-weight: 600; font-size: 19px; letter-spacing: -.022em;
  display: flex; align-items: center; gap: 7px;
}
.chips { display: flex; gap: 7px; margin-top: 8px; flex-wrap: wrap; }
.chip {
  background: var(--sunk); border-radius: 6px; padding: 3px 9px;
  font-size: 11.5px; color: var(--gray);
}
.chip b { color: var(--ink); font-weight: 500; }

/* ============================ 表格 ============================ */

.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; }
thead th {
  text-align: left; font-size: 11.5px; font-weight: 500; color: var(--gray);
  padding: 11px 14px; border-bottom: 1px solid var(--hair); white-space: nowrap;
}
tbody td { padding: 12px 14px; border-bottom: 1px solid var(--hair); vertical-align: middle; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: #FAFBFB; }
th.right, td.right { text-align: right; }
td .t-title { font-weight: 500; font-size: 13.5px; }
td .t-title:hover { text-decoration: underline; }
td .t-time { color: var(--gray); font-size: 12px; white-space: nowrap; }
td .t-num { font-weight: 600; font-variant-numeric: tabular-nums; }
td.actions { white-space: nowrap; }
td.actions .btn { margin-left: 5px; }

.code-chip {
  display: inline-block; font-family: var(--mono); font-size: 11px;
  background: var(--sunk); border-radius: 5px; padding: 2px 6px; color: var(--ink-2);
}
.target-hint { color: var(--gray-2); font-size: 11.5px; }

.tag {
  display: inline-block; font-size: 11.5px; color: var(--gray);
  background: var(--sunk); border-radius: 6px; padding: 2px 9px; white-space: nowrap;
}
.tag-green { color: var(--green); background: var(--green-bg); }
.tag-red   { color: var(--red);   background: var(--red-bg); }
.tag-amber { color: var(--amber); background: var(--amber-bg); }

/* ============================ 列表（Top5 那种） ============================ */

.rank-row {
  display: flex; align-items: center; gap: 11px;
  padding: 9px 17px; border-top: 1px solid var(--hair);
}
.rank-row .ix { color: var(--gray-2); font-size: 11.5px; width: 10px; flex-shrink: 0; }
.rank-row .tx { flex: 1; min-width: 0; }
.rank-row .t1 {
  font-weight: 500; font-size: 12.5px;
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.rank-row .t2 { color: var(--gray-2); font-size: 11px; margin-top: 1px; font-family: var(--mono); }
.rank-row .n { font-weight: 600; font-size: 13px; font-variant-numeric: tabular-nums; }

/* ============================ 图表 ============================ */

/*
 * 图表高度固定，不随宽度变化。
 *
 * SVG 若用 viewBox + height:auto，宽度变大高度会等比拉高 ——
 * 宽屏下会变成一个几百像素高的巨块。所以这里：
 *   · svg 用 preserveAspectRatio="none" + 固定高度，横向自由拉伸
 *   · 坐标轴文字移到 SVG 外面用 HTML 渲染，避免被横向拉扁
 *   · 描边加 vector-effect="non-scaling-stroke"，非等比缩放下线宽不变形
 */
:root { --chart-h: 200px; }

.chart-wrap { display: flex; gap: 9px; padding: 6px 17px 0; }

.chart-y {
  display: flex; flex-direction: column; justify-content: space-between;
  height: var(--chart-h); flex-shrink: 0;
  font-size: 9.5px; color: var(--gray-2); text-align: right;
  font-variant-numeric: tabular-nums;
}
.chart-y span { line-height: 1; transform: translateY(-50%); }
.chart-y span:first-child { transform: none; }
.chart-y span:last-child { transform: translateY(-100%); }

.chart-plot { flex: 1; min-width: 0; }

.chart {
  display: block; width: 100%; height: var(--chart-h);
}
.chart .grid { stroke: var(--hair); stroke-width: 1; }

.chart-x {
  position: relative; height: 15px; margin-top: 4px;
  font-size: 9.5px; color: var(--gray-2);
}
.chart-x span { position: absolute; top: 0; white-space: nowrap; transform: translateX(-50%); }
.chart-x span.at-start { transform: none; }
.chart-x span.at-end   { transform: translateX(-100%); }

.legend {
  display: flex; justify-content: center; gap: 16px; flex-wrap: wrap;
  font-size: 11.5px; color: var(--gray); padding: 9px 0 14px;
}
.legend i { width: 7px; height: 7px; display: inline-block; margin-right: 5px; }

@media (max-width: 640px) {
  :root { --chart-h: 165px; }
  .chart-wrap { padding: 6px 13px 0; }
}

/* ============================ 表单 ============================ */

.form-group { margin-bottom: 15px; }
.form-group:last-child { margin-bottom: 0; }
label { display: block; font-size: 13px; font-weight: 500; margin-bottom: 6px; }
input[type=text], input[type=password], input[type=number],
input[type=url], input[type=datetime-local], select, textarea {
  width: 100%; font: inherit; font-size: 14px; padding: 9px 12px;
  color: var(--ink); background: var(--card);
  border: 1px solid var(--line-2); border-radius: var(--r);
  transition: border-color .14s, box-shadow .14s;
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--ink); box-shadow: 0 0 0 3px rgba(23,24,26,.07);
}
textarea { resize: vertical; min-height: 84px; line-height: 1.6; }
textarea.code { font-family: var(--mono); font-size: 12.5px; }
select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%239AA0A6' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 11px center; padding-right: 32px;
}
.hint { color: var(--gray); font-size: 12px; margin-top: 5px; }
.hint code {
  font-family: var(--mono); background: var(--sunk);
  border-radius: 4px; padding: 1px 5px; font-size: .95em;
}
.field-row { display: flex; gap: 11px; flex-wrap: wrap; }
.field-row > * { flex: 1; min-width: 160px; }

/* 单选分段 */
.seg { display: flex; gap: 9px; flex-wrap: wrap; }
.seg label {
  flex: 1; min-width: 180px; margin: 0; cursor: pointer;
  border: 1px solid var(--line-2); border-radius: var(--r);
  padding: 11px 13px; display: flex; gap: 9px; align-items: flex-start;
  font-weight: 400; transition: border-color .13s, background .13s;
}
.seg label:hover { border-color: var(--gray-3); }
.seg input { margin-top: 2px; accent-color: var(--ink); flex-shrink: 0; }
.seg label:has(input:checked) { border-color: var(--ink); background: var(--sunk); }
.seg .t { font-weight: 500; font-size: 13px; }
.seg .d { color: var(--gray); font-size: 11.5px; margin-top: 1px; }

/* 开关 */
.switch-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; cursor: pointer;
}
.switch-row .label-main { margin: 0; }
.switch { position: relative; width: 40px; height: 23px; flex-shrink: 0; }
.switch input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.switch .track {
  position: absolute; inset: 0; background: #D4D8DA; border-radius: 99px;
  transition: background .17s;
}
.switch .track::after {
  content: ''; position: absolute; top: 2.5px; left: 2.5px;
  width: 18px; height: 18px; background: #fff; border-radius: 50%;
  transition: transform .17s; box-shadow: 0 1px 2px rgba(0,0,0,.14);
}
.switch input:checked + .track { background: var(--ink); }
.switch input:checked + .track::after { transform: translateX(17px); }

/* 复选格（分配模块用） */
.check-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); gap: 9px; }
.check-grid label {
  margin: 0; background: var(--sunk); border-radius: var(--r);
  padding: 10px 12px; display: flex; align-items: center; gap: 8px;
  font-size: 12.5px; font-weight: 400; cursor: pointer;
}
.check-grid input { accent-color: var(--ink); flex-shrink: 0; }
.check-grid label:has(input:disabled) { opacity: .6; cursor: default; }

/* 权益格（只读展示） */
.perm-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); gap: 9px; }
.perm {
  background: var(--sunk); border-radius: var(--r); padding: 10px 12px;
  display: flex; align-items: center; gap: 8px; font-size: 12.5px;
}
.perm .yes { color: var(--green); }
.perm .no  { color: var(--gray-3); }
.perm.off  { color: var(--gray-2); }

/* 搜索筛选条 */
.filter-bar {
  display: flex; gap: 9px; align-items: center; flex-wrap: wrap;
  padding: 11px 15px;
}
.search-box {
  flex: 1; min-width: 180px; display: flex; align-items: center; gap: 8px;
  background: var(--sunk); border-radius: var(--r); padding: 0 11px;
}
.search-box input {
  border: 0; background: transparent; padding: 8px 0; font-size: 13px;
}
.search-box input:focus { box-shadow: none; }
.filter-bar select { width: auto; min-width: 120px; padding: 7px 30px 7px 11px; font-size: 12.5px; }

/* ============================ 提示条 ============================ */

.alert {
  border-radius: var(--r); padding: 11px 14px; font-size: 13px; margin-bottom: 12px;
  background: var(--green-bg); border: 1px solid var(--green-ln); color: #14532D;
}
.alert-error { background: var(--red-bg); border-color: var(--red-ln); color: #B42318; }
.alert-warn  { background: var(--amber-bg); border-color: var(--amber-ln); color: #92400E; }

.empty { text-align: center; padding: 52px 24px; color: var(--gray); }
.empty .ic { color: var(--gray-3); margin: 0 auto 13px; }
.empty .t { font-weight: 600; font-size: 14.5px; color: var(--ink); margin-bottom: 4px; }
.empty .d { font-size: 12.5px; }
.empty .btn { margin-top: 16px; }

.foot { text-align: center; color: var(--gray-2); font-size: 11.5px; padding: 16px 0 8px; }

/* ============================ 富文本编辑器 ============================ */

.editor-toolbar {
  display: flex; gap: 3px; flex-wrap: wrap; padding: 7px;
  background: var(--sunk); border: 1px solid var(--line-2);
  border-bottom: 0; border-radius: var(--r) var(--r) 0 0;
}
.editor-toolbar button {
  border: 0; background: transparent; border-radius: 6px; padding: 5px 9px;
  font: 400 12.5px/1.4 var(--sans); color: var(--ink-2); cursor: pointer;
}
.editor-toolbar button:hover { background: #E7E9E9; color: var(--ink); }
.editor-toolbar .sep { width: 1px; background: var(--line-2); margin: 3px 4px; }

/*
 * 正文编辑框。
 *
 * 高度固定在 560px 上，超出的内容在框内滚动。
 * 之前是 min-height:340px —— 没有上限，正文里放十几张图就能把页面撑到
 * 几屏高，工具栏滚上去了、下面的「保存文章」也够不着，
 * 编辑到一半想加粗还得先往回滚。
 *
 * 用 height 而不是 max-height：max-height 在内容少时框会缩成一小条，
 * 点进去编辑的区域忽大忽小。
 *
 * resize:vertical 让人可以自己拉高 —— 有的正文确实需要一屏放更多，
 * 那是各人习惯，不该由我们定死。横向不给拉：框宽跟着页面走，
 * 拉开就会和卡片边缘错位。
 */
.editor-area {
  border: 1px solid var(--line-2); border-radius: 0 0 var(--r) var(--r);
  padding: 15px 17px; height: 560px; background: var(--card);
  font-size: 15px; line-height: 1.8; overflow-y: auto;
  resize: vertical;
}
.editor-area:focus { outline: none; border-color: var(--ink); }
.editor-area img { max-width: 100%; height: auto; border-radius: 6px; margin: 7px 0; }
.editor-area h2 { font-size: 20px; margin: 18px 0 9px; }
.editor-area h3 { font-size: 17px; margin: 15px 0 7px; }
.editor-area p { margin: 9px 0; }
.editor-area ul, .editor-area ol { margin: 9px 0 9px 24px; }
.editor-area blockquote {
  margin: 12px 0; padding: 3px 0 3px 14px;
  border-left: 3px solid var(--line-2); color: var(--gray);
}
.editor-area a { color: #1D4ED8; text-decoration: underline; }

/* 上传进度提示 */
.upload-tip {
  position: fixed; left: 50%; bottom: 26px; transform: translateX(-50%);
  background: var(--ink); color: #fff; border-radius: 99px;
  padding: 9px 19px; font-size: 12.5px; z-index: 90;
  box-shadow: 0 6px 22px rgba(0,0,0,.2);
}

/* ============================ 图床网格 ============================ */

.img-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 11px; }
.img-cell {
  border: 1px solid var(--line); border-radius: var(--r); overflow: hidden;
  background: var(--sunk); position: relative;
}
.img-cell .thumb { aspect-ratio: 1; width: 100%; object-fit: cover; display: block; background: var(--sunk); }
.img-cell .meta { padding: 8px 10px; background: var(--card); border-top: 1px solid var(--line); }
.img-cell .meta .n {
  font-size: 11.5px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.img-cell .meta .s { font-size: 10.5px; color: var(--gray-2); margin-top: 2px; }
.img-cell .ops { display: flex; gap: 5px; padding: 0 10px 9px; background: var(--card); }
.img-cell .ops .btn { flex: 1; }

.dropzone {
  border: 1.5px dashed var(--line-2); border-radius: var(--r-lg);
  padding: 30px 20px; text-align: center; color: var(--gray);
  background: var(--card); cursor: pointer; transition: border-color .15s, background .15s;
}
.dropzone:hover, .dropzone.over { border-color: var(--ink); background: var(--sunk); }
.dropzone .t { font-weight: 600; color: var(--ink); font-size: 14px; margin: 9px 0 3px; }
.dropzone .d { font-size: 12px; }

/* ============================ 分页 ============================ */

.pager { display: flex; gap: 5px; align-items: center; justify-content: center; padding: 14px 0 4px; }
.pager a, .pager span {
  min-width: 31px; height: 31px; padding: 0 9px; border-radius: 7px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 12.5px; color: var(--ink-2); border: 1px solid var(--line-2); background: var(--card);
}
.pager a:hover { border-color: var(--gray-3); }
.pager .on { background: var(--ink); color: #fff; border-color: var(--ink); font-weight: 500; }
.pager .gap { border: 0; background: transparent; color: var(--gray-2); }

/* ============================ 移动端 ============================ */

.menu-btn { display: none; }
.scrim { display: none; }

@media (max-width: 860px) {
  .sidebar {
    position: fixed; z-index: 60; left: 0; top: 0; bottom: 0; height: 100%;
    transform: translateX(-100%); transition: transform .2s ease;
    box-shadow: 0 0 40px rgba(0,0,0,.12);
  }
  body.nav-open .sidebar { transform: none; }
  body.nav-open .scrim {
    display: block; position: fixed; inset: 0; z-index: 55; background: rgba(0,0,0,.28);
  }
  .menu-btn {
    display: inline-flex; align-items: center; gap: 7px;
    background: var(--card); border: 1px solid var(--line-2); border-radius: var(--r);
    padding: 7px 11px; font: 500 13px var(--sans); color: var(--ink); cursor: pointer;
    margin-bottom: 12px;
  }
  .main-inner { padding: 13px 13px 10px; }
  .kpi .v { font-size: 23px; }
  .greet { flex-wrap: wrap; }
  td.actions .btn { margin: 2px 0 2px 4px; }

  /* 手机上 560px 可能比整个屏幕还高，反而看不见工具栏。
     改成跟视口走，并且留出工具栏和按钮的位置。 */
  .editor-area { height: 52vh; }
}
