/* ===== 爱彼公寓管理系统 统一样式 ===== */
@import url("components.css");
@import url("modules.css");
:root {
  --bg: #f5f6f4;
  --surface: #ffffff;
  --surface-2: #fafbf9;
  --border: #e3e6e1;
  --text: #1f2a26;
  --text-soft: #5b6b64;
  --muted: #8a978f;
  --primary: #0f766e;      /* 墨绿 */
  --primary-dark: #0b5a54;
  --primary-soft: #d7ede9;
  --accent: #ea580c;       /* 暖橙 */
  --accent-soft: #fde4d3;
  --ok: #16a34a;
  --warn: #d97706;
  --danger: #dc2626;
  --shadow: 0 1px 3px rgba(31,42,38,.06), 0 6px 20px rgba(31,42,38,.05);
  --radius: 12px;
  --radius-sm: 8px;
  /* 吸顶元素的让位高度：顶栏 / 顶栏下的分类 tab 条。窄屏顶栏收成一行会变矮，在移动端区块里改这两个值，
     所有 sticky/scroll-margin 跟着变，不用各处再写死像素 */
  --topbar-h: 58px;
  --tabs-h: 58px;
  /* 悬浮元素与屏幕底部的安全距离：刘海屏把 Home 指示条高度算进来（需 viewport-fit=cover 才有值） */
  --safe-b: env(safe-area-inset-bottom, 0px);
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  /* 横屏时刘海/圆角会遮住最左右两列内容，左右各让出安全区（竖屏这两个值为 0，无影响） */
  padding-left: env(safe-area-inset-left, 0px);
  padding-right: env(safe-area-inset-right, 0px);
  font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", "Segoe UI", sans-serif;
  background: var(--bg);
  color: var(--text);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
a { color: var(--primary); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ===== 顶栏 ===== */
.topbar {
  position: sticky; top: 0; z-index: 40;
  /* 加到主屏后全屏运行(standalone + viewport-fit=cover)时，页面会铺到状态栏底下，顶部补出安全区 */
  padding-top: env(safe-area-inset-top, 0px);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  box-shadow: 0 1px 2px rgba(0,0,0,.03);
}
.topbar-inner {
  max-width: none; margin: 0 auto; padding: 0 52px;   /* 跟 .container 同宽同边距，导航与页面内容左右对齐 */
  display: flex; align-items: center; gap: 10px; height: 58px;
}
/* 品牌名同时是「回总览」的链接：去掉链接默认样式，hover 才有轻微反馈 */
.brand { font-weight: 700; font-size: 17px; color: var(--primary); white-space: nowrap; text-decoration: none; }
a.brand:hover { opacity: .8; text-decoration: none; }   /* 压掉全局 a:hover 的下划线：品牌名是标题，不该有链接下划线 */
.brand .dot { color: var(--accent); }
.nav { display: flex; gap: 2px; flex: 1; flex-wrap: wrap; }
.nav a {
  padding: 7px 13px; border-radius: 8px; color: var(--text-soft);
  font-size: 14px; font-weight: 500;
}
.nav a:hover { background: var(--surface-2); text-decoration: none; color: var(--text); }
.nav a.active { background: var(--primary-soft); color: var(--primary-dark); }
.nav-group { position: relative; }
.nav-more { font: inherit; cursor: pointer; border: none; background: transparent;
  padding: 7px 13px; border-radius: 8px; color: var(--text-soft); font-size: 14px; font-weight: 500; }
.nav-more:hover { background: var(--surface-2); color: var(--text); }
.nav-more.active { background: var(--primary-soft); color: var(--primary-dark); }
.nav-menu { display: none; position: absolute; top: 100%; left: 0; margin-top: 4px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
  box-shadow: var(--shadow); padding: 6px; min-width: 170px; z-index: 50; }
.nav-group:hover .nav-menu, .nav-group:focus-within .nav-menu { display: block; }
.nav-menu a { display: block; padding: 8px 12px; border-radius: 6px; color: var(--text-soft); font-size: 14px; white-space: nowrap; }
.nav-menu a:hover { background: var(--surface-2); color: var(--text); text-decoration: none; }
.nav-menu a.active { background: var(--primary-soft); color: var(--primary-dark); }
.topbar-actions { display: flex; align-items: center; gap: 8px; }
.save-hint { font-size: 12px; color: var(--muted); min-width: 64px; text-align: right; }
.save-hint.saving { color: var(--warn); }
.save-hint.saved { color: var(--ok); }

/* ===== 布局 ===== */
.container { max-width: none; margin: 0 auto; padding: 24px 52px 64px; }   /* 全宽：宽表(装饰预算/主材/验收)横向能多放几列，少一次横滚 */
.page-head { margin: 8px 0 22px; }
.page-head h1 { margin: 0 0 6px; font-size: 24px; }
.page-head p { margin: 0; color: var(--text-soft); }
.section { margin: 28px 0; }
.section > h2,
.section > .row > h2,
.section > .row > .ledger-head > h2 { font-size: 18px; margin: 0 0 14px; display: flex; align-items: center; gap: 8px; }
.section > .row > h2, .section > .row > .ledger-head > h2 { margin: 0; }
/* 带按钮的区块标题行（h2 + 右侧按钮）与下方内容留统一间距 */
.section > .row.between { margin-bottom: 14px; }
.section > h2::before,
.section > .row > h2::before,
.section > .row > .ledger-head > h2::before { content: ''; width: 4px; height: 18px; background: var(--primary); border-radius: 2px; }

/* ===== 卡片 ===== */
.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow); padding: 18px 20px;
}
.grid { display: grid; gap: 16px; }
.grid.cols-2 { grid-template-columns: repeat(2, 1fr); }
.grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.grid.cols-4 { grid-template-columns: repeat(4, 1fr); }
.grid.cols-5 { grid-template-columns: repeat(5, 1fr); }
.grid.cols-6 { grid-template-columns: repeat(6, 1fr); }
/* 自适应统计格：按可用宽度自动定每行个数（不写死列数）。大屏一行放满，平板/手机随宽度递减；
   手机端由下方 @560 的「.grid:has(>.stat) → 两列」兜底。房源详情页顶部 8 个概览格用它 */
.grid.auto-stats { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }

/* 统计块 */
.stat { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 16px 18px; box-shadow: var(--shadow);
  min-width: 0; }   /* grid 项默认 min-width:auto，格内长金额会把整行顶宽、页面整屏能左右滑 */
.stat .label { font-size: 13px; color: var(--muted); }
/* 金额是「¥3,456,789」这种无处断行的连续串，anywhere 兜底：宁可折行也不冲出屏幕 */
.stat .value { font-size: 26px; font-weight: 700; margin-top: 4px; overflow-wrap: anywhere; }
/* 概览 6 格的数值单独收到 22px：26px 时一格放不下「¥776,256.58」，在 1440/1512 这类常见宽度上会折行 */
#overall .stat .value { font-size: 22px; }
/* 统计格右上角按钮（如累计电费卡「记实缴」）：绝对定位贴右上，不挤占标签行 */
.stat.has-corner { position: relative; }
.stat .stat-corner { position: absolute; top: 10px; right: 10px; width: auto; height: 26px; padding: 0 10px;
  border-radius: 999px; font-size: 12px; color: var(--primary); border: 1px solid var(--border); background: var(--surface); }
.stat .stat-corner:hover { border-color: var(--primary); }
.stat .value small { font-size: 14px; font-weight: 500; color: var(--muted); }
.stat-click { cursor: pointer; transition: border-color .12s, box-shadow .12s; }
.stat-click:hover { border-color: var(--primary); box-shadow: 0 2px 10px rgba(0, 0, 0, .08); }
/* 收益核算 6 栏等高：标签留两行统一高度、数值缩小不换行、数值底对齐 */
/* 收益核算：合计(#returns) 与展开各房源(#returnsBreakdown) 的卡片共用同一套紧凑/不换行样式，保持一致 */
#returns, #returnsBreakdown .grid { align-items: stretch; }
#returns .stat, #returnsBreakdown .stat { display: flex; flex-direction: column; }
#returns .stat .label, #returnsBreakdown .stat .label { min-height: 2.4em; line-height: 1.2; }
/* 标签行右上角的状态小标（如「回本中 0.7%」）：跟在金额后面会把格子撑破，改挂标签行末尾。
   只对带小标的格子转 flex（:has），别影响其它 stat 标签里 ⓘ 紧贴文字的排版。
   窄屏一行放不下时让小标整块换到下一行右侧——标签文字本身 nowrap，不会被拆成「回本盈/亏」 */
.stat .label:has(.stat-tag) { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 2px 6px; }
.stat .label:has(.stat-tag) .lbl-t { white-space: nowrap; }
.stat-tag { margin-left: auto; flex-shrink: 0; font-size: 11.5px; color: var(--text-soft); white-space: nowrap; }
#returns .stat .value, #returnsBreakdown .stat .value { margin-top: auto; font-size: 20px; white-space: nowrap; }

/* ===== 徽章 / 状态 ===== */
.badge { display: inline-block; padding: 3px 9px; border-radius: 999px; font-size: 12px; font-weight: 600; }
/* 表格锁定行（收租/花销通用）：柔和薄荷绿底、文字变淡，🔒 小标记（与米色表头区分） */
tr.row-locked, tr.rent-locked { background: var(--accent-soft); }
tr.row-locked td, tr.rent-locked td { color: var(--text-soft); }
.lock-tag { font-size: 11px; }
/* 花销表里合并进来的「日常维护」行：只读，浅背景 + 柔和文字与自有花销区分 */
tr.row-daily { background: var(--surface-2); }
tr.row-daily td { color: var(--text-soft); }

.badge.planning { background: #eef1ef; color: #64716a; }
.badge.vacant { background: #eef1ef; color: #64716a; }
.badge.renovating { background: var(--accent-soft); color: #b3450a; }
.badge.design { background: #e5edff; color: #3557b7; }
.badge.construction { background: var(--accent-soft); color: #b3450a; }
.badge.finishing { background: #fef3c7; color: #a16207; }
.badge.renting { background: #dcfce7; color: #15803d; }
.badge.done { background: var(--primary-soft); color: var(--primary-dark); }

/* ===== 进度条 ===== */
.progress { height: 8px; background: #ecefec; border-radius: 999px; overflow: hidden; }
.progress > i { display: block; height: 100%; background: var(--primary); border-radius: 999px; transition: width .3s; }

/* ===== 按钮 ===== */
.btn { display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  border: 1px solid var(--border); background: var(--surface); color: var(--text);
  padding: 8px 14px; border-radius: var(--radius-sm); font-size: 14px; font-weight: 500;
  font-family: inherit; transition: background .12s, border-color .12s; }
.btn:hover { background: var(--surface-2); }
.btn.primary { background: var(--primary); border-color: var(--primary); color: #fff; }
.btn.primary:hover { background: var(--primary-dark); }
.btn.accent { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn.ghost { border-color: transparent; background: transparent; color: var(--text-soft); }
.btn.sm { padding: 5px 10px; font-size: 13px; }
.btn.danger { color: var(--danger); border-color: #f2c6c6; }
.btn.danger:hover { background: #fdecec; }

/* ===== 图标操作条（全站唯一组件，样式源自「前期学习」）=====
   编辑/删除/复制/链接等操作统一走此组件，尺寸/位置/外观全站一致。用 App.actionBar() 生成，别手写图标按钮。
   两种形态：
   · 卡片/条目 → 容器加 .act-host，App.actionBar(...) 产出 .act-bar 悬浮胶囊（右下角，默认隐藏，hover/聚焦显示，触屏常显）
   · 表格行   → App.actionBar(..., {inline:true}) 产出 .act-inline（在操作列内，随行 hover 显示） */
.act-host { position: relative; }
.act-bar { position: absolute; right: 8px; bottom: 6px; display: flex; gap: 4px; opacity: 0; transition: opacity .15s;
  background: var(--surface); border-radius: 8px; padding: 2px; box-shadow: 0 1px 6px rgba(0, 0, 0, .08); }
.act-host:hover .act-bar, .act-host:focus-within .act-bar { opacity: 1; }
.act-inline { display: inline-flex; gap: 4px; }
/* 操作列（含图标条的单元格）靠右对齐，图标贴表格最右侧 */
table.data td:has(> .act-inline) { text-align: right; }
table.data tbody tr .act-inline { opacity: 0; transition: opacity .15s; }
table.data tbody tr:hover .act-inline, table.data tbody tr:focus-within .act-inline { opacity: 1; }
@media (hover: none) { .act-bar, table.data tbody tr .act-inline { opacity: 1; } }
.act-btn { display: flex; align-items: center; justify-content: center; width: 22px; height: 22px; padding: 0;
  border: 1px solid var(--border); border-radius: 6px; background: var(--surface); color: #555; cursor: pointer; text-decoration: none; }
.act-btn:hover { border-color: var(--primary); color: var(--primary); }
.act-btn.danger { color: var(--danger); }
.act-btn.danger:hover { border-color: var(--danger); color: var(--danger); }
.act-btn svg { width: 12px; height: 12px; }

/* ===== 信息提示气泡（App.infoTip）===== 小 ⓘ 图标，hover/聚焦弹出说明 */
.info-dot { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px;
  color: var(--muted); cursor: help; position: relative; vertical-align: middle; }
.info-dot:hover, .info-dot:focus { color: var(--primary); outline: none; }
.info-dot svg { width: 15px; height: 15px; }
.info-pop { position: absolute; top: calc(100% + 6px); left: 0; z-index: 40; width: max-content; max-width: min(230px, 76vw);
  white-space: pre-line; word-break: break-word;   /* 覆盖 dt 的 nowrap；pre-line 保留提示里的换行(排公式)，普通文字仍自动换行 */
  background: var(--text); color: #fff; font-size: 12px; line-height: 1.55; font-weight: 400; text-align: left;
  padding: 8px 10px; border-radius: 8px; box-shadow: 0 4px 16px rgba(0, 0, 0, .2);
  opacity: 0; visibility: hidden; transform: translateY(-2px); transition: opacity .15s, transform .15s; pointer-events: none;
  /* 隐藏态用 display:none —— 只 visibility:hidden 的话它仍占布局，靠右的气泡会把页面撑出横向滚动条 */
  display: none; }
.info-dot.tip-left .info-pop { left: auto; right: 0; }   /* 图标在容器右上角时向左展开，避免冲出右边 */
.info-dot:hover .info-pop, .info-dot:focus .info-pop { opacity: 1; visibility: visible; transform: translateY(0); display: block; }

/* ===== 表格 ===== */
.table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius); }
/* 「可左右滑」提示：App.watchTableScroll 测到内容超出可视宽时打 .can-scroll。
   只要能横滚就一直显示（文案是双向「← 左右滑动查看 →」，滑到最右仍可往左滑回，不再随 .more-right 消失）。
   提示条用 sticky 贴在滚动区左侧，不随表格横向滚走；仅窄屏出现（宽屏鼠标滚轮/触控板天然能滑） */
.table-wrap.can-scroll::after {
  content: '← 左右滑动查看 →'; display: none; position: sticky; left: 0;
  padding: 6px 10px; font-size: 12px; color: var(--muted); background: var(--surface-2);
  border-top: 1px dashed var(--border); text-align: center;
}
table.data { width: 100%; border-collapse: collapse; background: var(--surface); font-size: 14px; }
table.data th, table.data td { padding: 10px 12px; text-align: left; border-bottom: 1px solid var(--border); }
table.data th { background: var(--surface-2); font-weight: 2000; color: var(--text-soft); font-size: 13px; white-space: nowrap; }
table.data tr:last-child td { border-bottom: none; }
table.data td.num, table.data th.num { text-align: right; font-variant-numeric: tabular-nums; }
table.data tfoot td { font-weight: 700; background: var(--primary-soft); color: var(--primary-dark); border-top: 2px solid var(--primary); }
/* editableTable 的 image 列缩略图：定宽小图、点击看大图，鼠标 hover 提示可点 */
.et-thumb { width: 56px; height: 42px; object-fit: cover; border-radius: var(--radius-sm, 6px); border: 1px solid var(--border); cursor: zoom-in; display: block; }
table.data input, table.data select { width: 100%; border: none; background: transparent;
  font: inherit; color: inherit; padding: 2px 0; }
table.data input:focus, table.data select:focus { outline: 2px solid var(--primary-soft); border-radius: 4px; }

/* ===== 表单 ===== */
/* editableTable / 购置等弹窗表单的网格布局（通用组件样式，供所有用 App.editableTable 的页面共享）：
   默认两列，--pf-cols 可按表单改列数；.full 独占整行；窄屏自动退回两列/单列 */
.pf-grid { display: grid; grid-template-columns: repeat(var(--pf-cols, 2), 1fr); gap: 10px 14px; align-items: start; }
.pf-grid .full { grid-column: 1 / -1; }
/* 跨列：4 列布局里给长字段用（2 列布局下 span 会被网格截到实际列数，自动变整行，无需额外适配） */
.pf-grid .span2 { grid-column: span 2; }
.pf-grid .span3 { grid-column: span 3; }
/* 字段特别多的表单（新增房产）铺 4 列。用类而不是内联 --pf-cols，内联会压过下面的窄屏规则 */
.pf-grid.cols4 { --pf-cols: 4; }
/* 20 个字段撑到 868px 高，普通 Mac 视口要滚一截才够着「保存」。只在这个表单、且只在宽屏收紧
   行距/内边距（约省 110px → 758px），配合弹窗 95vh，760px 以上的视口都能一屏填完。
   窄屏不收紧：那边退回两列、且要保住 44px 触摸目标 */
@media (min-width: 821px) {
  .pf-grid.cols4 { gap: 6px 14px; }
  .pf-grid.cols4 label.field > span { margin-bottom: 3px; }
  .pf-grid.cols4 .text { padding: 7px 11px; }
  .pf-grid.cols4 .pf-sec { margin: 8px 0 2px; }
}
/* 平板/小窗多列每格太窄，一律退两列（cols4 也要显式写上，否则特异性输给上面那条）。
   跨列字段同时降级成整行——不降的话 span 3 在两列网格里会挤出一条不受控的隐式列 */
@media (max-width: 820px) {
  .pf-grid, .pf-grid.cols4 { --pf-cols: 2; }
  .pf-grid .span2, .pf-grid .span3 { grid-column: 1 / -1; }
}
/* label.field 的 margin-bottom:14px 特异性(0,1,1)压过 .mb-0(0,1,0)，弹窗里 mb-0 失效、每格多出底边距；
   表单靠 grid gap 控间距，这里按原意归零 */
.pf-grid label.field.mb-0, .pf-row3 label.field.mb-0 { margin-bottom: 0; }
.pf-sec { font-weight: 600; color: var(--primary-dark); margin: 16px 0 2px; grid-column: 1 / -1; }
/* 三个短字段并排一行（分类/金额/日期）；顶部对齐，金额下方算式预览不把邻列撑高 */
.pf-row3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px 14px; align-items: start; }
@media (max-width: 640px) { .pf-row3 { grid-template-columns: 1fr; } }
/* 算式预览：空时不占高度，有内容才撑开 */
.pf-calc { font-size: 12px; color: var(--muted); }
.pf-calc:not(:empty) { margin-top: 3px; }
.pf-calc.bad { color: var(--danger); }
label.field { display: block; margin-bottom: 14px; }
label.field > span { display: block; font-size: 13px; color: var(--text-soft); margin-bottom: 5px; }
input.text, select.text, textarea.text {
  width: 100%; padding: 9px 11px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  font: inherit; color: var(--text); -webkit-text-fill-color: var(--text); background: var(--surface); }
input.text:focus, select.text:focus, textarea.text:focus { outline: none; border-color: var(--primary); }
/* 数字框的上下箭头(spinner)是贴右边缘绘制的方形原生控件，会把右侧圆角盖成直角，窄格里还挤占输入区。
   金额/读数都是直接键入，用不上它——一律隐藏，四角圆弧才一致 */
input[type="number"].text::-webkit-outer-spin-button,
input[type="number"].text::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
input[type="number"].text { -moz-appearance: textfield; appearance: textfield; }
textarea.text { min-height: 90px; resize: vertical; }
/* 单行高的多行框：跟同一行的 input 等高（配合 rows="1"），需要多写时仍可自己拖高 */
textarea.text.oneline { min-height: 0; }
/* 覆盖浏览器自动填充：文字保持主文本色、背景保持白，避免同排数字深浅不一/发灰 */
input.text:-webkit-autofill, input.text:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--text); -webkit-box-shadow: 0 0 0 100px var(--surface) inset; }

/* ===== 可编辑区块 ===== */
[data-edit] {
  border-radius: 6px; transition: background .12s;
  padding: 2px 4px; margin: -2px -4px;
}
[data-edit]:hover { background: #fffaf2; box-shadow: inset 0 0 0 1px var(--accent-soft); cursor: text; }
[data-edit]:focus { outline: none; background: #fff; box-shadow: inset 0 0 0 2px var(--primary-soft); }
.edit-block {
  background: var(--surface-2); border: 1px dashed var(--border); border-radius: var(--radius-sm);
  padding: 12px 14px; white-space: pre-wrap; min-height: 40px;
}
.edit-block:hover { border-color: var(--accent); }
.editable-tip { font-size: 12px; color: var(--muted); }
.editable-tip::before { content: '✎ '; color: var(--accent); }

/* ===== 工具类 ===== */
.row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.row.between { justify-content: space-between; }
.muted { color: var(--muted); }
.soft { color: var(--text-soft); }
.mt-0 { margin-top: 0; } .mb-0 { margin-bottom: 0; }
.tag { display: inline-block; background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 6px; padding: 2px 8px; font-size: 12px; color: var(--text-soft); }
.hr { height: 1px; background: var(--border); border: none; margin: 20px 0; }

/* 右下角悬浮新增按钮（前期学习 / 案例共用）：主色胶囊，固定右下角 */
.fab { position: fixed; right: 20px; bottom: 20px; z-index: 80; border: none; cursor: pointer;
  background: var(--accent); color: #fff; padding: 12px 18px; border-radius: 999px;
  font-size: 15px; font-weight: 600; box-shadow: 0 6px 20px rgba(234, 88, 12, .4); }

/* ===== 响应式 ===== */
/* 总览页概览(#overall)与收益核算(#returns)的 6 格：值是 7 位数金额，1500px 以下每格已放不下，
   硬挤 6 列会把整页顶宽、手机/iPad 上整屏能左右滑。按宽度降档到 3 列、2 列（都整除 6，不留孤格），字号同步收小 */
@media (max-width: 1500px) {
  #overall, #returns, #returnsBreakdown .grid { grid-template-columns: repeat(3, 1fr); }
  /* 房源卡（总览「房源列表」）：4 列时 iPad Pro 上每格只剩约 70px，四位数的累计收租/押金会被省略号截掉，退到 3 列 */
  .grid.unit-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 700px) {
  #overall, #returns, #returnsBreakdown .grid { grid-template-columns: repeat(2, 1fr); }
  #overall .stat .value { font-size: 18px; }
}

@media (max-width: 1100px) {
  /* 全宽布局下边距按屏宽收窄：52px 在小窗口上会吃掉太多可用宽度 */
  .container { padding: 24px 28px 64px; }
  .topbar-inner { padding: 0 28px; }
  .grid.cols-5 { grid-template-columns: repeat(3, 1fr); }
  .grid.cols-6 { grid-template-columns: repeat(4, 1fr); }
}
/* iPad：收租统计 6 格一行 3 个（默认 cols-6 在此宽度是 4 个，第 5/6 格落到下一行显得散）。
   下限 641px 让手机仍走两列（#rStats 是 id，特异性高于 .grid.cols-6，须用 min-width 卡住不越界到手机） */
@media (min-width: 641px) and (max-width: 1100px) {
  #rStats { grid-template-columns: repeat(3, 1fr); }
  /* iPad：统计格标签(购置现金支出/累计租金收入等)13px 配大号金额显小，提到 15px */
  .stat .label { font-size: 16px; }
  .unit-card .uc-top-right { font-size: 13.5px; }
  .unit-card .uc-k { font-size: 13.5px; }
}
/* iPad 横屏：房屋购置 4 格等宽时「房屋总价合计」12 位数被拆两行。压窄末列(总间数 21 间很短)、
   加宽房屋总价列。竖屏(≤860px)已降 2 列不挤，故只作用于 861–1100px */
@media (min-width: 861px) and (max-width: 1100px) {
  #pStats { grid-template-columns: 1fr 1.3fr 1fr 0.7fr; }
}
@media (max-width: 860px) {
  .grid.cols-4 { grid-template-columns: repeat(2, 1fr); }
  .grid.cols-3 { grid-template-columns: repeat(2, 1fr); }
  .grid.cols-5 { grid-template-columns: 1fr; }   /* 移动端案例一行 1 个 */
  .grid.cols-6 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .topbar-inner { height: auto; flex-wrap: wrap; padding: 8px 14px; }
  /* 注意：这里不要给 .nav 设 order —— 会把「退出」挤到汉堡菜单最前面。
     菜单顺序按 DOM：导航各页在前、退出在最后 */
  .grid.cols-6, .grid.cols-5, .grid.cols-4, .grid.cols-3, .grid.cols-2 { grid-template-columns: 1fr; }
  .container { padding: 16px 14px 48px; }
}

/* ===== 可访问性 ===== */
/* 键盘焦点环:仅键盘导航时出现,清晰可见 */
:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; border-radius: 4px; }
.btn:focus-visible, a:focus-visible, input:focus-visible, select:focus-visible,
textarea:focus-visible, [contenteditable]:focus-visible {
  outline: 2px solid var(--text); outline-offset: 2px;
}
/* 尊重系统「减少动态效果」:关闭过渡与卡片倾斜/位移 */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important; scroll-behavior: auto !important;
  }
  .theme-journal .unit-card,
  .theme-journal .grid > .unit-card:nth-child(odd),
  .theme-journal .grid > .unit-card:nth-child(even),
  .theme-journal .login-card { transform: none !important; }
}

/* ===== 移动端适配 ===== */
.nav-toggle { display: none; background: none; border: none; cursor: pointer; color: var(--text); padding: 6px; border-radius: 8px; }
.nav-toggle:hover { background: var(--surface-2); }
.clip-modal { width: 75vw; max-width: none; }
/* 采集弹窗:左右布局(左图片框 + 右表单) */
.clip-cols { display: flex; gap: 18px; margin-top: 10px; }
.clip-left { flex: 0 0 35%; display: flex; flex-direction: column; }
.clip-right { flex: 1; min-width: 0; }
/* flex:1 让图片框撑满左列高度，与右列自动等高(视觉对齐) */
.clip-drop { position: relative; flex: 1; border: 2px dashed var(--border); border-radius: 12px; min-height: 440px;
  display: flex; align-items: center; justify-content: center; cursor: pointer; overflow: hidden; background: var(--surface-2); }
.clip-drop.dragover { border-color: var(--primary); background: var(--primary-soft); }
.clip-drop-hint { color: var(--muted); font-size: 14px; text-align: center; padding: 24px; line-height: 1.9; }
.clip-preview { position: absolute; inset: 0; display: none; }
.clip-preview img { width: 100%; height: 100%; object-fit: contain; background: #fff; }
.clip-drop.has-img .clip-drop-hint { display: none; }
.clip-drop.has-img .clip-preview { display: block; }
/* 删图按钮:仅 deletable 且有图时显示在预览右上角,点它清空图片(不触发选图) */
.clip-drop-x { position: absolute; top: 8px; right: 8px; z-index: 2; width: 28px; height: 28px; display: none;
  align-items: center; justify-content: center; border: none; border-radius: 50%; cursor: pointer;
  background: rgba(0,0,0,.55); color: #fff; font-size: 18px; line-height: 1; }
.clip-drop-x:hover { background: rgba(0,0,0,.75); }
.clip-drop.has-img.deletable .clip-drop-x { display: flex; }
/* 右侧第一行:出处 + 分类 并排两列 */
.clip-row2 { display: flex; gap: 12px; }
.clip-row2 .field { flex: 1; min-width: 0; }
/* 底部操作行:与上方两列对齐 —— AI解析落在左列(35%)右下角，取消/保存落在右列末尾，同一视觉行。
   用 .m-actions.clip-actions 双类提高优先级，压过 .modal .m-actions 的 flex-end */
.m-actions.clip-actions { justify-content: flex-start; gap: 18px; }
.clip-actions .clip-a-left { flex: 0 0 35%; display: flex; align-items: center; justify-content: flex-end; gap: 10px; }
.clip-actions .clip-a-right { flex: 1; display: flex; align-items: center; justify-content: flex-end; gap: 10px; }
/* 窄屏/触屏总断点 = 900px：iPad 竖屏（mini 744 / 10.9" 820 / Pro 11" 834）都归到这一档——
   桌面顶栏在 820 宽下导航会挤成两行，且 iPad 本身是触屏，宽表首列吸附、44px 触摸目标同样适用 */
@media (max-width: 900px) {
  .clip-row2 { flex-direction: column; gap: 0; }
  /* 竖排后左右两块各占一行、各自靠边 */
  .clip-actions .clip-a-left { flex: 1 1 auto; justify-content: flex-start; }
  /* 顶栏收成汉堡菜单:导航 + 备份/导出/导入/退出都进面板 */
  .nav-toggle { display: inline-flex; align-items: center; }
  .topbar-inner { flex-wrap: wrap; height: auto; padding: 8px 16px; gap: 8px; }
  .brand { flex: 1; }
  .save-hint { display: none; }
  .data-op { display: none; }
  /* flex:0 0 100% 而不是只写 width —— .nav 桌面态是 flex:1(basis 0%)，只给 width 的话它会挤在品牌名同一行不换行 */
  .nav, .topbar-actions { display: none; flex: 0 0 100%; width: 100%; flex-direction: column; align-items: stretch; gap: 4px; }
  .topbar.nav-open .nav, .topbar.nav-open .topbar-actions { display: flex; }
  .topbar.nav-open .topbar-actions { border-top: 1px solid var(--border); margin-top: 4px; padding-top: 8px; }
  .nav a { padding: 11px 12px; min-height: 44px; display: flex; align-items: center; border-radius: 8px; }
  .topbar-actions .btn { min-height: 44px; justify-content: flex-start; }
  /* 触摸目标 */
  .btn { min-height: 42px; }
  .btn.sm { min-height: 38px; }
  /* 输入框≥16px 防 iOS 自动缩放 */
  input.text, select.text, textarea.text, table.data input, table.data select { font-size: 16px; }
  /* 采集弹窗窄屏铺宽 */
  .clip-modal { width: 94vw; }
  .clip-cols { flex-direction: column; }
  .clip-left { flex: none; }
  .clip-drop { min-height: 200px; }

  /* 顶栏收成一行后变矮：吸顶让位高度跟着改，acc-tabs / 文档编辑器工具条 / 锚点偏移自动对齐 */
  :root { --topbar-h: 52px; --tabs-h: 60px; }

  /* ---- 宽表：横向滚动 + 首列吸附 ---- */
  .table-wrap.can-scroll::after { display: block; }
  /* 首列（日期/房间/项目名这类定位列）滚动时固定在左侧，右滑看后面的列时仍知道是哪一行。
     td 默认透明会漏出下层内容，必须逐类补回背景（含锁定行/日常行/分组行/表尾的特殊底色） */
  /* 限定 thead 第一行：两行表头的表（如装饰工程预算）第二行首格是「数量」，钉住它会错位 */
  .table-wrap.can-scroll table.data thead tr:first-child th:first-child,
  .table-wrap.can-scroll table.data tbody td:first-child {
    position: sticky; left: 0; z-index: 1; background: var(--surface);
    box-shadow: 1px 0 0 var(--border);
  }
  .table-wrap.can-scroll table.data thead tr:first-child th:first-child { z-index: 2; background: var(--surface-2); }
  .table-wrap.can-scroll table.data tfoot td:first-child { background: var(--primary-soft); }
  .table-wrap.can-scroll table.data tr.row-locked > td:first-child,
  .table-wrap.can-scroll table.data tr.rent-locked > td:first-child { background: var(--accent-soft); }
  .table-wrap.can-scroll table.data tr.row-daily > td:first-child,
  .table-wrap.can-scroll table.data tr.decor-sect > td:first-child,
  .table-wrap.can-scroll table.data tr.mat-sect > td:first-child,
  .table-wrap.can-scroll table.data tr.appl-sect > td:first-child { background: var(--surface-2); }
  /* 触屏没有真正的 hover，手指点过的行会「粘」上高亮色并盖掉吸附列底色，直接关掉。
     选择器多带一层 body 才压得过后加载的 journal.css 同名规则 */
  body.theme-journal table.data tr:hover td { background: none; }

  /* 触摸目标：行内图标钮 22px 太小，放大到 30px（仍小于按钮 44px，但表格行高可控） */
  .act-btn { width: 30px; height: 30px; }
  .act-btn svg { width: 15px; height: 15px; }
  .act-bar, .act-inline { gap: 6px; }

  /* 悬浮层避开刘海屏底部 Home 条 */
  .fab { bottom: calc(20px + var(--safe-b)); }
  .toast { bottom: calc(24px + var(--safe-b)); }
  .container { padding-bottom: calc(72px + var(--safe-b)); }   /* 留白够高，fab 不压住最后一行内容 */

  /* 弹窗：窄屏(手机/iPad)也上下左右居中(遮罩 flex 居中已由基础规则给出，这里只收紧内边距)。
     弹窗自身 max-height:calc(100vh-48px) 且内部滚动，永远放得下，居中不会把顶部裁到屏外 */
  .modal-mask { padding: 24px 12px; }
  .modal { padding: 18px 16px; max-height: calc(100vh - 48px); }
  .modal:has(.m-diff) { max-height: calc(100vh - 48px); }
  .modal .m-actions > .btn { flex: 1; justify-content: center; }   /* 取消/确认平分一行，好按（只管直接子按钮，不打乱采集弹窗的左右分组） */
}
@media (max-width: 560px) {
  /* 统计块例外：数字短，竖排一列会拉得很长，保持两列更好扫读（写在 .grid.cols-* 之后才压得住） */
  .grid:has(> .stat) { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  /* 窄屏放开不换行：格宽只有约 148px，「-¥123,456 回本中 12.3%」一行放不下 */
  #returns .stat .value, #returnsBreakdown .stat .value { font-size: 16px; white-space: normal; }
  /* 现场照片墙：跟统计块同理，一行一张太浪费，保持两列（房源详情页） */
  .grid.cols-4.photo-grid { grid-template-columns: repeat(2, 1fr); }
  /* 装修阶段行：日期 150px + 备注挤在一行会把备注压成 120px，让备注独占下一行 */
  .stage-row .row > .text:last-child { flex-basis: 100%; }
  .card { padding: 14px 14px; }
  .page-head h1 { font-size: 21px; }
  .theme-journal .page-head h1 { font-size: 25px; }
  .section { margin: 20px 0; }
  .stat { padding: 13px 14px; }
  .stat .value { font-size: 22px; }
}

