/* 世界官方新闻地图 —— 样式
   ------------------------------------------------------------
   主题：默认夜间；html[data-theme="light"] 切白天。
   两套主题共用同一组变量名，新增颜色一律走变量，别再写死十六进制，
   否则切主题时总会漏掉几处。
   首次访问没有 na_theme 时跟随系统 prefers-color-scheme。 */
:root{
  --bg:#080d14; --bg2:#0d1420; --panel:#111a26; --panel2:#16202e;
  --line:#1e2b3c; --tx:#e8eef6; --tx2:#9fb0c4; --tx3:#6b7f96;
  --acc:#3da9fc; --ok:#2fbf71; --warn:#f0a93b; --off:#7b8794;
  --r:10px;
  /* 以下是从各处写死的深色抽出来的 */
  --topbar1:#0e1724; --topbar2:#0a111b;
  --sb:#223145;              /* 滚动条滑块 */
  --row-hover:#182436;       /* 列表行 hover 底 */
  --acc-soft:rgba(61,169,252,.12);
  --acc-soft2:rgba(61,169,252,.16);
  --on-acc:#04121e;          /* 压在强调色上的文字 */
  --land:#cfe8ff;            /* 已选中按钮的文字 */
  --hl:#ffffff;              /* 地图上的高亮描边 */
  --mm-tx:#e8eef6; --mm-tx2:#9fb0bf;   /* SVG 内的文字填充 */
  --mm-ring:rgba(120,170,230,.10);
  --mm-on:#0b1523;           /* 思维导图关系标签的底色 */
  --tip-bg:rgba(12,19,29,.97);
  --legend-bg:rgba(13,20,32,.9);
  --gate-bg:rgba(8,11,18,.92);
  --shadow:0 12px 32px rgba(0,0,0,.55);
  --warn-tx:#f3c98a;
  --err:#ff8a8a;
  --map-bg:radial-gradient(ellipse at 50% 45%, #0a1220 0%, #05080e 70%);
}
html[data-theme="light"]{
  /* 白天模式要「一眼看出是白天」，不能只是把深色调浅一点：
     底色真正接近白、卡片纯白带真实投影、正文接近黑、描边明显加深。 */
  --bg:#f2f5f9; --bg2:#ffffff; --panel:#ffffff; --panel2:#ffffff;
  --line:#ccd8e6; --tx:#0f1a26; --tx2:#42566c; --tx3:#6d8098;
  --acc:#0b62c4; --ok:#0d7a41; --warn:#a8690a; --off:#5d6e82;
  --topbar1:#ffffff; --topbar2:#f7fafd;
  --sb:#b9c8da;
  --row-hover:#e4edf9;
  --acc-soft:rgba(11,98,196,.10);
  --acc-soft2:rgba(11,98,196,.16);
  --on-acc:#ffffff;
  --land:#083f85;
  --hl:#083f85;
  --mm-tx:#0f1a26; --mm-tx2:#4d5f76;
  --mm-ring:rgba(30,80,140,.20);
  --mm-on:#ffffff;
  --tip-bg:rgba(255,255,255,.99);
  --legend-bg:rgba(255,255,255,.96);
  --gate-bg:rgba(242,245,249,.96);
  /* 浅色下纯黑阴影太脏，换成带蓝色的中性投影 */
  --shadow:0 10px 28px rgba(28,54,86,.16);
  --card-shadow:0 1px 3px rgba(20,45,80,.10);
  --warn-tx:#7a4d05;
  --err:#b91c1c;
  --map-bg:radial-gradient(ellipse at 50% 45%, #ffffff 0%, #dbe8f8 70%);
}
/* 白天模式给卡片一点真实投影，否则白底白卡完全糊在一起 */
html[data-theme="light"] .panel,
html[data-theme="light"] .mm-item,
html[data-theme="light"] .mm-colcard,
html[data-theme="light"] .mm-detailbox,
html[data-theme="light"] .citem,
html[data-theme="light"] .rcard,
html[data-theme="light"] .news-item,
html[data-theme="light"] .legend-item,
html[data-theme="light"] .gate-card{
  box-shadow:var(--card-shadow);
}
html[data-theme="light"] .topbar{box-shadow:0 1px 0 rgba(20,45,80,.10)}
*{box-sizing:border-box}
html,body{height:100%}
body{
  margin:0; background:var(--bg); color:var(--tx);
  font:14px/1.6 "Microsoft YaHei","PingFang SC","Segoe UI",system-ui,-apple-system,sans-serif;
  display:flex; flex-direction:column; overflow:hidden;
}

/* ---------- 顶栏 ---------- */
.topbar{
  display:flex; align-items:center; justify-content:space-between; gap:20px;
  padding:10px 20px; background:linear-gradient(180deg,var(--topbar1),var(--topbar2));
  /* 刘海屏：顶栏会被挖孔/灵动岛压住，这里补上安全区内边距。
     env() 在不支持的浏览器上返回 0，桌面行为不变。 */
  padding-left:calc(20px + env(safe-area-inset-left));
  padding-right:calc(20px + env(safe-area-inset-right));
  padding-top:calc(10px + env(safe-area-inset-top));
  border-bottom:1px solid var(--line); flex:0 0 auto; z-index:20;
}
.brand{display:flex; align-items:center; gap:12px; min-width:0}
.logo{font-size:26px; color:var(--acc); line-height:1}
.topbar h1{margin:0; font-size:19px; letter-spacing:.5px}
.topbar .sub{margin:1px 0 0; font-size:12px; color:var(--tx3)}
/* min-width:0 是关键：flex 子项默认 min-width:auto，内容不换行时
   会把整个工具栏撑到超过顶栏宽度，实测在 768px 溢出 43px。
   给 .tools 和 .search 都加 0，允许它们被压缩。 */
.tools{display:flex; align-items:center; gap:12px; min-width:0; flex:0 1 auto}
.search{position:relative; min-width:0; flex:1 1 auto}
.search input{
  width:100%; max-width:260px; min-width:0;
  padding:7px 12px; border-radius:20px; border:1px solid var(--line);
  background:var(--bg2); color:var(--tx); font-size:13px; outline:none;
}
.search input:focus{border-color:var(--acc)}
.results{
  position:absolute; top:38px; right:0; width:300px; max-height:320px; overflow:auto;
  background:var(--panel); border:1px solid var(--line); border-radius:var(--r);
  box-shadow:var(--shadow); z-index:40; padding:4px;
}
.ritem{
  display:block; width:100%; text-align:left; padding:7px 10px; border:0; border-radius:7px;
  background:transparent; color:var(--tx); font-size:13px; cursor:pointer;
}
.ritem:hover{background:var(--panel2)}
.ritem.sel{background:var(--acc-soft2); color:var(--land)}
.ritem.empty-hit{color:var(--tx3); cursor:default; justify-content:center}
.ritem.empty-hit:hover{background:transparent}
.ritem.is-region{color:var(--acc)}
.btn{
  padding:7px 15px; border-radius:20px; border:1px solid var(--acc); background:transparent;
  color:var(--acc); font-size:13px; cursor:pointer; white-space:nowrap;
}
.btn:hover:not(:disabled){background:var(--acc-soft)}
.btn:disabled{opacity:.5; cursor:wait}
.status{font-size:12px; color:var(--tx3); white-space:nowrap; min-width:150px; text-align:right}
.status.warn{color:var(--warn)}

/* ---------- 地图折叠条 ----------
   地图默认收起，收起时只留这一条。放在顶栏外面而不是塞进顶栏：
   顶栏在 390px 上已经挤了 6 个控件，再加折叠+主题两个按钮会把搜索框压没。 */
.mapbar{
  display:flex; align-items:center; gap:10px; flex:0 0 auto;
  padding:0 16px; background:var(--bg2); border-bottom:1px solid var(--line);
  padding-left:calc(16px + env(safe-area-inset-left));
  padding-right:calc(16px + env(safe-area-inset-right));
}
.mapbar-btn{
  display:flex; align-items:center; gap:7px; min-height:40px; padding:0 12px;
  background:transparent; border:1px solid var(--line); border-radius:20px;
  color:var(--tx2); font-size:13px; cursor:pointer;
}
.mapbar-btn:hover{border-color:var(--acc); color:var(--acc)}
.mapbar-caret{display:inline-block; font-size:11px; transition:transform .16s}
body.map-open .mapbar-caret{transform:rotate(90deg)}
.mapbar-sub{font-size:11.5px; color:var(--tx3); overflow:hidden;
            text-overflow:ellipsis; white-space:nowrap}
.mapbar-theme{margin-left:auto; flex:0 0 auto}
/* 三个全屏视图（串联 / 多源对照 / 分数段）都要藏掉折叠条：
   它属于地图区，进了全屏视图里会占一整行，还点得开地图。 */
body.thread-mode .mapbar,
body.event-mode .mapbar,
body.band-mode .mapbar{display:none}

/* ---------- 布局 ----------
   grid-template-rows 必须写 minmax(0,1fr)：不写的话这一行是 auto 尺寸，
   而行高又取决于 .map 里 canvas 的高度、canvas 高度又写的是 height:100%
   —— 循环依赖，canvas 会用自身 backing store 当固有尺寸，越撑越大直到
   溢出视口（实测桌面球体 818×818 直接切掉一截）。写死 1fr 后高度确定。 */
/* 缩放倍率徽标：放大后必须给一条「怎么退回去」的出路，否则用户会卡在
   放大状态里不知道还能不能回全局。点一下复位到 1×。 */
.zoomind{
  position:absolute; right:14px; bottom:14px; z-index:6;
  min-width:52px; min-height:34px; padding:0 12px;
  background:var(--legend-bg); border:1px solid var(--line); border-radius:20px;
  color:var(--tx2); font-size:12.5px; cursor:pointer;
}
.zoomind[hidden]{display:none}
.zoomind:hover{border-color:var(--acc); color:var(--acc)}
@media (max-width:1024px){
  /* 移动端图例/提示都是流式的，绝对定位会压到球上，改成排在小地图下面 */
  .zoomind{position:static; margin:6px 12px 0; align-self:flex-end; min-height:40px}
}
@media (hover:none) and (pointer:coarse){
  .zoomind{min-height:44px; min-width:44px}
}

/* [hidden] 必须显式补 display:none，这条不能删。
   .layout 是 display:grid、.threadview 是 display:flex、.eventview 也是 display:flex，
   而作者样式的 display 优先级高于浏览器默认的 [hidden]{display:none} —— 于是
   closeThreads()/closeEvents() 里的 host.hidden = true 完全失效，视图关不掉，
   只会叠在要闻列表上面，表现为「点返回没反应、之前的要闻被顶到上面」。
   ⚠ 新增任何 display:flex/grid 的全屏视图，都必须把它的类名加进这一行。 */
.layout[hidden],.threadview[hidden],.eventview[hidden],.bandview[hidden]{display:none}

.layout{flex:1 1 auto; display:grid; grid-template-columns:1fr 430px;
        grid-template-rows:minmax(0,1fr); min-height:0}
.mapwrap{position:relative; padding:14px 16px 10px; min-width:0; display:flex; flex-direction:column}
.map{flex:1 1 auto; min-height:0; display:flex; align-items:center}
.map svg{width:100%; height:100%; max-height:100%}
.country{cursor:pointer; transition:fill .12s, opacity .12s}
.country:hover{stroke:var(--hl); stroke-width:1.1}
.country.dim{opacity:.22}
.country.sel{stroke:var(--hl); stroke-width:1.6}
.hit{cursor:pointer}

/* ---------- 地图收起 ----------
   收起后地图区高度归零、面板吃满整屏。桌面端同时把双栏并成单栏，
   否则左边会空一大块。收起时面板内容限宽居中，否则桌面上一行新闻
   会横跨 1400px 没法读。 */
body.map-collapsed .mapwrap{display:none}
body.map-collapsed .layout{grid-template-columns:minmax(0,1fr)}
body.map-collapsed .panel > *{max-width:880px; margin-left:auto; margin-right:auto}

/* ---------- 平面 / 球形 切换 ---------- */
.modeswitch{display:flex; gap:0; align-items:center}
.btn.sm{padding:5px 12px; font-size:12px; border-radius:0}
.modeswitch .btn.sm:first-child{border-radius:20px 0 0 20px}
.modeswitch .btn.sm:last-child{border-radius:0 20px 20px 0; border-left:0}
.btn.sm.on{background:var(--acc-soft2); color:var(--land)}

/* ---------- 球形地球 ---------- */
.globecv{
  width:100%; height:100%; display:block;
  cursor:grab; touch-action:none;              /* 关掉浏览器默认手势，拖动才跟手 */
  background:var(--map-bg);
}
.globecv:active{cursor:grabbing}
/* 球体模式下隐藏平面 svg 的提示文案，改为旋转提示 */
body.globe-mode .maphint::after{content:' · 拖动可旋转地球'}

/* ============================================================
   新闻串联 / 思维导图
   ============================================================ */
.threadview{
  flex:1 1 auto; min-height:0; display:flex; flex-direction:column;
  padding:12px 16px 16px; overflow:hidden;
}
body.thread-mode .layout{display:none}

.threadbar{display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-bottom:8px}
.threadbar .btn.back{flex:0 0 auto; color:var(--tx2); border-color:var(--line)}
.threadbar .btn.back:hover{border-color:var(--acc); color:var(--acc)}
.threadbar .tb-left{display:flex; align-items:baseline; gap:10px; flex:1 1 auto; min-width:0}
/* 标题不许被 .tb-sub 挤到折行——之前「多源对照」在 390px 下被压成「多源对/照」两行 */
.threadbar b{font-size:17px; white-space:nowrap; flex:0 0 auto}
.tb-sub{font-size:12px; color:var(--tx3); white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.tb-modes{display:flex; gap:0}
.tb-modes .btn.sm:first-child{border-radius:20px 0 0 20px}
.tb-modes .btn.sm:last-child{border-radius:0 20px 20px 0; border-left:0}

.threadnote{font-size:11.5px; color:var(--tx3); margin-bottom:8px; display:flex;
            align-items:center; gap:8px; flex-wrap:wrap}
.threadnote em{font-style:normal; padding:2px 7px; border-radius:10px; font-size:11px}
.bg-local{background:rgba(61,169,252,.16); color:#7fc4ff}
.bg-api{background:rgba(200,146,234,.16); color:#d6a8f5}
.bg-algo{background:rgba(127,140,155,.18); color:#9fb0bf}
.tn-note{margin-left:auto; opacity:.8}
.th-gen{font-size:11px; color:var(--tx3); padding:1px 7px;
        background:rgba(127,140,155,.12); border-radius:6px}
/* 「已是最新」：告诉用户那个「重算」按钮是条件显示，不是坏了 */
.th-fresh{font-size:11px; color:var(--ok); padding:1px 7px; border-radius:6px;
          background:rgba(47,191,113,.10)}
.th-undated{font-size:11px; color:#c9a227; padding:1px 7px;
            background:rgba(201,162,39,.10); border-radius:6px;
            border:1px dashed rgba(201,162,39,.35)}
.btn.xs{padding:3px 9px; font-size:11px; border-radius:12px; min-height:0}
.btn.warn{border-color:#e0a13a; color:#e0a13a; background:rgba(224,161,58,.10)}
.btn.warn:hover:not(:disabled){background:rgba(224,161,58,.20)}
.th-spinner{
  display:inline-block; width:11px; height:11px; vertical-align:-1px;
  border:2px solid rgba(61,169,252,.28); border-top-color:#3dd9a4;
  border-radius:50%; animation:thspin .8s linear infinite; margin-right:4px;
}
@keyframes thspin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion: reduce){
  .th-spinner{animation-duration:2.4s}
}

.threadarea{flex:1 1 auto; min-height:0; overflow-y:auto; padding-bottom:24px}

/* 「回到串联栏」悬浮按钮：滚到图区/簇详情深处后，顶部那排形态切换按钮
   就够不着了，点这个一下回到顶部。默认隐藏，滚动 >150px 才出现。
   必须用 fixed 不能用 sticky —— sticky + bottom 只会把元素「在它自己即将
   滚出视口底部时」顶住，而这个按钮排在长列表末尾，结果整段正中间都看不到它。 */
.tb-top{
  position:fixed; right:16px; z-index:60; display:block;
  bottom:calc(16px + env(safe-area-inset-bottom));
  padding:0 14px; min-height:40px; margin:0;
  background:var(--legend-bg); border:1px solid var(--line); border-radius:20px;
  color:var(--tx2); font-size:12.5px; cursor:pointer;
  opacity:0; visibility:hidden; transition:opacity .18s;
  box-shadow:0 6px 18px rgba(0,0,0,.35);
}
.tb-top.on{opacity:1; visibility:visible}
.tb-top:hover{border-color:var(--acc); color:var(--acc)}
@media (hover:none) and (pointer:coarse){
  .tb-top{min-height:44px; min-width:44px; right:12px}
}

/* --- 导图通用元素 --- */
.mm-svg{display:block; max-width:100%}
.mm-ring{fill:none; stroke:var(--mm-ring); stroke-width:1; stroke-dasharray:2 6}
.mm-edge{transition:opacity .15s}
.mm-node{cursor:pointer}
.mm-node circle{transition:fill-opacity .15s}
.mm-node:hover circle{fill-opacity:.4}
.mm-big{font-size:15px; fill:var(--mm-tx); font-weight:600}
.mm-num{font-size:11px; fill:var(--mm-tx); font-weight:600}
.mm-sub{font-size:10px; fill:var(--mm-tx2)}
.mm-rel{font-size:10px; font-weight:600}

.mm-list{margin-top:14px; display:grid; gap:10px; grid-template-columns:repeat(auto-fill,minmax(320px,1fr))}
.mm-item{background:var(--panel2); border:1px solid var(--line); border-radius:10px; padding:10px 12px}
.mm-item-h{display:flex; align-items:center; gap:7px; margin-bottom:7px}
.mm-item-h b{font-size:13px; font-weight:600; line-height:1.35}
.mm-base{font-size:11.5px; color:var(--tx3); line-height:1.4; padding:3px 0 1px;
         border-bottom:1px dashed var(--line); margin-bottom:5px}
.mm-meta{display:flex; gap:8px; font-size:10.5px; color:var(--tx3);
         margin:-3px 0 6px; flex-wrap:wrap}
.mm-meta span{padding:1px 6px; background:rgba(127,140,155,.12); border-radius:6px}
.mb{width:8px; height:8px; border-radius:50%; flex:0 0 auto}
.mm-node-row{
  display:flex; align-items:flex-start; gap:7px; font-size:12px; line-height:1.45;
  padding:4px 0 4px 8px; border-left:2px solid var(--line); margin-top:4px;
}
.rr{flex:0 0 auto; font-size:10px; padding:1px 6px; border-radius:8px; color:var(--mm-on); font-weight:700}
.rt{flex:1 1 auto; color:var(--tx)}
.rw{flex:0 0 42%; color:var(--tx3); font-size:11px}
.mm-stat{grid-column:1/-1; font-size:11.5px; color:var(--tx3); padding-top:4px;
         border-top:1px solid var(--line)}
.mm-stat-note{display:block; margin-top:3px; font-size:11px; color:var(--tx3); opacity:.9}

/* 簇里若已有中文译文而标题仍是外文，把译文单独标出来而不是混在一行里 */
.mm-item-zh{font-size:12.5px; color:var(--tx); margin:2px 0 4px}

/* 点节点后展开的簇详情 */
.mm-detailbox{
  margin-top:12px; background:var(--panel2); border:1px solid var(--line);
  border-radius:10px; padding:10px 12px;
}
.mm-detail.empty{color:var(--tx3); font-size:12.5px; text-align:center; padding:14px 12px}
.mm-openlink{flex:0 0 auto; font-size:11px; color:var(--acc); text-decoration:none;
             white-space:nowrap}
.mm-openlink:hover{text-decoration:underline}

/* --- 纵向时间线 --- */
.mm-col{position:relative; padding-left:22px}
.mm-spine{position:absolute; left:6px; top:6px; bottom:6px; width:2px;
          background:linear-gradient(180deg,#ff6b6b,#a3d977,#5ab0f0,#c792ea,#f08a7b)}
.mm-colrow{position:relative; margin-bottom:16px}
.mm-colrow::before{
  content:''; position:absolute; left:-20px; top:6px; width:9px; height:9px;
  border-radius:50%; background:var(--acc); box-shadow:0 0 0 3px var(--bg);
}
.mm-colhead{display:flex; align-items:center; gap:8px; margin-bottom:7px}
.mm-colhead b{font-size:13.5px}
.mm-colhead .dot{width:8px; height:8px; border-radius:50%}
.mm-coln{font-size:11px; color:var(--tx3)}
/* 可折叠的时间线档：整行做按钮，12 档全展开会到几千像素 */
.mm-fold{width:100%; text-align:left; padding:6px 8px; margin-left:-8px;
         background:transparent; border:0; border-radius:8px; color:inherit;
         font:inherit; cursor:pointer}
.mm-fold:hover{background:var(--panel2)}
.mm-foldcaret{display:inline-block; font-size:10px; color:var(--tx3);
              transition:transform .15s; width:10px}
.mm-colrow.open > .mm-fold .mm-foldcaret{transform:rotate(90deg)}
.mm-colrow > .mm-colbody{display:none}
.mm-colrow.open > .mm-colbody{display:grid}
.mm-colbody{display:grid; gap:8px; grid-template-columns:repeat(auto-fill,minmax(300px,1fr))}
.mm-colcard{background:var(--panel2); border:1px solid var(--line); border-radius:10px; padding:9px 11px}
.mm-colempty{font-size:12px; color:var(--tx3); padding:6px 0}

/* --- 图例 --- */
.mm-legend{
  display:flex; flex-wrap:wrap; gap:14px; margin:8px 0 12px; padding:9px 12px;
  background:var(--panel2); border:1px solid var(--line); border-radius:9px;
}
.lg-sec{display:flex; align-items:center; gap:9px; flex-wrap:wrap}
.lg-t{font-size:11px; color:var(--tx3); font-weight:600}
.lg-i{display:inline-flex; align-items:center; gap:4px; font-size:11px; color:var(--tx2)}
.lg-i i{width:9px; height:9px; border-radius:2px; display:inline-block}

/* --- 移动端 --- */
@media (max-width: 640px) {
  .threadview{padding:8px 10px 12px}
  .threadbar b{font-size:15px}
  .tb-sub{font-size:11px}
  .mm-list{grid-template-columns:1fr}
  .mm-colbody{grid-template-columns:1fr}
  .mm-node-row{flex-wrap:wrap}
  .rw{flex:1 0 100%; padding-left:2px}
  /* 导图在窄屏保持可读宽度，容器横向滚动。
     但下面必须让**图和新闻卡片同宽**，否则用户看到的是「上面 560px、
     下面 358px」两套宽度，完全对不上（实测截图就是这个问题）。
     mm-list / mm-colbody / mm-detailbox 都是块级流，给它们同一个
     min-width，横向滚动时图和文字一起走，两边严格对齐。 */
  .mm-svg{min-width:560px}
  .mm-list,.mm-colbody,.mm-detailbox,.mm-legend,.mm-colwrap{min-width:560px}
  .threadarea{overflow-x:auto}
  .tn-note{margin-left:0; flex:1 0 100%}
  .th-gen{order:9}
  /* 触摸端明确提示可横滑，否则用户不知道导图右边还有内容 */
  body.thread-mode .maphint-scroll{display:flex}
}

.maphint-scroll{
  display:none; align-items:center; gap:6px; justify-content:center;
  font-size:10.5px; color:var(--tx3); padding:5px 0 2px;
}
.maphint-scroll::before{content:'⇄'}
@media (max-width: 640px) and (orientation: landscape) {
  .maphint-scroll{display:flex}
}
@media (max-width: 640px) and (max-height: 720px) {
  .threadarea{overflow-y:auto}
}

.maphint{margin-top:6px; font-size:11.5px; color:var(--tx3); text-align:center}

/* tooltip */
.tip{
  position:absolute; pointer-events:none; background:var(--tip-bg);
  border:1px solid var(--line); border-radius:8px; padding:7px 11px; z-index:30;
  font-size:12.5px; max-width:200px; box-shadow:0 8px 22px rgba(0,0,0,.5);
}
.tip b{display:block; font-size:13.5px}
.tip span{display:block; color:var(--tx3); font-size:11px}
.tip em{display:block; color:var(--acc); font-size:11px; margin-top:3px; font-style:normal}

/* ---------- 图例 ---------- */
.legend{
  position:absolute; left:22px; top:22px; background:var(--legend-bg);
  border:1px solid var(--line); border-radius:var(--r); padding:9px; z-index:10;
  backdrop-filter:blur(3px);
  max-width:calc(100% - 44px);   /* 绝对定位时也要有上限，否则窄屏直接溢出 */
}
.legend-title{font-size:11px; color:var(--tx3); margin:0 0 6px 2px; letter-spacing:1px}
.legend-item{
  display:flex; align-items:center; gap:8px; width:100%; padding:4px 8px; margin-bottom:2px;
  border:0; border-radius:6px; background:transparent; color:var(--tx2);
  font-size:12.5px; cursor:pointer; text-align:left;
}
.legend-item:hover{background:var(--panel2); color:var(--tx)}
.legend-item.on{background:var(--panel2); color:var(--tx); font-weight:600}
.legend-item .sw{width:13px; height:13px; border-radius:3px; background:var(--c,#3a4a5e); flex:0 0 auto}
.legend-item.all{border-top:1px solid var(--line); margin-top:5px; padding-top:7px}
.legend-item.all .sw{background:linear-gradient(135deg,#3f7fbf,#2e8b57,#d94f4f)}

/* ---------- 右侧面板 ---------- */
.panel{
  background:var(--panel); border-left:1px solid var(--line);
  overflow-y:auto; padding:16px 18px 40px;
}
.panel::-webkit-scrollbar{width:9px}
.panel::-webkit-scrollbar-thumb{background:var(--sb); border-radius:5px}
.loading,.empty{padding:40px 0; text-align:center; color:var(--tx3); font-size:13px}

.crumb{
  display:inline-block; margin:0 6px 8px 0; padding:4px 11px; border-radius:16px;
  border:1px solid var(--line); background:var(--panel2); color:var(--tx2);
  font-size:12px; cursor:pointer;
}
.crumb:hover{border-color:var(--acc); color:var(--acc)}
.crumb.back{color:var(--tx3)}
.crumb.reg{border-color:var(--acc); color:var(--acc)}

.ph{margin:6px 0 14px}
.ph h2{margin:0; font-size:23px; letter-spacing:.5px}
.psub{margin:3px 0 0; color:var(--tx3); font-size:12.5px}

.stats{display:grid; grid-template-columns:repeat(4,1fr); gap:8px; margin:12px 0 6px}
.stat{background:var(--panel2); border:1px solid var(--line); border-radius:8px; padding:9px 6px; text-align:center}
.stat b{display:block; font-size:19px; color:var(--acc)}
.stat span{font-size:11px; color:var(--tx3)}

h3{margin:20px 0 9px; font-size:13.5px; color:var(--tx2); letter-spacing:.6px;
   border-left:3px solid var(--acc); padding-left:8px; font-weight:600}

.note{margin:8px 0 0; font-size:12px; color:var(--tx3); line-height:1.7}
.note2{margin:12px 0; font-size:12.5px; color:var(--tx2); background:var(--panel2);
       border:1px solid var(--line); border-radius:8px; padding:9px 11px; line-height:1.75}
.note2 b{color:var(--warn)}

.alert{
  margin:10px 0; padding:11px 13px; border-radius:8px; font-size:12.5px; line-height:1.8;
  background:rgba(240,169,59,.09); border:1px solid rgba(240,169,59,.35); color:var(--warn-tx);
}
.alert.soft{background:rgba(123,135,148,.1); border-color:var(--line); color:var(--tx2)}
.alert b{color:var(--warn)}

/* 官方机构 */
.chlist{list-style:none; margin:0; padding:0}
.chlist li{
  padding:8px 11px; margin-bottom:5px; background:var(--panel2);
  border:1px solid var(--line); border-left:3px solid var(--acc); border-radius:7px;
  font-size:12.5px; line-height:1.65; color:var(--tx);
}
.meta{margin:12px 0; background:var(--panel2); border:1px solid var(--line); border-radius:8px; padding:4px 11px}
.mrow{display:flex; gap:10px; padding:7px 0; border-bottom:1px dashed var(--line); font-size:12.5px}
.mrow:last-child{border-bottom:0}
.mk{flex:0 0 82px; color:var(--tx3)}
.mv{flex:1; color:var(--tx2); line-height:1.7}

/* 数据源 */
.srcs{margin:12px 0}
.srch{font-size:12px; color:var(--tx3); margin-bottom:6px}
.src{display:flex; align-items:center; gap:8px; padding:5px 9px; margin-bottom:4px;
     background:var(--panel2); border:1px solid var(--line); border-radius:6px; font-size:12px}
.src.bad{opacity:.72}
.src .dot{width:7px; height:7px; border-radius:50%; background:var(--off); flex:0 0 auto}
.src .dot.on{background:var(--ok)}
.src .dot.warn{background:var(--warn)}
.src.viol{border-color:rgba(240,169,59,.4)}
.src b{font-weight:600}
.src span{color:var(--tx3); flex:1}
.src em{font-style:normal; color:var(--tx3); font-size:11px; max-width:150px;
        overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.src.bad em{color:var(--warn)}
.src .rss{color:var(--acc); text-decoration:none; font-size:11.5px}

/* 新闻 */
.news{display:flex; flex-direction:column; gap:7px}
.news-item{
  display:block; text-decoration:none; color:var(--tx); padding:10px 12px;
  background:var(--panel2); border:1px solid var(--line); border-radius:8px;
  transition:border-color .12s, transform .12s;
}
.news-item:hover{border-color:var(--acc); transform:translateX(2px)}
.news-meta{display:flex; align-items:center; gap:7px; flex-wrap:wrap; margin-bottom:5px}
.tag{background:var(--acc); color:var(--on-acc); font-size:10.5px; font-weight:700;
     padding:1px 7px; border-radius:9px}
.kind{font-size:10.5px; color:var(--tx3); border:1px solid var(--line); padding:1px 6px; border-radius:9px}
.cty{font-size:10.5px; color:var(--tx2)}
.time{font-size:10.5px; color:var(--tx3); margin-left:auto}

/* ---- 重要性评分 / 覆盖范围 / 分布图 / 排序 ----
   配色约定：≥50 分用强调色（值得点开看），<20 分压暗（琐事），
   公式分（尚未 AI 评分）加一条虚线边框，和真实 AI 分区分开。 */
.imp{font-size:10.5px; font-weight:700; padding:1px 7px; border-radius:9px;
     background:var(--panel2); color:var(--tx2); border:1px solid var(--line)}
.imp.hi{background:var(--acc); color:var(--on-acc); border-color:transparent}
.imp.lo{color:var(--tx3); opacity:.72}
.imp.approx{border-style:dashed; opacity:.8}
.cov{font-size:10.5px; color:var(--tx2); border:1px solid var(--line);
     padding:1px 6px; border-radius:9px}

.topblock{display:block}
.sortbar{display:flex; gap:6px; margin:0 0 10px; flex-wrap:wrap}
.sbtn{font-size:11.5px; padding:4px 11px; border-radius:14px; cursor:pointer;
      background:transparent; color:var(--tx2); border:1px solid var(--line)}
.sbtn:hover{color:var(--tx1); border-color:var(--acc)}
.sbtn.on{background:var(--acc); color:var(--on-acc); border-color:transparent; font-weight:700}

.hist{margin:0 0 12px; padding:10px 10px 6px; border:1px solid var(--line);
      border-radius:10px; background:var(--panel2)}
.histbars{display:flex; align-items:flex-end; gap:3px; height:56px}
/* .hcol 现在是 <button>（可点），要抹掉按钮默认样式：
   否则浏览器会给它加背景、边框、内边距，柱状图就变形了。 */
.hcol{flex:1 1 0; display:flex; flex-direction:column; justify-content:flex-end;
      align-items:center; height:100%; min-width:0;
      background:none; border:0; padding:0; margin:0; cursor:pointer;
      font:inherit; color:inherit; border-radius:4px}
.hcol:hover .hbar{opacity:1; filter:brightness(1.12)}
.hcol:focus-visible{outline:2px solid var(--acc); outline-offset:1px}
.hcol.off{cursor:default; opacity:.55}
.hbar{display:block; width:100%; min-height:2px; background:var(--acc);
      border-radius:3px 3px 0 0; opacity:.85}
.hbar.low{background:var(--tx3); opacity:.45}
.hnum{font-size:9.5px; color:var(--tx2); line-height:1.25}
.hlo{font-size:9px; color:var(--tx3); font-style:normal; line-height:1.2}
.hnote{font-size:10.5px; color:var(--tx3); margin-top:6px; line-height:1.5}
/* 手指友好：手机上柱子太小点不准 */
@media (hover: none) and (pointer: coarse){
  .histbars{gap:2px; height:64px}
}

/* ---- 同一事件 · 多源对照（独立视图）---- */
.eventview{flex:1 1 auto; min-height:0; display:flex; flex-direction:column;
           padding:12px 16px 16px; overflow-y:auto; overflow-x:hidden}
body.event-mode .layout{display:none}
.evwrap{display:block}
.evcard.wide{margin-bottom:11px}
.evsearch{font-size:12.5px; padding:5px 10px; border-radius:8px; width:170px;
          border:1px solid var(--line); background:var(--panel2); color:var(--tx1)}
.evsearch:focus{outline:none; border-color:var(--acc)}
.evnote{margin:0 0 10px}
.sortbar .sbtn.on, .threadbar .btn.on{background:var(--acc); color:var(--on-acc);
                                    border-color:transparent; font-weight:700}
/* 三个排序按钮成组：窄屏换行时整组一起换，不会剩下一个孤零零掉到下一行 */
.evsorts{display:flex; gap:6px; flex:0 0 auto}

/* ---- PWA：安装按钮、提示条、离线/更新提示 ---- */
.pwatoast{
  position:fixed; left:50%; bottom:calc(20px + env(safe-area-inset-bottom));
  transform:translateX(-50%) translateY(14px);
  z-index:200; max-width:min(92vw, 420px);
  padding:10px 16px; border-radius:22px;
  background:var(--panel); border:1px solid var(--acc);
  color:var(--tx); font-size:13px; line-height:1.5;
  box-shadow:var(--shadow); text-align:center;
  opacity:0; pointer-events:none; transition:opacity .22s, transform .22s;
}
.pwatoast.on{opacity:1; transform:translateX(-50%) translateY(0)}

.installhelp{
  position:fixed; left:50%; top:50%; transform:translate(-50%,-50%);
  z-index:210; width:min(90vw, 360px);
  padding:18px 18px 14px; border-radius:14px;
  background:var(--panel); border:1px solid var(--line);
  box-shadow:var(--shadow); color:var(--tx);
}
.installhelp b{color:var(--acc)}
.installhelp p{margin:8px 0 0; font-size:13.5px; line-height:1.65; color:var(--tx2)}
.installhelp p.dim{font-size:12px; color:var(--tx3)}
.installhelp .btn{margin-top:12px; width:100%}

/* 装到桌面后以独立应用运行时，不需要「装到桌面」按钮了 */
@media (display-mode: standalone) {
  #install{display:none !important}
}

/* ---- 重要性分数段（点柱状图进来）---- */
.bandview{flex:1 1 auto; min-height:0; display:flex; flex-direction:column;
           padding:12px 16px 16px; overflow-y:auto; overflow-x:hidden}
body.band-mode .layout{display:none}
.bandlist{display:block}
.bandmore{display:flex; justify-content:center; padding:10px 0 4px}
@media (max-width: 640px){
  .bandview{padding:8px 10px 12px}
}
@media (max-width: 640px) {
  /* 窄屏：搜索框和排序各占一整行，三个排序等宽铺满，好点也好读 */
  .threadbar .evsearch{order:10; width:100%}
  .evsorts{order:11; width:100%}
  .evsorts .btn.sm{flex:1 1 0; min-width:0}
  .evsrcl{min-width:104px}
}

.evcard{border:1px solid var(--line); border-radius:10px; background:var(--panel2);
       padding:10px 12px; margin-bottom:9px}
.evhead{display:flex; align-items:baseline; gap:8px; flex-wrap:wrap}
.evtitle{font-size:14px; font-weight:600; color:var(--tx1); text-decoration:none;
         line-height:1.45; flex:1 1 auto}
.evtitle:hover{color:var(--acc)}
/* ⚠ min-height 必须显式压回 0：下面 @media (hover:none) 里的触控规则
   `.mini{min-height:34px; padding:6px 12px}` 会命中这个元素（它带 .mini 类），
   而 `.imp.mini` 只覆盖了 padding、没覆盖 min-height，结果分数徽章在手机上
   被撑成 34px 高的竖条。 */
.imp.mini{font-size:9.5px; padding:1px 5px; border-radius:7px;
          min-height:0; align-self:center; line-height:1.45}
.evtog{margin-top:8px; font-size:11.5px; padding:3px 10px}
.evlist{margin-top:8px; border-top:1px dashed var(--line); padding-top:8px}
.evrow{display:flex; align-items:flex-start; gap:8px; padding:4px 0;
       border-bottom:1px solid var(--line)}
.evrow:last-child{border-bottom:0}
.evsrcl{display:flex; align-items:center; gap:5px; flex:0 0 auto; min-width:118px}
.evsrc{font-size:12.5px; color:var(--tx1); text-decoration:none; line-height:1.5; flex:1 1 auto}
.evsrc:hover{color:var(--acc)}
/* 时间列不参与压缩：窄屏下「11 小时前」会被压成「11 小/时前」两行 */
.evrow .time{white-space:nowrap; flex:0 0 auto}
.today{font-size:10px; color:var(--on-acc); background:var(--ok); padding:1px 6px; border-radius:9px; font-weight:700}
/* 新闻标题（中文译文 / 原文） */
.news-title{font-size:13.5px; line-height:1.6; color:var(--tx)}
.news-title.zh{font-size:14.5px; line-height:1.65}
.news-orig{font-size:11px; color:var(--tx3); margin-top:3px; line-height:1.5;
          padding-left:8px; border-left:2px solid var(--line)}
.news-sum{font-size:11.5px; color:var(--tx3); margin-top:4px; line-height:1.6}

/* 翻译覆盖率条 */
.trbar{display:flex; align-items:center; gap:8px; flex-wrap:wrap;
       background:var(--panel2); border:1px solid var(--line); border-radius:8px;
       padding:8px 11px; margin:10px 0 4px; font-size:11.5px}
.trlab{color:var(--tx3)}
.trbar b{color:var(--acc); font-size:13px}
.trbar .trn{color:var(--tx3); font-size:11px}
.trbar .track{flex:1 1 90px; min-width:70px; height:5px; border-radius:3px;
              background:var(--sb); overflow:hidden}
.trbar .fill{height:100%; background:linear-gradient(90deg,#3f7fbf,#17a2b8); border-radius:3px}
.mini{padding:4px 10px; border-radius:12px; border:1px solid var(--line);
      background:transparent; color:var(--tx2); font-size:11.5px; cursor:pointer; white-space:nowrap}
.mini:hover:not(:disabled){border-color:var(--acc); color:var(--acc)}
.mini.on{border-color:var(--acc); color:var(--acc); background:rgba(61,169,252,.1)}
.mini:disabled{opacity:.55; cursor:wait}

/* ---------- 触摸设备：保证 32px+ 触控目标 ----------
   平板实测：切换按钮 28px、小按钮 25px、搜索框 31px，
   都低于手指友好阈值（Apple 44pt / Material 48dp 的下限）。
   用 hover:none 判定，只影响真触摸设备，不动桌面观感。 */
@media (hover: none) {
  .mini{min-height:34px; padding:6px 12px}
  .btn.sm{min-height:34px; padding:6px 13px}
  .btn.xs{min-height:32px; padding:5px 11px}
  .search input{min-height:36px}
  .ritem{min-height:38px; display:flex; align-items:center}
  .legend-item{min-height:36px}
  .citem{min-height:40px}
  .news-item{padding:11px 12px}
  /* ⚠ 三个排序按钮（按重要性/按覆盖范围/按最新）用的是 .sbtn，不是 .btn.sm，
     所以一直漏在触控放大规则外面——实测只有 25px 高，手指很难点准。
     44px 那条规则里也要补上。 */
  .sortbar .sbtn{min-height:34px; padding:6px 13px; font-size:12.5px}
  .hist .hcol{min-height:56px}
}

/* 国家列表 */
.clist{display:flex; flex-direction:column; gap:5px}
.citem{
  display:block; width:100%; text-align:left; padding:9px 11px; cursor:pointer;
  background:var(--panel2); border:1px solid var(--line); border-radius:8px; color:var(--tx);
}
.citem:hover{border-color:var(--acc); background:var(--row-hover)}
.citem b{font-size:13px}
.ctags{display:inline-flex; gap:5px; margin-left:8px; vertical-align:1px}
.pill{font-size:10px; font-style:normal; padding:1px 6px; border-radius:8px; white-space:nowrap}
.pill.ok{background:rgba(47,191,113,.16); color:var(--ok)}
.pill.warn{background:rgba(240,169,59,.16); color:var(--warn)}
.pill.dim{background:rgba(123,135,148,.16); color:var(--off)}
.pill.off{background:rgba(123,135,148,.1); color:var(--off); border:1px solid var(--line)}
.ctop{font-size:11.5px; color:var(--tx3); margin-top:4px; line-height:1.55;
      overflow:hidden; text-overflow:ellipsis; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical}

/* 区域卡片 */
.rgrid{display:grid; grid-template-columns:1fr 1fr; gap:8px}
.rcard{
  padding:12px; border:0; border-radius:9px; cursor:pointer; text-align:left;
  background:var(--panel2); border:1px solid var(--line); border-left:4px solid var(--c);
  color:var(--tx);
}
.rcard:hover{background:var(--row-hover)}
.rcard b{display:block; font-size:13.5px}
.rcard span{font-size:11.5px; color:var(--tx3)}

/* 空数据国家的出口区块：把同区域里确实有要闻的国家列出来。
   feeds.json 只给 52 国配了源，没有出口的话 143/195 个国家点进去是死胡同。 */
.altbox{margin-top:24px; padding-top:16px; border-top:1px solid var(--line)}
.altbox h3{margin:0 0 4px}
.altbox .psub{margin:0 0 10px}

/* 网络受限源面板 */
.blocked{margin-top:22px; padding-top:16px; border-top:1px solid var(--line)}
.blocked h3{margin:0 0 8px}
.btn.ghost{width:100%; margin-bottom:8px; border-color:var(--line); color:var(--tx2)}
.btn.ghost:hover:not(:disabled){border-color:var(--acc); color:var(--acc); background:var(--acc-soft)}
.blist{max-height:420px; overflow-y:auto}
.blist::-webkit-scrollbar{width:7px}
.blist::-webkit-scrollbar-thumb{background:var(--sb); border-radius:4px}
.blsum{font-size:12px; color:var(--tx3); margin-bottom:9px}
.bcat{margin:10px 0 5px; font-size:12.5px}
.bcat b{color:var(--tx)}
.bcat span{display:block; color:var(--tx3); font-size:11.5px; margin-top:2px}
.bitem{display:flex; align-items:center; gap:7px; padding:5px 9px; margin-bottom:3px;
      background:var(--panel2); border:1px solid var(--line); border-radius:6px; font-size:11.5px}
.bitem .bdot{width:6px; height:6px; border-radius:50%; background:var(--warn); flex:0 0 auto}
.bitem b{font-weight:600; min-width:64px}
.bitem span{flex:1; color:var(--tx2); overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.bitem em{font-style:normal; color:var(--tx3); font-size:10.5px; max-width:190px;
         overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.bitem a{color:var(--acc); text-decoration:none; font-size:10.5px}

/* ================================================================
   响应式：桌面 → 平板 → 手机
   ���机端把右侧面板改为底部抽屉，地图固定在上半屏
   ================================================================ */

/* ---- 平板：1024px 以下，地图与面板改为上下 ---- */
@media (max-width: 1024px) {
  .layout{grid-template-columns:1fr; grid-template-rows:auto minmax(0,1fr)}

  /* ---- 整页滚动（≤1024，手机和平板统一）----
     原来只在 ≤640 开了整页滚动，视图的 overflow:visible 却放在 ≤1024，
     两边对不上：641~1024px（平板）就成了混合态——视图不再自己滚、
     而 body{overflow:hidden} 又把整页滚动关掉了，内容直接被裁掉。
     iPadOS 上尤其明显：window.scrollTo 还能滚（程序化滚动不受影响），
     但**手指滑动完全不响应**——body 上的 overflow:hidden 会让文档的
     触摸滚动手势失效。这正是「平板滑不动、手机正常」的原因。

     现在把整页滚动和视图的 overflow:visible 放在同一个断点里，
     两者永远配套，不会再出现只开一半的混合态。 */
  html{height:auto}
  body{height:auto; min-height:100dvh; overflow-y:auto; overflow-x:hidden}
  .layout{flex:1 0 auto}
  .panel{overflow:visible; padding-bottom:calc(24px + env(safe-area-inset-bottom))}

  /* 窄屏上串联页改为**整页**纵向滚动。
     原来头部（返回/形态切换/推理来源/过期告警/生成时间）在手机上能占掉
     半屏以上，而它固定占位、只有下面 .threadarea 能滚 —— 结果图区被压到
     剩下几十像素，用户既看不到图、也滑不动（实测 390×844：头部约 470px，
     图区只剩 ~60px）。改成整页滚、图区按内容取高，就都能看见了。 */
  .threadview{overflow:visible; -webkit-overflow-scrolling:touch}
  .threadarea{flex:0 0 auto; min-height:min(58vh,430px);
               overflow-x:auto; overflow-y:visible}
  /* 对照 / 分数段同样整页滚。⚠ 不要给它们写 height:calc(100dvh - chrome)：
     那样它们变成固定高度的内部滚动区，顶栏就永远推不出去，滑不走。 */
  .eventview,.bandview{overflow:visible; -webkit-overflow-scrolling:touch}
  /* 平面地图的显示尺寸**完全由宽度决定**（viewBox 1000×501 ≈ 2:1）。
     行高写死 vh 只会让 SVG 在信箱模式里上下留白 —— 地图一分没变大，
     高度全被空白吃掉。改成地图按自身比例自适应，剩下全给新闻面板。
     实测 390×844：地图区 380px 里只有 187px 是图，约 190px 是空白。 */
  .map{flex:0 1 auto; min-height:0}
  .map svg{height:auto; max-height:none}       /* 按 viewBox 比例，不再上下留白 */
  /* 球形地球是 canvas，球的大小由高度决定，得单独给高度。
     球是正圆，容器越接近正方形半径越大：原来只给 min(48vh,360px)，
     宽而扁的容器会白白浪费宽度、把球压小。高度往宽度靠，
     但仍受可用高度和上限约束，别把新闻面板挤没。 */
  body.globe-mode .map{flex:0 0 auto; height:min(50vh,500px)}
  .panel{border-left:0; border-top:1px solid var(--line); padding-bottom:48px}
  .mapwrap{padding:10px 12px 6px}
  /* 图例单行横向滚动，不占垂直空间，把高度让给地图 */
  .legend{
    position:static; margin-top:6px; display:flex; flex-wrap:nowrap;
    overflow-x:auto; -webkit-overflow-scrolling:touch; scrollbar-width:none;
    background:transparent; border:0; padding:0 0 2px; gap:6px;
  }
  .legend::-webkit-scrollbar{display:none}
  .legend-title{display:none}
  .legend-item{flex:0 0 auto; width:auto; margin:0; padding:7px 12px; min-height:38px;
               border:1px solid var(--line); border-radius:20px; background:var(--panel2)}
  .legend-item.all{border:1px solid var(--line); margin:0; padding:7px 12px}
  .maphint{display:none}
  /* 平板竖屏（768px）实测顶栏溢出 43px：工具栏不换行会被硬撑开。
     允许换行 + 搜索框可压缩，空间不足时自动折行而不是溢出。
     副标题在这档隐藏，把标题行让给工具栏，减少一行高度。 */
  .topbar{flex-wrap:wrap; row-gap:5px}
  .topbar .sub{display:none}
  .topbar h1{font-size:17px}
  .tools{flex-wrap:wrap; row-gap:5px; flex:1 1 auto; justify-content:flex-start}
  .search{flex:1 1 160px; max-width:260px}
  .status{margin-left:auto}
  h3{font-size:14px}
  .ph h2{font-size:21px}
  .rgrid{grid-template-columns:1fr 1fr}
  .trbar{gap:6px}
}

/* ---- 手机：640px 以下 ---- */
@media (max-width: 640px) {
  body{font-size:15px}

  /* 球形模式：窄屏下球会很小，缩小边距让球尽量大 */
  body.globe-mode .mapwrap{padding:6px 6px 2px}
  body.globe-mode .maphint{font-size:10.5px; margin-top:2px}

  /* 顶栏保持单行（nowrap 优先级高于平板的 wrap）。
     代价：4 个控件（搜索 + 平面/球形 + 串联 + 刷新）要挤进 ~340px。
     做法：手机上把「平面地图/球形地球」收成一个图标切换组，
     「新闻串联」缩成「串联」，标题只留图标——省下约 90px。 */
  .topbar{
    /* 安全区要加在**上**边距：刘海/灵动岛在顶部。
       （原来写成 padding:6px 8px calc(6px + env(...)) 是把顶部内 inset
        加到了第三段=padding-bottom，顶部只有 6px，刘海屏上标题会被挖孔压住。）*/
    padding-top:calc(6px + env(safe-area-inset-top));
    padding-bottom:6px;
    padding-left:calc(8px + env(safe-area-inset-left));
    padding-right:calc(8px + env(safe-area-inset-right));
    gap:5px; flex-wrap:nowrap; align-items:center;
  }
  .brand{flex:0 0 auto; gap:6px}
  .topbar h1{font-size:15px; white-space:nowrap}
  .topbar .sub{display:none}
  .logo{font-size:18px}
  .tools{flex:1 1 auto; min-width:0; gap:5px; flex-wrap:wrap}
  /* ⚠ 手机上搜索框必须**独占一行**。
     原来它和 5 个按钮挤在同一行，加了「对照」之后实测只剩 26–31px，
     而占位文字要 154px —— 等于这个控件废了。改成 100% 基准自己换行，
     下面一行放按钮，宽度足够（实测 291px < 374px）。 */
  .search{flex:1 1 100%; min-width:0; order:-1}
  .search input{width:100%; height:38px; font-size:13px; padding:5px 10px}
  /* 输入框加高到 38px 了，下拉结果要跟着往下挪，否则会压住输入框下沿 */
  .results{width:100%; right:0; left:0; max-height:46vh; top:44px}
  .btn{padding:6px 10px; min-height:34px; font-size:12.5px}
  .status{display:none}          /* 抓取状态/覆盖率在面板内已有，不重复占屏 */
  /* 工具块变成两行后，logo 要对齐第一行，否则会垂直居中在两行中间 */
  .topbar{align-items:flex-start}
  .brand{padding-top:9px}

  /* 整页滚动和三个视图的 overflow 都在 ≤1024 那段统一设了，这里不再重复。
     ⚠ 早先这里单独写过一份 body{overflow-y:auto}，而视图的 overflow:visible
     放在 ≤1024 —— 断点对不上，平板上就成了「视图不滚 + 整页也不滚」的
     被裁状态（iPadOS 上手指滑动直接失效）。别再拆开写。 */

  /* 标题只留 logo：窄屏下文案会占掉 60px，挤扁搜索框 */
  .brand h1{display:none}
  .modeswitch{flex:0 0 auto}
  /* 手机上「平面地图/球形地球」两个文字按钮要 210px，太奢侈。
     换成图标（▤ 平面 / ◐ 球体），省下约 130px 给搜索框。 */
  .modeswitch .btn.sm{padding:5px 9px; min-height:34px; font-size:0; letter-spacing:0}
  .modeswitch .btn.sm::before{font-size:15px; line-height:1}
  .modeswitch .btn.sm[data-mode="flat"]::before{content:'▤'}
  .modeswitch .btn.sm[data-mode="globe"]::before{content:'◐'}
  /* 「新闻串联」缩成「串联」，省 28px */
  #open-threads{padding:6px 9px; font-size:0}
  #open-threads::after{content:'串联'; font-size:12.5px}
  #refresh{padding:6px 9px; font-size:12px}

  /* ---- 真机宽度专项修正（一加 15T 等）----
     这台机器 1216×2640 像素、460PPI，Chrome 视口只有 **310–344 CSS px**
     （截图 890px ÷ DPR 2.75 ≈ 323）。在这个宽度下 6 个按钮放不下，
     最后那个「⚿ 修改访问口令」会**单独掉到第三行**——实测独占一行的
     精确区间是 310–344px，360px 以上才不会。

     上一轮只按 390px 优化，等于完全没覆盖到用户的真机。 */
  .tools{gap:4px}
  #refresh{font-size:0; padding:6px 10px}
  #refresh::after{content:'刷新'; font-size:12.5px}
  /* 超窄屏藏掉 logo：纯装饰（标题本来就只在 ≤640 显示 logo 图形）。
     留着它要多占 29px，正好是让 ⚿ 掉行的那几px。 */
  @media (max-width: 344px) {
    .brand{display:none}
  }

  /* 折叠条：手机上顶栏已满，条本身也要保证 44px 触控高度 */
  .mapbar{padding:0 10px;
          padding-left:calc(10px + env(safe-area-inset-left));
          padding-right:calc(10px + env(safe-area-inset-right))}
  .mapbar-btn{min-height:44px; padding:0 14px; font-size:13.5px}
  .mapbar-sub{font-size:11px}
  .mapbar-theme{min-width:44px; min-height:44px}
  /* 手机本来就是单栏，不需要桌面那条 880px 限宽 */
  body.map-collapsed .panel > *{max-width:none}

  /* 地图不再占固定的上半屏：平面地图按自身比例自适应，省下的高度全给新闻列表。
     地图本身的显示尺寸不变（宽度决定），所以可点面积一点没缩水。
     390×844 实测：面板 387px → 约 520px。 */
  /* ⚠ 这里原来写的是 height:calc(100dvh - 46px)，把顶栏高度写死了。
     现在顶栏在手机上改成两行（搜索独占一行），实际是 106px + 45px 地图条，
     比 46px 多了 100px —— 只是因为 .layout 是 flex:1 1 auto、flex-shrink
     会把它压回可用高度，才没出事。那是**碰巧**：一旦有人把 flex-shrink 改成 0，
     或者再往顶栏加一行，内容就会被 body{overflow:hidden} 直接裁掉。
     这里删掉写死的高度，交给 flex 自己算——body 是 column flex，
     .layout{flex:1 1 auto; min-height:0} 天然就是「填满剩余空间」。 */
  .layout{grid-template-rows:auto minmax(0,1fr)}
  .mapwrap{padding:8px 8px 4px; min-height:0}
  .map{flex:0 1 auto; min-height:0}
  /* 球形：高度尽量贴近宽度（正方形容器球最大），同时别超过可用高度。
     390×844 实测：容器 374×290 时半径 131px，改为 374×354 后半径 163px（+24%）。 */
  body.globe-mode .map{flex:0 0 auto; height:min(calc(100vw - 16px), 42vh, 400px)}

  /* 图例横向滚动条，单行 */
  .legend{
    flex-wrap:nowrap; overflow-x:auto; -webkit-overflow-scrolling:touch;
    padding-bottom:4px; gap:6px; scrollbar-width:none;
  }
  .legend::-webkit-scrollbar{display:none}
  .legend-title{display:none}
  .legend-item{flex:0 0 auto; padding:7px 12px; min-height:40px; font-size:12.5px;
               border:1px solid var(--line); border-radius:20px; background:var(--panel2)}
  .legend-item.all{border:1px solid var(--line)}

  /* 面板：加大字号与点按面积 */
  .panel{padding:12px 14px calc(24px + env(safe-area-inset-bottom))}
  .ph h2{font-size:20px}
  .psub{font-size:12px}
  h3{font-size:13.5px; margin:16px 0 8px}
  /* 统计卡保持 4 列紧凑排布：2×2 在手机上会把首屏要闻挤下去 */
  .stats{grid-template-columns:repeat(4,1fr); gap:5px}
  .stat{padding:7px 3px}
  .stat b{font-size:16px}
  .stat span{font-size:9.5px; line-height:1.3}

  .news-item{padding:12px 13px; border-radius:10px}   /* ≥44px 触控区 */
  .news-item:hover{transform:none}
  .news-title{font-size:15px}
  .news-title.zh{font-size:16px; line-height:1.6}
  .news-orig{font-size:11.5px}
  .news-sum{font-size:12px}
  .news-meta{gap:6px}

  .btn.ghost{min-height:44px; font-size:13.5px}
  .mini{min-height:36px; padding:7px 13px}
  .trbar{padding:10px 12px; gap:8px}
  .trbar .track{flex:1 1 100%; order:5}

  .citem{padding:12px 13px}
  .citem b{font-size:14.5px}
  .ctop{-webkit-line-clamp:2; font-size:12px}
  .pill{font-size:10.5px; padding:2px 8px}
  .rgrid{grid-template-columns:1fr}
  .rcard{padding:14px}
  .rcard b{font-size:15px}

  .src{font-size:12px; padding:8px 10px; min-height:40px; flex-wrap:wrap}
  .src .em{max-width:100%; flex:1 1 100%}
  .blist{max-height:60vh}
  .bitem{font-size:12px; padding:8px 10px; flex-wrap:wrap}
  .bitem b{min-width:56px}
  .bitem em{flex:1 1 100%; max-width:100%}
  .empty{padding:28px 0}
}

/* ---- 矮屏手机（如 360×640）：进一步压缩地图，保证面板有可读高度 ---- */
@media (max-width: 640px) and (max-height: 720px) {
  .layout{grid-template-rows:auto minmax(0,1fr)}
  .legend-item{padding:5px 10px; min-height:34px; font-size:11.5px}
  .legend .sw{width:11px; height:11px}
  .ph h2{font-size:18px}
  /* 球形模式在矮屏上给足高度，否则球会被压扁。
     图例保留（还要靠它切区域），但压成更薄的一条。 */
  body.globe-mode .map{flex:0 0 auto; height:min(calc(100vw - 12px), 44vh, 300px)}
  body.globe-mode .legend-item{padding:3px 8px; min-height:28px; font-size:11px}
  body.globe-mode .legend .sw{width:9px; height:9px}
  body.globe-mode .legend .sw{width:9px; height:9px}
  body.globe-mode .mapwrap{padding:4px 4px 0}
  /* 下面这组统计卡压缩原本也在这个矮屏 media 里，但前面多了一个 } 把
     media 提前关掉了，导致它们泄漏成全局规则（在桌面端也生效）。 */
  .stats{grid-template-columns:repeat(4,1fr)}
  .stat{padding:6px 3px}
  .stat b{font-size:15px}
  .stat span{font-size:9.5px}
}

/* ---- 超窄屏（≤360px）---- */
@media (max-width: 360px) {
  .stats{grid-template-columns:1fr 1fr}
  .rgrid{grid-template-columns:1fr}
  .legend-item{font-size:11.5px; padding:6px 10px}
  /* 直方图：10 根柱子平分宽度，360px 以下每根只有 22–29px，低于 30px 的
     触控下限（实测 300px 时只有 24px）。这个宽度下再怎么抠内边距也塞不下
     10×30px，所以改成**横向可滑动**、给每根一个 32px 的硬下限：
     宁可让用户左右滑一下，也不能把点击目标做成一条细缝。 */
  .hist{overflow-x:auto; overflow-y:hidden; -webkit-overflow-scrolling:touch}
  .histbars{min-width:352px; gap:2px}
  .hcol{min-width:32px}
}

/* ---- 横屏手机：地图与面板并排，避免上下太挤 ---- */
@media (max-width: 900px) and (orientation: landscape) {
  /* 必须写 minmax(0,1fr) 而不是 1fr：1fr 的自动最小值是内容的 min-content，
     地图按比例撑起来后会把这一行强行撑高，整块布局溢出视口底部。
     这里高度本来就紧张，地图允许被压缩。 */
  .layout{grid-template-columns:56% 44%; grid-template-rows:minmax(0,1fr)}
  .map{flex:0 1 auto; min-height:0}
  .map svg{height:auto; max-height:100%}     /* 被压缩时按比例缩，不溢出图例 */
  .legend{flex-wrap:wrap; max-height:76px; overflow-y:auto}
  .panel{border-top:0; border-left:1px solid var(--line)}
  .topbar{flex-wrap:wrap}
}

/* 触控设备：去掉 hover 位移，避免点击时元素跳动 */
@media (hover: none) {
  .news-item:hover{transform:none; border-color:var(--line)}
  .legend-item:hover{background:transparent}
  .citem:hover{background:var(--panel2); border-color:var(--line)}
}

/* ---------------------------------------------------------------
   触屏触控目标抬到 44px。
   实测（390x844）原来的尺寸：图例色块 40px、模式按钮 34px、
   返回键 34px、搜索框 36px —— 全部低于 Apple HIG / Material 建议的
   44px，手指点不准、容易误触相邻控件。
   只在真·触屏上抬，桌面鼠标不受影响（鼠标精确度高，44px 反而显笨重）。
   --------------------------------------------------------------- */
@media (hover: none) and (pointer: coarse) {
  /* 注意特异性：下面几条 min-height 早就写成 .modeswitch .btn.sm / .btn.xs /
     .mini 这类双类选择器，单纯写 .btn 是压不过它们的，必须同等或更高。 */
  .btn,
  .btn.sm,
  .btn.xs,
  .mini,
  .crumb,
  .legend-item,
  .threadbar .btn,
  .tb-modes .btn,
  .tb-modes .btn.sm,
  .modeswitch .btn,
  .modeswitch .btn.sm,
  .search input,
  .mapbar-btn,
  .mapbar-theme,
  .results > *,
  .sortbar .sbtn,
  .news-item .more{
    min-height:44px;
  }
  /* 排序按钮跟着抬到 44px，文字和内边距要一起调，否则会被撑得歪 */
  .sortbar .sbtn{
    display:inline-flex; align-items:center; justify-content:center;
    padding:0 14px; font-size:12.5px;
  }
  /* .btn.sm 原本靠 padding 撑到 34px，改用 flex 居中并让高度生效 */
  .btn.sm{
    display:inline-flex; align-items:center; justify-content:center;
    padding:0 12px; min-height:44px;
  }
  /* 手机端模式按钮是 font-size:0 + ::before 图标（▤/◐），
     高度抬到 44px 后图标要跟着放大，否则 15px 的图标在 44px 里显得很小。
     宽度也要够 44px：只有高度达标、宽度 40px 的话，两个相邻分段
     挨得太近，仍会误触。 */
  .modeswitch .btn.sm::before{font-size:18px; line-height:1}
  .modeswitch .btn.sm{padding:0; min-width:44px; min-height:44px}
  .tb-modes .btn.sm{min-height:44px; padding:0 12px}
  .btn.xs{font-size:12px; padding:0 10px; display:inline-flex; align-items:center; justify-content:center}
  .mini{display:inline-flex; align-items:center; justify-content:center}
  .legend-item{padding:0 10px; display:inline-flex; align-items:center}
  .search input{height:44px; line-height:44px; padding:0 12px}
  .mapbar-btn{min-width:44px}
  .mapbar-theme{min-width:44px; min-height:44px}
  /* 触摸设备没有 hover 态反馈，点击前给个按下反馈 */
  .btn:active,.legend-item:active,.mini:active{opacity:.75}
}

/* ---- 触屏字号下限 ------------------------------------------------------
   实测（390px）全页有 125 处文字小于 11px，最小的 9px。
   手机是**手持、户外、常在强光下看**，9–10.5px 实际读不出来；
   WCAG 1.4.4 也要求正文可缩放到 200% 而不丢失内容。

   单独拉一个区块集中写，不要散落到各个断点里：
   之前 .stat span 在**两个** max-width 断点里被写成 9.5px，
   比桌面的 11px 还小——手机上反而更看不清，方向完全反了。
   这类「顺手改小一点好腾地方」的写法，正是散落改动的后果。 */
@media (hover: none) and (pointer: coarse) {
  /* 直方图：刻度 9px / 柱顶数字 9.5px，这两个是最小的，也最难读 */
  .hlo{font-size:11px; line-height:1.35}
  .hnum{font-size:11px; line-height:1.35}
  .hnote{font-size:12px}

  /* 新闻元信息那一行的小徽章 */
  .tag,.kind,.cty,.time,.imp,.cov{font-size:11.5px}
  .today{font-size:11px}
  .pill{font-size:11px}

  /* 统计卡的说明文字（原来在手机断点里被压到 9.5px） */
  .stat span{font-size:11.5px; line-height:1.35}

  /* 事件卡里的行内小分（.imp.mini）本来就小，再大会挤到标题，
     给到 10.5px 是个折中 */
  .imp.mini{font-size:10.5px}

  /* 取不到源的清单、导图里的次要标注 */
  .bitem em,.bitem a,.mm-meta{font-size:11.5px}
  .maphint{font-size:11.5px}

  /* 新闻元信息行：实测 390px 下 5 个元素会换行成 4 行，竖向空间浪费很大。
     来源名和来源类型是里面最长的两个，让它们可截断，
     短名字照常显示全，只有超长的才省略号。 */
  .news-meta{gap:5px}
  .tag,.kind{min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
            max-width:44vw; display:inline-block; vertical-align:middle}
  .kind{max-width:26vw}
}

/* 底部 Home 指示条安全区：两个滚动区都要让开，否则最后一条新闻点不到 */
.panel,
.threadarea{
  padding-bottom:calc(8px + env(safe-area-inset-bottom));
  -webkit-overflow-scrolling:touch;
}

/* 尊重系统的减少动效设置 */
@media (prefers-reduced-motion: reduce) {
  *{transition:none !important; animation:none !important}
}

/* ============================================================
   访问口令闸门
   原来用原生 prompt()，iOS Safari 会屏蔽非用户手势触发的 prompt，
   异步 fetch 回调里根本不弹框 —— 手机上就卡在「后端未就绪」，
   用户没法输入口令。改成页面内表单。
   ============================================================ */
.gate{
  position:fixed; inset:0; z-index:9999;
  display:flex; align-items:center; justify-content:center;
  padding:calc(16px + env(safe-area-inset-top)) 16px calc(16px + env(safe-area-inset-bottom));
  background:var(--gate-bg);
  -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
  overflow-y:auto;
}
.gate[hidden]{display:none}
body.gate-open{overflow:hidden}
.gate-card{
  width:100%; max-width:380px; margin:auto;
  background:var(--panel); border:1px solid var(--line); border-radius:14px;
  padding:26px 22px 20px; text-align:center;
  box-shadow:0 18px 50px rgba(0,0,0,.5);
}
.gate-logo{font-size:30px; color:var(--acc); line-height:1}
.gate-card h2{margin:10px 0 6px; font-size:18px; font-weight:600}
.gate-card p{margin:0 0 16px; font-size:13px; color:var(--tx3); line-height:1.6}
/* 关键：字号必须 >=16px。iOS Safari 聚焦小于 16px 的输入框会自动放大页面，
   导致输入框被顶出可视区、用户看不到自己打的字。 */
#gate-input{
  width:100%; box-sizing:border-box;
  font-size:16px; line-height:1.4;
  padding:11px 12px; margin:0 0 12px;
  border:1px solid var(--line); border-radius:9px;
  background:var(--panel2); color:inherit;
  -webkit-appearance:none; appearance:none;
}
#gate-input:focus{outline:2px solid var(--acc); outline-offset:1px}
.gate-go{
  width:100%; min-height:46px; font-size:16px; font-weight:600;
  border:0; border-radius:9px; cursor:pointer;
  background:var(--acc); color:var(--on-acc);
}
.gate-go:active{transform:translateY(1px)}
.gate-msg{min-height:18px; margin-top:10px; font-size:13px; color:var(--err)}
.gate-msg:empty{min-height:0; margin-top:0}

/* 顶栏的口令入口：手机上 localStorage 常被清，得能随时改回来 */
.btn.icon{
  min-width:40px; min-height:40px; padding:0 10px;
  font-size:16px; line-height:1;
}
@media (max-width:640px){
  .btn.icon{min-width:44px; min-height:44px}   /* 触控目标按 44px 走 */
}

