/* ==========================================================================
   移植适配样式
   上游 styles.css 保持逐字节不变，所有对上游样式的补救都集中在本文件。
   加载顺序必须是 vendor/fonts.css → styles.css → adapt.css（本文件必须最后加载，
   否则同优先级的选择器会被上游覆盖掉）。
   ========================================================================== */

/* --------------------------------------------------------------------------
   中文名字的显示效果
   上游的展示字体 Archivo Black 只有拉丁字形：节点名、站点名只要是中文，浏览器就会
   掉到系统默认无衬线的常规字重上——卡片上其余元素都是粗边框 + 超粗标签，只有中文
   标题细一截，整张卡片看着不协调。
   这里不动上游的字体声明，只补一个「中文专用的本机粗体」字面：
   - @font-face + unicode-range 只吃中日韩文字与全角标点，拉丁文仍由 Archivo Black 负责，
     所以「测试节点 · Tokyo」这种混排也不会变成两种字体的拼贴；
   - src 全部用 local()，只挑本机已有的字体（Windows / macOS / Linux 各取常用名），
     不下载 CJK 字体——思源黑体这类即使用子集也有好几 MB，中文站又必须能用；
   - size-adjust 把中文稍微收一点，和 Archivo Black 的字面大小对齐。
   本机没有命中任何一款时，会回落到上游原本的系统默认字体，即与未改前一致，不会更差。
   -------------------------------------------------------------------------- */
@font-face {
  font-family: 'Monitor Display CJK';
  src:
    local('Microsoft YaHei UI Bold'), local('Microsoft YaHei Bold'),
    local('PingFang SC Semibold'), local('PingFang SC Bold'),
    local('Hiragino Sans GB W6'), local('Hiragino Sans GB'),
    local('Source Han Sans SC Bold'), local('Source Han Sans CN Bold'),
    local('Noto Sans CJK SC Bold'), local('Noto Sans SC Bold'),
    local('WenQuanYi Micro Hei Bold');
  font-weight: 400 900;
  font-display: swap;
  size-adjust: 96%;
  unicode-range: U+2E80-2EFF, U+3000-303F, U+3400-4DBF, U+4E00-9FFF, U+F900-FAFF, U+FE30-FE4F, U+FF00-FFEF;
}

/* 与上游 styles.css 里所有用 Archivo Black 的选择器一一对应。
   scripts/check-adapt.mjs 会核对这份清单：上游升级后新增了用法而这里没跟上，
   npm run check 会直接报错，而不是让中文又悄悄变细。 */
h1, h2, h3, h4, h5, h6,
.stat-value,
.node-name,
.row-node-name,
.row-arrow,
.footer-signature-author,
.modal-content h2,
.modal-content h3,
.modal-node-status-tag {
  font-family: 'Archivo Black', 'Monitor Display CJK', sans-serif;
}

/* --------------------------------------------------------------------------
   页脚：左侧原有的那行 Powered by 已并入右下角徽章（同一句话不必出现两遍），
   徽章本身保持不变，用 margin-left: auto 继续钉在右下角。
   窄屏下页脚本来就是居中排列（上游样式），这个 auto 会把徽章顶到右边不对称，
   所以只在宽屏生效。
   -------------------------------------------------------------------------- */
@media (min-width: 681px) {
  .footer-signature {
    margin-left: auto;
  }
}

/* --------------------------------------------------------------------------
   新增：分组（Hub 节点的 group 字段）
   上游没有分组概念，这一块是新加的样式：main 内的分组筛选标签行 + 节点列表里的分段标题
   （script.js 的 renderGroupTabs / createGroupHeading）。视觉沿用上游的新粗野主义：
   3px 黑边、硬阴影、激活态用强调色 + 按下位移，与顶栏的 .btn-view / .btn-admin 同款。
   -------------------------------------------------------------------------- */
.group-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1.25rem;
}

/* 与 .btn-admin 同理：作者样式里的 display 会压过浏览器的 [hidden]，
   没有这一条时「没有分组就把标签行收起来」会静默失效（标签行照旧占着位置）。
   scripts/check-adapt.mjs 会核对这条规则存在。 */
#group-tabs[hidden] {
  display: none;
}

.group-tab {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--black);
  background: var(--card-bg);
  border: 3px solid var(--black);
  box-shadow: 3px 3px 0 var(--black);
  padding: 0.5rem 0.9rem;
  cursor: pointer;
  transition: transform 0.1s ease, box-shadow 0.1s ease;
}

.group-tab:hover {
  transform: translate(-2px, -2px);
  box-shadow: 5px 5px 0 var(--black);
}

.group-tab.active {
  transform: translate(3px, 3px);
  box-shadow: none;
  background: var(--accent);
}

/* 分段标题：网格视图里横跨整行（与 .empty-state 同款做法），列表视图在下面单独摆 */
.group-heading {
  grid-column: 1 / -1;
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  padding-bottom: 0.5rem;
  border-bottom: 3px solid var(--black);
}

.group-heading-name {
  font-family: 'Archivo Black', 'Monitor Display CJK', sans-serif;
  font-size: 1rem;
  text-transform: uppercase;
  letter-spacing: -0.02em;
  word-break: break-word;
}

.group-heading-count {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--text-muted);
}

/* 列表视图：标题带跟着 .node-row 一起横向滚动（行本身 min-width: 820px，见上游注释），
   所以给它同样的 min-width；线只画在标题上方，下面那条留给紧随其后的行边框，
   否则会叠成 4px 的双线。 */
.nodes-container.list-view .group-heading {
  min-width: 820px;
  padding: 0.7rem 0.85rem 0.55rem;
  border-bottom: 0;
  border-top: 2px solid var(--black);
  background: var(--card-bg);
}

.nodes-container.list-view .group-heading:first-child {
  border-top: 0;
}

/* --------------------------------------------------------------------------
   移植差异：卡片上的三网延迟（站点设置 showNodePing，逻辑见 script.js 的 applyCardPings）
   位置：卡片内容末尾，NETWORK 区之后（原来的底部栏已拆掉，这一块就是卡片底部那一段）。
   排版上刻意与卡片自己的语言对齐（实测过尺寸）：
     · 延迟值用 .metric-value 的 0.85rem，右列数字才和上面的 CPU/内存/磁盘成一条竖线
       （原来照抄 0.75rem，比指标值小一号，同一列里数字突然变矮）；
     · 分割线 3px，与 .node-header 的下边线同粗（原为 2px，两条线挨着时粗细不一很显眼）；
     · 上留白 1.5rem 对齐卡片里其它分区的节奏；下留白由卡片自身的 padding 给。
   三列：线路名（可省略号）| 最新延迟 | 丢包率。这说的是 rows（竖排）那一档；后两列固定宽度 + 右对齐，
   数字在竖直方向成两列。默认的 columns（横排）档见下面 .ping-layout-columns 那段。
   丢包率与弹窗「延迟监控」同一口径（0.0% 常显，有丢包才变红，复用 .has-loss 语义）。
   卡片整体可点（打开节点详情），这里不单独挂点击——点上去还是同一个动作，
   详情弹窗里的「延迟监控」就是它的放大版。
   -------------------------------------------------------------------------- */
.node-ping {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-top: 1.5rem;
  padding-top: 0.75rem;
  border-top: 3px solid var(--black);
}

.node-ping-row {
  display: flex;
  align-items: baseline;
  /* 不用 space-between：三列各自定位，右两列靠固定宽度对齐成两条竖线 */
  justify-content: flex-start;
  gap: 0.75rem;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.05em;
}

.node-ping-name {
  flex: 1 1 auto;
  min-width: 0;
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.node-ping-value {
  flex: none;
  min-width: 4.2rem;
  text-align: right;
  font-family: 'Space Grotesk', 'SF Mono', 'Consolas', 'Monaco', monospace;
  font-variant-numeric: tabular-nums;
  font-size: 0.85rem;   /* 与 .metric-value 同号，右列数字对齐 */
  color: var(--black);
}

.node-ping-loss {
  flex: none;
  min-width: 3.1rem;
  text-align: right;
  font-family: 'Space Grotesk', 'SF Mono', 'Consolas', 'Monaco', monospace;
  font-variant-numeric: tabular-nums;
  font-size: 0.75rem;
  color: var(--text-muted);
}

.node-ping-loss.has-loss {
  color: var(--accent-red);
}

/* 站点设置 cardPingLayout = columns（默认）：三条线路并排成三列，每条是
   「线路名 / 延迟 / 丢包率」三行。列宽用 flex:1 1 0 均分（三个数字块因此左对齐成三竖列），
   gap 比竖排时更紧（0.4rem）——卡片实测只有 326px 宽，均分后每列约 88px，
   延迟值与丢包率放在同一行会放不下（需要 ~92px），所以让它们各自占一行；
   flex-wrap 仍留着：窄卡片上万一某一列装不下，丢包率会自己换行，不会溢出被裁。
   按要求（2026-09-26）：每列内容各自居中，列与列之间用竖条隔开（表格感，与卡片其它分割线同一套粗野主义语言）。 */
.node-ping.ping-layout-columns {
  flex-direction: row;
  /* stretch 让三列等高：竖条的高度才一致（某列多折一行时也不会参差） */
  align-items: stretch;
  gap: 0.5rem;
}

.node-ping.ping-layout-columns .node-ping-row {
  flex: 1 1 0;
  min-width: 0;
  flex-direction: column;
  align-items: center;   /* 每列内容各自居中（横向由 align-items 定） */
  text-align: center;    /* 文本本身居中（线路名、数值、丢包率） */
  row-gap: 0.2rem;
  padding: 0 0.25rem;
  position: relative;    /* 列间竖条的定位基准 */
}

/* 列间竖条：3px（与卡片里其它分割线同粗），画在两列之间那 8px 空隙的正中——
   left:-0.25rem 把它的左边定在空隙中线，再 translateX(-50%) 让它以中线为轴，
   于是「上一列文字到竖线」与「竖线到下一列文字」的留白完全相等（padding 两边都是 0.25rem）；
   上下各内缩 3px：比通高轻，也不会与上面的 3px 分割线连成一张网格。 */
.node-ping.ping-layout-columns .node-ping-row + .node-ping-row::before {
  content: '';
  position: absolute;
  left: -0.25rem;
  transform: translateX(-50%);
  top: 3px;
  bottom: 3px;
  width: 3px;
  background: var(--black);
}

/* 竖排时的 flex:1 1 auto 是让线路名吃掉整行剩下的宽度；变成列之后它会想撑满列高，
   改成按内容宽（align-items: flex-start 决定横向宽度），max-width 兜住超长线路名的省略号 */
.node-ping.ping-layout-columns .node-ping-name {
  flex: 0 0 auto;
  max-width: 100%;
}

/* 竖排时延迟/丢包靠固定 min-width + 右对齐成两条竖线；列里没有那两条竖线要对，
   min-width 归零（否则 88px 的列会被 4.2rem 的下限撑出去），文本跟着整列居中 */
.node-ping.ping-layout-columns .node-ping-value,
.node-ping.ping-layout-columns .node-ping-loss {
  min-width: 0;
  text-align: center;
}

/* --------------------------------------------------------------------------
   移植差异：上行/下行速度并入 NETWORK 区（原来在卡片底部那一栏，已拆掉）。
   结构：合计(↑) · 速率 …… 合计(↓) · 速率 —— 左一组、右一组，用 margin-left:auto 分组。
   合计与速率是各自独立的元素（不是嵌套），因为轮询更新走 scrambleTextIfChanged，
   它会直接改 textContent —— 嵌在里面的 <b> 会在第一次刷新时被抹掉；
   同理「·」分隔符只能用 ::before，不能写进 HTML。
   颜色：合计沿用上游的绿/蓝语义；速率用黑色，让随轮询跳动的数字更醒目。
   -------------------------------------------------------------------------- */
.net-totals {
  align-items: baseline;
  justify-content: flex-start;
  gap: 0.45rem;
}

.net-total-item.net-total-up {
  color: var(--accent-green);
}

.net-total-item.net-total-down {
  margin-left: auto;
  color: var(--accent-blue);
}

.net-rate {
  font-family: 'Space Grotesk', 'SF Mono', 'Consolas', 'Monaco', monospace;
  font-variant-numeric: tabular-nums;
  color: var(--black);
}

.net-rate::before {
  content: '·';
  margin-right: 0.35rem;
  color: var(--text-muted);
}

/* --------------------------------------------------------------------------
   移植差异：成本汇总卡片（站点设置 showCostCard / showCostMonthCard）
   参照上游主题仓库的 custom-body/cost.html：上游把「每月花多少」与「还剩多少没用掉」
   做成两张卡，移植版合成**一张卡里的两栏**——上半左 COST / MONTH、中间竖线、右
   RESIDUAL VALUE，下半一条 cost-foot：左边到期印章、右边口径小字。卡片外壳与 .node-card
   同一套语言：粗边框 + 硬阴影（含 card-style-thin / -double 变体）。
   一栏 = 标题 + 大数字 +（未计入说明）+ 只列已折算币种的标签行。
   节点一台都没填价格时由 JS 加 hidden 收起（下面有配套的 [hidden] 规则）。
   -------------------------------------------------------------------------- */
.cost-card {
  display: flex;
  align-items: center;
  column-gap: 1.5rem;
  row-gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.5rem;
  padding: 1.25rem;
  background: var(--card-bg);
  border: var(--border-width) solid var(--black);
  box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--shadow);
}

/* 一栏（COST / MONTH 或 RESIDUAL VALUE）：两栏等宽。
   宽度跟着内容走时，竖线和右栏的起点会随币种标签的多少左右漂，
   等宽之后竖线恒定在卡片中线、两个大数字也各就各位。 */
.cost-block {
  flex: 1 1 0;
  min-width: 0;
}

.cost-title {
  display: block;
  margin-bottom: 0.35rem;
  font-family: 'Archivo Black', 'Monitor Display CJK', sans-serif;
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--black);
}

.cost-amount {
  font-family: 'Archivo Black', 'Monitor Display CJK', sans-serif;
  font-size: 1.8rem;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--black);
  text-shadow: 1px 1px 0 var(--white);
}

/* 两栏之间的竖线：跟着两栏的高度拉满（align-self: stretch） */
.cost-divider {
  align-self: stretch;
  width: 4px;
  min-height: 2.5rem;
  flex-shrink: 0;
  background: var(--black);
}

.cost-chips {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.6rem;
}

/* 「未计入 …」：这一栏的合计里少了哪些钱。
   虚线描边（不是实心的粗野主义块）表示「这项没有计入」，与已折算的实心蓝标签区分开；
   摆在大数字正下方，读作一句补充说明而不是又一条金额。 */
.cost-note {
  display: inline-block;
  margin-top: 0.5rem;
  padding: 0.15rem 0.5rem;
  border: 2px dashed var(--black);
  font-family: 'Space Grotesk', 'SF Mono', 'Consolas', 'Monaco', monospace;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--black);
}

.cost-chip {
  display: inline-flex;
  align-items: center;
  padding: 0.3rem 0.75rem;
  border: 2px solid var(--black);
  box-shadow: 3px 3px 0 var(--black);
  font-family: 'Space Grotesk', 'SF Mono', 'Consolas', 'Monaco', monospace;
  font-size: 0.75rem;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--black);
}

.cost-chip-blue {
  background: var(--accent-blue);
}

.cost-chip-red {
  background: var(--accent-red);
}

/* 没有告警时的那行字：与卡片里的次要信息同一个灰度 */
.cost-clear {
  font-family: 'Space Grotesk', 'SF Mono', 'Consolas', 'Monaco', monospace;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* 卡片底下那一条：左边到期印章、右边口径小字。
   flex-basis: 100% 让它自己占一行（两栏在上面并排），位置不再随内容左右漂——
   从前那行小字跟在两栏后面用 margin-left: auto 顶到右边，内容一变就掉到第二行。 */
.cost-foot {
  flex: 1 1 100%;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
}

.cost-alerts {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  min-width: 0;
}

/* 宽屏：逐台列出一枚一枚红印章；窄屏：收成可点开的汇总（见下面的 @media）。
   两份都在 DOM 里，谁显示由 CSS 决定——不引 JS 状态，卡片每 5 分钟重画也不会丢展开态。 */
.cost-alert-full {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.cost-alert-compact {
  display: none;
  flex-wrap: wrap;
  gap: 0.5rem;
}

/* 汇总那一枚就是 .cost-chip 本体（红底印章），点开列出名字 */
.cost-alert > summary {
  cursor: pointer;
  list-style: none;
  user-select: none;
}

.cost-alert > summary::-webkit-details-marker {
  display: none;
}

.cost-alert > summary::after {
  content: '▾';
  margin-left: 0.4rem;
}

.cost-alert[open] > summary::after {
  content: '▴';
}

.cost-alert-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 0.5rem;
}

/* 右侧小字：margin-left: auto 把它顶到这一条的最右边 */
.cost-meta {
  margin-left: auto;
  text-align: right;
  font-family: 'Space Grotesk', 'SF Mono', 'Consolas', 'Monaco', monospace;
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* 卡片风格变体：与 .node-card 的三种粗细保持一致 */
.card-style-thin .cost-card {
  border-width: 2px;
  box-shadow: 4px 4px 0 var(--shadow);
}

.card-style-double .cost-card {
  border-width: 6px;
  box-shadow: 8px 8px 0 var(--shadow);
  position: relative;
}

.card-style-double .cost-card::before {
  content: '';
  position: absolute;
  inset: 6px;
  border: 2px solid var(--black);
  pointer-events: none;
}

#cost-card[hidden] {
  display: none;
}

@media (max-width: 768px) {
  .cost-card {
    column-gap: 1rem;
    row-gap: 0.85rem;
    padding: 1rem;
  }
  /* 竖线在两栏堆叠时就没有意义了 */
  .cost-divider {
    display: none;
  }
  /* 让两栏自己决定并排还是堆叠：有空间就并排，放不下才换行 */
  .cost-block {
    flex: 1 1 11rem;
  }
  .cost-amount {
    font-size: 1.5rem;
  }
  /* 窄屏的标签也收一档：一行能多放一枚，手机上这张卡就少一两行高度
     （合计行有 6 枚币种标签，390 宽下 1.2rem 的边距会把它们挤成三行）。 */
  .cost-chip {
    padding: 0.2rem 0.5rem;
    font-size: 0.6875rem;
  }
  /* 到期印章换成汇总形态：窄屏逐台列出实测能把这张卡撑到 493px 高（首屏一半没了） */
  .cost-alert-full {
    display: none;
  }
  .cost-alert-compact {
    display: flex;
  }
  .cost-meta {
    margin-left: 0;
    text-align: left;
  }
}

/* 卡片上的节点名：恒定一行 + 省略号。
   上游只写了 word-break: break-word，名字多长就占多少行——长名卡片的名字下方
   （分隔线、CPU、RAM…）整体被推下去，和同一行里名字短的卡片错开（实测 3 行名 → 头部 120px、
   短名 74px，CPU 行差 46px；网格又会把卡片高度拉齐，于是短名卡片空出一大块）。
   列表视图的 .row-node-name 本来就是单行省略，这里让卡片视图跟上同一口径；
   全名看 title（悬停）或详情页弹窗，卡片上不再拿高度换字数。
   注意必须先给名字那一列 min-width: 0：flex 子项默认 min-width: auto，
   不可断行的长名字会把这一列撑开、省略号根本不生效（实测名字会直接冲出卡片）。 */
.node-header > div:first-child {
  min-width: 0;
}

/* 网格轨道是 minmax(320px, 1fr)：卡片作为 grid item，min-width 默认是 auto（= min-content），
   而名字那一行现在是 nowrap 的，它的 min-content 就是整个名字的宽度——卡片被撑到 590px，
   手机（390 视口）整页横向溢出（实测 documentElement.scrollWidth 616 > 390）。
   给卡片 min-width: 0 让轨道从 320 起步，名字自己用省略号收进卡片里。 */
.node-card {
  min-width: 0;
}

.node-name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 标题下那行「系统 · CPU 型号」：最多两行 + 省略号，悬停看全（title 由 script.js 挂）。
   上游的行高是 normal（约 1.15），两行贴着像一块灰砖，给到 1.35 才读得成一段说明；
   更要紧的是**它固定占满两行**：CPU 型号长短不一（「AMD EPYC Processor」一行、
   「AMD EPYC 9654 96-Core Processor」两行），不预留高度时同一排卡片会差一行（实测 74 vs 91px），
   下面的分隔线与指标行跟着错开——这正是名字那次修的同一个毛病。 */
.node-info {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: 2.7em;
  line-height: 1.35;
}

/* --------------------------------------------------------------------------
   部件状态：JS 用 hidden 属性开关的元素
   script.js 关闭「显示后台入口按钮」（showLoginButton=false）时，是给按钮加
   hidden 属性。但浏览器默认的 [hidden] { display: none } 来自 UA 样式表，
   而作者样式里的 .btn-admin { display: flex } 优先级更高——实测开关关掉后按钮
   照旧显示（hidden 属性在、computed display 仍是 flex，34×34 可见）。
   上游 styles.css 里没有全局 [hidden] 规则（只有 .auth-oauth[hidden]），所以这里
   补一条作者规则；本文件在 styles.css 之后加载且特异性更高，不依赖顺序。
   scripts/check-adapt.mjs 会核对：凡 script.js 用 hidden 属性开关的元素，
   都必须有配套的 [hidden] 规则，否则这类开关以后还会静默失效。
   -------------------------------------------------------------------------- */
.btn-admin[hidden] {
  display: none;
}

/* --------------------------------------------------------------------------
   节点备注（详情页）
   hub 后台给每台节点填的两个字段：公开备注（随公开视图下发、匿名可见）与私有备注
   （只在登录态下发、仅管理员可见）。script.js 的 remarkChipsHTML 把它们拆成一串小卡片，
   **私有在前、公有在后**；私有那几枚的版式与公开完全一致，只多一枚小锁图标（站长口径）。
   hub 只把私有下发给登录的管理员，所以访客那边根本不会出现 own 那几枚——不需要两套分支。
   两个字段都没写（或只有空白）时整块不渲染，一个像素都不占。
   位置：详情页页头里、「系统 · 架构 · 地区」那一行的下面（页头那条 6px 黑分隔线之上）。
   -------------------------------------------------------------------------- */
.modal-node-remark {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.9rem;
}

.remark-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  max-width: 100%;
  padding: 0.25rem 0.6rem;
  border: 2px solid var(--black);
  background: var(--white);
  box-shadow: 3px 3px 0 var(--black);
  font-size: 0.8rem;
  font-weight: 700;
  line-height: 1.35;
}

/* 私有（仅自己可见）：版式与公开那几枚**完全一致**（实线边 + 白底 + 硬阴影），
   区分只靠多出来的一枚小锁图标 + 悬停提示（站长口径：不要另一种边框/底色，只留锁）。 */
.remark-chip.own {
  cursor: help;
}

.remark-chip-text {
  min-width: 0;
  overflow-wrap: anywhere;
}

.remark-lock {
  width: 0.9em;
  height: 0.9em;
  flex: 0 0 auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

