:root {
  /* 声明页面自己适配深浅两套配色：不声明的话，移动端浏览器的「自动深色」会把
     自己的强制改色叠在页面之上 —— 图片被加反色滤镜泛白、卡片按钮被改成纯黑、
     半透明的选中背景直接被吃掉 */
  color-scheme: light dark;
  --bg: #F4F6F8;
  --card: #FFFFFF;
  --text: #1F2430;
  --text-2: #5A6280;
  --border: #E2E6EC;
  /* 加深一档的描边：给「必须一眼看出是按钮」的控件用（导出按钮等） */
  --border-2: #C7D0DC;
  --track: #E6EAEE;
  --bar-a: #8FAEA6;
  --bar-b: #67897F;
  --hover: #F0F3F6;
  /* 下面三个与 LvchaxsBS 主题字典同值，专供排序按钮（SortOptionButtonStyle）使用：
     PrimaryBrush 蓝条 / AccentSoftBrush 选中底 / HoverBackgroundBrush 悬停玻璃（#9E = 62%） */
  --accent: #3B82F6;
  --accent-soft: rgba(59, 130, 246, .13);
  --glass: rgba(255, 255, 255, .62);
  /* 今日增减：多了绿、少了红（与 LvchaxsBS 的 SuccessBrush / DangerBrush 同值） */
  --good: #10B981;
  --bad: #EF4444;
}

html[data-theme="dark"] {
  --bg: #1A1D22;
  --card: #22262C;
  --text: #E4E8EE;
  --text-2: #A9B1CE;
  --border: #333941;
  --border-2: #4C545F;
  --track: #2E343B;
  --bar-a: #8FB5AB;
  --bar-b: #BBD6CE;
  --hover: #2A2F36;
  --accent: #5B93FF;
  /* 选中底色用深色 accent 的蓝色半透明，而不是半透明白 —— 白 8% 在深底上几乎看不见，
     排序按钮选中后只剩蓝条、看不出选中底 */
  --accent-soft: rgba(91, 147, 255, .16);
  --glass: rgba(56, 56, 56, .62);
  --good: #4ADE80;
  --bad: #F87171;
}

/* 主题只由 <html> 上的 data-theme 决定（index.html 头部脚本首帧写好、按钮手动切换），
   不再跟随系统深浅色。深色变量就一份，见上面 html[data-theme="dark"]。 */

/* 主题切换过渡：切换那一下给 <html> 临时挂 .theme-transition（平时不挂，避免影响 hover / 折叠等动画），
   整页所有元素用**同一条曲线**一起变：底色、卡片、描边、阴影、图标填充都是 .22s linear。
   · 用 linear 是为了让每个颜色的中点都正好落在 110ms，各元素亮度推进比例始终一致；
   · 文字（color）不跟着插值 220ms：深字与浅底、浅字与深底同步插值时中途会撞成同一个颜色，
     那一段字就真的看不见。改成在第 110ms（背景正好到中点、深字浅字对比度最平衡处）用 .01s（1 帧）翻面，
     之前深字压浅底、之后浅字压深底，全程都读得清，也不会「先消失再出现」。
   暗月那边 darkmoon4/css/dm-theme.css 有同款规则，两边同一帧挂上。 */
html.theme-transition,
html.theme-transition::before,
html.theme-transition *,
html.theme-transition *::before,
html.theme-transition *::after {
  transition: background-color .22s linear, border-color .22s linear, outline-color .22s linear,
              box-shadow .22s linear, fill .22s linear, background-image .22s linear,
              color .01s linear .1s !important;
}

* { box-sizing: border-box; }

/* 点击/触摸任何按钮都不给反馈：去掉移动端默认的淡蓝色 tap 高亮方块，以及点完留下的焦点方框 */
* { -webkit-tap-highlight-color: transparent; }
*:focus, *:focus-visible { outline: none; }

/* 必须放在所有规则之前又带 !important：
   作者样式表的 display 会盖掉浏览器默认的 [hidden]{display:none}，
   不补这条的话元素加了 hidden 属性也照样显示（关不掉）。 */
[hidden] { display: none !important; }

/* 数量输入框：去掉浏览器自带的上下加减箭头（瞄准网页里干净的输入框观感） */
input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* 页面底色画在 html::before 这个 fixed 层上，body 自身保持透明：
   根元素（html/body）的背景会被浏览器「传播」到 canvas，那一层不参与逐帧重绘 —— 切主题时
   内容区早就变完了，整页底色要等过渡结束才一下跳过来（实测 t150 时 html 的 computed 是
   rgb(82,85,90)、屏幕上的像素还是 rgb(47,52,58)）。fixed 层是普通元素，和卡片/文字同一条曲线。
   --bg 是各页通用底色；暗月页（body.dm-view）另有固定底色，用 :has 挂到同一层上。
   不支持 :has 的浏览器退回 --bg，与 #fff / #151a21 只差几个色阶。 */
html::before {
  content: '';
  position: fixed;
  /* 不用 inset:0 —— 那只能盖住「布局视口」。移动端往下滑时地址栏收起，可视区会高出一截
     （正好是地址栏的高度），多出来的那一条在本层之外，露的是浏览器默认白色画布，
     看着就是「底部滑上来的背景是浅色的」。上下各多铺一截，视口怎么变都盖得住；
     上溢那截顺带盖住下拉回弹时露出的画布。 */
  left: 0;
  top: -20vh;
  width: 100%;
  height: 140vh;    /* 回退：老浏览器把 vh 当大视口 */
  height: 140lvh;   /* 大视口 ×1.4，地址栏收放的落差全在里面 */
  z-index: -1;
  pointer-events: none;
  background-color: var(--bg);
}
html:has(body.dm-view)::before { background-color: #fff; }
html:has(body.dm-view.dm-dark)::before { background-color: #151a21; }

body {
  margin: 0;
  background: transparent;
  color: var(--text);
  font: 14px/1.5 "Microsoft YaHei", "PingFang SC", system-ui, sans-serif;
  -webkit-text-size-adjust: 100%;
}

/* 展开 / 合并会让卡片高度连续变化，浏览器默认的「滚动锚定」会逐帧补偿 scrollTop，
   表现为视口内容上下一起抽（看着像回弹）；关掉它，高度变化只影响卡片下方，卡片顶不动 */
html, body { overflow-anchor: none; }

.topbar {
  position: sticky;
  top: 0;
  z-index: 10;
  padding: 4px 6px;
  background: var(--card);
  border-bottom: 1px solid var(--border);
}

/* ================= 顶部导航（照抄 LvchaxsBS 的 NavButtonStyle） =================
   四项 = 主程序左侧「锄地记录」下的四个子项：每日锄地 / 路线管理 / 材料统计 / 分析总结。
   常态：透明底 + 次要文字；选中（Tag=1）：浅蓝底 + 左侧 2px 蓝竖杠 + 文字加粗
   （★ 文字颜色不变，与 XAML 一样只靠底色、竖杠、字重区分）。 */
.nav { display: flex; }

/* 暂时关闭「每日锄地」「分析总结」两个导航：只隐藏不删，恢复时删掉这条规则即可 */
/* 「每日锄地」「分析总结」的显隐由 JS 控制（云端同步页的开关 + 登录态）：
   未登录或开关未勾选 ⇒ nav.hidden = true；不在这里写死 display:none */

.nav-item {
  position: relative;
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 6px 2px 5px 4px;
  font-family: inherit;
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.2;
  color: var(--text-2);
  background: transparent;
  border: 0;
  border-radius: 8px;
  cursor: pointer;
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
}

/* 图标一律描边（不填充），颜色跟着按钮的 color 走：
   与 XAML 里 Stroke 绑到 Button.Foreground 是同一套做法。 */
.nav-icon {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linejoin: round;
  stroke-linecap: round;
  flex: none;
}

/* 选中时的左竖杠：从中间展开（scaleY 0→1），与 XAML 的 Rect+ScaleTransform 同一套时序 */
.nav-item::before {
  content: "";
  position: absolute;
  left: 1px;
  top: 50%;
  width: 2px;
  height: 14px;
  margin-top: -7px;
  border-radius: 1px;
  background: var(--accent);
  opacity: 0;
  transform: scaleY(0);
  transition: transform .18s cubic-bezier(0, 0, .58, 1), opacity .08s;
}

/* 悬停底色同样只给真有鼠标的设备（触屏粘滞问题同上） */
@media (hover: hover) {
  .nav-item:hover { background: var(--glass); color: var(--text); }
}

/* 查看别人的时候：每日锄地 / 导入导出 不能进，按钮直接置灰不给点 */
.nav-item:disabled { opacity: .32; cursor: default; }

.nav-item.on { background: var(--accent-soft); font-weight: 700; color: var(--text); }
.nav-item.on::before { opacity: 1; transform: scaleY(1); }

/* 通用 button 的 :active 缩放是给按钮用的，导航项不要跟着弹 */
.nav-item:active { transform: none; }

/* 还没接入内容的页面：一行浅色说明，不铺任何假控件 */
.empty {
  margin: 0;
  padding: 48px 14px;
  text-align: center;
  font-size: 13px;
  color: var(--text-2);
}

button, select, input[type="text"], input[type="search"], input[type="number"] {
  font: inherit;
  color: var(--text);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px 10px;
}

button {
  cursor: pointer;
  transition: transform .12s ease, background .12s ease;
}
/* 悬停底色只给真有鼠标的设备：触屏上点完按钮 :hover 会一直粘着不消失
   （浅色的 --hover 偏白 ⇒ 点完选择再取消后按钮看着变白，点别处才恢复） */
@media (hover: hover) {
  button:hover { background: var(--hover); }
}
button:active { transform: scale(1.15); }

/* 页面容器：同一时间只显示一页，由导航切换 hidden */
main { padding: 0 0 24px; }

/* 排序条贴着导航，下面才是材料行 */
.page > .sort-bar { padding: 10px 14px 6px; }

/* 材料统计一条不剩时的空态：整行居中（#list 已经有左右留白，这里不再叠 margin） */
#list .list-empty { margin: 10px 0 0; }

/* ================= 排序按钮（照抄 LvchaxsBS 的 SortOptionButtonStyle） =================
   常态：透明底 + 次要文字色；悬停：玻璃底 + 文字提亮；
   选中（Tag=1）：浅蓝底 + 左侧 2px 蓝竖杠 + 文字加粗（★ 不换文字颜色，区分只靠底色和竖杠）。
   ★ 竖杠用「scaleY 0→1 + EaseOut 0.18s」，与 XAML 的 Rect+ScaleTransform 动画同一套时序。 */
.sort-bar { display: flex; align-items: center; }

/* 材料统计排序栏：左 / 右 两组 —— 两组各占一半剩余空间（贴边）：左=排序键与隐藏毕业，右=砂糖/多莉 + 合成 */
#sort-bar { justify-content: space-between; }
.sort-grp { display: flex; align-items: center; }
/* ★ basis 必须是 auto（按内容宽）而不是 0：写 0 时左右两组只按「剩余空间的一半」定宽，
   与自己的内容宽无关 —— 左组按钮多、右组少，左组窄于内容就向右溢出，
   直接压到右边的按钮上（表现为按钮重叠）。auto 保证组宽不小于内容。
   1 0 auto：只长不缩，组内按钮永远不会被压到互相叠字 */
#sort-left { flex: 1 0 auto; min-width: 0; justify-content: flex-start; }
#sort-right { flex: 1 0 auto; min-width: 0; justify-content: flex-end; }

/* 右侧「合成」切换按钮：外观与普通排序按钮完全一致（含选中左蓝条），
   只是 data-k=swap 走场景切换逻辑，不做任何排序 */

.sort-opt {
  position: relative;
  height: 24px;
  padding: 0 10px 0 11px;      /* 左边 11：给左竖杠留位置，与 XAML Padding="11,0,10,0" 一致 */
  margin-right: 4px;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 700;           /* 默认粗体：选中与否都粗，区分只靠蓝底和左竖杠 */
  color: var(--text-2);
  background: transparent;
  /* 去掉浏览器 / X5(QQ浏览器) 自带的按钮外观：不写这些，有些内核会自己描一圈边框、
     再叠上内阴影和内边距，按钮实际变宽 ⇒ 一行放不下时「降序」和「隐藏毕业」会挤到重叠 */
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  border: 0;
  box-shadow: none;
  border-radius: 4px;         /* CornerRadius=4 */
  cursor: pointer;
  white-space: nowrap;        /* 按钮文字永不换行（窄屏靠压 padding 保一行） */
  flex: 0 0 auto;             /* 空间不够也不许压窄（压窄会变成文字互相叠） */
  -webkit-text-size-adjust: 100%;   /* 别让浏览器按自己的字号设置把按钮文字撑大 */
  text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
}

.sort-opt::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  width: 2px;
  height: 12px;
  margin-top: -6px;
  border-radius: 1px;
  background: var(--accent);  /* PrimaryBrush */
  opacity: 0;
  transform: scaleY(0);
  transition: transform .18s cubic-bezier(0, 0, .58, 1), opacity .08s;   /* EaseOut */
}

/* 悬停底色只给真有鼠标的设备：触屏上点完再取消后 :hover 粘着不消失（浅色 glass 偏白 ⇒ 按钮变白，点别处才恢复） */
@media (hover: hover) {
  .sort-opt:hover { background: var(--glass); color: var(--text); }
}

.sort-opt.on {
  background: var(--accent-soft);
  font-weight: 700;
}
/* 选中态不叠加悬停玻璃（与 XAML 里 selBg 盖住 hoverBg 的顺序一致） */
.sort-opt.on::before { opacity: 1; transform: scaleY(1); }

/* 通用 button 那条 :active 缩放是给主题/导入导出按钮的，排序按钮不要跟着弹 */
.sort-opt:active { transform: none; }

/* 组之间的竖分隔条：XAML 里是 1×14 的 Border，Margin="6,0,10,0" */
.sep {
  width: 1px;
  height: 14px;
  margin: 0 10px 0 6px;
  background: var(--border);
  flex: none;
}

/* 「砂糖 / 多莉」这一组（路线页头的加成、材料统计合成场景的加成共用）：
   ★ 不瞬间显示/隐藏，而是从它右边那个按钮的右缘逐渐展开、向左逐渐收起：
     收起 = max-width 0 + 透明；展开 = .open。overflow 裁掉内容，过渡才顺。 */
.who-set {
  display: flex;
  align-items: center;
  overflow: hidden;
  max-width: 0;
  opacity: 0;
  white-space: nowrap;
  transition: max-width .22s cubic-bezier(.22, .61, .36, 1), opacity .18s ease;
}
.who-set > * { flex: none; }
.who-set.open { max-width: 190px; opacity: 1; }

/* 一行一族：与 LvchaxsBS 材料统计页同一排法
   —— 【图标|输入框】×3 → 进度条（吃掉剩余宽度）→ 百分比，整行不换行。
   ★ 行本身不加边框/背景/圆角（不要卡片感）。 */
.fam {
  display: flex;
  align-items: center;
  gap: 3px;
  padding: 6px 6px;
}

.tier { display: flex; align-items: center; gap: 1px; }

/* 一档 = 图标 +（数量框 / 底下那行今日增减小字） */
.qbox {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-right: 1px;
}

/* 材料图标本身是无背景透明图，不要加圆角（会把边角裁掉） */
.tier img { width: 32px; height: 32px; flex: none; }

/* 数量输入框：照抄 LvchaxsBS 的 QuantityBoxStyle
   —— 默认 背景透明 + 边框透明（看不出是个框），数字居中；
      只在鼠标悬停 / 正在输入时才显出边框，方便辨认点到哪了。
   ★ 窄框：省下来的横向空间全部让给右侧进度条。
   ★ 字号 / 字重 / 字体族与右侧百分比完全一致（.pct），
     不加粗 —— 加粗会让同样 12px 的数字看起来比百分比大一圈。 */
.tier input[type="number"] {
  width: 52px;
  padding: 1px 4px;
  text-align: center;
  font-family: inherit;
  font-size: 12px;
  font-weight: 400;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
}
.tier input[type="number"]:focus {
  outline: none;
  background: var(--hover);
  border-color: var(--bar-b);
}

/* 查看别人的材料：数量只读 —— 外观不变，但点不进去也滚不动，
   免得弹出输入法或者误以为能改（数据本来也不会写出去） */
.tier input[type="number"][readonly] {
  pointer-events: none;
  caret-color: transparent;
}

/* 数量为 0 时框里那个 0 是 placeholder 水印，**不是真值**：
   敲第一个数字它自动让位（不用先删 0），与 LvchaxsBS 的 Opacity=0.4 弱化观感对齐。
   ⛔ 千万别把它写成 value="0" —— 那是真值，点进去还得手动删。 */
.tier input[type="number"]::placeholder,
.tier input[type="number"]::-webkit-input-placeholder {
  color: var(--text-2);
  opacity: .4;
}

/* 数量框下面那行「今日增减」：多了绿、少了红、没变化留空占位。
   ★ 用 visibility:hidden（不是 display:none）—— 照抄 XAML 用 Hidden 而非 Collapsed 的做法，
     52 行的高度才不会一跳一跳；字号/字重同 DeltaTextStyle（10 / SemiBold）。 */
/* 数量下面的增减小数字：
   ★ 左右留等宽的空白，符号挂进左边那块空白（absolute，不占布局）
     ⇒ 数字本身永远压在输入框数字的同一条中轴线上，不会被「+/-」顶偏。 */
.dl {
  position: relative;
  padding: 0 .5em;
  height: 9px;
  line-height: 9px;
  font-size: 9px;
  font-weight: 600;
  white-space: nowrap;
  visibility: hidden;
}
.dl .sgn {
  position: absolute;
  left: 0;
  font-style: normal;
}
.dl.up { color: var(--good); visibility: visible; }
.dl.down { color: var(--bad); visibility: visible; }

/* 百分比 + 底下那行增减百分比：两行右对齐贴在一起 */
.pwrap {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  flex: none;
}

/* 百分比：只是个数字，不是按钮（本工具只记录数量） */
.pct {
  width: 56px;   /* 要放得下 2 位小数的「100.00%」 */
  text-align: right;
  font-size: 12px;
  color: var(--text-2);
  flex: none;
  padding: 0 4px;
}

/* 增减百分比（+3.20% / -1.50%）：与左边的小数字落在同一条水平线上 */
.dp {
  width: 56px;
  text-align: right;
  padding: 0 4px;
  height: 9px;
  line-height: 9px;
  font-size: 9px;
  font-weight: 600;
  white-space: nowrap;
  visibility: hidden;
}
.dp.up { color: var(--good); visibility: visible; }
.dp.down { color: var(--bad); visibility: visible; }

/* 「期望」时代的小字已废弃（盈亏改到分析页；合成数字走下面的 craft-info 展开区） */

/* ================= 合成信息展开区（点「合成」按钮时展开） =================
   每行 = famwrap{ fam(主行) + craft-info }；craft-info 用 grid 0fr→1fr 做平滑展开。
   三行内容：毕业 / 配平 / 溢出。标签压在第一列图标下面，
   数字与中/高两档输入框对齐（.ccol 复刻 .tier 的 图标宽+输入框宽），低档是原料没有数字。 */
.famwrap { min-width: 0; contain: layout style; }   /* 隔离每一行的重排：一行撑开不再触发整张列表重排，移动端展开更顺 */

/* 合成展开：grid 0fr→1fr 平滑撑开（改回最初的展开效果；移动端不像 max-height 那样逐帧重排卡顿）。 */
.craft-info {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .28s cubic-bezier(0, 0, .58, 1);
}
.craft-in {
  overflow: hidden;
  min-height: 0;
  opacity: 0;
  padding: 0 3px;   /* 与 .fam 左右 padding 一致，标签/数字才能对到图标/输入框正下方 */
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;   /* 窄屏放不下时，就地合成那组自动落到下一行（占满整宽） */
}
.crows { display: flex; flex-direction: column; flex: none; align-items: flex-start; }
#list.syn .craft-info { grid-template-rows: 1fr; }
#list.syn .craft-in { opacity: 1; }
/* 只在展开/收起的 320ms 内提示浏览器单独优化网格行高插值（结束即移除，避免常驻几十个图层拖垮移动端内存） */
#list.animating .craft-info { will-change: grid-template-rows; }

.crow { display: flex; align-items: center; height: 16px; }

/* ================= 就地合成（「毕业/配平/溢出」右侧的空白格，配平行） =================
   「合成高阶 / 合成中阶」两个按钮，口径与暗月计算器的「合成」按钮完全一致：
   中阶 = 3 低 → 1 中，高阶 = 3 中 → 1 高；点击弹出数量输入，「1000 100」的第二段是砂糖/多莉的额外产出。 */
.craft-act { display: flex; align-items: center; gap: 4px; margin-left: 2px; }
.craft-do {
  height: 20px;
  padding: 0 8px;
  font-family: inherit;
  font-size: 11px;
  color: var(--text-2);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  white-space: nowrap;
}
.craft-do:hover { color: var(--text); background: var(--hover); }
.craft-do:active { transform: translateY(1px); }
.craft-do[disabled] { opacity: .45; cursor: default; }
/* 每列 = 图标槽 + 数字槽，宽度/间距与主行 .tier 一致（基础档 32 图标 + 48 输入框） */
.ccol { display: flex; align-items: center; flex: none; margin-right: 3px; gap: 1px; }
.clabel, .cskip { width: 32px; flex: none; }
.clabel { text-align: center; font-size: 9.5px; color: var(--text-2); }
.cnum, .cskip2 { width: 48px; flex: none; text-align: center; }
.cnum { font-size: 12px; font-family: inherit; font-weight: 400; }
.cnum.grad, .cnum.bal { color: var(--good); }
.cnum.ov { color: var(--bad); }
.cnum.zero { color: var(--text-2); opacity: .45; }

.bar {
  flex: 1 1 80px;
  min-width: 60px;
  height: 6px;
  border-radius: 3px;
  background: var(--track);
  overflow: hidden;
}

.bar > i {
  display: block;
  height: 100%;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--bar-a), var(--bar-b));
  transition: width .2s ease;
}

.chip {
  position: fixed;
  right: 14px;
  bottom: 14px;
  z-index: 20;
  background: var(--bar-b);
  color: #fff;
  border: none;
  border-radius: 999px;
  padding: 9px 16px;
  font-size: 13px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .18);
  cursor: pointer;
}

.toast {
  position: fixed;
  left: 50%;
  bottom: 22px;
  transform: translateX(-50%);
  z-index: 30;
  background: rgba(0, 0, 0, .82);
  color: #fff;
  border-radius: 8px;
  padding: 8px 14px;
  font-size: 13px;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s ease;
}
.toast.show { opacity: 1; }

/* ================= 卡片 / 通用小件（每日锄地、路线管理、分析总结共用） ================= */
.card {
  margin: 10px 14px 0;
  padding: 12px 14px 14px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
}

.card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.3;
}

.muted { font-size: 11px; font-weight: 400; color: var(--text-2); }

.tag {
  padding: 2px 8px;
  border-radius: 6px;
  font-size: 10px;
  font-weight: 600;
  background: var(--accent-soft);
  color: var(--accent);
}

/* ---- 分析总结的日期切换（照主程序：◀ 日期 ▶，点日期弹月历） ---- */
.day-arrow {
  width: 22px;
  height: 22px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 0;
  border-radius: 6px;
  color: var(--text-2);
  cursor: pointer;
}
.day-arrow:disabled { opacity: .3; cursor: default; }
.day-pick:active { transform: none; }   /* 点它直接弹月历，不要像普通按钮那样按一下放大 */

/* 月历弹窗：有记录的日子正常色可点，没记录的压淡且点不动；
   位置贴着日期按钮右下，右对齐（日期按钮本来就在卡片右上角） */
.cal-head { display: flex; align-items: center; }
.cal-week, .cal-days { display: grid; grid-template-columns: repeat(7, 1fr); }
.cal-week span { text-align: center; font-size: 10.5px; color: var(--text-2); }
.cal-day {
  height: 28px;
  padding: 0;
  font-family: inherit;
  font-size: 12px;
  color: var(--text);
  background: transparent;
  border: 0;
  border-radius: 6px;
  cursor: pointer;
}
.cal-day.on { background: var(--accent-soft); color: var(--accent); font-weight: 700; }

/* ---- 今日进度（精英 400 / 小怪 2000，一人一行） ---- */
.pv-line { display: flex; align-items: baseline; justify-content: space-between; }
.pv-num { font-size: 12px; font-weight: 600; }
.bar.big { height: 6px; }

/* ---- 页面头（路线列表标题 + 添加按钮） ---- */
.page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px 2px;
}
.page-title { font-size: 13px; color: var(--text-2); }

/* 路线管理页头：标题 + 添加按钮 + 期望口径切换，一起装进卡片
   （内边距归卡片管，里面的 .page-head 不再自己撑边） */
/* 路线管理页头只有一行：两组二选一靠左，「+ 添加路线」贴右 */
.route-head { padding: 9px 12px 10px; }
.route-head .btn-add { margin-left: auto; flex: none; }
/* 编辑页头：同一张卡片里「标题在左、返回按钮在右」，按钮右缘与列表页的「添加路线」对齐 */
.head-row { display: flex; align-items: center; gap: 8px; }
.head-row .btn-back { margin-left: auto; flex: none; }
/* 编辑页头：切换栏里返回按钮贴右，和列表页的「+ 添加路线」同一位置（两页高度一致） */
.route-head .btn-back { margin-left: auto; flex: none; }

.btn-add {
  height: 26px;
  padding: 0 10px;
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 6px;
}

/* ---- 每日锄地：一条路线一行（上排名称/标签/累计，下排三个计数器） ---- */

/* 中间那条提示卡（占满整行）：虚线框，内容说明「把下面的路线移上来才能分配怪量」；
   ★ 它是 .farm-row 的一员 ⇒ 拖动排序时占一个槽位，拖动越过它就等于移出 / 移入上方区域 */
/* 拖动时：能拖到它上面跨区 ⇒ 蓝框；拖的这条已经分配了车数、不能再移回列表 ⇒ 红框 */
.farm-row.farm-hint.drag-no { border-color: var(--bad); color: var(--bad); }
/* 跨区拖动松手：被拖的卡先在当前位置淡出，表示“已经移走/移入” */
.farm-hint-text { min-width: 0; }
.farm-row.farm-hint[aria-expanded="true"] .farm-hint-chev { transform: rotate(180deg); }

/* 「其他路线」里的卡片：内容照常显示（含加减），只是按钮点不动 */
.counters.locked button { cursor: default; }

/* 一键移出 / 移入：无文字，只有箭头
   （在「其他路线」里朝上 = 移到上方；在上方朝下 = 移回列表） */
/* 已分配今日怪量的路线不能移回列表 ⇒ 箭头置灰 */
.farm-move svg {
  width: 13px;
  height: 13px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.farm-top { display: flex; align-items: center; gap: 6px; min-width: 0; }
/* 名称优先占位：最多半行宽，再长就省略号；材料图标不许把它挤没 */
/* 每日锄地里「路线已被删掉、但那天还留着记录」的那一行：只加一个小标签，没有排序手柄 */
/* 材料图标条：占名称剩下的宽度，装不下就横向滑动查看（不换行、不压缩、不挤名称） */
.farm-mats::-webkit-scrollbar { display: none; }
/* 一枚材料 = 图标 + 底下一行小字：这套材料现在的进度 */
.farm-mats img { width: 18px; height: 18px; }

/* 卡片右上角的排序手柄：照主程序 SortHandleButtonStyle 的形状 —— 20×20 点击区、14px 图标、
   纵向居中、往卡片右缘靠；静止偏淡，悬停 100ms 放到 1.2 倍并提亮 */
.sort-handle {
  flex: none;
  width: 20px;
  height: 20px;
  margin: 0 -5px 0 0;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 0;
  border-radius: 4px;
  color: var(--text-2);
  opacity: .55;
  cursor: grab;
  touch-action: pan-y;           /* 按住手柄上下滑仍然滚页面（不会误触发排序），进入拖动后由 JS 拦 touchmove */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
  transition: transform .1s cubic-bezier(.215,.61,.355,1), opacity .1s;
}
/* 只在真能悬停的设备上放大提亮：触屏拖完手指抬起来后 :hover 会一直挂着，看起来像卡在高亮态 */
@media (hover: hover) {
  .sort-handle:hover { opacity: 1; transform: scale(1.2); }
}
/* 全局 button:hover 会铺一层 --hover 底色，手柄不要：悬停 / 按下都保持透明 */
.sort-handle:hover, .sort-handle:active { background: transparent; }
.sort-ico { width: 14px; height: 14px; display: block; overflow: visible; }

/* 拖动中：被拖的卡保持原样、浮在其它卡上面，整页光标变抓 */
.sorting { position: relative; z-index: 100; user-select: none; -webkit-user-select: none; }
body.sorting { cursor: grabbing; }

.counters { display: flex; gap: 10px; margin-top: 8px; }
.counter { flex: 1 1 0; display: flex; align-items: center; justify-content: space-between; gap: 2px; }
.counter-label { font-size: 11px; color: var(--text-2); flex: none; }
.counter-val { min-width: 18px; text-align: center; font-size: 13px; font-weight: 600; }
.counter-val.zero { color: var(--text-2); opacity: .55; }

/* −1 / +1：与 FlatButtonStyleRound6 同一观感（小、无边框、悬停才显底） */
.counter button {
  width: 26px;
  height: 22px;
  padding: 0;
  font-family: inherit;
  font-size: 10px;
  line-height: 1;
  color: var(--text-2);
  background: transparent;
  border: 0;
  border-radius: 6px;
}
.counter button:active { transform: none; }

/* ---- 路线管理：列表卡片 ---- */
.route-row {
  margin: 8px 14px 0;
  padding: 9px 12px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 8px;
}
/* 长按到位、现在可以拖了：卡片边框换成荧光蓝实线提示
   ★ 必须写在 .route-row / .farm-row 之后（它们用 border 简写会把边框色和线型重置回实线灰）；
   ★ 只改颜色、不动宽度和线型：边框本来就是 1px solid，换色 ⇒ 卡片尺寸、内容、相邻卡片位置都不变 */
.route-row.drag-armed, .farm-row.drag-armed {
  border-color: #00AEFF;
}

.route-top { position: relative; display: flex; align-items: center; gap: 6px; min-width: 0; }
.route-name {
  font-size: 13.5px;
  font-weight: 600;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.route-count { margin-left: auto; font-size: 11px; color: var(--text-2); flex: none; }

/* 卡片上的编辑 / 删除：照主程序 IconEditButtonStyle（铅笔 + 底下一条短横）/
   IconDeleteButtonStyle（垃圾桶）—— 16px 见方、无边框、悬停放大 1.15 倍 */
.icon-btn {
  flex: none;
  width: 22px;
  height: 22px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 0;
  border-radius: 5px;
  color: var(--text-2);
  transition: transform .12s ease, color .12s ease;
}
/* 全局 button:hover 会铺一层 --hover 底色（style.css 顶部的 button 规则），
   卡片上的图标按钮一律不要底色：静止 / 悬停 / 按下都保持透明 */
.icon-btn, .icon-btn:hover, .icon-btn:active { background: transparent; }
.icon-btn svg { width: 15px; height: 15px; display: block; }
.icon-btn.del { color: var(--bad); }
.icon-btn:active { transform: scale(1); }
/* 路线卡片的编辑按钮：静止偏淡（半透明没那么抢眼），可悬停设备上悬停恢复不透明 */
.icon-btn.edit { opacity: .4; transition: transform .12s ease, color .12s ease, opacity .12s ease; }
@media (hover: hover) {
  .icon-btn.edit:hover { opacity: 1; }
}
/* 路线卡片合并/展开按钮：绝对定位在排序手柄正下方，与手柄同一竖列。
   尺寸取 20×20（与手柄同宽）、图标 14px（与手柄同尺寸）⇒ 两者图标中心落在同一条竖线上；
   颜色与透明度固定成手柄的静止态（--text-2 + .55），悬停 / 按下都不改色、不铺底色。 */
.icon-btn.collapse {
  position: absolute;
  top: calc(100% + 10px);  /* 紧贴 route-top 下方、垂直居中于材料第一行（第一行中心距 route-top 底 20px，按钮 20 高 ⇒ 10px） */
  right: -5px;             /* 与手柄 margin-right:-5px 同理，右缘一起外溢 5px ⇒ 同一列、同一条竖线 */
  width: 20px;
  height: 20px;
  z-index: 5;
  color: var(--text-2);
  opacity: .55;
  background: transparent;
}
.icon-btn.collapse svg { width: 14px; height: 14px; }
/* 按下时不缩回：hover 已放大 1.15，若沿用全局 .icon-btn:active 的 scale(1)，
   点一下会「缩一下再弹回来」，就是肉眼可见的回弹。保持同一倍率即无回弹 */
.icon-btn.collapse:active { transform: scale(1.15); }
.icon-btn.collapse:active { color: var(--text-2); background: transparent; }
.icon-btn.collapse .chev { transition: transform .18s cubic-bezier(.215,.61,.355,1); }
.icon-btn.collapse:not(.collapsed) .chev { transform: rotate(180deg); }

/* 路线卡片的展开 / 合并内容：两块都常驻 DOM，切 .collapsed 时用 grid 行高 0fr ⇄ 1fr 过渡。
   用 grid 而不用 max-height —— max-height 是「数值」插值，上限（2000px）远大于真实高度，
   数值在过渡早期就冲过真实高度，观感是「弹一下就不动了」；0fr→1fr 插值的是真实高度，全程匀速顺滑。
   · .expanded-part = 每材料一行的数量明细      · .collapsed-part = 一行横排图标 */
.route-body { margin-top: 8px; }
.expanded-part, .collapsed-part {
  display: grid;
  grid-template-rows: 0fr;
  overflow: hidden;          /* 收到 0 时把内容裁干净（放在容器上，内层 .collapse-scroll 的横向滑动不受影响） */
  opacity: 0;
  /* 慢入慢出、无过冲的曲线：之前 cubic-bezier(0,0,.58,1) 起步极快、尾巴拖长，
     观感像「弹一下再停」；这里改成材质标准曲线，全程匀称。透明度与高度同时长，避免内容先闪出来 */
  transition: grid-template-rows .28s cubic-bezier(.4, 0, .2, 1), opacity .28s cubic-bezier(.4, 0, .2, 1);
}
/* 子项必须 min-height:0，grid 行高才压得到 0 */
.expanded-part > *, .collapsed-part > * { min-height: 0; }
.route-row:not(.collapsed) .expanded-part { grid-template-rows: 1fr; opacity: 1; }
.route-row:not(.collapsed) .collapsed-part { grid-template-rows: 0fr; opacity: 0; }
.route-row.collapsed .expanded-part { grid-template-rows: 0fr; opacity: 0; }
.route-row.collapsed .collapsed-part { grid-template-rows: 1fr; opacity: 1; }

/* 合并后的图标行：一行横排（每个材料取最高品质图标），放不下横向滑动（照每日锄地 .farm-mats）；
   右侧 28px 给合并按钮让位（只占水平空间，折叠时不影响高度） */
.collapsed-part { padding-right: 28px; }
.collapse-scroll {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 3px 0;            /* 上下 3px ⇒ 与普通单行 drop-row 同高，合并卡片高度不变 */
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.collapse-scroll::-webkit-scrollbar { display: none; }
.collapse-scroll .ci { width: 18px; height: 18px; flex: none; }

/* 掉落明细：一套材料一行 = 三档材料图标 + 每车期望数量（品质高的在左，同主程序卡片）
   同族的多个变体（大/小、丘丘暴徒+丘丘王…）在数据上合并成一行，所以行里只有图标和数字 */
.drop-rows { margin-top: 8px; }
.drop-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  align-items: center;
  gap: 6px;
  padding: 3px 28px 3px 0;    /* 右侧留 28px 给合并/展开按钮，所有行统一 ⇒ 材料列对齐不被挤歪 */
  font-size: 10.5px;
  color: var(--text-2);
}
.drop-row + .drop-row { border-top: 1px solid var(--border); }
/* 附带掉落（路线里没有怪把它当主材料）只把期望数字压淡，图标保持原样：
   一眼能看出这数量是别的怪顺带来的 */
.drop-row.extra .drop-cell b { opacity: .45; }
.drop-cell { display: flex; align-items: center; gap: 4px; min-width: 0; }
.drop-cell img { width: 18px; height: 18px; flex: none; }
.drop-cell b {
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* ---- 毕业期望：一行只留最高品质那一个图标（三档已折成同一份等效进度）；
        后面三列走 grid 定宽轨道 ⇒ 跨行同一列必然对齐：
        图标 ｜ 当前 X% ｜ 每车 +Y ｜ 剩余车数 N（三列都靠左，起始位置固定；
        末列用 minmax(0,1fr) 保证窄屏能压缩，但文字左对齐 ⇒ 起点始终固定） ---- */
.drop-row.grad {
  display: grid;
  grid-template-columns: auto 7.2em 7.8em minmax(0, 1fr);
  align-items: center;
  gap: 8px;
}
.drop-row.grad .drop-cell { gap: 0; }
.grad-num, .grad-per, .grad-trip {
  font-weight: 600;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.grad-num { color: var(--text); }
.grad-per { color: var(--text-2); }
.grad-trip { color: var(--text-2); }   /* 和「每车 +Y%」同一档次要色，不抢「当前X%」的主色 */
/* 附带掉落同样压淡（与掉落模式里 b 的 45% 一致） */
.drop-row.extra .grad-num,
.drop-row.extra .grad-per,
.drop-row.extra .grad-trip { opacity: .45; }

/* ---- 编辑路线（整页占用：列表整块让位，靠右上角「‹ 路线列表」回去） ---- */
/* 头部直接复用 .page-head（标题左、按钮右），窄屏的内边距也跟着一起走 */
.btn-back {
  height: 26px;
  padding: 0 10px;
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 6px;
}

.field { display: block; margin-top: 12px; }
.field-label { display: block; font-size: 11.5px; color: var(--text-2); margin-bottom: 5px; }

.field input[type="text"],
.field input[type="password"] {
  width: 100%;
  height: 30px;
  padding: 0 10px;
  font-family: inherit;
  font-size: 13px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
}

/* 路线名称 + 删除：删除固定在输入框右侧那一格，新建路线时隐藏 */
.name-row { display: flex; align-items: center; gap: 8px; }
.name-row input[type="text"] { flex: 1 1 auto; min-width: 0; }
.name-row .icon-btn { width: 30px; height: 30px; }

/* 编辑器里的一只怪：图标 + 三个等级数量 */
.mon-box {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 8px;
  margin-top: 6px;
  background: var(--bg);
  border-radius: 8px;
}
.mon-box img { width: 30px; height: 30px; flex: none; }
/* 怪物名 + 三个等级数量：名字一行、输入框一行，窄屏也不会把名字挤没 */
.mon-info { flex: 1 1 auto; min-width: 0; }
.mon-name {
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mon-lvs { display: flex; gap: 6px; margin-top: 4px; }
.mon-lv { display: flex; flex-direction: column; align-items: center; gap: 3px; }
.mon-lv span { font-size: 9.5px; color: var(--text-2); }
.mon-lv input {
  width: 48px;
  height: 24px;
  padding: 0 2px;
  text-align: center;
  font-family: inherit;
  font-size: 12px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 5px;
}
.mon-del {
  margin-left: auto;
  width: 24px;
  height: 24px;
  padding: 0;
  font-size: 12px;
  color: var(--text-2);
  background: transparent;
  border: 0;
  border-radius: 6px;
  flex: none;
}
.mon-del:active { transform: none; }

.btn-dashed {
  width: 100%;
  height: 30px;
  margin-top: 8px;
  font-family: inherit;
  font-size: 12px;
  color: var(--text-2);
  background: transparent;
  border: 1px dashed var(--border);
  border-radius: 8px;
}

.editor-actions { display: flex; gap: 8px; margin-top: 14px; }
.editor-actions button {
  flex: 1 1 0;
  height: 32px;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  border-radius: 7px;
  border: 1px solid var(--border);
}
.btn-primary { color: #fff; background: var(--accent); border-color: transparent; }
.btn-plain { color: var(--text-2); background: transparent; }
/* 编辑器「保存」：不用蓝底（中性卡底 + 正文色），只在新建路线时出现 */
.btn-save { color: var(--text); background: var(--card); }
/* 编辑器「删除路线」：和保存同款中性底，红色字（只在编辑已有路线时出现） */
.btn-del-route { color: var(--bad); background: var(--card); }

/* ---- 选材料面板 ---- */
.picker {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: flex;
  align-items: flex-end;
  background: rgba(0, 0, 0, .42);
}
.picker-panel {
  width: 100%;
  max-height: 72vh;
  display: flex;
  flex-direction: column;
  padding: 12px 14px 14px;
  background: var(--card);
  border-radius: 14px 14px 0 0;
}
.picker-close {
  width: 26px;
  height: 26px;
  padding: 0;
  font-size: 13px;
  color: var(--text-2);
  background: transparent;
  border: 0;
  border-radius: 6px;
}
.picker-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(46px, 1fr));
  gap: 6px;
  margin-top: 10px;
  overflow-y: auto;
}
.picker-cell {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 1px;
  padding: 4px 2px 3px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 8px;
}
.picker-cell { width: 100%; }
.picker-cell img { width: 34px; height: 34px; }
.picker-cell:active { transform: none; }
/* 图标底下这枚小字：这套材料现在的进度（与材料统计页同一口径） */
.pc-pct {
  font-size: 9px;
  line-height: 1;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* 这条路线里已经用到的材料：进度字改成强调蓝，回来加料时一眼能找到 */
.picker-cell.used .pc-pct { color: var(--accent); font-weight: 600; }

/* 第二步：掉这套材料的怪物（大/小、驮兽…各一枚胶囊） */
.picker-hint { margin-top: 10px; font-size: 11.5px; color: var(--text-2); }
.picker-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.chip-mon {
  padding: 5px 11px;
  font-family: inherit;
  font-size: 12px;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 12px;
}
.chip-mon:active { transform: none; }
/* 已选中：蓝底填充表示「这只已经在列表里」，再点一下取消 */
.chip-mon.on {
  color: #fff;
  background: var(--accent);
  border-color: transparent;
}

/* 面板底部两个动作按钮（同编辑器保存/取消那排的尺寸）
   两个都是中性底色；「添加其他材料」点不动的时候压成深一层的底，能点的时候与左边完全一致 */
.picker-actions { display: flex; gap: 8px; margin-top: 12px; }
.picker-actions button {
  flex: 1 1 0;
  height: 32px;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  border-radius: 7px;
  border: 1px solid var(--border);
}
.picker-actions .btn-plain:disabled {
  color: var(--text-2);
  background: var(--bg);
  border-color: var(--border);
}

/* ---- 清除数据弹窗：沿用选材料面板的遮罩 / 面板 / 底部按钮那排，只是居中不贴底 ---- */
.clear-dlg { align-items: center; justify-content: center; padding: 14px; }
.clear-panel { max-width: 340px; border-radius: 14px; }
/* 合成数量弹窗：与清除弹窗同一套面板（居中、同宽度、同一排底部按钮） */
.craft-dlg { align-items: center; justify-content: center; padding: 14px; }
.craft-dlg .field { margin-top: 10px; }
.craft-dlg .io-note { margin: 2px 0 0; }
.clear-opts { margin-top: 4px; }
.clear-opt {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 10px 0;
  font-size: 13px;
  border-bottom: 1px solid var(--border);
}
.clear-opt:last-of-type { border-bottom: 0; }
/* 复选框：不要实心填充块 —— 勾上之后框退掉，只留一个对号。
   对号取正文色（--text），浅色主题是深灰、深色主题是浅白，两边都清楚。 */
.clear-opt input[type="checkbox"],
.io-all input[type="checkbox"],
.io-rt input[type="checkbox"] {
  -webkit-appearance: none;
  appearance: none;
  position: relative;
  width: 16px;
  height: 16px;
  margin: 2px 0 0;
  flex: none;
  border: 1.3px solid var(--border-2);
  border-radius: 4px;
  background: none;
  cursor: pointer;
  transition: border-color .18s ease;
}
.clear-opt input[type="checkbox"]:hover,
.io-all input[type="checkbox"]:hover,
.io-rt input[type="checkbox"]:hover { border-color: var(--text-2); }
.clear-opt input[type="checkbox"]:checked,
.io-all input[type="checkbox"]:checked,
.io-rt input[type="checkbox"]:checked { border-color: transparent; }
.clear-opt input[type="checkbox"]::after,
.io-all input[type="checkbox"]::after,
.io-rt input[type="checkbox"]::after {
  content: "";
  position: absolute;
  left: 4.9px;
  top: 1.5px;
  width: 4.6px;
  height: 9px;
  border: solid var(--text);
  border-width: 0 1.8px 1.8px 0;
  opacity: 0;
  transform: rotate(42deg) scale(.35);
  transform-origin: 50% 55%;
  transition: opacity .16s ease, transform .2s cubic-bezier(.2, .9, .3, 1);
  pointer-events: none;
}
.clear-opt input[type="checkbox"]:checked::after,
.io-all input[type="checkbox"]:checked::after,
.io-rt input[type="checkbox"]:checked::after {
  opacity: 1;
  transform: rotate(42deg) scale(1);
}
.clear-opt input[type="checkbox"]:focus-visible,
.io-all input[type="checkbox"]:focus-visible,
.io-rt input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--accent-soft);
  outline-offset: 2px;
}
.clear-opt > span { flex: 1 1 auto; min-width: 0; }
.clear-opt em {
  display: block;
  margin-top: 2px;
  font-size: 11px;
  font-style: normal;
  line-height: 1.45;
  color: var(--text-2);
}
/* 确定清除：与「删除路线」同一套中性底 + 红字；一个分类都没勾时压灰、点不动 */
.clear-panel .btn-danger { color: var(--bad); background: var(--card); }
.clear-panel .btn-danger:disabled {
  color: var(--text-2);
  background: var(--bg);
  border-color: var(--border);
}

/* ---- 分析总结 ---- */
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; margin-top: 16px; }
.stat-num { font-size: 24px; font-weight: 700; line-height: 1.1; }
.stat-label { margin-top: 3px; font-size: 11px; color: var(--text-2); }

.split { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 16px; }
.split-item { padding: 10px 12px; background: var(--hover); border-radius: 9px; }
.split-label { font-size: 12px; color: var(--text-2); }
.split-num { display: flex; align-items: baseline; gap: 1px; margin-top: 3px; white-space: nowrap; }
.split-num b { font-size: 18px; font-weight: 700; }
.split-num span { font-size: 12px; color: var(--text-2); }
/* 完成度贴在「进度条右上方」：跟在数字行末尾、靠右 */
.split-num .split-pct { margin-left: auto; padding-left: 6px; font-size: 11px; }
.split-item.elite .split-num b { color: #A055DE; }
.split-item.mob .split-num b { color: #4E7EC9; }
.split-item .bar { margin-top: 8px; }

.ana-row:last-child { border-bottom: 0; }
/* 中间的这条路线产出的材料图标：沿用每日锄地那套（图标 + 进度小字），多了可以横向滑 */
.ana-num { margin-left: auto; font-size: 11.5px; color: var(--text-2); flex: none; white-space: nowrap; }

/* 材料变化：直接照搬「材料统计」那一行 —— 三档图标 + 数量 + 增减小字 + 进度条 + 右侧百分比，
   ★ 唯一区别是数量只读（分析页不能改），左侧本来就没有怪物名。
   行本身与材料统计共用 .fam，间距/留白由上面的 #ana-mats 统一管，这里不再单独压行内边距 */
/* 头部左侧：标题 + 对比口径小字（同一行、基线对齐） */
.ana-head-l .muted { font-size: 11px; font-weight: 400; }
/* 头部右侧：增减对比 / 亏损对比 二选一 —— 复用排序条 .sort-opt 的外观
   （左侧竖杠选中指示 + 选中段 accent-soft 高亮，无连体轨道，和「升序/降序」「砂糖/多莉」一致） */
.ana-mode-btn {
  position: relative;
  height: 24px;
  padding: 0 10px 0 11px;      /* 左边 11：给左竖杠留位置，与 .sort-opt 对齐 */
  margin-right: 4px;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 700;           /* 默认粗体：选中与否都粗，区分只靠蓝底和左竖杠 */
  color: var(--text-2);
  background: transparent;
  border: 0;
  border-radius: 4px;          /* CornerRadius=4，同 .sort-opt */
  cursor: pointer;
  white-space: nowrap;         /* 按钮文字永不换行（窄屏靠压 padding 保一行） */
  -webkit-tap-highlight-color: transparent;
}
@media (hover: hover) {
}
.ana-mode-btn.on::before { opacity: 1; transform: scaleY(1); }



/* 账号卡片标题行：左边昵称（太长省略），右边 UID */
.acc-nick {
  min-width: 0;
  font-size: 14px;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---- 导入 / 导出 ----
   两块：材料数量（一键带走）、路线（勾选哪几条走）。
   载体二选一：短码 / JSON 文件，按钮沿用排序按钮那套外观。 */
.io-fmt { display: flex; align-items: center; gap: 6px; margin: 10px 0 0; }

.io-block { margin-top: 14px; }
.io-block-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.io-title { font-size: 12.5px; color: var(--text-2); }

/* 账号同步状态：一行一条，左标签右数值 */
.sync-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: 6px;
  font-size: 11.5px;
}

/* 改密码：展开在原卡片里，和上面几段同一套留白 */
.acc-pass-box { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }

/* 导出按钮：虚线 + 透明底 + 灰字太弱，几乎看不出是按钮；
   这里改成实线描边 + 浅底 + 正文色，保持中性配色，不引入语义色 */
.io-block .btn-dashed {
  color: var(--text);
  background: var(--track);
  border: 1px solid var(--border-2);
}
.io-block .btn-dashed:active { filter: brightness(.96); }

/* 全选：复选框 + 小字，整块可点 */
.io-all { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--text-2); }
.io-all input { margin: 0; }

/* 一条路线：勾选框 + 名字 + 右侧「N 只/车」 */
.io-rt {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 0;
  font-size: 13px;
  border-bottom: 1px solid var(--border);
}
.io-rt:last-of-type { border-bottom: 0; }
.io-rt-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.io-rt-num { flex: none; font-size: 11px; color: var(--text-2); }

/* 短码 / 粘贴框：等宽字体，长串能整段看到、能选中复制 */
#io-out,
#io-in {
  width: 100%;
  padding: 8px 10px;
  font-family: ui-monospace, Consolas, "Courier New", monospace;
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 7px;
  resize: vertical;
  word-break: break-all;
}
#io-out { color: var(--text-2); }

.io-note { margin-top: 10px; font-size: 11px; line-height: 1.5; color: var(--text-2); }

/* 空状态：还没建路线 / 今天还没打 */
.empty-tip {
  margin: 10px 14px 0;
  padding: 26px 14px;
  text-align: center;
  font-size: 12.5px;
  color: var(--text-2);
  background: var(--card);
  border: 1px dashed var(--border);
  border-radius: 10px;
}

/* 窄屏：整行仍然不换行（进度条照旧跟在第三个输入框后面），只把各元素同步收窄 */
@media (max-width: 480px) {
  main { padding: 0 0 20px; }
  .ana-head { padding: 14px 14px 2px; }
  /* 排序条与列表的左右边距对齐导航按钮的内容边距（顶栏 4px + 导航按钮左内边距 3px = 7px），留一点不贴边 */
  #list { padding: 4px 7px 6px; }
  .page > .sort-bar { padding: 8px 7px 6px; }
  /* 顶栏：四个导航按钮在 320px 上也要一行放完，字号与留白一起压一档 */
  .topbar { padding: 3px 4px; }
  .nav-item { font-size: 11px; gap: 2px; padding: 5px 1px 4px 3px; }
  .nav-icon { width: 17px; height: 17px; }
  /* 排序按钮：字号与留白一起压紧 */
  .sort-bar { flex-wrap: nowrap; }
  /* 材料统计那排按钮：永远一行不换行（含展开的砂糖/多莉）；
     间距始终用紧凑档（不随合成展开切换，避免展开瞬间按钮收紧的顿挫感） */
  #sort-bar { flex-wrap: nowrap; }
  .sort-grp { flex-wrap: nowrap; }
  /* 排序按钮：内边距随屏宽自适应 —— 把三组铺开后剩下的横向余量几乎吃干净（留 ~10px 防换行）。
     先给一条固定紧凑值兜底：部分手机浏览器内核（如 QQ 浏览器用的 X5）不支持 clamp()/calc(vw)，
     整条自适应 padding 会被丢掉、退回桌面档 21px 内边距 ⇒ 一行放不下，「降序」和「隐藏毕业」挤到重叠 */
  .sort-opt {
    font-size: 12px;
    margin-right: 0;
    padding: 0 6px 0 7px;
  }
  .sort-opt {
    padding: 0 clamp(3px, calc(7.14vw - 18px), 11px) 0 clamp(4px, calc(7.14vw - 17px), 12px);
  }
  .sep { margin: 0 1px; }
  /* 路线管理页头：两组切换 + 添加路线要挤在一行，添加按钮也压一档 */
  .route-head { padding: 8px 8px 9px; }
  .route-head .btn-add, .route-head .btn-back { height: 24px; padding: 0 7px; font-size: 11px; }
  .fam { gap: 1px; padding: 6px 3px; }
  .tier { gap: 0; }
  .tier img { width: 32px; height: 32px; }
  /* 输入框收窄 + 字号再小一档：右边留给进度条的宽度从 ~30px 提到 ~90px */
  .qbox { margin-right: 0; }
  .tier input[type="number"] { width: 34px; padding: 0 1px; font-size: 11px; }
  /* 合成展开三行：列宽与主行 .tier 对齐（28 图标 + 34 输入框、fam gap 1px、tier gap 0） */
  .crow { height: 15px; }
  .ccol { margin-right: 1px; gap: 0; }
  .clabel, .cskip { width: 32px; }
  .cnum, .cskip2 { width: 34px; }
  .cnum { font-size: 11px; }
  .craft-in { padding: 0 3px; }
  /* 分析页的只读数字跟着输入框同宽同字号 ⇒ 两页的进度条等宽 */
  .bar { flex: 1 1 30px; min-width: 30px; }
  .pct { width: 50px; font-size: 11px; padding: 0 2px; }
  .dp { width: 50px; padding: 0 2px; }
  /* 卡片与行也跟着往两边各收 4px，和材料列表左右对齐 */
  .card, .farm-row, .route-row, .empty-tip { margin-left: 10px; margin-right: 10px; }
  .page-head { padding: 10px 10px 2px; }
  .stats { gap: 4px; }
  .stat-num { font-size: 20px; }
  .stat-label { font-size: 10px; }
  .split { gap: 8px; }
  .split-item { padding: 9px 10px; }
  .counter { gap: 0; }
  .counter-label { font-size: 10px; }
  .counter button { width: 24px; }
  .mon-lv input { width: 44px; }
}

/* 五档等级输入框在 320~359 的窄屏上再收一档，别把这一行撑出卡片
   （放在 480 断点之后：同权重靠源顺序生效） */
/* 更窄的屏幕（≤359px）排序按钮再收一档内边距，保证三个组 + 砂糖/多莉仍在一行
   （放在 480 断点之后：同权重靠源顺序生效） */
@media (max-width: 359px) {
  .mon-lvs { gap: 4px; }
  .mon-lv input { width: 40px; }
}

/* 481~560：夹在移动端（≤480）与桌面（≥760）之间的窄窗口 / 手机横屏 ——
   这一档走的是桌面样式，但 8 个按钮按桌面档内边距要 509px（再加两侧留白），放不下会溢出；
   收一档内边距与字号就够，760 以上的正常桌面不受影响 */
@media (min-width: 481px) and (max-width: 560px) {
  .page > .sort-bar { padding: 10px 10px 6px; }
  #sort-bar .sort-opt { font-size: 12px; padding: 0 7px 0 8px; }
  #sort-bar .sep { margin: 0 6px 0 4px; }
}

/* ================= 桌面端适配（≥760px 宽窗口 / 电脑浏览器） =================
   移动端布局原样保留；桌面上只做三件事：
   1. 内容整体限宽居中（880px），不再铺满整屏把按钮和文字拉散；
   2. 顶部导航从「等分铺满 + 图标文字竖排」改为「宽度自适应居中 + 横排」；
   3. 计数器一行、悬浮按钮等贴边元素跟随内容宽度，不贴屏幕边缘。 */
@media (min-width: 760px) {
  /* 导航：居中收拢，图标与文字同一行 */
  .topbar { padding: 5px 10px; }
  .topbar .nav {
    max-width: 860px;
    margin: 0 auto;
    justify-content: center;
    gap: 4px;
  }
  .nav-item {
    flex: 0 0 auto;
    flex-direction: row;
    justify-content: center;
    gap: 9px;
    /* 四项文字都是 4 个字，锁定同宽：选中时加粗不再把邻居推开（点一下整排会「抖」一下的原因） */
    min-width: 168px;
    padding: 10px 18px 10px 21px;   /* 左多 3px：给选中竖杠留位 */
    font-size: 14.5px;
  }
  .nav-icon { width: 19px; height: 19px; }
  .nav-item::before { height: 17px; margin-top: -8.5px; }

  /* 鼠标点击不放大：按钮一按体积就变、看着像整排在抖（移动端触屏保留这个反馈） */
  button:active { transform: none; }

  /* 各页内容长短不同，竖向滚动条会忽有忽无：视口一窄 15px，居中的导航就整体挪几像素。
     常驻预留滚动条槽位，切页时宽度恒定（材料统计页最长，这条主要是为它加的） */
  html { scrollbar-gutter: stable; }

  /* 内容整体限宽：所有卡片 / 列表 / 编辑器跟着居中 */
  main { max-width: 880px; margin: 0 auto; }

  /* 每日锄地：三个计数器在宽卡里会被拉得很开，限个顺眼的宽度 */
  .counters { max-width: 520px; }

  /* 右下角悬浮按钮（回到材料页顶部之类）跟内容右缘对齐，不贴屏幕边 */
  .chip { right: max(14px, calc(50% - 440px + 14px)); }

  /* 选怪面板：手机上是贴底弹层，桌面上改成居中弹窗 */
  .picker { align-items: center; justify-content: center; padding: 20px; }
  .picker-panel {
    width: 560px;            /* flex 子项里 width:100% 会缩到内容宽，桌面给固定宽 */
    max-width: 100%;
    max-height: 78vh;
    border-radius: 12px;
    border: 1px solid var(--border);
  }

  /* ---- 桌面屏大，控件与字号整体放大一档（移动端尺寸一点不动） ---- */
  body { font-size: 15px; }

  .page-head { padding: 18px 20px 6px; }
  .page-title { font-size: 16px; }
  .btn-add, .btn-back { height: 36px; padding: 0 16px; font-size: 15px; }

  .card { margin: 16px 20px 0; padding: 18px 20px 20px; border-radius: 16px; }
  .route-head { padding: 14px 18px 12px; }
  .card-head { font-size: 18.5px; }
  .muted { font-size: 13.5px; }
  .pv-name, .pv-num { font-size: 16px; }

  .farm-row, .route-row, .empty-tip { margin: 14px 20px 0; }
  .farm-row, .route-row { padding: 16px 18px 18px; border-radius: 14px; }
  .farm-name, .route-name { font-size: 18.5px; }
  .route-count { font-size: 14px; }
  .farm-mats img { width: 32px; height: 32px; }
  .drop-rows { margin-top: 12px; }
  .drop-row { font-size: 14.5px; gap: 11px; padding: 7px 28px 7px 0; }
  /* 桌面屏够宽：展开行 = 左三列「每车材料」+ 右三列「当前 / 每车 / 剩余车数」同排，
     六条等宽轨道 ⇒ 跨行每一列都对齐（手机上没有 .both，仍是两种口径二选一） */
  .drop-row.both { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  /* 两种口径桌面同排常驻 ⇒ 「每车材料 / 剩余车数」切换删掉，砂糖 / 多莉改为常驻 */
  #exp-mode [data-exp], #exp-mode-ed [data-exp] { display: none; }
  #exp-mode .who-set, #exp-mode-ed .who-set { max-width: 190px; opacity: 1; transition: none; }
  #exp-mode .who-set .sep, #exp-mode-ed .who-set .sep { display: none; }
  /* 「当前进度」与「每车 / 剩余车数」同色：右边三列整体是毕业区，与左边每车材料区分开 */
  .drop-row.both .grad-num { color: var(--text-2); }
  .route-body { margin-top: 12px; }
  .collapse-scroll { padding: 7px 0; }
  .icon-btn.collapse { width: 28px; height: 28px; top: calc(100% + 22px); }   /* 跟手柄同尺寸（28×28），垂直居中于更高的材料第一行（12 + 48/2 - 14 = 22） */
  .icon-btn.collapse svg { width: 21px; height: 21px; }
  /* 毕业期望这三列是辅助信息，桌面不跟着材料行一起放大，也不加粗 */
  .grad-num, .grad-per, .grad-trip { font-size: 12.5px; font-weight: 400; }
  /* 期望数量同理：桌面不要 600 的粗体 */
  .drop-cell b { font-weight: 400; }
  .drop-cell { gap: 9px; }
  .drop-cell img { width: 34px; height: 34px; }
  .collapse-scroll .ci { width: 34px; height: 34px; }
  .icon-btn { width: 32px; height: 32px; }
  .icon-btn svg { width: 21px; height: 21px; }
  .sort-handle { width: 28px; height: 28px; }
  .sort-ico { width: 21px; height: 21px; }

  .counters { gap: 18px; margin-top: 14px; }
  .counter-label { font-size: 14.5px; }
  .counter-val { font-size: 19px; min-width: 26px; }
  .counter button { width: 42px; height: 34px; font-size: 14px; }

  /* 材料统计：图标、输入框、进度条、百分比一起放大，进度条仍然吃掉剩余宽度
     顶部内边距压到 6px：排序条自身已有 8px 下内边距，再叠 18px 会在按钮下面空出一条明显的空行 */
  #list { padding: 6px 28px 3px; font-size: 16px; }
  .page > .sort-bar { padding: 12px 16px 8px; }
  .sort-opt { height: 28px; padding: 0 12px 0 13px; font-size: 13.5px; }
  .sep { height: 16px; }
  .fam { gap: 6px; padding: 8px 8px; }
  .tier { gap: 2px; }
  .tier img { width: 56px; height: 56px; }
  .tier input[type="number"] { width: 54px; font-size: 13px; padding: 4px 4px; }
  /* 合成展开三行（桌面）：列宽 56 图标 + 54 输入框、tier gap 2px、fam gap 6px */
  .ccol { margin-right: 6px; gap: 2px; }
  .clabel, .cskip { width: 56px; }
  .clabel { font-size: 11px; }
  .cnum, .cskip2 { width: 54px; }
  .cnum { font-size: 13px; }
  .crow { height: 20px; }
  .craft-in { padding: 0 8px; }
  .dl { font-size: 10px; height: 12px; line-height: 12px; }
  .pct { width: 64px; font-size: 13px; }
  .dp { width: 64px; height: 12px; line-height: 12px; font-size: 10px; }

  /* 进度条不跟着放大：桌面屏大也保持基础粗细，太粗反而显笨（移动端同款 6px） */
  .bar, .bar.big { height: 6px; }

  /* 编辑路线 */
  .field { margin-top: 16px; }
  .field-label { font-size: 13.5px; margin-bottom: 6px; }
  .field input[type="text"],
  .field input[type="password"] { height: 38px; font-size: 15px; }
  .name-row .icon-btn { width: 38px; height: 38px; }
  .mon-box { padding: 12px 12px; gap: 10px; border-radius: 10px; }
  .mon-box img { width: 38px; height: 38px; }
  .mon-name { font-size: 14px; }
  .mon-lvs { gap: 8px; margin-top: 6px; }
  .mon-lv span { font-size: 11.5px; }
  .mon-lv input { width: 52px; height: 32px; font-size: 14px; }
  .mon-del { width: 32px; height: 32px; font-size: 15px; }
  .btn-dashed { height: 38px; font-size: 14px; }
  .editor-actions button, .picker-actions button { height: 40px; font-size: 15px; }

  /* 选怪面板 */
  .picker-panel { padding: 16px 18px 18px; }
  .picker-grid { grid-template-columns: repeat(auto-fill, minmax(54px, 1fr)); gap: 8px; }
  .picker-cell img { width: 38px; height: 38px; }
  .picker-close { width: 30px; height: 30px; font-size: 15px; }

  /* 分析总结 */
  .stat-num { font-size: 32px; }
  .stat-label { font-size: 13px; }
  .split-item { padding: 14px 16px; }
  .split-label { font-size: 13px; }
  .split-num .split-pct { font-size: 12.5px; }
  .split-num b { font-size: 23px; }
  .split-num span { font-size: 14px; }
  .ana-row { font-size: 15.5px; padding: 11px 0; }
  #ana-mats .qv { width: 58px; padding: 5px 6px; font-size: 13px; }

  /* 拖动排序的自动滚动按窗口算的，桌面窗口高，滚动速度也按原逻辑走，无需改 */
}

/* ================= 出现过渡 =================
   导航切页时内容区平滑淡入、材料统计切排序时列表轻淡入，
   均改用 Web Animations API 在 js/app.js 内播放（第一帧即透明、无中间态不闪烁，
   且无需强制回流，移动端大列表不卡）。prefers-reduced-motion 也在 JS 内判断关闭。 */



/* ================= 触屏彻底关闭悬停 =================
/* 触屏内核点完按钮 :hover 会一直粘着不消失（浅色底看着像变白，点别处才恢复），
   所有悬停效果一律只给真有鼠标的设备：触屏下不匹配任何 hover 规则，
   按钮/输入框/卡片在触屏上永远保持静止态外观 */
@media (hover: hover) {
  .nav-item:disabled:hover { background: transparent; color: var(--text-2); }
  .nav-item.on:hover { background: var(--accent-soft); }
  .sort-opt.on:hover { background: var(--accent-soft); }
  .tier input[type="number"]:hover {
    background: var(--hover);
    border-color: var(--border);
  }
  .chip:hover { background: var(--bar-a); }
  .day-arrow:hover:not(:disabled) { background: var(--hover); color: var(--text); }
  .cal-day:hover:not(:disabled) { background: var(--hover); }
  .btn-add:hover { background: var(--hover); }
  .farm-row.farm-hint:hover { background: var(--hover); color: var(--text); }
  .farm-move:disabled:hover { background: transparent; color: var(--text-2); }
  .counter button:hover { background: var(--hover); color: var(--text); }
  .icon-btn:hover { transform: scale(1.15); color: var(--text); }
  .icon-btn.del:hover { color: var(--bad); }
  .icon-btn.collapse:hover { transform: scale(1.15); }
  .icon-btn.collapse:hover,
  .btn-back:hover { background: var(--hover); color: var(--text); }
  .mon-del:hover { background: var(--hover); color: var(--bad); }
  .btn-dashed:hover { background: var(--hover); color: var(--text); }
  .btn-primary:hover { background: var(--accent); filter: brightness(1.06); }
  .btn-plain:hover { background: var(--hover); color: var(--text); }
  .btn-save:hover { background: var(--hover); }
  .btn-del-route:hover { background: var(--hover); }
  .picker-cell:hover { background: var(--hover); border-color: var(--border); }
  .chip-mon:hover { border-color: var(--accent); color: var(--accent); }
  .ana-mode-btn.on:hover { background: var(--accent-soft); }
  .io-block .btn-dashed:hover { border-color: var(--text-2); }
}
/* ================= 触屏悬停硬关闭（JS 检测打标 html.touch） ================= */
/* QQ 浏览器等触屏内核无视 hover 媒体查询：点完按钮 :hover 一直粘着不消失，
   浅色的悬停底色看着就像「变白、点别处才恢复」。不赌浏览器的标准行为，
   JS 检测到触屏后直接把悬停底色钉回各自的静止值（触屏上 hover 常驻 ⇒ 等效于悬停不存在）。
   豁免：自带非透明静止底色的按钮（蓝主按钮/保存/删除路线/悬浮chip）钉回自身底色；
   选中态(.on)的底色是选中样式，不受影响。字色的轻微粘滞不在此处理 */
html.touch button:not(.on):not(.btn-primary):not(.btn-save):not(.btn-del-route):not(.chip):hover {
  background: transparent;
}
html.touch .btn-primary:hover { background: var(--accent); }
html.touch .btn-save:hover { background: var(--card); }
html.touch .btn-del-route:hover { background: var(--card); }
html.touch .chip:hover { background: var(--bar-b); }
html.touch button:hover { transform: none; }

/* ================= 暗月计算器（完整嵌入原作者页面） =================
   顶栏吸顶（sticky），iframe 填满剩下的视口高度，滚动交给暗月自己内部处理，
   边框由顶栏的 border-bottom 承担，不再额外画线。dvh 在地址栏收放时也撑满。 */
.darkmoon-frame {
  display: block;
  width: 100%;
  height: calc(100dvh - 55px);   /* 顶栏实测高：窄屏 55px（含 1px 下边框） */
  border: 0;
  /* 透明：页面底色只有 html::before 那一层（暗月的文档也不画自己的底色），
     iframe 里的控件直接落在这层背景上 —— 从视口最底到内容区是同一个背景面 */
  background: transparent;
  /* ★ 关键：宿主声明了 color-scheme: light dark（见 index.html 的 meta 与 :root），
     这个值会传播进 iframe，浏览器于是给 iframe 铺一块**不透明的 UA 底色**（白），
     暗月文档里再怎么写 background: transparent 都没用（实测：摘掉它全部样式表仍是纯白）。
     把 iframe 的 color-scheme 显式收窄成 light only，它就恢复真透明、直接透出宿主那层底色。
     暗月内部的下拉/输入框自己有 color-scheme: dark，不受影响。 */
  color-scheme: light only;
  /* 暗月里是渐进渲染（骨架 → 图标数字 → 主题），先整块藏着，
     等主题/列表/图标都就位再一次放出来（app.js 加 .dm-ready，另有 6s 兜底） */
  opacity: 0;
}

.darkmoon-frame.dm-ready { opacity: 1; }

@supports not (height: 100dvh) {
  .darkmoon-frame { height: calc(100vh - 55px); }
}

@media (min-width: 760px) {
  /* 桌面档顶栏变成横排图标+文字，实测高 50px */
  .darkmoon-frame { height: calc(100dvh - 50px); }
  @supports not (height: 100dvh) {
    .darkmoon-frame { height: calc(100vh - 50px); }
  }
}

/* 页面显隐只认 hidden 属性：任何给 section 写的 display 都不能把它顶掉 */
.page[hidden] { display: none !important; }

/* 停在暗月计算器页时，整页背景切成暗月那套浅色（它固定浅色主题），
   否则桌面端两侧会露出宿主的深色底，只剩中间一小块是亮的 */
/* 停在暗月计算器页时整页底色切成 #fff / #151a21（规则在文件头部 html:has(body.dm-view)::before，
   和通用底色同一个 fixed 层，切主题时一起渐变）。body 与 iframe 都保持透明 ——
   任何一处再铺底色，就会多出一层「内容区背景」，和整页背景各变各的。 */
/* 暗月页由 iframe 自己铺满，main 的 24px 下内边距会变成底部一条空白 */
body.dm-view main { padding-bottom: 0; }

/* 暗月页入场（与材料列表 flashList 同参数）：iframe 元素上的 CSS 动画由父页面合成器驱动，
   比 WAAPI 更稳（WAAPI 在部分环境下与 iframe 合成层配合会不推进） */
@keyframes dm-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.darkmoon-frame.dm-in { animation: dm-in 240ms cubic-bezier(.22, .61, .36, 1); }

/* 暗月导航按钮用绮良良表情图代替月亮矢量图（原图 340×340 透明底，按图标尺寸等比缩放） */
.nav-img { object-fit: contain; }

/* === DESKTOP-SIDEBAR-START ===
   宽屏桌面：左侧固定导航区 + 右侧铺满的内容区。
   只在 >=1100px 生效，760~1099px 仍用上面的居中桌面档，<=760px 完全保持移动端布局。
   这一段同时被单文件版 dist/MaterialCalc.html 内联，两份必须同步。 */
@media (min-width: 1100px) {
  /* 细滚动条：系统默认的纯黑条在浅色页上太扎眼，深色页上也会亮成一条白杠。
     用正文色压到低透明度、槽位透明；深浅两套同一观感，不做 hover 变色。 */
  :root { --sb-thumb: rgba(31, 36, 48, .20); }
  html[data-theme="dark"] { --sb-thumb: rgba(228, 232, 238, .20); }
  html, #route-list, #rt-preview, #rt-monsters {
    scrollbar-color: var(--sb-thumb) transparent;
    scrollbar-width: thin;
  }
  ::-webkit-scrollbar { width: 8px; height: 8px; }
  ::-webkit-scrollbar-track { background: transparent; }
  ::-webkit-scrollbar-thumb {
    background: var(--sb-thumb);
    border: 2px solid transparent;
    background-clip: padding-box;
    border-radius: 8px;
  }

  /* ---- 左侧导航 ---- */
  .topbar {
    position: fixed;
    left: 0;
    top: 0;
    bottom: 0;
    width: 208px;
    height: 100dvh;
    padding: 0 12px 20px;
    background: var(--card);
    border-right: 1px solid var(--border);
    border-bottom: 0;
    overflow-y: auto;
  }
  .topbar::before {
    content: "Just 锄 it";
    display: block;
    padding: 26px 12px 20px;
    margin-bottom: 14px;
    border-bottom: 1px solid var(--border);
    font-size: 21px;
    font-weight: 700;
    line-height: 1.25;
    letter-spacing: .4px;
    color: var(--text);
  }
  .topbar {
    display: flex;
    flex-direction: column;
  }
  .topbar .nav {
    flex: 1 1 auto;
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
    max-width: none;
    margin: 0;
    justify-content: flex-start;
  }
  /* 云端同步钉在侧栏最底部 */
  .nav-item[data-page="account"] { margin-top: auto; }
  .nav-item {
    width: 100%;
    min-width: 0;
    justify-content: flex-start;
    gap: 14px;
    padding: 14px 14px 14px 20px;
    font-size: 16.5px;
    border-radius: 10px;
  }
  .nav-icon { width: 22px; height: 22px; }
  .nav-item::before { height: 26px; margin-top: -13px; left: 6px; }

  /* ---- 右侧内容区：吃掉侧栏以外的全部宽度 ---- */
  main {
    max-width: none;
    margin: 0 0 0 208px;
    padding: 0 clamp(28px, 3vw, 56px) 40px;
  }
  /* 内容区统一由 main 的左右内边距控边，卡片/列表不再各自叠一份留白 */
  .card, .farm-row, .route-row, .empty-tip { margin-left: 0; margin-right: 0; }
  #list { padding-left: 0; padding-right: 0; }
  .page > .sort-bar { padding-left: 0; padding-right: 0; }
  .chip { right: 28px; }

  /* ---- 桌面宽屏整体放大一档：字体、图标、输入框、按钮 ---- */
  body { font-size: 17px; }
  .card { margin-top: 20px; padding: 22px 26px 24px; border-radius: 18px; }
  .route-head { padding: 18px 22px 16px; }
  .card-head { font-size: 21px; }
  .muted { font-size: 15px; }
  .page-head { padding: 22px 0 8px; }
  .page-title { font-size: 18px; }
  .pv-name, .pv-num { font-size: 18px; }
  .farm-name, .route-name { font-size: 21px; }
  .route-count { font-size: 15.5px; }
  .farm-row, .route-row { padding: 20px 22px 22px; border-radius: 16px; }
  .farm-mats img { width: 36px; height: 36px; }
  .drop-rows { margin-top: 16px; }
  .drop-row { font-size: 16px; gap: 14px; padding: 9px 32px 9px 0; }
  .drop-cell { gap: 12px; }
  .drop-cell img { width: 40px; height: 40px; }
  .collapse-scroll .ci { width: 40px; height: 40px; }
  .icon-btn { width: 36px; height: 36px; }
  .icon-btn svg { width: 24px; height: 24px; }
  .icon-btn.collapse { width: 32px; height: 32px; top: calc(100% + 27px); }
  .icon-btn.collapse svg { width: 24px; height: 24px; }
  .sort-handle { width: 32px; height: 32px; }
  .sort-ico { width: 24px; height: 24px; }
  .grad-num, .grad-per, .grad-trip { font-size: 14px; }

  .counters { gap: 22px; margin-top: 18px; max-width: 640px; }
  .counter-label { font-size: 16px; }
  .counter-val { font-size: 22px; min-width: 30px; }
  .counter button { width: 48px; height: 38px; font-size: 16px; }

  .page > .sort-bar { padding-top: 16px; padding-bottom: 10px; }
  .sort-opt { height: 36px; padding: 0 16px 0 17px; font-size: 15.5px; }
  .sep { height: 20px; }
  .btn-add, .btn-back { height: 44px; padding: 0 20px; font-size: 16.5px; }

  #list { padding-top: 10px; font-size: 18px; }
  .fam { gap: 8px; padding: 10px 10px; }
  .tier { gap: 4px; }
  .tier img { width: 68px; height: 68px; }
  .tier input[type="number"] { width: 64px; font-size: 15px; padding: 5px 4px; }
  .ccol { margin-right: 8px; gap: 4px; }
  .clabel, .cskip { width: 68px; }
  .clabel { font-size: 12.5px; }
  .cnum, .cskip2 { width: 64px; }
  .cnum { font-size: 15px; }
  .crow { height: 24px; }
  .craft-in { padding: 0 10px; }
  .craft-do { height: 26px; font-size: 13px; padding: 0 11px; }
  .dl { font-size: 11px; height: 14px; line-height: 14px; }
  .pct { width: 78px; font-size: 15px; }
  .dp { width: 78px; height: 14px; line-height: 14px; font-size: 11px; }
  .bar, .bar.big { height: 8px; min-width: 80px; }

  .field { margin-top: 20px; }
  .field-label { font-size: 15.5px; margin-bottom: 8px; }
  .field input[type="text"],
  .field input[type="password"],
  .field textarea,
  textarea { height: auto; min-height: 46px; font-size: 17px; }
  .name-row .icon-btn { width: 44px; height: 44px; }
  .mon-box { padding: 16px 16px; gap: 12px; border-radius: 12px; }
  .mon-box img { width: 44px; height: 44px; }
  .mon-name { font-size: 16px; }
  .mon-lvs { gap: 10px; margin-top: 8px; }
  .mon-lv span { font-size: 13px; }
  .mon-lv input { width: 58px; height: 36px; font-size: 16px; }
  .mon-del { width: 36px; height: 36px; font-size: 17px; }
  .btn-dashed { height: 44px; font-size: 16px; }
  .editor-actions button, .picker-actions button { height: 46px; font-size: 16.5px; }
  .io-note { font-size: 14px; }
  .io-title { font-size: 17px; }
  .acc-nick { font-size: 19px; }
  input[type="checkbox"] { width: 18px; height: 18px; }

  .picker-panel { width: 680px; padding: 22px 26px 26px; }
  .picker-grid { grid-template-columns: repeat(auto-fill, minmax(64px, 1fr)); gap: 10px; }
  .picker-cell img { width: 44px; height: 44px; }
  .picker-close { width: 34px; height: 34px; font-size: 17px; }
  .picker-hint { font-size: 14px; }
  .clear-opt > span { font-size: 17px; }
  .clear-opt em { font-size: 14px; }

  .stat-num { font-size: 36px; }
  .stat-label { font-size: 15px; }
  .split-item { padding: 18px 20px; }
  .split-label { font-size: 15px; }
  .split-num b { font-size: 26px; }
  .split-num span, .split-num .split-pct { font-size: 15px; }
  .ana-row { font-size: 17px; padding: 13px 0; }
  #ana-mats .qv { width: 68px; padding: 6px 8px; font-size: 15px; }

  /* ---- 路线配置：左列路线名导航 + 右列这条路线详情 ----
     三列（路线名 / 怪物配置 / 掉落信息）统一 20px 间隔、顶端对齐，
     每条列表按内容占高，内容多了才各自滚动。 */
  #page-route {
    display: grid;
    grid-template-columns: 260px minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr);
    column-gap: 20px;
    align-items: stretch;
    height: 100dvh;
    overflow: hidden;
  }
  #route-list-view { grid-column: 1; grid-row: 1; min-width: 0; }
  #route-editor { grid-column: 2; grid-row: 1; min-width: 0; }
  #route-list-view[hidden], #route-editor[hidden] { display: none !important; }

  /* 整页锁在视口里，三条列表各自独立滚动；只在路线页锁 body */
  body:has(#page-route:not([hidden])) { height: 100dvh; overflow: hidden; }
  main:has(#page-route:not([hidden])) { height: 100dvh; padding-bottom: 0; }

  /* 两列页头等高、卡片内边距统一：三列内容从同一条线开始，列间不留多余空白 */
  #route-list-view > .route-head,
  #route-editor > .route-head {
    height: 64px;
    display: flex;
    align-items: center;
    padding: 0 18px;
    margin-bottom: 20px;
  }
  #route-editor > .card:not(.route-head) { padding: 18px 18px 20px; }
  #rt-preview .route-row { margin: 0; padding: 18px 18px 20px; }

  /* 三条列表的滚动条槽常驻在容器右缘、内容之外 */
  #route-list, #rt-preview, #rt-monsters {
    scrollbar-gutter: stable;
    overscroll-behavior: contain;
  }

  #route-list-view {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
  }
  #route-list-view > .route-head { flex: none; }
  #route-list {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding-right: 0;
  }

  /* 右列：页头固定；掉落信息与表单各按内容占高，过长时各自滚动 */
  #route-editor {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, auto) minmax(0, 1fr);
    height: 100%;
    min-height: 0;
  }
  #route-editor > .route-head { grid-column: 1; grid-row: 1; }
  #rt-preview {
    grid-column: 1;
    grid-row: 2;
    align-self: start;
    min-height: 0;
    max-height: 42vh;
    overflow-y: auto;
    padding-right: 0;
  }
  #rt-preview:empty { display: none; }
  #page-route.route-viewing #rt-preview { grid-row: 2 / span 2; max-height: 100%; }

  /* 表单卡片：第一行是「路线名称 + 操作按钮」，第二行才是怪物列表。
     卡片按内容收拢，怪物少时多高就多高；怪多了卡片受列高限制，只有怪物列表内部滚。 */
  #route-editor > .card:not(.route-head) {
    grid-column: 1;
    grid-row: 3;
    margin-top: 12px;
    min-height: 0;
    align-self: start;
    max-height: 100%;
    display: grid;
    grid-template-columns: minmax(0, 220px) minmax(0, 1fr);
    grid-template-rows: auto auto minmax(0, 1fr);
    column-gap: 12px;
    overflow: hidden;
  }
  #route-editor > .card > .field:first-child { display: contents; }
  #route-editor > .card > .field:first-child > .field-label {
    grid-column: 1 / -1;
    grid-row: 1;
    margin: 0 0 10px;
  }
  #route-editor > .card > .field:first-child > .name-row {
    grid-column: 1; grid-row: 2; min-width: 0;
  }
  /* 保存 / 放弃添加 / 删除路线 / 添加怪物统一短一档，紧贴输入框右侧 */
  #route-editor > .card > .editor-actions {
    grid-column: 2; grid-row: 2;
    margin: 0;
    align-self: center;
    gap: 8px;
    flex-wrap: nowrap;
  }
  #route-editor .name-row input[type="text"] { flex: 0 0 100%; max-width: none; }
  #route-editor .editor-actions button {
    flex: 0 0 92px;
    height: 44px;
    padding: 0 4px;
    font-size: 14.5px;
  }
  #route-editor > .card > .field:has(#rt-monsters) {
    grid-column: 1 / -1;
    grid-row: 3;
    margin-top: 14px;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }
  #rt-monsters {
    flex: 0 1 auto;
    min-height: 0;
    max-height: 100%;
    overflow-y: auto;
    align-content: start;
    /* 负外边距把滚动条推到卡片边框（内容区之外），与另两列槽位一致 */
    margin-right: -18px;
    padding-right: 18px;
  }

  /* 左列页头只留「+ 添加路线」，口径切换交给右列页头那一组 */
  #route-list-view > .route-head .sort-opt,
  #route-list-view > .route-head .who-set,
  #route-list-view > .route-head .sep { display: none; }
  #route-list-view > .route-head .btn-add {
    display: block;
    width: 100%;
    margin: 0;
    /* 与下面的路线卡片同一套外形：14px 内边距、12px 圆角、16.5px 字 */
    height: auto;
    padding: 14px;
    border-radius: 12px;
    font-size: 16.5px;
    font-weight: 600;
    line-height: 28px;   /* 与路线卡片里那行标题同高，按钮和卡片高度一致 */
  }
  /* 左列只有这一个按钮，不再套卡片容器：去掉底色/描边/圆角，高度仍与右列页头对齐 */
  #route-list-view > .route-head {
    background: none;
    border: 0;
    border-radius: 0;
    padding: 0;
  }
  /* 切换条在左列是包着按钮的容器：让它撑满，按钮的 100% 才等于整列宽 */
  #route-list-view > .route-head .sort-bar { flex: 1 1 auto; min-width: 0; }

  /* 预览卡顶部的砂糖 / 多莉：与「N 只 / 车」同一行，比页头那组小一档 */
  #rt-preview .who-inline { display: flex; align-items: center; gap: 6px; }
  #rt-preview .who-inline .sort-opt { height: 32px; padding: 0 14px; font-size: 14px; }
  /* 两列布局里口径切换与砂糖/多莉都已经在卡片里，右列页头没有内容；
     只保留占位（visibility）⇒ 顶部间距与左列路线卡片对齐，不会贴顶 */
  #route-editor > .route-head { visibility: hidden; }

  /* 左列卡片压成一行路线名 */
  #route-list-view .route-row {
    margin: 0 0 12px;
    padding: 14px;
    border-radius: 12px;
    cursor: pointer;
  }
  #route-list-view .route-name { font-size: 16.5px; }
  #route-list-view .route-count,
  #route-list-view .route-body,
  #route-list-view .icon-btn.edit,
  #route-list-view .icon-btn.collapse { display: none; }
  #route-list-view .sort-handle { margin-left: auto; width: 28px; height: 28px; }
  #route-list-view .sort-handle .sort-ico { width: 20px; height: 20px; }
  #route-list-view .route-row.active {
    background: var(--accent-soft);
    border-color: var(--accent);
    box-shadow: inset 3px 0 0 var(--accent);
  }
  #route-list-view .route-row.active .route-name { font-weight: 700; }
  #route-list-view .empty-tip { margin: 0; padding: 22px 12px; font-size: 15px; }

  /* 两列同屏时页头的返回按钮没有意义，一直隐藏 */
  #route-editor .btn-back { display: none !important; }
  /* 新建态：无图标的「放弃添加」与「保存」并排 */
  #page-route.route-new #btn-rt-cancel-new { display: inline-block !important; }
  /* 多只怪并排放（窄档）；一行一只由 1800+ 档覆盖 */
  #rt-monsters {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(420px, 1fr));
    gap: 12px;
  }
  #rt-monsters .mon-box { margin-top: 0; }

  /* 编辑路线：左侧表单（一行一只怪）/ 右侧掉落信息，同屏并排。
     ★ 只在 >=1800px 生效，窄屏掉落数字与怪物等级输入会挤到一起。 */
  @media (min-width: 1800px) {
    #route-editor {
      grid-template-columns: minmax(480px, 0.8fr) minmax(0, 1.2fr);
      grid-template-rows: auto minmax(0, 1fr);
      column-gap: 20px;
      align-items: stretch;
    }
    #route-editor > .route-head { grid-column: 1 / -1; grid-row: 1; }
    #route-editor > .card:not(.route-head) { grid-column: 1; grid-row: 2; margin-top: 0; }
    #rt-preview { grid-column: 2; grid-row: 2; align-self: start; max-height: 100%; }
    /* 右列预览区很宽：标题、材料图标、数量与进度文字统一放大一档 */
    #rt-preview .route-row { padding: 22px 22px 24px; }
    #rt-preview .route-name { font-size: 24px; }
    #rt-preview .route-count { font-size: 17px; }
    #rt-preview .route-body { margin-top: 16px; }
    #rt-preview .drop-row.both {
      gap: 10px;
      padding: 12px 0;
      font-size: 16px;
    }
    #rt-preview .drop-row.both .drop-cell { gap: 10px; }
    #rt-preview .drop-row.both .drop-cell img { width: 40px; height: 40px; }
    #rt-preview .drop-row.both .drop-cell b { font-size: 16px; }
    #rt-preview .drop-row.both .grad-num,
    #rt-preview .drop-row.both .grad-per,
    #rt-preview .drop-row.both .grad-trip { font-size: 14px; }
    #rt-monsters { grid-template-columns: minmax(0, 1fr); }
    /* 新建态还没有掉落信息：表单铺满整行 */
    #page-route.route-new #route-editor > .card:not(.route-head) { grid-column: 1 / -1; }
    #page-route.route-new #rt-preview { display: none; }
    /* 查看别人：只留掉落信息，铺满整行 */
    #page-route.route-viewing #rt-preview { grid-column: 1 / -1; grid-row: 2; }
  }
  #page-route.route-viewing #route-editor > .card:not(.route-head) { display: none; }

  /* 一条路线都没有：右列给一块空态 */
  #page-route.route-empty #route-editor { display: none !important; }
  #page-route.route-empty::after {
    content: "还没有路线 —— 点左侧「+ 添加路线」新建一条";
    grid-column: 2;
    grid-row: 1;
    align-self: start;
    margin-top: 20px;
    padding: 64px 24px;
    text-align: center;
    font-size: 17px;
    color: var(--text-2);
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 18px;
  }

  /* 侧栏不占垂直空间，暗月 iframe 直接铺满整屏高度 */
  .darkmoon-frame { height: 100dvh; }
}
@supports not (height: 100dvh) {
  @media (min-width: 1100px) {
    .topbar { height: 100vh; }
    .darkmoon-frame { height: 100vh; }
    body:has(#page-route:not([hidden])) { height: 100vh; }
    main:has(#page-route:not([hidden])) { height: 100vh; }
    #page-route { height: 100vh; }
  }
}
/* === DESKTOP-SIDEBAR-END === */

/* === SITE-ICP-START ===
   备案号页脚：跟在内容末尾，内容滚到底才出现，不单独占一条常驻栏。
   高度统一走 --icp-h，内容区与路线页按它扣减，页脚落在视口最底部。 */
:root { --icp-h: 54px; }
.site-icp {
  height: var(--icp-h);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  color: var(--text-2);
}
.site-icp a { color: inherit; text-decoration: none; }
.site-icp a:active { color: inherit; }

/* 内容少的页面也把 main 撑满一屏，页脚落在视口底部而不是悬在内容后面 */
main { min-height: calc(100dvh - 55px - var(--icp-h)); }
@media (min-width: 760px) {
  main { min-height: calc(100dvh - 50px - var(--icp-h)); }
}
@media (min-width: 1100px) {
  main { min-height: calc(100dvh - var(--icp-h)); }
  /* 路线页整页锁在视口内不滚，内容区同样减掉页脚高度 */
  #page-route { height: calc(100dvh - var(--icp-h)); }
  body:has(#page-route:not([hidden])) { height: auto; overflow: hidden; }
  main:has(#page-route:not([hidden])) { height: calc(100dvh - var(--icp-h)); padding-bottom: 0; }
  @supports not (height: 100dvh) {
    #page-route { height: calc(100vh - var(--icp-h)); }
    main:has(#page-route:not([hidden])) { height: calc(100vh - var(--icp-h)); }
  }
}
/* === SITE-ICP-END === */

/* === DM-CENTER-START ===
   暗月计算器页保持原来的居中宽度：内容区最宽 880px，宽屏下在导航栏右侧居中，
   不跟随其他页面铺满整个内容区。 */
@media (min-width: 1100px) {
  body.dm-view main {
    max-width: 880px;
    margin-left: max(208px, calc((100vw - 880px) / 2));
    margin-right: auto;
    /* 暗月页原来就是 content 贴边 880px，桌面档的左右内边距在这里归零 */
    padding-left: 0;
    padding-right: 0;
  }
}
/* === DM-CENTER-END === */

/* 导入导出页的主题切换：图标 + 当前主题文字，跟暗月里的按钮共用 lvcalc.theme */
.theme-toggle { display: flex; align-items: center; justify-content: center; gap: 8px; }
.theme-toggle .theme-ico {
  width: 18px;
  height: 18px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
