/* ============================================================
   岸基中心平台 · 统一设计系统
   深色海事工业风 · 品牌蓝 #3d8ef0 · Ant Design 组件气质
   ============================================================ */
:root{
  /* 色板 */
  --bg:#0a0f1a;
  --bg-grid:#0d1422;
  --surface:#101828;
  --surface-2:#141f33;
  --surface-3:#1a2740;
  --surface-hover:#182540;
  --fg:#e8eef8;
  --fg-2:#a7b6cd;
  --muted:#6a7c9c;
  --faint:#4d5f7e;
  --border:#1f2c47;
  --border-soft:#16223a;

  --accent:#3d8ef0;
  --accent-hover:#5ca3ff;
  --accent-strong:#2f7be0;
  --accent-dim:rgba(61,142,240,.13);
  --accent-line:rgba(61,142,240,.45);
  --cyan:#46c3ff;
  --cyan-dim:rgba(70,195,255,.13);

  --success:#34c77b;
  --success-dim:rgba(52,199,123,.13);
  --warn:#f0b03c;
  --warn-dim:rgba(240,176,60,.13);
  --danger:#f0504e;
  --danger-dim:rgba(240,80,78,.13);
  --danger-line:rgba(240,80,78,.5);

  /* 字体 */
  --font-body:"PingFang SC","HarmonyOS Sans SC","Microsoft YaHei","Segoe UI",system-ui,-apple-system,sans-serif;
  --font-mono:"SF Mono",ui-monospace,"JetBrains Mono",Menlo,Consolas,monospace;

  /* 布局 */
  --sidebar-w:200px;
  --topbar-h:58px;

  /* 圆角 / 阴影 */
  --r-s:6px; --r-m:10px; --r-l:14px;
  --sh-1:0 1px 2px rgba(0,0,0,.35);
  --sh-2:0 8px 26px rgba(0,0,0,.45);
  --sh-3:0 20px 60px rgba(0,0,0,.6);
  --focus:0 0 0 3px var(--accent-dim);
}

*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
body{
  font-family:var(--font-body);
  font-size:13px;
  color:var(--fg);
  background:var(--bg);
  line-height:1.5;
  -webkit-font-smoothing:antialiased;
}
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:var(--surface-3);border-radius:6px;border:2px solid var(--bg)}
::-webkit-scrollbar-thumb:hover{background:var(--border)}
a{color:var(--accent-hover);text-decoration:none}
button{font-family:inherit}
svg.ic{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;flex:none}
.mono{font-family:var(--font-mono)}
.hidden{display:none!important}
/* hidden 属性恢复标准语义：.alertbar / .data-error 等横幅类若定义 display:flex 会覆盖
   hidden 属性的 UA 样式，导致「加载失败」默认文案在数据正常时也永远可见（幽灵横幅）。 */
[hidden]{display:none!important}

/* ---------------- 布局框架 ---------------- */
.app{min-height:100vh}
.sidebar{
  position:fixed;inset:0 auto 0 0;width:var(--sidebar-w);
  background:var(--surface);
  border-right:1px solid var(--border);
  display:flex;flex-direction:column;z-index:30;
}
.brand{height:var(--topbar-h);display:flex;align-items:center;gap:10px;padding:0 16px;border-bottom:1px solid var(--border-soft);flex:none}
.brand-logo{width:30px;height:30px;border-radius:8px;background:linear-gradient(135deg,#5ca3ff,#1f5fb8);display:grid;place-items:center;box-shadow:0 2px 8px rgba(61,142,240,.35);flex:none}
.brand-logo svg{width:17px;height:17px;color:#fff;stroke-width:2}
.brand-txt{line-height:1.1}
.brand-name{font-size:14.5px;font-weight:700;letter-spacing:.01em}
.brand-sub{font-size:9.5px;color:var(--muted);letter-spacing:.18em;text-transform:uppercase;margin-top:1px}
.nav{flex:1;overflow-y:auto;padding:6px 10px 12px}
.nav-group-label{font-size:10px;color:var(--faint);letter-spacing:.12em;padding:12px 12px 5px;font-weight:600;display:flex;align-items:center;gap:6px}
.nav-group-label::before{content:"";width:8px;height:8px;border-radius:3px;background:var(--surface-3);border:1px solid var(--border);flex:none}
.nav-group-label.on{color:#8ec2ff}
.nav-group-label.on::before{background:var(--accent-dim);border-color:var(--accent-line)}
.nav-item{display:flex;align-items:center;gap:10px;padding:0 12px;height:34px;border-radius:8px;color:var(--fg-2);cursor:pointer;font-size:13px;position:relative;transition:background .12s,color .12s;margin-bottom:1px}
.nav-item.sub{padding-left:18px}
.nav-item.sub .ic{width:14px;height:14px}
.nav-item:hover{background:var(--surface-hover);color:var(--fg)}
.nav-item.active{background:var(--accent-dim);color:#8ec2ff;font-weight:600}
.nav-item.active::before{content:"";position:absolute;left:-10px;top:9px;bottom:9px;width:3px;border-radius:2px;background:var(--accent)}
.nav-item .ic{width:17px;height:17px;color:var(--faint)}
.nav-item.active .ic{color:var(--accent)}
.nav-item .n-badge{margin-left:auto;font-size:10.5px;background:var(--danger-dim);color:#ff8582;border-radius:999px;padding:0 7px;height:17px;line-height:17px;font-weight:600}
.side-foot{flex:none;border-top:1px solid var(--border-soft);padding:10px 12px}
.user-card{display:flex;align-items:center;gap:10px;padding:6px 6px;border-radius:10px;cursor:pointer}
.user-card:hover{background:var(--surface-hover)}
.side-logout-btn{height:24px;padding:0 9px;border-radius:999px;border:1px solid rgba(255,133,130,.28);background:rgba(240,80,78,.1);color:#ff9d9b;font-size:11px;font-weight:600;cursor:pointer;white-space:nowrap}
.side-logout-btn:hover{background:rgba(240,80,78,.2);border-color:rgba(255,133,130,.52);color:#ffd0cf}
.avatar{width:32px;height:32px;border-radius:50%;background:var(--accent-dim);border:1px solid var(--accent-line);color:#8ec2ff;display:grid;place-items:center;font-size:12.5px;font-weight:600;flex:none}
.user-meta{line-height:1.15;min-width:0;flex:1}
.user-meta b{font-size:13px;font-weight:600;display:block}
.user-meta span{font-size:11px;color:var(--muted)}

.main{margin-left:var(--sidebar-w);padding-top:var(--topbar-h);min-height:100vh}
.topbar{
  position:fixed;top:0;left:var(--sidebar-w);right:0;height:var(--topbar-h);
  display:flex;align-items:center;justify-content:space-between;gap:14px;
  padding:0 18px;background:rgba(9,15,27,.82);backdrop-filter:blur(12px);
  border-bottom:1px solid var(--border);z-index:20;
}
.top-title{display:flex;align-items:baseline;gap:10px;min-width:0}
.top-title-main{min-width:0;font-size:15px;font-weight:700;color:var(--fg);letter-spacing:.01em;white-space:nowrap}
.top-title-main b{font:inherit;color:inherit}
.top-title-sub{font-size:11.5px;color:var(--muted);white-space:nowrap}
.crumb{font-size:13px;color:var(--muted);display:flex;align-items:center;gap:8px}
.crumb .sep{color:var(--faint)}
.crumb b{color:var(--fg);font-weight:600}
.top-right{display:flex;align-items:center;gap:9px;min-width:0}
.gstat{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--fg-2);padding:4px 10px;border:1px solid var(--border);border-radius:999px;background:rgba(16,24,40,.72);white-space:nowrap}
.gstat .ic{width:13px;height:13px}
.gstat.ok .ic{color:var(--success)}
.gstat.warn .ic{color:var(--warn)}
.gstat.bad .ic{color:var(--danger)}
.gstat.click{cursor:pointer}
.gstat.click:hover{border-color:var(--accent-line)}
.top-status{height:28px;padding:0 10px}
.top-alarm{position:relative;width:30px;height:30px;display:grid;place-items:center;color:var(--fg-2);background:rgba(16,24,40,.72);border:1px solid var(--border);border-radius:9px;cursor:pointer;transition:background .14s,border-color .14s,color .14s}
.top-alarm:hover{background:var(--surface-hover);border-color:var(--accent-line);color:var(--fg)}
.top-alarm .ic{width:16px;height:16px}
.top-user{height:30px;display:flex;align-items:center;gap:8px;padding:0 9px 0 2px;border:1px solid var(--border-soft);border-radius:999px;background:rgba(16,24,40,.45);min-width:0}
.top-user-name{max-width:96px;font-size:12.5px;color:var(--fg-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.top-icon{width:34px;height:34px;border-radius:8px;display:grid;place-items:center;color:var(--fg-2);cursor:pointer;border:1px solid transparent}
.top-icon:hover{background:var(--surface-hover);color:var(--fg)}
.top-icon .ic{width:18px;height:18px}
.logout-btn{height:30px;padding:0 12px;border-radius:999px;border:1px solid rgba(255,133,130,.28);background:rgba(240,80,78,.08);color:#ff9d9b;font-size:12px;font-weight:600;cursor:pointer;white-space:nowrap;transition:background .14s,border-color .14s,color .14s,box-shadow .14s}
.logout-btn.compact{padding:0 10px}
.logout-btn:hover{background:rgba(240,80,78,.18);border-color:rgba(255,133,130,.56);color:#ffd0cf;box-shadow:0 0 0 3px rgba(240,80,78,.08)}
.logout-btn:active{background:var(--danger);border-color:var(--danger);color:#fff}
.bell-wrap{position:relative}
.badge-dot{position:absolute;top:-6px;right:-6px;min-width:17px;height:17px;padding:0 5px;border-radius:999px;background:var(--danger);border:1px solid rgba(10,15,26,.9);color:#fff;font-size:10px;font-weight:700;line-height:15px;text-align:center}
.bell-dot{position:absolute;top:7px;right:8px;width:8px;height:8px;border-radius:50%;background:var(--danger);border:1.5px solid var(--bg)}
.page-wrap{padding:16px 20px 32px;max-width:1560px;margin:0 auto}
.page-head{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;margin:2px 0 14px}
.page-title{font-size:19px;font-weight:700;letter-spacing:-.01em}
.page-sub{font-size:12px;color:var(--muted);margin-top:3px}
.page-actions{display:flex;align-items:center;gap:8px;flex:none}

/* ---------------- 面板 ---------------- */
.panel{background:var(--surface);border:1px solid var(--border);border-radius:var(--r-m);box-shadow:var(--sh-1)}
.panel-hd{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 14px;border-bottom:1px solid var(--border-soft)}
.panel-title{font-size:13.5px;font-weight:600;display:flex;align-items:center;gap:8px;color:var(--fg)}
.panel-title .ic{width:15px;height:15px;color:var(--accent)}
.panel-sub{font-size:11.5px;color:var(--muted);font-weight:400;margin-left:2px}
.panel-bd{padding:14px}
.panel-bd.flush{padding:0}
.hd-actions{display:flex;align-items:center;gap:6px}
.hd-link{font-size:12px;color:var(--accent-hover);cursor:pointer;display:flex;align-items:center;gap:4px}
.hd-link:hover{text-decoration:underline}
.hd-link .ic{width:13px;height:13px}

/* ---------------- 按钮 ---------------- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;height:32px;padding:0 14px;border-radius:8px;font-size:13px;font-weight:500;border:1px solid transparent;cursor:pointer;transition:background .14s,border-color .14s,color .14s,box-shadow .14s;white-space:nowrap;background:none;color:inherit}
.btn .ic{width:14px;height:14px}
.btn-primary{background:var(--accent);color:#fff;box-shadow:0 2px 6px rgba(61,142,240,.35)}
.btn-primary:hover{background:var(--accent-hover)}
.btn-primary:active{background:var(--accent-strong)}
.btn-default{background:var(--surface-2);border-color:var(--border);color:var(--fg)}
.btn-default:hover{border-color:var(--accent-line);color:#cfe4ff}
.btn-danger{background:var(--danger-dim);border-color:var(--danger-line);color:#ff9d9b}
.btn-danger:hover{background:var(--danger);color:#fff}
.btn-ghost{color:var(--fg-2)}
.btn-ghost:hover{color:var(--fg);background:var(--surface-hover)}
.btn-sm{height:26px;padding:0 10px;font-size:12px;border-radius:6px}
.btn-sm .ic{width:13px;height:13px}
.btn-lg{height:38px;padding:0 18px;font-size:14px;border-radius:10px}
.btn-icon{width:32px;height:32px;padding:0}
.btn-icon.btn-sm{width:26px;height:26px}
.btn.block{width:100%}
.btn[disabled]{opacity:.45;cursor:not-allowed}

/* ---------------- 表单 ---------------- */
.input,.select{height:32px;padding:0 10px;background:var(--surface-2);border:1px solid var(--border);border-radius:8px;color:var(--fg);font-size:13px;width:100%;transition:border-color .14s,box-shadow .14s}
.input::placeholder{color:var(--faint)}
.input:focus,.select:focus{outline:none;border-color:var(--accent);box-shadow:var(--focus)}
.input:hover:not(:focus){border-color:var(--border)}
textarea.input{height:auto;min-height:72px;padding:8px 10px;resize:vertical;line-height:1.5}
.select{appearance:none;-webkit-appearance:none;padding-right:28px;cursor:pointer;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%236a7c9c' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 10px center}
.field{display:flex;flex-direction:column;gap:6px}
.field>label{font-size:12px;color:var(--fg-2);font-weight:500}
.field-row{display:flex;gap:10px}
.field-row>.field{flex:1}
.hint{font-size:11.5px;color:var(--muted)}
.search{position:relative;width:240px}
.search .ic{position:absolute;left:10px;top:50%;transform:translateY(-50%);width:14px;height:14px;color:var(--faint);pointer-events:none}
.search .input{padding-left:32px}
.switch{width:36px;height:20px;border-radius:999px;background:var(--surface-3);border:1px solid var(--border);position:relative;cursor:pointer;transition:background .15s;flex:none}
.switch::after{content:"";position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;background:var(--fg-2);transition:left .15s,background .15s}
.switch.on{background:var(--accent);border-color:var(--accent)}
.switch.on::after{left:18px;background:#fff}
.checkbox{width:16px;height:16px;border-radius:4px;border:1px solid var(--border);background:var(--surface-2);cursor:pointer;display:inline-grid;place-items:center;flex:none;transition:background .12s,border-color .12s}
.checkbox.on{background:var(--accent);border-color:var(--accent)}
.checkbox.on svg{width:11px;height:11px;color:#fff;stroke-width:3}
.radio{width:16px;height:16px;border-radius:50%;border:1px solid var(--border);background:var(--surface-2);cursor:pointer;display:inline-grid;place-items:center;flex:none}
.radio.on{border-color:var(--accent)}
.radio.on::after{content:"";width:8px;height:8px;border-radius:50%;background:var(--accent)}
.range{height:4px;border-radius:2px;background:var(--surface-3);position:relative;flex:1}
.range::before{content:"";position:absolute;inset:0 auto 0 0;width:40%;background:var(--accent);border-radius:2px}
.range-knob{position:absolute;left:40%;top:50%;transform:translate(-50%,-50%);width:14px;height:14px;border-radius:50%;background:#fff;border:2px solid var(--accent);box-shadow:0 1px 3px rgba(0,0,0,.5)}
.chip-row{display:flex;gap:6px;flex-wrap:wrap}
.chip{display:inline-flex;align-items:center;gap:5px;height:26px;padding:0 11px;border-radius:999px;font-size:12px;color:var(--fg-2);background:var(--surface-2);border:1px solid var(--border);cursor:pointer}
.chip:hover{color:var(--fg)}
.chip.on{background:var(--accent-dim);border-color:var(--accent-line);color:#8ec2ff}

/* ---------------- 标签 / 状态 ---------------- */
.tag{display:inline-flex;align-items:center;gap:5px;height:22px;padding:0 8px;border-radius:6px;font-size:11.5px;font-weight:500;white-space:nowrap}
.tag .ic{width:12px;height:12px}
.tag-accent{background:var(--accent-dim);color:#7fb4ff}
.tag-success{background:var(--success-dim);color:#4cd98f}
.tag-warn{background:var(--warn-dim);color:#ffc35c}
.tag-danger{background:var(--danger-dim);color:#ff8582}
.tag-cyan{background:var(--cyan-dim);color:#62c8ff}
.tag-muted{background:rgba(154,170,196,.09);color:var(--muted)}
.tag-outline{background:transparent;border:1px solid var(--border);color:var(--fg-2)}
.dot{width:7px;height:7px;border-radius:50%;display:inline-block;flex:none}
.dot-success{background:var(--success);box-shadow:0 0 0 3px var(--success-dim)}
.dot-warn{background:var(--warn);box-shadow:0 0 0 3px var(--warn-dim)}
.dot-danger{background:var(--danger);box-shadow:0 0 0 3px var(--danger-dim)}
.dot-accent{background:var(--accent);box-shadow:0 0 0 3px var(--accent-dim)}
.dot-muted{background:var(--faint)}
.dot-cyan{background:var(--cyan);box-shadow:0 0 0 3px var(--cyan-dim)}
.dot-pulse{position:relative}
.dot-pulse::after{content:"";position:absolute;inset:-4px;border-radius:50%;border:1px solid currentColor;animation:pulse 1.8s ease-out infinite}
@keyframes pulse{0%{opacity:.7;transform:scale(.6)}70%{opacity:0;transform:scale(1.4)}100%{opacity:0;transform:scale(1.4)}}
.ldot{display:inline-flex;align-items:center;gap:7px;font-size:12.5px;color:var(--fg-2)}
.ldot b{color:var(--fg);font-weight:600}

/* ---------------- 表格 ---------------- */
.table-wrap{overflow:auto;width:100%}
.table{width:100%;border-collapse:collapse;font-size:12.5px}
.table thead th{position:sticky;top:0;background:var(--surface-2);color:var(--muted);font-weight:600;font-size:11.5px;text-align:left;padding:8px 12px;border-bottom:1px solid var(--border);white-space:nowrap;z-index:1}
.table tbody td{padding:8px 12px;border-bottom:1px solid var(--border-soft);color:var(--fg-2);vertical-align:middle}
.table tbody tr:hover td{background:var(--surface-hover)}
.table tbody tr.selected td{background:var(--accent-dim)}
.table .strong{color:var(--fg);font-weight:500}
.table .th-sort{cursor:pointer;display:inline-flex;align-items:center;gap:4px}
.table .th-sort:hover{color:var(--fg)}
.table .td-actions{display:flex;gap:4px;opacity:0;transition:opacity .12s}
.table tr:hover .td-actions{opacity:1}
.row-link{color:var(--accent-hover);cursor:pointer}
.row-link:hover{text-decoration:underline}
.tfoot{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;border-top:1px solid var(--border-soft);font-size:12px;color:var(--muted)}
.pager{display:flex;align-items:center;gap:4px}
.page-btn{min-width:26px;height:26px;padding:0 6px;border-radius:6px;display:grid;place-items:center;font-size:12px;color:var(--fg-2);cursor:pointer;border:1px solid transparent}
.page-btn:hover{background:var(--surface-hover);color:var(--fg)}
.page-btn.on{background:var(--accent);color:#fff}
.page-btn .ic{width:13px;height:13px}

/* ---------------- KPI / 统计 ---------------- */
.kpi-grid{display:grid;gap:12px}
.kpi{background:var(--surface);border:1px solid var(--border);border-radius:var(--r-m);padding:13px 15px;position:relative;overflow:hidden}
.kpi::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--kpi-c,var(--accent))}
.kpi .k-label{font-size:12px;color:var(--muted);display:flex;align-items:center;gap:6px}
.kpi .k-val{font-size:25px;font-weight:700;margin-top:6px;font-family:var(--font-mono);letter-spacing:-.01em;line-height:1}
.kpi .k-trend{font-size:11.5px;margin-top:7px;display:flex;align-items:center;gap:5px;color:var(--muted)}
.kpi .k-trend .up{color:var(--danger)}
.kpi .k-trend .down{color:var(--success)}
.kpi .k-foot{font-size:11.5px;margin-top:6px;color:var(--faint)}
.ksub{font-size:11.5px;color:var(--muted)}

/* ---------------- 标签页 / 面包屑 ---------------- */
.tabs{display:flex;gap:2px;border-bottom:1px solid var(--border);margin-bottom:14px}
.tab{padding:9px 14px;font-size:13px;color:var(--muted);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;display:inline-flex;align-items:center;gap:6px}
.tab:hover{color:var(--fg)}
.tab.active{color:#8ec2ff;border-bottom-color:var(--accent);font-weight:600}
.tab .n-badge{font-size:10.5px;background:var(--surface-3);color:var(--fg-2);border-radius:999px;padding:0 6px;height:16px;line-height:16px}
.tab.active .n-badge{background:var(--accent-dim);color:#8ec2ff}

/* ---------------- 树 / 列表 ---------------- */
.tree{font-size:13px;user-select:none}
.tree-item{display:flex;align-items:center;gap:8px;height:32px;padding:0 8px;border-radius:7px;cursor:pointer;color:var(--fg-2);position:relative}
.tree-item:hover{background:var(--surface-hover);color:var(--fg)}
.tree-item.active{background:var(--accent-dim);color:#8ec2ff}
.tree-item.active::after{content:"";position:absolute;right:0;top:7px;bottom:7px;width:3px;border-radius:2px;background:var(--accent)}
.tree-item .tw{width:14px;height:14px;color:var(--faint);cursor:pointer;display:grid;place-items:center}
.tree-item .tw svg{width:12px;height:12px}
.tree-item .t-ic{width:15px;height:15px;color:var(--faint)}
.tree-item.active .t-ic{color:var(--accent)}
.tree-item .t-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tree-item .t-meta{font-size:11px;color:var(--faint)}
.tree-indent{padding-left:22px}
.tree-count{font-size:11px;color:var(--faint)}
.list-item{display:flex;align-items:center;gap:10px;padding:9px 10px;border-radius:8px;cursor:pointer;transition:background .12s}
.list-item:hover{background:var(--surface-hover)}
.list-item.active{background:var(--accent-dim)}
.list-item.active .li-title{color:#cfe4ff}
.li-ic{width:32px;height:32px;border-radius:8px;background:var(--surface-3);display:grid;place-items:center;color:var(--muted);flex:none}
.li-ic .ic{width:16px;height:16px}
.list-item.active .li-ic{background:var(--accent-dim);color:var(--accent)}
.li-body{flex:1;min-width:0}
.li-title{font-size:13px;font-weight:500;color:var(--fg);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.li-sub{font-size:11.5px;color:var(--muted);margin-top:1px}
.li-right{text-align:right;flex:none}
.li-meta{font-size:11px;color:var(--muted)}

/* ---------------- 进度 / 条 ---------------- */
.progress{height:6px;border-radius:3px;background:var(--surface-3);overflow:hidden;min-width:50px}
.progress>span{display:block;height:100%;border-radius:3px;background:var(--accent);transition:width .3s}
.progress.p-success>span{background:var(--success)}
.progress.p-warn>span{background:var(--warn)}
.progress.p-danger>span{background:var(--danger)}
.meter{display:flex;align-items:center;gap:8px}
.meter .p-val{font-family:var(--font-mono);font-size:11.5px;color:var(--fg-2);min-width:34px;text-align:right}

/* ---------------- 时间线 ---------------- */
.timeline{position:relative;padding-left:20px}
.timeline::before{content:"";position:absolute;left:5px;top:4px;bottom:6px;width:2px;background:var(--border-soft)}
.tl-item{position:relative;padding:0 0 16px 8px}
.tl-item:last-child{padding-bottom:0}
.tl-item::before{content:"";position:absolute;left:-18px;top:5px;width:9px;height:9px;border-radius:50%;background:var(--bg);border:2px solid var(--muted)}
.tl-item.tl-s::before{border-color:var(--success)}
.tl-item.tl-w::before{border-color:var(--warn)}
.tl-item.tl-d::before{border-color:var(--danger)}
.tl-item.tl-a::before{border-color:var(--accent)}
.tl-time{font-size:11px;color:var(--faint);font-family:var(--font-mono)}
.tl-title{font-size:12.5px;color:var(--fg);margin-top:1px}
.tl-body{font-size:12px;color:var(--fg-2);margin-top:2px}

/* ---------------- 抽屉 / 弹窗 ---------------- */
.drawer-mask{position:fixed;inset:0;background:rgba(4,8,16,.55);opacity:0;pointer-events:none;transition:opacity .2s;z-index:50}
.drawer-mask.show{opacity:1;pointer-events:auto}
.drawer{position:fixed;top:0;right:-460px;bottom:0;width:460px;max-width:94vw;background:var(--surface);border-left:1px solid var(--border);transition:right .24s cubic-bezier(.2,0,0,1);z-index:51;display:flex;flex-direction:column;box-shadow:var(--sh-3)}
.drawer.open{right:0}
.drawer-hd{padding:14px 16px;border-bottom:1px solid var(--border-soft);display:flex;align-items:center;justify-content:space-between;flex:none}
.drawer-hd .d-title{font-size:14.5px;font-weight:600}
.drawer-hd .d-sub{font-size:11.5px;color:var(--muted);margin-top:2px}
.drawer-bd{padding:16px;overflow-y:auto;flex:1}
.drawer-ft{padding:12px 16px;border-top:1px solid var(--border-soft);display:flex;justify-content:flex-end;gap:8px;flex:none}
.icon-btn{width:28px;height:28px;border-radius:7px;display:grid;place-items:center;color:var(--muted);cursor:pointer;border:none;background:none}
.icon-btn:hover{background:var(--surface-hover);color:var(--fg)}
.icon-btn .ic{width:15px;height:15px}
.modal-mask{position:fixed;inset:0;background:rgba(4,8,16,.6);display:grid;place-items:center;z-index:60;opacity:0;pointer-events:none;transition:opacity .2s;padding:20px}
.modal-mask.show{opacity:1;pointer-events:auto}
.modal{width:520px;max-width:100%;background:var(--surface-2);border:1px solid var(--border);border-radius:14px;box-shadow:var(--sh-3);transform:translateY(10px) scale(.98);transition:transform .2s cubic-bezier(.2,0,0,1);display:flex;flex-direction:column;max-height:88vh}
.modal-mask.show .modal{transform:none}
.modal-hd{padding:16px 18px;border-bottom:1px solid var(--border-soft);display:flex;align-items:flex-start;justify-content:space-between}
.modal-hd .m-title{font-size:15px;font-weight:600}
.modal-hd .m-sub{font-size:12px;color:var(--muted);margin-top:3px}
.modal-bd{padding:18px;overflow-y:auto}
.modal-ft{padding:12px 18px;border-top:1px solid var(--border-soft);display:flex;justify-content:flex-end;gap:8px}
.w-560{width:560px}.w-640{width:640px}.w-720{width:720px}

/* ---------------- 分隔 / 工具 ---------------- */
.divider{height:1px;background:var(--border-soft);margin:12px 0}
.vdivider{width:1px;height:16px;background:var(--border)}
.empty{display:grid;place-items:center;padding:38px 20px;color:var(--muted);font-size:13px;text-align:center;gap:8px}
.empty .ic{width:34px;height:34px;color:var(--faint);stroke-width:1.2}
.flex{display:flex;align-items:center}
.flex-between{display:flex;align-items:center;justify-content:space-between}
.flex-col{display:flex;flex-direction:column}
.gap-4{gap:4px}.gap-6{gap:6px}.gap-8{gap:8px}.gap-10{gap:10px}.gap-12{gap:12px}.gap-14{gap:14px}.gap-16{gap:16px}
.mt-4{margin-top:4px}.mt-6{margin-top:6px}.mt-8{margin-top:8px}.mt-10{margin-top:10px}.mt-12{margin-top:12px}.mt-16{margin-top:16px}.mt-20{margin-top:20px}
.mb-8{margin-bottom:8px}.mb-12{margin-bottom:12px}.mb-14{margin-bottom:14px}
.ml-auto{margin-left:auto}
.grow{flex:1;min-width:0}
.nowrap{white-space:nowrap}
.ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.grid{display:grid;gap:12px}
.grid-2{grid-template-columns:1fr 1fr}
.grid-3{grid-template-columns:repeat(3,1fr)}
.grid-4{grid-template-columns:repeat(4,1fr)}
.text-muted{color:var(--muted)}
.text-warn{color:var(--warn)}
.text-danger{color:#ff8582}
.text-success{color:#4cd98f}
.text-accent{color:#8ec2ff}
.text-cyan{color:#62c8ff}
.text-sm{font-size:12px}
.text-xs{font-size:11px}
.text-lg{font-size:16px;font-weight:600}
.w-100{width:100%}

/* ---------------- 弱网 / 无信号 / 占位 ---------------- */
.sig-badge{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;padding:3px 9px;border-radius:999px;border:1px solid;white-space:nowrap}
.sig-badge.s-ok{color:#4cd98f;border-color:rgba(52,199,123,.4);background:var(--success-dim)}
.sig-badge.s-warn{color:#ffc35c;border-color:rgba(240,176,60,.4);background:var(--warn-dim)}
.sig-badge.s-bad{color:#ff8582;border-color:var(--danger-line);background:var(--danger-dim)}
.sig-badge.s-muted{color:var(--muted);border-color:var(--border);background:var(--surface-2)}
.sig-badge .ic{width:12px;height:12px}
.offline-stamp{position:absolute;inset:0;display:grid;place-items:center;background:repeating-linear-gradient(45deg,rgba(8,12,20,.35) 0 12px,rgba(8,12,20,.2) 12px 24px);z-index:3}
.offline-stamp .stamp{display:flex;flex-direction:column;align-items:center;gap:8px;color:var(--muted)}
.offline-stamp .ic{width:30px;height:30px;stroke-width:1.4}
.weak-stamp{position:absolute;left:8px;bottom:30px;display:flex;align-items:center;gap:6px;font-size:11px;color:#ffc35c;background:rgba(10,16,28,.82);border:1px solid rgba(240,176,60,.4);padding:4px 9px;border-radius:7px;z-index:3}
.feed-tag{position:absolute;left:8px;top:8px;display:flex;align-items:center;gap:6px;font-size:11px;color:var(--fg-2);background:rgba(8,12,20,.78);border:1px solid var(--border);padding:3px 8px;border-radius:6px;z-index:3;backdrop-filter:blur(4px)}
.feed-tag .dot{width:6px;height:6px}
.feed-corner{position:absolute;right:8px;top:8px;font-family:var(--font-mono);font-size:10.5px;color:rgba(255,255,255,.8);background:rgba(8,12,20,.7);padding:3px 7px;border-radius:6px;z-index:3;display:flex;flex-direction:column;align-items:flex-end;gap:2px;line-height:1.2}
.feed-reuse{position:absolute;left:8px;bottom:8px;display:flex;align-items:center;gap:6px;font-size:11px;color:#62c8ff;background:rgba(10,18,32,.85);border:1px solid rgba(70,195,255,.35);padding:3px 8px;border-radius:6px;z-index:3}
.feed-reuse .ic{width:12px;height:12px}

/* ---------------- 视频窗口 ---------------- */
.vcell{position:relative;background:#05080f;border-radius:var(--r-m);overflow:hidden;border:1px solid var(--border);min-height:0}
.vcell img.feed{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:.92}
.vcell .vgrad{position:absolute;inset:auto 0 0 0;height:64px;background:linear-gradient(transparent,rgba(3,6,12,.8));z-index:2;pointer-events:none}
.vcell.sel{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent),0 0 20px rgba(61,142,240,.25)}
.vcell .rec{position:absolute;right:8px;bottom:8px;display:flex;align-items:center;gap:5px;font-size:10.5px;color:#ff8582;background:rgba(20,8,8,.7);padding:2px 7px;border-radius:5px;z-index:3}
.vcell .rec::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--danger);animation:blink 1.2s infinite}
@keyframes blink{50%{opacity:.2}}
.vgrid{display:grid;gap:10px;height:100%}

/* ---------------- 地图 ---------------- */
.map-stage{position:relative;overflow:hidden;background:var(--bg-grid)}
.map-stage svg{position:absolute;inset:0;width:100%;height:100%}
.map-ship{position:absolute;width:12px;height:12px;transform:translate(-50%,-50%);cursor:pointer;z-index:5}
.map-ship svg{width:100%;height:100%;color:#fff}
.map-ship::after{content:"";position:absolute;inset:-6px;border-radius:50%;border:1px solid rgba(61,142,240,.4);animation:pulse 2.4s infinite}
.map-ship .tip{position:absolute;left:50%;bottom:14px;transform:translateX(-50%);background:rgba(10,16,28,.94);border:1px solid var(--border);border-radius:8px;padding:7px 10px;font-size:11.5px;white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .15s;z-index:10;box-shadow:var(--sh-2)}
.map-ship:hover .tip,.map-ship.sel .tip{opacity:1}
.map-ship .tip b{display:block;color:var(--fg);font-size:12px}
.map-ship .tip span{color:var(--fg-2)}
.map-ship.sel{z-index:8}
.map-ship.sel svg{color:var(--warn)}
.map-label{position:absolute;font-size:10.5px;color:var(--faint);letter-spacing:.06em;pointer-events:none}
.map-overlay{position:absolute;left:12px;top:12px;z-index:6;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.map-scale{position:absolute;right:16px;bottom:14px;z-index:6;font-size:10px;color:var(--faint)}
.map-scale .bar{height:3px;background:var(--faint);position:relative;width:70px;margin-top:4px}
.map-scale .bar::before,.map-scale .bar::after{content:"";position:absolute;top:-3px;height:9px;width:3px;background:var(--faint)}
.map-scale .bar::before{left:0}.map-scale .bar::after{right:0}
.compass{position:absolute;right:16px;top:12px;z-index:6;color:var(--faint);font-size:10px;text-align:center;line-height:1}
.compass svg{width:34px;height:34px;display:block;margin-bottom:2px}

/* ---------------- 告警 / 通知条 ---------------- */
.alertbar{display:flex;align-items:center;gap:10px;padding:9px 14px;border-radius:var(--r-m);font-size:12.5px;border:1px solid}
.alertbar.danger{background:var(--danger-dim);border-color:var(--danger-line);color:#ff9d9b}
.alertbar.warn{background:var(--warn-dim);border-color:rgba(240,176,60,.4);color:#ffc35c}
.alertbar .ic{width:15px;height:15px;flex:none}
.notif{display:flex;gap:10px;padding:10px;border-radius:9px;border:1px solid var(--border-soft);background:var(--surface);cursor:pointer}
.notif:hover{border-color:var(--border);background:var(--surface-hover)}
.notif .n-ic{width:30px;height:30px;border-radius:8px;display:grid;place-items:center;flex:none}
.notif .n-ic .ic{width:15px;height:15px}
.notif.danger .n-ic{background:var(--danger-dim);color:#ff8582}
.notif.warn .n-ic{background:var(--warn-dim);color:#ffc35c}
.notif.success .n-ic{background:var(--success-dim);color:#4cd98f}
.notif.accent .n-ic{background:var(--accent-dim);color:#8ec2ff}
.notif .n-t{font-size:12.5px;color:var(--fg);font-weight:500}
.notif .n-d{font-size:11.5px;color:var(--muted);margin-top:1px}
.notif .n-time{font-size:10.5px;color:var(--faint);font-family:var(--font-mono)}

/* ---------------- 工具提示 / 徽标 ---------------- */
.badge-dot{position:absolute;top:6px;right:6px;min-width:15px;height:15px;border-radius:999px;background:var(--danger);color:#fff;font-size:9.5px;font-weight:700;display:grid;place-items:center;padding:0 4px;border:1.5px solid var(--bg)}
.logo-wave{position:relative;height:3px;border-radius:2px;background:var(--accent-dim);overflow:hidden;margin-top:2px}
.logo-wave::after{content:"";position:absolute;inset:0;background:linear-gradient(90deg,transparent,var(--accent),transparent);animation:wave 2.6s ease-in-out infinite;width:40%}
@keyframes wave{0%{transform:translateX(-100%)}100%{transform:translateX(280%)}}
.alert-line{position:relative;padding-left:16px}
.alert-line::before{content:"";position:absolute;left:0;top:3px;bottom:3px;width:3px;border-radius:2px;background:var(--danger)}
.alert-line.warn::before{background:var(--warn)}
.toast{position:fixed;left:50%;bottom:28px;transform:translateX(-50%) translateY(16px);background:var(--surface-2);border:1px solid var(--accent-line);color:var(--fg);font-size:13px;padding:10px 18px;border-radius:10px;box-shadow:var(--sh-3);opacity:0;pointer-events:none;transition:opacity .2s,transform .2s;z-index:90;max-width:78vw;text-align:center}
.toast.show{opacity:1;transform:translateX(-50%) translateY(0)}
.toast.warn{border-color:rgba(240,176,60,.5)}
.toast.success{border-color:rgba(52,199,123,.5)}

/* ============================================================
   2026-08 视觉精修层
   目标：不改业务结构，只提升中心端整体质感、层次和可读性
   ============================================================ */
body{
  background:
    radial-gradient(circle at 18% 12%,rgba(61,142,240,.13),transparent 30%),
    radial-gradient(circle at 78% 4%,rgba(70,195,255,.09),transparent 26%),
    linear-gradient(180deg,#08111f 0%,#070d18 42%,#050912 100%);
}
body::before{
  content:"";
  position:fixed;
  inset:0;
  pointer-events:none;
  z-index:-1;
  background:
    linear-gradient(rgba(255,255,255,.026) 1px,transparent 1px),
    linear-gradient(90deg,rgba(255,255,255,.02) 1px,transparent 1px);
  background-size:34px 34px;
  mask-image:linear-gradient(180deg,rgba(0,0,0,.72),transparent 74%);
}
.sidebar{
  background:
    linear-gradient(180deg,rgba(16,27,48,.98),rgba(8,15,28,.98)),
    var(--surface);
  box-shadow:8px 0 34px rgba(0,0,0,.22);
}
.brand{
  height:58px;
  padding:0 17px;
  border-bottom-color:rgba(116,158,210,.16);
  background:linear-gradient(180deg,rgba(255,255,255,.035),rgba(255,255,255,0));
}
.brand-logo{
  width:34px;
  height:34px;
  border-radius:12px;
  background:
    radial-gradient(circle at 30% 20%,rgba(255,255,255,.58),transparent 22%),
    linear-gradient(135deg,#64c8ff 0%,#2c83e8 48%,#1451ad 100%);
  box-shadow:0 10px 26px rgba(61,142,240,.28),inset 0 1px rgba(255,255,255,.28);
}
.brand-name{max-width:148px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:15.5px;font-weight:820}
.brand-sub{color:#6f8aaa}
.nav{padding:10px 10px 14px}
.nav-group-label{
  margin-top:4px;
  color:#6f86a6;
  font-weight:760;
}
.nav-item{
  height:38px;
  border-radius:11px;
  color:#b6c5dc;
  margin-bottom:3px;
}
.nav-item:hover{
  background:linear-gradient(90deg,rgba(61,142,240,.13),rgba(255,255,255,.035));
  color:#fff;
}
.nav-item.active{
  color:#fff;
  background:linear-gradient(90deg,rgba(61,142,240,.32),rgba(70,195,255,.11));
  border:1px solid rgba(119,181,255,.22);
  box-shadow:inset 0 1px rgba(255,255,255,.08),0 10px 24px rgba(5,12,24,.18);
}
.nav-item.active::before{
  left:-10px;
  top:8px;
  bottom:8px;
  width:4px;
  background:linear-gradient(180deg,#72d4ff,#3d8ef0);
  box-shadow:0 0 14px rgba(70,195,255,.55);
}
.nav-item .ic{color:#7890af}
.nav-item.active .ic{color:#7ed1ff}
.n-badge,.nav-item .n-badge,.tab .n-badge{
  border:1px solid rgba(255,133,130,.2);
  box-shadow:inset 0 1px rgba(255,255,255,.08);
}
.side-foot{
  background:linear-gradient(180deg,rgba(255,255,255,0),rgba(255,255,255,.035));
  border-top-color:rgba(116,158,210,.14);
}
.user-card{
  border:1px solid rgba(139,164,210,.12);
  background:rgba(255,255,255,.025);
}
.topbar{
  height:58px;
  padding:0 22px;
  background:rgba(8,16,30,.78);
  border-bottom-color:rgba(116,158,210,.16);
  box-shadow:0 10px 32px rgba(0,0,0,.2);
}
.crumb{
  color:#7c90ad;
  letter-spacing:.01em;
}
.crumb b{color:#f7fbff;font-weight:760}
.gstat{
  height:30px;
  padding:0 12px;
  background:rgba(13,24,43,.66);
  border-color:rgba(125,159,205,.18);
  box-shadow:inset 0 1px rgba(255,255,255,.055);
}
.gstat.ok{color:#bfead5}
.gstat.warn{color:#ffe0a5}
.gstat.bad{color:#ffc3c0}
.top-icon{
  background:rgba(13,24,43,.48);
  border-color:rgba(125,159,205,.13);
}
.page-wrap{padding-top:18px}
.page-head{
  margin:4px 0 16px;
  padding:0 2px;
}
.page-title{
  font-size:21px;
  font-weight:820;
  color:#f8fbff;
  letter-spacing:-.02em;
}
.page-sub{color:#8395b1}
.panel,.kpi,.modal,.drawer,.list-item.active{
  background:
    linear-gradient(180deg,rgba(255,255,255,.035),rgba(255,255,255,.012)),
    rgba(12,22,39,.9);
  border-color:rgba(126,158,204,.16);
  box-shadow:0 12px 34px rgba(0,0,0,.18),inset 0 1px rgba(255,255,255,.055);
}
.panel-hd{
  min-height:46px;
  padding:12px 15px;
  border-bottom-color:rgba(126,158,204,.12);
  background:linear-gradient(180deg,rgba(255,255,255,.032),rgba(255,255,255,0));
}
.panel-title{
  color:#f4f8ff;
  font-weight:760;
}
.panel-title .ic{
  color:#71caff;
  filter:drop-shadow(0 0 8px rgba(70,195,255,.2));
}
.panel-sub{color:#7f91ac}
.btn{
  border-radius:10px;
  font-weight:650;
}
.btn-primary{
  background:linear-gradient(135deg,#4ba9ff,#2f7be0);
  box-shadow:0 10px 22px rgba(61,142,240,.24),inset 0 1px rgba(255,255,255,.22);
}
.btn-primary:hover{
  background:linear-gradient(135deg,#68bdff,#3588ee);
  box-shadow:0 12px 26px rgba(61,142,240,.32),inset 0 1px rgba(255,255,255,.26);
}
.btn-default,.input,.select,.chip,.page-btn{
  background:rgba(14,26,46,.78);
  border-color:rgba(126,158,204,.18);
}
.btn-default:hover,.chip:hover,.page-btn:hover{
  border-color:rgba(106,179,255,.42);
  background:rgba(31,52,84,.72);
}
.input:focus,.select:focus{
  border-color:#5ca3ff;
  box-shadow:0 0 0 3px rgba(61,142,240,.16),0 0 22px rgba(61,142,240,.08);
}
.tag{
  border:1px solid rgba(255,255,255,.055);
  box-shadow:inset 0 1px rgba(255,255,255,.05);
}
.table{
  border-spacing:0;
}
.table thead th{
  background:rgba(18,32,54,.96);
  color:#8ea2bf;
  padding:10px 12px;
  border-bottom-color:rgba(126,158,204,.16);
}
.table tbody td{
  padding:10px 12px;
  border-bottom-color:rgba(126,158,204,.09);
}
.table tbody tr:hover td{
  background:rgba(61,142,240,.08);
}
.kpi{
  padding:15px 16px;
}
.kpi::before{
  width:4px;
  background:linear-gradient(180deg,var(--kpi-c,var(--accent)),rgba(70,195,255,.28));
  box-shadow:0 0 14px color-mix(in srgb,var(--kpi-c,var(--accent)) 55%,transparent);
}
.kpi .k-val{
  color:#fff;
  text-shadow:0 0 18px rgba(61,142,240,.12);
}
.drawer-mask,.modal-mask{
  backdrop-filter:blur(6px);
}
.modal{
  background:linear-gradient(180deg,rgba(19,35,60,.98),rgba(10,18,32,.98));
  border-color:rgba(137,174,225,.2);
}
.toast{
  background:rgba(16,29,50,.94);
  border-color:rgba(106,179,255,.42);
  box-shadow:0 18px 52px rgba(0,0,0,.35),inset 0 1px rgba(255,255,255,.08);
  backdrop-filter:blur(12px);
}

/* ---------------- Sidebar collapse ---------------- */
.app.sidebar-collapsed{
  --sidebar-w:78px;
}
.app{
  position:relative;
}
.app.sidebar-collapsed .sidebar{
  overflow:hidden;
}
.app.sidebar-collapsed .brand{
  position:relative;
  justify-content:center;
  padding:0 10px;
}
.app.sidebar-collapsed .brand-txt,
.app.sidebar-collapsed .side-foot,
.app.sidebar-collapsed .nav-group-label,
.app.sidebar-collapsed .user-meta,
.app.sidebar-collapsed .nav-item .n-badge{
  display:none;
}
.app.sidebar-collapsed .brand-logo{
  margin-left:2px;
}
.app.sidebar-collapsed .nav{
  padding:10px 8px 12px;
}
.app.sidebar-collapsed .nav-item{
  width:50px;
  height:50px;
  padding:0;
  margin:0 auto 6px;
  justify-content:center;
  font-size:0;
  color:transparent;
  border-radius:16px;
  background:
    linear-gradient(180deg,rgba(255,255,255,.05),rgba(255,255,255,.02)),
    rgba(14,23,38,.92);
  border:1px solid rgba(126,158,204,.16);
  box-shadow:inset 0 1px rgba(255,255,255,.05),0 8px 18px rgba(0,0,0,.12);
  transition:transform .16s,border-color .16s,background .16s,box-shadow .16s;
}
.app.sidebar-collapsed .nav-item:hover{
  transform:translateX(3px);
  background:
    linear-gradient(180deg,rgba(61,142,240,.18),rgba(70,195,255,.07)),
    rgba(17,30,50,.96);
  border-color:rgba(106,179,255,.46);
  box-shadow:0 12px 20px rgba(5,12,24,.2),inset 0 1px rgba(255,255,255,.06);
}
.app.sidebar-collapsed .nav-item::after{
  content:attr(data-tip);
  position:absolute;
  left:62px;
  top:50%;
  transform:translateY(-50%) translateX(-4px);
  opacity:0;
  pointer-events:none;
  white-space:nowrap;
  padding:7px 10px;
  min-width:72px;
  background:rgba(12,20,34,.96);
  color:#f4f8ff;
  border:1px solid rgba(106,179,255,.18);
  border-radius:10px;
  box-shadow:0 12px 28px rgba(0,0,0,.28);
  font-size:12px;
  font-weight:620;
  z-index:10;
  transition:opacity .14s,transform .14s;
}
.app.sidebar-collapsed .nav-item:hover::after,
.app.sidebar-collapsed .nav-item:focus::after,
.app.sidebar-collapsed .nav-item:focus-within::after{
  opacity:1;
  transform:translateY(-50%) translateX(0);
}
.app.sidebar-collapsed .nav-item.active::before{
  left:-4px;
  top:12px;
  bottom:12px;
  width:4px;
  border-radius:999px;
}
.app.sidebar-collapsed .nav-item .ic{
  width:20px;
  height:20px;
}
.app.sidebar-collapsed .sidebar-toggle{
  position:fixed;
  left:calc(var(--sidebar-w) - 15px);
  top:16px;
  transform:rotate(180deg);
  width:30px;
  height:30px;
  border-radius:999px;
  box-shadow:0 10px 22px rgba(0,0,0,.25),inset 0 1px rgba(255,255,255,.1);
}
.sidebar,.main,.topbar{
  transition:width .18s ease,left .18s ease,margin-left .18s ease;
}
.sidebar-toggle{
  position:fixed;
  left:calc(var(--sidebar-w) - 15px);
  top:16px;
  width:28px;
  height:28px;
  display:grid;
  place-items:center;
  border-radius:9px;
  border:1px solid var(--border);
  background:var(--surface-2);
  color:var(--fg-2);
  cursor:pointer;
  transition:background .14s,border-color .14s,color .14s,transform .14s;
  flex:none;
  z-index:40;
  box-shadow:0 8px 20px rgba(0,0,0,.2),inset 0 1px rgba(255,255,255,.06);
}
.sidebar-toggle:hover{
  color:var(--fg);
  border-color:var(--accent-line);
  background:var(--surface-hover);
}
.sidebar-toggle .ic{
  width:15px;
  height:15px;
  stroke-width:1.8;
}

html.shorebase-embedded .sidebar-toggle{
  display:none!important;
}

/* 骨架屏（数据加载占位） */
.sk-line{display:block;height:12px;border-radius:6px;background:linear-gradient(90deg,rgba(255,255,255,.05) 25%,rgba(255,255,255,.13) 50%,rgba(255,255,255,.05) 75%);background-size:200% 100%;animation:skShimmer 1.5s infinite}
.sk-block{border-radius:8px;background:linear-gradient(90deg,rgba(255,255,255,.05) 25%,rgba(255,255,255,.13) 50%,rgba(255,255,255,.05) 75%);background-size:200% 100%;animation:skShimmer 1.5s infinite}
.sk-row td{padding:14px 12px}
@keyframes skShimmer{to{background-position:-200% 0}}
