/* ============================================================
   VANSHI · 内页层  pages.css
   楼盘详情页 + 区域 / 商圈 / 地铁 落地页
   —— 复用 ed.css 的纸、墨、线、衬线；这里只加"内页语法"：
      重线起头、编号隐去、测度收窄到可读宽度、粘性报价卡。
   ============================================================ */

/* ---------------- 面包屑 ---------------- */
.crumb{
  display:flex; flex-wrap:wrap; align-items:center; gap:0 8px;
  padding:20px 0 0; font-size:var(--fs-bs); color:var(--ink3); letter-spacing:.01em;
}
.crumb a{ display:inline-flex; align-items:center; min-height:32px; color:var(--ink3); padding:4px 0; border-bottom:1px solid transparent; transition:color .2s var(--ease),border-color .2s var(--ease); }
.crumb a:hover{ color:var(--ink); border-bottom-color:var(--ink); }
.crumb .sp{ color:var(--ink4); opacity:.6; }
.crumb .cur{ color:var(--ink); }

/* ---------------- 楼盘详情：题头 ---------------- */
.dhead{ padding:var(--sp-head) 0 0; }
/* 题头是一整行，不再分成两栏：CTA 已经移进首屏右栏，
   原来这里是 flex space-between，标题只有四个字，右边按钮被推到容器最右，
   中间空出 800px，整块看起来像断成两截。 */
.dhead .wrap{ display:block; }
.dhead-l{ min-width:0; }
.dhead h1{
  font-family:var(--serif); font-weight:500; letter-spacing:.01em; line-height:var(--lh-h1);
  font-size:calc(var(--fs-h1) * var(--k));
}
/* h1 后缀「写字楼出租」。要解决的是「这是哪一类物业」这个第一疑问 ——
   只写楼名的时候，从搜索点进来的人得先往下读两屏才能确认这是写字楼。
   同时 <h1> 里带上品类词，检索相关性也跟着对上了。
   字号不进 h1 那一档：它是楼名的注脚，不是第二个标题；
   改用正文字号 + 一档浅墨 + 一个细竖线隔开，读起来是「企业天地五号 | 写字楼出租」。 */
.dhead h1 .h1-k{
  font-family:var(--sans); font-size:var(--fs-md); font-weight:400;
  color:var(--ink3); letter-spacing:.06em; white-space:nowrap;
  margin-left:.55em; vertical-align:.18em;
}
.dhead .en{
  margin-top:8px; font-family:var(--en); font-size:var(--fs-bs); letter-spacing:.03em;
  color:var(--ink3);
}
/* 别名行（2026-11-03）。为什么放在 .en 下面：它和英文名是同一类信息 ——
   「这栋楼还有别的叫法」，不是正文。字号与 .en 同档、颜色更浅，
   避免它跟 .loc 里的地址抢注意力（地址才是读者用来定位的东西）。
   <b> 用 norml 字重而不是 600：七个楼盘页里有六个没有别名，这一行本来就不常出现，
   一出现就加粗反而像在喊。 */
.dhead .aka{
  margin-top:6px; font-size:var(--fs-bs); color:var(--ink3); letter-spacing:.02em;
}
.dhead .aka b{ font-weight:400; color:var(--ink3); margin-right:.4em; }
.dhead .aka b::after{ content:"："; }
.dhead .loc{ margin-top:16px; display:flex; flex-wrap:wrap; align-items:center; gap:0 16px; font-size:var(--fs-md); color:var(--ink2); }
/* 2026-10-27：`.dhead .loc` 里如果是**整段话**（ai/index.html 就是），
   它会铺满整个 .dhead-l（857px），14px 排到 61 个汉字一行。
   加类而不是加规则，是因为同一个选择器在 3,676 个楼盘页上是行内元信息，
   一刀切限宽会把那一行的右栏挤到换行（首屏高度敏感）。

   ⚠ 宽度用 `45 × 字号` 而不是 `--measure`（690px）：
   站内有**两把**行宽尺子，量法不同 ——
     · `audit_look` 第 25 步：每行 >46 字**且**行宽 ≥720px 才判红，
       所以 690px 在它那里是绿的；
     · `check_type` 第 4 步：每行 >46 字就判红，没有宽度条件，
       690px ÷ 14px = **49.3 字** → 第 3 次全站检查当场在「选址顾问@1440」判红。
   同一个 `--measure` 是按 15px 正文定的（690÷15=46），拿来卡 14px 必然溢出。
   按字号算 45 个字宽，两把尺子同时满足，且与正文的字数口径一致。 */
.dhead .loc.loc-p{ display:block; max-width:calc(45 * var(--fs-md)); }
.dhead .loc .sep{ width:1px; height:11px; background:var(--line); }
.dhead .loc .cert{ color:var(--ink); }
.dhead .tags{ margin-top:16px; display:flex; flex-wrap:wrap; gap:8px; }

/* 首屏右栏顶部的主操作：右对齐，正好压在数据表的上墨线上 */
.dtop-cta{ display:flex; justify-content:flex-end; margin-bottom:16px; }

/* ---------------- 楼盘详情：首屏（左图 + 右数据） ----------------
   两件事一起改：
   一、图。这批封面中位只有 750px 宽，满幅显示等于放大 1.9 倍 —— 越大越糊。
       现在图宽按源图像素封顶（--mw 由生成器逐页注入），比例夹在 1.0–1.6，
       宁可按比例缩，也不裁掉半栋楼。
   二、数据。原来六个格子四周全是竖线，像张表格。现在只用横线，
       标签在上、数字在下，右栏读起来像一页设备清单（spec sheet），
       而不是"参数更多的一段卡片"。 */
.dtop{
  /* 左栏宽度**跟着图走**，不写死比例（2026-10-21 实测）：
     原来写 minmax(0,1.28fr)，左栏恒为 694px；而图按源图比例开框、且不许放大
     （--mw 是源图原生宽），竖构图实测只有 438px 宽 —— 一张 438 的图占着 694 的栏，
     右边空出 256px，再加上 60px 的列间距，中间就是一条 316px 的白带，
     数据表孤零零挂在右边。老板的原话是「图片比例、布局一定要合理」。
     改成 fit-content(56%)：栏宽 = 图的实际宽度，上限仍是原来的 56%（横构图时
     与旧版完全一致，不引入回归）；竖构图时省下的宽度全部让给右栏。
     用百分比而不是固定 px，是因为 8903/2K/平板各档容器的宽度都不一样。 */
  display:grid; grid-template-columns:fit-content(56%) minmax(0,1fr);
  /* 必须是 stretch 不能是 start：start 让右栏高度=内容高度，
     下面 .dsum 的 margin-top:auto 没有可推的空间，结论句贴不到图的下沿。 */
  gap:clamp(36px,4.2vw,84px); align-items:stretch; margin-top:32px;
}
/* 题注不能反过来把栏撑宽：长楼名 + 长说明的 max-content 可以超过图宽，
   fit-content 会把整栏拉到题注的宽度，于是又出现那条白带。 */
.dfig{ min-width:0; }
.dfig figcaption{ min-width:0; flex-wrap:wrap; }
/* 没有实拍图（682 栋 / 30%）：占位块按 4:3 撑满左栏，页面结构与有图的页一致。
   不加这一段，空图框的 max-content 只有题注那点宽度，fit-content 会把左栏
   压到 115px、右栏拉到 1,121px，整页比例就全乱了。
   颜色刻意压到最淡：这是「没有」的说明，不该抢首屏。 */
.dfig-no{
  /* 宽度必须显式 100%：只写 aspect-ratio 时浏览器会为了满足 max-height
     反过来把宽度缩掉 —— 实测 726 的栏里只长了 362 宽的一块。
     比例取 16:9 而不是 4:3：这里没有照片，没必要为不存在的图预留 545px 高。 */
  width:100%; aspect-ratio:16/9; display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:8px; background:var(--paper2); border:1px solid var(--line2); text-align:center; padding:20px;
}
.dfig-no b{ font-family:var(--serif); font-weight:500; font-size:var(--fs-h3); color:var(--ink3); letter-spacing:.04em; }
.dfig-no span{ font-size:var(--fs-sm); color:var(--ink3); }
/* 无图页左栏不跟图走（没有图），固定回原来的 56% */
.dtop.nofig{ grid-template-columns:minmax(0,56%) minmax(0,1fr); }
.dfig{ margin:0; position:relative; }
.dfig img{
  width:100%; height:auto; display:block;
  /* 比例跟着源图走（--ar 由生成器按真实像素算，夹在 0.95–1.9）。
     原来这里写死 aspect-ratio:3/2 + max-height:58vh —— 两个约束一起上，
     宽不变、高被压，容器实际比例变成 1.56–1.9，一张 4:3 的楼被裁掉两成，
     一张方图被裁掉三成。所谓「拉宽」，在源码里其实是「框比图宽」。 */
  aspect-ratio:var(--ar,3/2);
  /* 高度上限改由宽度联动：宽 = 高上限 × 源图比例，比例恒定 ⇒ 零裁切。
     取 max-width 而不是 max-height，是因为后者会改比例（见上）。 */
  max-width:min(var(--mw,840px), calc(min(58vh,540px) * var(--ar,1.5)));
  object-fit:cover; object-position:var(--pos,50% 50%);
  filter:saturate(.96) contrast(1.02);
}
.dfig figcaption{
  display:flex; align-items:baseline; gap:12px; padding-top:12px;
  font-size:var(--fs-sm); color:var(--ink3); letter-spacing:.05em;
}
.dfig figcaption b{ font-weight:500; color:var(--ink); letter-spacing:.02em; }


/* 右栏：细横线清单 + 结论句 + 动作 */
/* 顶对齐，不是居中（2026-10-21 实测定案）：
   右栏是「按钮 + 四格数据 + 结论句」，实测高度恒定 324px；左图按源图比例开框、
   不许放大，实测高度在 324–572px 之间浮动（抽 8 页：324/324/324/438/513/572/572/572）。
   原来 justify-content:center，差的这截被**平分成上下两份空** —— 图高 572 的页面，
   右栏顶上 124px、底下 124px 全空，数据条孤零零浮在正中间，老板一句「布局不合理」。
   也试过 space-between：两端贴齐了，但数据条被夹在两块空白中间，还是浮。
   最后选顶对齐：按钮、数据、结论连成一块贴着图的上沿，多出来的高度整块留在底部
   —— 那一块空白紧挨着照片的下半截，眼睛把它读成「照片还没结束」，不是漏洞。
   图本来就矮（324）的页面没有余量，三种写法渲染结果完全一样，不引入回归。 */
.dtop-r{ min-width:0; display:flex; flex-direction:column; justify-content:flex-start; }
/* 特异性要压过 .dkpi（六列数据条），否则右栏又被排成一行六格 */
.dkpi.kpi2{
  grid-template-columns:1fr 1fr; border-top:1px solid var(--ink); border-bottom:1px solid var(--line);
}
.dkpi.kpi2 > div{ padding:16px 24px 16px 0; border-right:0; border-bottom:0; }
.dkpi.kpi2 > div:nth-child(2n){ padding-right:0; padding-left:24px; border-left:1px solid var(--line2); }
.dkpi.kpi2 > div:nth-child(n+3){ border-top:1px solid var(--line2); }
.dkpi.kpi2 dt{ font-size:var(--fs-xs); letter-spacing:.06em; color:var(--ink3); }
.dkpi.kpi2 dd{ margin-top:8px; font-size:calc(var(--fs-num) * var(--k)); white-space:nowrap; }
.dkpi.kpi2 dd em{ font-family:var(--sans); font-size:var(--fs-sm); color:var(--ink3); margin-left:4px; font-weight:400; }

.dsum{
  position:relative; margin:var(--sp-h2) 0 0; padding-top:20px;
  /* 不能贴底：右栏内容天然比左图矮，贴底会在「数据」与「结论」之间
     空出 160px，读起来像断了一截。紧跟数据就好，留白留在整块下沿。 */
  /* 宋体正文段全站只有一个重量：300。这里原来写 400，浏览器映射到 500，
     于是和隔壁 .db-lead（300）并排时一段细一段粗，同一层级两种重量。 */
  font-family:var(--serif); font-weight:300; line-height:1.75;
  letter-spacing:.01em; font-size:var(--fs-lg); color:var(--ink); max-width:28em;
}
.dsum::before{
  content:""; position:absolute; left:0; top:0; width:34px; height:2px; background:var(--brand);
}
/* 首屏行动区已撤：页头「索取可租面积与报价」+ 右侧粘性面板两个按钮已经够，
   再加一个文字入口，一屏三处都在促同一个动作，谁都不突出。 */

/* ---------------- 楼盘详情：数据条 ---------------- */
.dkpi{
  display:grid; grid-template-columns:1.34fr repeat(5,minmax(0,1fr));
  border-top:1px solid var(--ink); border-bottom:1px solid var(--line);
}
.dkpi > div{ padding:20px 24px 20px 0; border-right:1px solid var(--line2); }
.dkpi > div:last-child{ border-right:0; }
.dkpi dt{ font-size:var(--fs-sm); color:var(--ink3); letter-spacing:.04em; }
.dkpi dd{
  margin:8px 0 0; font-family:var(--serif); font-weight:500; line-height:1.25;
  font-size:calc(var(--fs-h3) * var(--k)); font-variant-numeric:tabular-nums;
}
.dkpi dd em{ font-style:normal; font-size:var(--fs-bs); color:var(--ink3); margin-left:2px; font-family:var(--sans); font-weight:400; }

/* ---------------- 楼盘详情：一句话结论 ---------------- */

/* 这段是详情页的「一句话结论」。原来写 400，浏览器取 500；
   而下一行的 .dlead p b 也是 500 —— 段内 <b> 的强调跟正文同重，
   一个像素都看不出来。正文退到 300，<b> 的 500 才重新变成强调。 */




/* ---------------- 楼盘详情：页内大纲条 ----------------
   为什么要有：详情页实测 25,000px 高、13 个小节，从首屏一路滚到底
   没有任何页内导航；右侧 344px 的转化侧栏是报价 / 经纪人 / 关于，
   不能拿来放目录。所以做一条吸顶大纲条。

   挂载位置：<main> 的直接子级，不在 .wrap 里。
   因为 .wrap 到 .dbody 就结束，吸顶会在 .dnear/.co/.dbelt 之前松开，
   最后三个小节（附近楼盘 / 数据出处 / 签约服务）就点不到了。
   挂 main 才能一路吸到 main 结束；通栏背景给 .dtoc 自己，内容宽度给 .dtoc-in。

   跳转不用 JS：靠下面 .dsec 的 scroll-margin-top 让出「头部 76 + 条高 52」。
   JS 只负责把当前节标成 aria-current。 */
.dtoc{
  position:sticky; top:76px; z-index:var(--z-chrome);
  background:var(--paper); border-bottom:1px solid var(--line);
  /* 上边和 .dbody 的 56px 内边距之间不要多出一条缝：负 1px 吃掉自己的下边框 */
  margin:0;
}
.dtoc-in{
  max-width:var(--w); margin:0 auto; padding:0 32px;
  display:flex; align-items:center;
  height:52px; overflow-x:auto; overflow-y:hidden;
  scrollbar-width:none; -ms-overflow-style:none;
  -webkit-overflow-scrolling:touch;
}
.dtoc-in::-webkit-scrollbar{ display:none; }
.dtoc-i{
  position:relative; flex:0 0 auto;
  display:inline-flex; align-items:center;
  height:52px; padding:0 12px;
  font-size:var(--fs-sm); line-height:1; color:var(--ink3);
  text-decoration:none; white-space:nowrap;
  transition:color .18s ease;
}
/* 不要前面的小圆点：横排里 13 个点只会变成噪声，指示器交给底部那根红线 */
.dtoc-i > i{ display:none; }
.dtoc-i::after{
  content:""; position:absolute; left:12px; right:12px; bottom:0; height:2px;
  background:var(--brand);
  transform:scaleX(0); transform-origin:left center;
  transition:transform .22s ease;
}
.dtoc-i:hover{ color:var(--ink); }
/* 当前节只换颜色 + 亮红线，不加粗：
   加粗会让文字宽度变化，滚动时整条目录左右抽搐。 */
.dtoc-i[aria-current="true"]{ color:var(--ink); }
.dtoc-i[aria-current="true"]::after{ transform:scaleX(1); }
.dtoc-i:focus-visible{ outline:2px solid var(--brand); outline-offset:-6px; }

/* 锚点让位：走 --anchor 这个令牌，不在小节上再写死一个像素数。
   ed.css 里已经有 `:target,[id]{ scroll-margin-top:var(--anchor) }`，
   pages.css 又有 `#units{ scroll-margin-top:var(--anchor) }`（id 优先级压过
   任何类选择器）—— 所以在小节上写 scroll-margin-top 是抢不过 #units 的，
   第一版就是这么错的：#units 仍按全局 89px 落位，正好被 53px 的条压住。
   正确做法是把令牌在**祖先**上调高，让它继承下去，两条规则就一起生效了。

   为什么用兄弟选择器而不是 :has()：.dtoc 是 <main> 的直接子级，
   详情页要管的 .wrap / .dnear / .co / .dbelt 全是它后面的兄弟或后代。
   而 .co / .dnear / .dbelt 在 xiezilou、area 这些落地页也有（那些页没有
   大纲条），所以不能无条件改 —— 兄弟选择器天然只命中挂了条的页。 */
.dtoc ~ .wrap .dmain,
.dtoc ~ .dnear, .dtoc ~ .co, .dtoc ~ .dbelt{ --anchor:141px; }

/* 矮屏（≤700px 高）头部会缩到 64，条要跟着上移，否则中间漏 12px 正文 */
@media (max-height:700px){
  .dtoc{ top:64px; }
  .dtoc ~ .wrap .dmain,
  .dtoc ~ .dnear, .dtoc ~ .co, .dtoc ~ .dbelt{ --anchor:129px; }
}
/* 手机：13 个短标签一行放不下（约 900px），条内横向滚动。
   滚动条已隐藏，靠右侧渐隐提示「还能往右滑」。
   渐隐只加在手机上 —— 桌面一行放得下，多一层遮罩反而脏。 */
@media (max-width:760px){
  .dtoc-in{
    height:48px; padding:0 20px;
    -webkit-mask-image:linear-gradient(90deg,#000 0,#000 calc(100% - 28px),transparent 100%);
            mask-image:linear-gradient(90deg,#000 0,#000 calc(100% - 28px),transparent 100%);
  }
  .dtoc-i{ height:48px; padding:0 11px; }
  .dtoc-i::after{ left:11px; right:11px; }
  .dtoc ~ .wrap .dmain,
  .dtoc ~ .dnear, .dtoc ~ .co, .dtoc ~ .dbelt{ --anchor:137px; }
}

/* ---------------- 楼盘详情：正文双栏 ---------------- */
.dbody{ display:grid; grid-template-columns:minmax(0,1fr) 344px; gap:72px; padding:56px 0 0; align-items:start; }
.dmain{ min-width:0; }

/* 每段之间原来是一条 1px 均匀的 --line，从左贯到右、两端硬切。
   22,240 个房源页 + 2,270 个楼盘页上，这条线出现十几次，每次都一样重，
   整页读下来是一排等号。改成从深到浅、82% 处淡出的单线（v3.1）：
   左边接住标题的墨色，右边自然消失在纸里 —— 视线会顺着它往下走，
   而不是被一条水平线一次次截断。伪元素画的，布局尺寸一个像素没动。 */
.dsec{ padding:32px 0 40px; position:relative; border-top:0; }
.dsec::before{
  content:""; position:absolute; inset:0 0 auto 0; height:1px; pointer-events:none;
  background:linear-gradient(90deg,var(--ink4),var(--line) 34%,transparent 82%);
}
/* 第一个 dsec 用一条实心墨线（它接在图集/结论块下面，是「正文开始」的分界）。
   这里必须把 ::before 关掉：那条渐隐线画在 border 内侧 1px 处，
   不关就等于墨线下面再压一条灰线，实测看着像 2–3px 的粗杠。 */
.dmain > .dsec:first-child{ border-top:1px solid var(--ink); padding-top:32px; }
.dmain > .dsec:first-child::before{ display:none; }
.dsec h2{
  display:flex; align-items:center; gap:20px;
  /* flex-wrap:wrap（2026-10-29）。320px 下 h2 的副标题 `.side` 是 flex:0 0 auto
     （不收缩），"月租约 11.24 万元/月 · 6.9 元/㎡/天" 这一条撑到 right=335，
     把 documentElement.scrollWidth 顶到 335 —— 整个页面横向滚动 15px。
     实测 800 页抽样里 294 页在 320 下溢出，根因基本都是这一条。
     加 wrap 之后空间不够就换行，330px 以上空间足够，行为完全不变（已逐宽验证）。 */
  flex-wrap:wrap;
  font-family:var(--serif); font-size:calc(var(--fs-h3) * var(--k)); font-weight:500; letter-spacing:var(--ls-h2);
  /* 以前没写行高，从 .dtxt 的 2.05 继承成 42px —— 24px 的标题被撑到 1.75，
     标题与正文之间（--sp-h2:26px）反而比标题内部的行距还紧，层级读不出来。
     统一走 --lh-h2。 */
  line-height:var(--lh-h2);
}
.dsec h2::after{ content:""; flex:1 1 auto; height:1px; background:var(--line); }
.dsec h2 .side{ order:3; flex:0 0 auto; font-family:var(--sans); font-size:var(--fs-sm); font-weight:400; color:var(--ink3); letter-spacing:.06em; }

/* 「暂未取得地铁数据」这种补充段落与上一段只差一行呼吸，别再用内联 margin */
.dtxt.gap{ margin-top:16px; }
.dtxt{ margin-top:20px; font-size:var(--fs-base); line-height:1.9; color:var(--ink2); max-width:64ch; }
.dtxt p + p{ margin-top:16px; }
.dtxt strong{ font-weight:500; color:var(--ink); }
/* 表格注脚：不是正文，是脚注。字号降一档、颜色退一档、与表格贴紧 */
/* max-width 是 measure 约束（约 44 个字）。没有它，1360 宽的页面上一条脚注能排到
   86 个字，眼睛回行会串行。2026-10-22 由闸门「每行 86 字（>46）」抓出来。 */
.dtnote{ margin-top:16px; font-size:var(--fs-sm); color:var(--ink3); letter-spacing:.02em; max-width:44em; }
/* 同一段注脚被拆成两句时，第二句不能再吃一次 margin-top ——
   那 14px 是「注脚与上文的距离」，不是「注脚句与句的距离」。 */
.dtnote + .dtnote{ margin-top:8px; }

/* 可租单元：只有后台录了单元才出现（没录就整块不渲染，不留空表）。
   视觉上跟「楼宇参数」同一套语言 —— 发丝线、无斑马纹、表头一条实线压顶。
   这一块是数据，不是卖点，不该比参数表更抢眼。 */
/* 在租房源：一行一套 —— 左图 · 中间信息 · 右价格。
   主栏只有 780 左右宽，做两列卡片墙会得到 340 的小卡：面积数字、装修标签、
   描述挤在一行里谁都读不顺。改成一列清单，一行只说一套房，
   十套在一屏半里排完，眼睛只往下走，横向不用找。 */
/* 在租房源：一行一套 —— 中间信息 · 右价格。
   ⚠ 2026-10-21：原来左侧还有一张 168×126 的缩略图，已撤。
   素材只有整栋的 3–5 张实拍，十套轮着用，同一张楼栋照片在一页里出现三四次，
   两行并排一模一样，看着像复制粘贴出错；而且它拍的也不是这一套。
   页顶「照片 N 张」已经把楼栋实拍给足了，这一节只留数据。
   撤掉之后行高从 145 降到约 96，十套一屏半就能扫完。 */
/* ⚠ 2026-11-02：这里原来有 `max-width:940px`，已撤。
   940 是「1440 屏、主栏 880」那个年代的余量值，当时主栏比它宽不了多少，
   所以看不出问题。而详情页是宽栏 + 344px 侧栏，主栏跟着 --w 一起长：
   1920 屏主栏 1200、2560 屏 1480，列表却还钉在 940 ——
   右边白出 260 / 540px，且同一节里三种右缘（标题线到 982、统计卡到 1200、
   列表到 1085），看着像没排完。老板原话：「列表右边有很大的留空」。
   列表宽度的正解就是主栏宽，不该有第二个数。 */
.dul{ margin-top:24px; border-top:1px solid var(--ink); }
/* 题头的「看 10 套在租房源」跳到这一节：不设偏移，标题会被吸顶栏压掉一半。
   2026-10-23：原本这里写 82、全局写 89、服务页卡写 96 —— 统一走 --anchor。 */
#units{ scroll-margin-top:var(--anchor); }
.dur{
  display:grid; grid-template-columns:108px minmax(0,1fr) 150px; gap:24px;
  align-items:center; padding:16px 0; border-bottom:1px solid var(--line2);
  transition:background-color .18s var(--ease);
}
/* 行主图（v6.0，2026-10-23）。老板要求「每一条房源要有主图」。
   图只来自这一套自己的 u.photos —— 本栋图十行轮着用会像复制粘贴出错
   （2026-10-21 就是因为这个撤掉过缩略图）。
   几何：固定 108×81 的相框，图**contain** 放进框里。
   为什么不用 object-fit:cover：角标水印压在图片底部，一裁就没了；
   W09 那条「框比例 == 源图比例」的判据管不到这个框（框是固定的 4:3），
   所以这里用 contain 保证**永远不裁** —— 不裁就不存在「把角标裁掉」这件事。
   框底用 paper3，留白读起来像装裱的照片而不是没铺满的图。 */
.dur-t{ width:108px; height:81px; margin:0; background:var(--paper3); overflow:hidden; }
.dur-t .gal-btn{ width:100%; height:100%; display:flex; align-items:center; justify-content:center; }
.dur-t img{ display:block; width:auto; height:auto; max-width:100%; max-height:100%; }
/* 没有本套实拍时的图签：不是灰块、不是裂图，是一枚明说「还没入库」的纸牌。
   图一进 u.photos，同一行自动换成真图，版式不动。 */
.dur-tph{
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4px;
  border:1px solid var(--line2); color:var(--ink3);
}
.dur-tph em{ font-style:normal; font-size:var(--fs-xs); letter-spacing:.04em; color:var(--ink3); }
.dur-tph svg{ width:16px; height:16px; opacity:.55; }
/* 行本身不可点（只有右边的「问这套」可点），但鼠标扫过一行时给一条浅底，
   让人知道这一行是一个整体、右边那个按钮属于它。 */
.dur:hover{ background:var(--paper2); }
.dur-h{ display:flex; align-items:baseline; flex-wrap:wrap; gap:8px; }
.dur-a{
  font-family:var(--sans); font-size:var(--fs-h3); font-weight:400; line-height:1.1;
  color:var(--ink); font-variant-numeric:tabular-nums; letter-spacing:-.01em;
}
.dur-a em{ font-style:normal; font-size:var(--fs-bs); color:var(--ink3); margin-left:2px; }
.dur-fit{ font-size:var(--fs-xs); color:var(--ink2); border:1px solid var(--line3); padding:2px 8px; letter-spacing:.04em; }
/* 「待核」和价格单位都不能用 ink4：14px 以下的小字，ink4 在纸底上只有 2.78:1，闸门会判红 */
.dur-d{ margin-top:8px; font-size:var(--fs-bs); color:var(--ink2); line-height:1.9; max-width:46em; }
.dur-r{ display:flex; flex-direction:column; align-items:flex-end; gap:8px; text-align:right; }
.dur-p{
  font-family:var(--sans); font-size:var(--fs-num); color:var(--ink);
  font-variant-numeric:tabular-nums; line-height:1.25;
}
.dur-p em{ display:block; font-style:normal; font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.04em; margin-top:1px; }
.dur-m{ font-size:var(--fs-xs); color:var(--ink3); font-variant-numeric:tabular-nums; }
.dur-ask{
  display:inline-flex; align-items:center; justify-content:center;
  min-height:34px; padding:0 16px; border:1px solid var(--line3);
  color:var(--ink); font-size:var(--fs-sm); text-decoration:none; transition:border-color .18s var(--ease);
}
.dur-ask:hover{ border-color:var(--ink); }
.dul-lead{ margin-top:16px; font-size:var(--fs-base); color:var(--ink2); line-height:1.9; max-width:64ch; }
/* 18px 是这一段与标题的距离。拆成多句之后，句与句之间只要 6px ——
   再给 18px 会把「一段话」读成「三段互不相干的话」。 */
.dul-lead + .dul-lead{ margin-top:8px; }
.dul-lead b{ font-weight:500; color:var(--ink); }

/* ── 本栋在租统计（2026-10-22）────────────────────────────────────────
   对标搜楼楼盘页的「本楼盘在租面积 / 本楼盘平均租金」两组统计卡。
   这里不另起卡片体系，仍走纸面 + 细线，与参数表 .dl2 同一套语言：
   一栏一个数，数字用无衬线等宽数位，单位退到右侧小字。 */
.dstat{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(128px,1fr));
  margin-top:24px; max-width:100%;
  border-top:1px solid var(--line2); border-bottom:1px solid var(--line2);
}
.dstat > div{ padding:12px 16px 12px 0; }
.dstat > div + div{ padding-left:16px; border-left:1px solid var(--line2); }
.dstat dt{ font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.04em; }
.dstat dd{
  margin-top:8px; font-family:var(--sans); font-size:var(--fs-md); line-height:1.25;
  color:var(--ink); font-variant-numeric:tabular-nums; letter-spacing:-.01em;
}
.dstat dd em{ font-style:normal; font-size:var(--fs-xs); color:var(--ink3); margin-left:4px; letter-spacing:.02em; }

/* ── 排序 / 面积筛选（2026-10-22）──────────────────────────────────────
   按钮沿用界面上既有的细线方角语言：无填充、2px 圆角、选中态只加深墨线。
   不引入 pill、不做彩色填充 —— 这一页只有两处深色块，不能被一排按钮破坏。
   最小高度 34px 是桌面值，手机上按全站触控下限提到 44px。 */
.dul-tools{
  display:flex; align-items:center; justify-content:space-between;
  gap:16px; flex-wrap:wrap; margin-top:24px; max-width:100%;
}
.dul-f, .dul-s{ display:flex; flex-wrap:wrap; gap:8px; }
.dul-s{ margin-left:auto; }
.dul-tools button{
  font-family:var(--sans); font-size:var(--fs-xs); line-height:1;
  color:var(--ink2); background:none; cursor:pointer;
  border:1px solid var(--line3); border-radius:var(--r-1);
  padding:8px 12px; min-height:34px;
  font-variant-numeric:tabular-nums;
  transition:color .16s var(--ease), border-color .16s var(--ease), background-color .16s var(--ease);
}
.dul-tools button:hover{ color:var(--ink); border-color:var(--ink2); }
.dul-tools button.on{ color:var(--ink); border-color:var(--ink); background:var(--paper2); }
.dul-tools button:focus-visible{ outline:2px solid var(--ink); outline-offset:2px; }
/* 被筛掉的行整行消失，不留空槽 */
.dur[hidden]{ display:none; }
.dul-empty{ margin-top:16px; font-size:var(--fs-bs); color:var(--ink2); line-height:1.9; max-width:56ch; }

@media (max-width:760px){
  /* ⚠ 2026-11-02：`.dur` 的六条（网格 84/1fr、图 84×63、价格落底横排、
     .dur-a 字号、.dur-d 间距）已搬到 premium.css 末尾。
     原因：premium.css 在 pages.css 之后加载，里面 478 行有 `.dur` 的
     基础规则（132/1fr/158），同特异性、更靠后 —— 写在这里的手机规则
     一条都赢不了，只是看着像在管手机。实测 390 屏下描述列只剩 55px。
     断点阶梯必须集中在最后定义它的那一层，中间层写等于没写。 */
  /* 手机上一排筛选按钮放不下六档：改成单行横滑，不做换行堆高 ——
     换行会占去两到三行，把第一套房源挤出首屏。 */
  .dul-tools{ margin-top:20px; gap:8px; }
  .dul-f{ flex-wrap:nowrap; overflow-x:auto; padding-bottom:4px; -webkit-overflow-scrolling:touch; scrollbar-width:none; }
  .dul-f::-webkit-scrollbar{ display:none; }
  .dul-f button{ white-space:nowrap; }
  .dul-tools button{ min-height:44px; padding:12px 12px; }
  .dul-s{ margin-left:0; }
  .dstat{ grid-template-columns:1fr 1fr; }
  .dstat > div{ padding:12px 12px 12px 0; }
  .dstat > div:nth-child(odd){ padding-left:0; border-left:0; }
  .dstat > div:nth-child(even){ padding-left:12px; border-left:1px solid var(--line2); }
  .dur-ask{ min-height:40px; padding:0 16px; }
  /* 房源节尾的顾问带子：390 宽放不下「一句话 + 按钮」并排，改成上下两行，按钮撑满 */
  .dul-ag{ flex-direction:column; align-items:stretch; gap:16px; padding:16px 16px; }
  .dul-ag-t{ justify-content:center; }
}

/* 「看楼前必读」：三行，左标签右判断。不做卡片、不用底色 ——
   这一段的价值在信息本身，包一层边框只会让它看起来像广告位。
   ⚠ 选择器一律带 `.dread-l` 前缀（2026-10-21 修）：原来写的是 `.dread li`，
   加了右栏之后这批规则**把右栏的 `.dnb li` 也一起命中了** ——
   网格把 `<a>` 压成 132px（正是一列的宽），楼名的小 `<b>` 又被改成
   sans 400/13px，于是右栏每条参数每行只剩 9 个字。
   `audit_craft` 报了 173 条「正文每行只有约 9 个字」，最重的 15 页全部是大楼页。
   **往同一个容器里加新子块之前，先 grep 这个容器下的所有后代选择器。** */
.dread-l ul{ margin-top:4px; }
.dread-l li{ display:grid; grid-template-columns:132px minmax(0,1fr); gap:20px; padding:16px 0; border-top:1px solid var(--line2); }
.dread-l li:first-child{ border-top:0; padding-top:16px; }
.dread-l li b{ font-family:var(--sans); font-size:var(--fs-bs); font-weight:400; color:var(--ink); letter-spacing:.02em; padding-top:1px; }
/* 一行判断最多两句，拆开之后仍是同一行的一个判断，句间 8px 就够 */
.dread-l li p + p{ margin-top:8px; }
.dread-l li p{ font-size:var(--fs-bs); color:var(--ink2); line-height:1.9; max-width:42em; }
@media (max-width:760px){
  /* 132 的标签列在 390 宽里会占掉三分之一，判断只剩两三个字一行 */
  .dread-l li{ grid-template-columns:minmax(0,1fr); gap:8px; padding:16px 0; }
}

/* 「看楼前必读」右栏：同商圈另外几栋的对照清单（2026-10-21）。
   这块不是新加的一节 —— 这一节原来右边是空的（880 的栏里正文只占 520 左右），
   副标题写着「与同类写字楼对照」，右栏正好把这句话兑现。 */
.dread-2{ display:grid; grid-template-columns:minmax(0,1fr) 300px; gap:56px; align-items:start; }
.dread-r{ border-left:1px solid var(--line2); padding-left:32px; }
.dnb-h{
  display:flex; justify-content:space-between; align-items:baseline; gap:12px;
  font-size:var(--fs-sm); color:var(--ink3); letter-spacing:.06em;
}
.dnb-h span{ font-size:var(--fs-xs); letter-spacing:.04em; }
/* 右栏里的第二组清单（虹口那 2 栋：邻居只有 1 栋，剩下的空位放本楼在租）。
   两组清单之间要有一条线，否则下面的「面积」会被读成上面那栋楼的参数。 */
.dnb-h2{ margin-top:24px; padding-top:20px; border-top:1px solid var(--line2); }
.dnb{ margin-top:8px; }
.dnb li + li{ border-top:1px solid var(--line2); }
.dnb a{ display:block; padding:12px 0; }
.dnb b{ display:block; font-family:var(--serif); font-size:var(--fs-base); font-weight:500; letter-spacing:.02em; }
.dnb a:hover b{ color:var(--brand); }
.dnb-m{ display:block; margin-top:4px; font-size:var(--fs-sm); color:var(--ink3); line-height:1.75; letter-spacing:.02em; }
.dnb-more{
  display:inline-flex; align-items:center; min-height:32px; margin-top:16px;
  font-size:var(--fs-bs); color:var(--ink2); border-bottom:1px solid var(--ink); padding-bottom:4px;
}
.dnb-more:hover{ color:var(--brand); border-color:var(--brand); }
/* 2026-10-27：深色带的「看某区全部 →」在手机上只有 32 高。
   它落在深色底上，是这一块唯一的出口，手指落点要给够 40。 */
@media (max-width:760px){ .dnb-more{ min-height:40px; } }

/* 房源页：同商圈相近面积，三格平铺 */
/* 同商圈相近面积：从「一条上横线 + 三列裸文字」改成三张卡片（2026-10-21）。
   原来这一段和上面的参数表、再上面的正文全是同一层灰字，整页看起来「一片」——
   老板原话。卡片给的是**面**而不是**线**：底色 --paper2、描边 --line3、
   hover 换白底 + --ink4 描边，视线能立刻分清「这是另一组房源」。 */
.ucross{ display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:16px; margin-top:16px; }
/* 卡片内边距挪进 .uc-bd（v7.0）：图要压到卡片边（出血），文字仍留白。
   写在 li 上的话，图会被 20px 的 padding 缩成一张带框的邮票。 */
.ucross li{ padding:0; border:1px solid var(--line3); background:var(--paper2); transition:border-color .18s var(--ease), background .18s var(--ease); }
.ucross li:hover{ border-color:var(--ink4); background:var(--white); }
.ucross a{ display:block; min-height:44px; }
.ucross .uc-bd{ padding:16px 20px 20px; }
/* 卡片主图 16:10。不用 4:3：楼栋图与室内图的常见比例是 1.33–1.78，
   16:10 落在这段的中间，裁掉的最少；竖图（0.81）会裁掉一半高度，
   所以图注角标必须写清「楼栋」还是「本套」—— 客户靠它判断自己在看什么。 */
.ucross .uc-f{
  margin:0; position:relative; aspect-ratio:16/10; overflow:hidden;
  background:var(--paper3);
}
.ucross .uc-f img{
  /* ⚠ 焦点从 44% 改成 100%（2026-10-24）：框是 16:10，横图 P50 只有 1.5 ——
     纵向必然裁 6.25%，居中偏上裁时**下沿被切掉 3.5%**，而水印的 slogan logo
     就压在下沿。改成底部对齐：裁切全落到天花板那侧，logo 完整。
     室内实拍裁掉一点天花板，比「图上有水印但被切了一半」代价小得多。 */
  width:100%; height:100%; object-fit:cover; object-position:50% 100%;
  display:block; transition:transform .4s var(--ease);
}
.ucross li:hover .uc-f img{ transform:scale(1.03); }
/* 角标底色 78% 墨、白字，与 .frm-no / .dh-more 同一档：
   按最坏情况（底图纯白）算约 9:1，任何照片上都读得清。 */
.ucross .uc-tag{
  position:absolute; right:8px; bottom:8px; z-index:var(--z-raised);
  padding:2px 8px; font-size:var(--fs-xs); line-height:1.5; letter-spacing:.06em;
  color:var(--white); background:rgba(var(--ink-rgb),.78);
}
.ucross b{ display:block; font-family:var(--serif); font-size:calc(var(--fs-h3) * var(--k)); font-weight:500; letter-spacing:.02em; font-variant-numeric:tabular-nums; }
.ucross b em{ font-style:normal; margin-left:2px; font-family:var(--sans); font-weight:400; font-size:var(--fs-bs); color:var(--ink3); }
.ucross .uc-a{ display:block; margin-top:8px; font-size:var(--fs-bs); color:var(--ink2); line-height:1.75; }
.ucross .uc-d{ display:block; margin-top:4px; font-size:var(--fs-sm); color:var(--ink3); }
.ucross .uc-p{ display:block; margin-top:8px; font-size:var(--fs-bs); color:var(--ink2); }
.ucross a:hover b{ color:var(--brand); }

@media (max-width:980px){
  /* 单列以后「左栏 · 竖线 · 右栏」这套并列关系不存在了，竖线改成一条上边线 */
  .dread-2,.ucond{ grid-template-columns:minmax(0,1fr); gap:24px; }
  .dread-r{ border-left:0; padding-left:0; padding-top:24px; border-top:1px solid var(--line2); }
  .ucross{ grid-template-columns:repeat(2,minmax(0,1fr)); }
}
@media (max-width:760px){
  .ucross{ grid-template-columns:minmax(0,1fr); }
  .ucross .uc-bd{ padding:16px 16px 16px; }
  .ucross b{ font-size:var(--fs-lg); }
}

/* 参数表：右侧单列表，标签左值右，扫读最快 */
/* 数据表：spec sheet（标签在上、值在下、三格一行）。
   原来做「标签左 · 值右对齐」，右对齐的长值（"流动车位 1,000 元/月 固定车位 2,000 元/月"）
   会把标签甩到 40px 之外，每行右边缘参差不齐，像一张没排版的 Excel；
   而且 dt/dd 用同一号字，读的人要靠"右对齐"去猜哪两个是一对。
   现在值左对齐、标签降一级、三格一行，右边缘是一条直线，纵向能扫。 */
.dl2{ margin-top:16px; display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:0 44px; }
.dl2 .i{ display:flex; flex-direction:column; gap:8px; padding:16px 0 16px; border-top:1px solid var(--line2); }
.dl2 dt{ font-size:var(--fs-sm); color:var(--ink3); letter-spacing:.02em; }
.dl2 dd{ margin:0; font-size:var(--fs-lg); color:var(--ink); line-height:1.75; text-wrap:balance; font-variant-numeric:tabular-nums; overflow-wrap:anywhere; }
.dl2 dd.na{ color:var(--ink3); font-size:var(--fs-md); }

/* 参数图标（2026-10-21）：由 portal.js 按标签文字注入到每个 <dt> 前面，
   全站只有那一份映射。这里只管几何与颜色 —— 描边、14px、比标签再淡一档
   （--ink4），让它像「标记」而不是「内容」。dt 原来是块级，加图标后必须
   转成 flex，否则 svg 会自己占一行、把标签挤到下面。 */
.dl2 dt,.dkpi dt,.dkpi.kpi2 dt{ display:flex; align-items:center; gap:8px; }
.ic{
  width:14px; height:14px; flex:none;
  fill:none; stroke:currentColor; stroke-width:1.4;
  stroke-linecap:round; stroke-linejoin:round;
  /* 和标签同色（--ink3）而不是更淡一档：14px 的描边线在纸上本来就细，
     再压到 --ink4 就只剩一个灰点，等于没画。 */
  color:var(--ink3);
}

/* 正文内插图墙 */
/* 图集：两列 3:2。原来是三列 4:3，每张只有 220px 宽 —— 页面上真正能看清的图
   只剩首屏那一张，中段全是字。改成两列之后每张 660×440，和主图一个量级，
   页面中段有了节奏；源图 750px 宽，倍率 1.14，也不虚。 */
/* 三张一组、三列并排。
   原来两列 + "奇数张时最后一张跨两列"，跨列那张在 1920 屏上要 1680 宽，
   可手里这批照片最大 846 宽 —— 750px 的图被拉到 2.2 倍，一眼糊（闸门实测 0.45×）。
   三列每格 558，源图 750–846 正好是缩小着用，既不发虚也不留空格。 */
/* 图集：图片 + 图下说明。
   说明试过三种：实心白底压图（像相册水印）、白字压图（碰上亮背景就糊，
   对比度闸门实测 1.12:1）、渐变遮罩 + 白字（能读，但多一层叠加要维护）。
   最后回到最简单的：说明放在图下面，用站点正文的灰。
   和首屏主图的 figcaption 同一套读法，也不再有任何叠加层。 */
/* 图集：两栏瀑布，每张按自己的比例落位（--ar 由生成器按真实像素写入）。
   为什么不是等宽网格：网格必须给每格定一个比例，而定成 3:2 就要裁 —— 4:3 的
   裁 11%、方图裁 33%，楼被切掉一角，读起来就是「图被拉扁了」。全按原比例
   塞进网格又会出现 291 高、153 高、218 高混排 + 第二行左侧一大块空白。
   两栏瀑布流两头都不占：列宽相等、图不裁不拉、列高自然，而且每张 620 宽 ——
   比三栏的 279 大一倍，源图 750 还是缩小着用，看得清。
   说明文字跟着图走（不用 flex，columns 里 flex 子项会被拆到两列）。 */
/* ⚠ 2026-10-21 二次改造：columns 换成 grid。
   columns:2 是「两列各自往下流」—— 左列第 1 张和右列第 1 张会并排出现在同一
   高度上，但它们是两个独立的流，高度各长各的。实测 golden-banks-610 那一行
   并排的是 0.63 竖幅与 1.78 横幅，底边差 182px，像没排完。
   栅格不一样：同一行的两项天生共享行高。配合生成器里「按比例排序 + 同行取
   比例均值」，行内两图高度完全相等，而每张的裁切损失都在 15% 以内。
   奇数张时最后一行只坐一张 —— 栅格标准的半行留白，不会被看成排错。 */
.dgal{ margin-top:32px; max-width:1440px; }
/* 一行一个 flex 容器，列宽按源图比例分配（flex-grow 取 --g），于是：
     宽_i = 行宽 × 比例_i / Σ比例   ⇒   高_i = 宽_i / 比例_i = 行宽 / Σ比例
   行内每张图高度必然相等，而每张图的**框比例等于它自己的源图比例** ⇒ 裁切为零。
   之前是等宽栅格 + 整行共享一个比例，竖幅图（源 0.67 对框 0.95）被 cover
   居中裁掉两三成 —— 角标水印就在底部，实测 151 张里 44 张的角标被裁掉或裁一角。
   等宽列与零裁切在数学上不可兼得：宽相等 + 高相等 ⇒ 框比例必须唯一。 */
.dgal-row{ display:flex; gap:24px; margin-top:24px; align-items:flex-start; }
.dgal-row:first-child{ margin-top:0; }
/* 折叠（v6.0）：前 3 行先给足，其余折起来。
   默认按钮 display:none、多余行照常显示 —— 折叠这件事只由 JS 加上的
   .is-fold 触发。没有 JS 就是「16 张全展开」，不会出现「图被藏了、按钮也点不动」。
   按钮 44 高是因为它落在触屏上就是主要操作之一（另一处是首屏「看这一套」）。 */
.dgal-more{
  display:none; align-items:center; gap:8px;
  min-height:44px; margin-top:24px; padding:0 24px;
  border:1px solid var(--line3); background:none; color:var(--ink);
  font-family:inherit; font-size:var(--fs-sm); letter-spacing:.02em; cursor:pointer;
  transition:border-color .18s var(--ease), background-color .18s var(--ease);
}
.dgal-more em{ font-style:normal; font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.04em; }
.dgal-more:hover{ border-color:var(--ink); background:var(--paper2); }
.dgal-more:focus-visible{ outline:2px solid var(--ink); outline-offset:2px; }
.dgal.is-fold .dgal-more{ display:inline-flex; }
.dgal.is-fold .dgal-row[data-more]{ display:none; }
.dgal-row figure{ margin:0; flex:var(--g,1.33) 1 0%; min-width:0; }
/* 每张图的框比例由生成器写成 --g，且**必须等于该图自己的源图比例**。
   ⚠ 不要再给 --g 加 0.95 / 1.6 这类夹逼：夹逼等于统一裁切，
     竖幅图会被 cover 切掉底部，把右下角的水印一起切走。 */
.dgal img{ width:100%; height:auto; max-width:var(--mw,100%); aspect-ratio:var(--g,1.33); object-fit:cover; display:block; background:var(--paper3);
  /* 内描边（v3.1）：图集里白墙、玻璃幕墙、天空这三种画面直接压在纸底上时，
     边缘会融进背景，一张 660 宽的图看着像没有边界。1px 的 10% 墨线把它钉住。
     outline 不占布局 —— 这条判据很硬：W09 量「框比例 == 源图比例」，
     换成 border 会让 660×440 变成 662×442，比例偏 0.3%，批量擦线。 */
  outline:1px solid rgba(var(--ink-rgb),.10); outline-offset:-1px; }

/* 可放大：按钮只做一层命中区，视觉与直接放一张 img 完全一致。
   不用 <a href="图片">：点开会跳到原图页，看完要按返回，带看时来回丢位置。 */
.gal-btn{ display:block; width:100%; padding:0; border:0; background:none; cursor:zoom-in; color:inherit; }
/* ── 焦点环：这类按钮**必须把环画在 <img> 上**（2026-10-25 实测）
   坑很深，写清楚免得后人再踩：
     · 环画在 button 上（outline）→ 图片作为子元素盖在 outline 之上，
       正偏移 3px 还被祖先 .frm{overflow:hidden} 裁掉，改成 -3px 内偏移依然不可见；
     · 环用 button 的 inset box-shadow → 一样被图片盖住。
       实测差异像素只有 **3 个**（就是边角渲染噪声），等于没有。
     · ::after 描边层也不可靠。
   **图片是最后绘制的，所以环必须画在图片自身上。** 给 img 加 outline + 负偏移，
   环落在图片边缘内侧，必然可见（实测差异像素 5,559，最大通道差 240）。
   outline 是画在元素自身内容之上的：给 img 加，它就压在图片位图上面。 */
.gal-btn:focus-visible img{
  outline:2px solid var(--brand); outline-offset:-3px;
}
.dfig .gal-btn{ width:auto; }

/* ── 平面图 ──────────────────────────────────────────────
   图纸和实景是两种东西：实景看观感，图纸看「能切多大、哪里是核心筒」。
   所以不塞进瀑布（620 宽的图纸上，单元面积那行字会糊成一条线），
   单独一块、缩略图排开、点开按原尺寸看。 */
.dplan .dp-list{
  display:grid; grid-template-columns:repeat(auto-fill,minmax(210px,1fr));
  gap:24px 16px; margin-top:20px;
}
.dp-list figure{ margin:0; }
.dp-btn{
  position:relative; display:block; width:100%; padding:0;
  border:1px solid var(--line); background:var(--white); cursor:zoom-in;
}
.dp-btn:focus-visible{ outline:2px solid var(--brand); outline-offset:2px; }
/* ⚠ 补 :hover（2026-10-26）。实测这一处只有 :active 与 :focus-visible，
   鼠标移上去页面**毫无反应** —— 而它旁边同样是放大按钮的 .gal-btn
   有 `.gal-btn:hover img{transform:scale(1.035)}`。
   不能照抄那条：这里的图纸是 object-fit:contain、框高写死 200，
   transform 放大会溢出边框（且 img 尺寸不变，视觉上只是图被框切了一角）。
   所以给它「框类元素」的反馈：描边加深一档。--line-hover 就是为这件事定义的。
   依据：Apple HIG / Material 3 要求任何可点元素在 hover 时必须有可见状态变化。 */
.dp-btn:hover{ border-color:var(--line-hover); }
/* contain 不裁：平面图被切掉一个角，等于把消防通道切没了，客户会看错。
   框高给到 200，宽图竖图都在里面完整露出来，留白由白底兜住。 */
/* 框高写死 200：图纸有横有竖，高度各随其比例的话，同一行会一高一低，
   读起来像排版掉了一格。固定框 + contain，图完整、行整齐。 */
.dp-btn img{
  display:block; width:100%; height:200px;
  object-fit:contain; object-position:center top;
}
/* 图注只写图纸名；「点开看原图」放到区块标题右侧写一次 ——
   八张图各写一遍，等于把同一句话念八遍。 */
.dp-list figcaption{ padding-top:8px; font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.06em; }

/* ── 大图 ───────────────────────────────────────────────
   背景用不透明墨黑：半透明底在浅色照片上会把「关闭」按钮压到看不见的地方。 */
.lb{
  padding:0; border:0; margin:0; background:none; color:var(--on-dark);
  width:100%; height:100%; max-width:100%; max-height:100%;
}
.lb[open]{ display:grid; place-items:center; }
.lb::backdrop{ background:var(--ink); }
.lb-box{ position:relative; display:flex; flex-direction:column; align-items:center; gap:16px; padding:20px; }
.lb img{ display:block; width:auto; height:auto; max-width:92vw; max-height:78vh; background:var(--white); }
.lb-bar{ display:flex; align-items:center; gap:20px; }
#lbCap{ font-size:var(--fs-sm); color:var(--on-dark2); letter-spacing:.06em; }
.lb-x{
  position:fixed; top:18px; right:20px; z-index:2;
  padding:8px 16px; min-height:44px;
  border:1px solid rgba(237,237,234,.38); background:var(--ink);
  color:var(--on-dark); font-size:var(--fs-sm); letter-spacing:.08em; cursor:pointer;
}
.lb-nav{
  width:44px; height:44px; border:1px solid rgba(237,237,234,.38); background:var(--ink);
  color:var(--on-dark); font-size:var(--fs-num); line-height:1; cursor:pointer;
}
.lb-x:hover,.lb-nav:hover{ border-color:var(--on-dark); }
.lb-x:focus-visible,.lb-nav:focus-visible{ outline:2px solid var(--on-dark); outline-offset:3px; }
.lb.is-single .lb-nav{ display:none; }

.dmetro{ margin-top:16px; }
.dmetro li{ display:flex; align-items:baseline; justify-content:space-between; gap:20px; padding:12px 0; border-bottom:1px solid var(--line2); }
.dmetro .l{ display:flex; align-items:center; gap:12px; min-width:0; }
.dmetro .ln{
  flex:0 0 auto; min-width:30px; height:22px; padding:0 8px; display:inline-flex; align-items:center; justify-content:center;
  border:1px solid var(--ink); border-radius:var(--r-1); font-family:var(--en); font-size:var(--fs-sm); font-variant-numeric:tabular-nums;
}
.dmetro .st{ font-size:var(--fs-base); }
/* 机场行紧接在地铁行下面，共用同一套横线，只把间距收一点免得读成两节 */
.dair{ margin-top:2px; }
/* 正文里的内联链接：行内元素加竖向 padding 不会撑高行框，但能把可点区域做到 24px 以上
   —— 之前 21px，在 1280×600 的窄矮屏上被回归判成"热区不足"。
   2026-10-21：房源页「看整栋」在 `<h2>` 的 `.side` 里量出 38×30，
   鼠标判据要求 ≥32，差 2px —— padding 由 4 加到 6（落地 34）。
   手机端另按触控 44 处理，不与桌面共用一档（桌面 44 会把 h2 撑高 14px）。 */
.tlink{ border-bottom:1px solid var(--ink); padding:8px 0; color:var(--ink); }
.tlink:hover{ color:var(--brand); border-color:var(--brand); }
@media (max-width:760px){
  .tlink{ display:inline-flex; align-items:center; min-height:44px; padding:0; }
}
.dmetro .wl{ font-size:var(--fs-bs); color:var(--ink3); font-variant-numeric:tabular-nums; flex:0 0 auto; }

/* 楼盘位置图（2026-10-20）：每栋楼下面都有。Leaflet + 高德瓦片（GCJ-02 同源），
   楼点常驻墨底白字标注。点位来自本地楼盘库，瓦片无 Key、不占 API 限额。 */
.dmap{
  position:relative; height:clamp(320px, 42vw, 460px); margin-top:16px;
  background:var(--paper2); border:1px solid var(--line3); overflow:hidden;
}
.dmap .leaflet-container{ height:100%; font-family:var(--sans); background:var(--paper2); }
.dmap .leaflet-control-attribution{
  background:rgba(var(--white-rgb), .86); color:var(--ink3);
  font-size:var(--fs-xs); line-height:1.5; padding:1px 8px; border-radius:var(--r-1) 0 0 0;
}
.dmap .leaflet-control-attribution a{ color:var(--ink3); text-decoration:none; display:inline-block; padding:4px 0; }
/* 缩放控件：Leaflet 默认 26×26，实际渲染出来只有 13 宽的可点区域（内边距吃了宽度），
   手指基本按不准。全站统一成 44×44（站点触控下限）—— 两个地图（详情页 .dmap /
   搜索页 .map-leaflet）共用这一条，不要再各写一份。
   2026-10-21：这里原来还有一条 `.dmap .leaflet-bar a{30px}` 把详情页的地图按钮
   又压回 30，比搜索页那两张还小 —— 同一个站两个地图、两套尺寸，运行时审计抓到的就是它。 */
/* 选择器必须带 .leaflet-touch —— Leaflet 自带的是 `.leaflet-touch .leaflet-bar a`（0,2,1），
   只写 `.leaflet-bar a`（0,1,1）会被它按特异性压回去，尺码白改。
   pages.css 在 leaflet.css 之后加载，特异性打平即胜出。 */
.leaflet-touch .leaflet-bar a,
.leaflet-bar a{ width:44px; height:44px; line-height:44px; font-size:var(--fs-num); }
.dmap .leaflet-bar{ border-color:var(--line3); }
/* 楼名标注：墨底白字小标签，与搜索页楼名气泡同一语言；箭头同色 */
.vmap-tip{
  background:var(--ink); color:var(--white); border:0; border-radius:var(--r-1);
  font-size:var(--fs-xs); line-height:1.5; padding:4px 8px; box-shadow:none;
}
.vmap-tip::before{ border-top-color:var(--ink); }
.dmap-note{ margin-top:8px; font-size:var(--fs-xs); color:var(--ink3); line-height:1.75; }

/* 配套 chips → 一行一行的并列词。
   20 来个描边小方块铺满屏，视觉噪音比信息量大：每个框都在喊"看我看我"，
   结果一个也没被记住。改成同色文字 + 中点分隔，分组靠小标题，密度一样、噪音归零。 */
.dperi{ margin-top:8px; }
.dperi .g + .g{ margin-top:16px; }
.dperi .g-h{ font-size:var(--fs-sm); color:var(--ink3); letter-spacing:.06em; margin-bottom:8px; }
.dperi .gs{ display:flex; flex-wrap:wrap; }
.dperi .chip{ font-size:var(--fs-bs); color:var(--ink2); line-height:1.9; border:0; padding:0; white-space:normal; }
/* 同上：点跟在上一项后面，换行时才不会把点甩到行首。 */
.dperi .chip:not(:last-child)::after{ content:"·"; color:var(--ink4); margin:0 8px; }

/* ---------------- 楼盘详情：右侧粘性报价 ---------------- */
/* 报价面板：从「1px 黑框卡片」改成「2px 墨线的版块」。
   全页正文只用横线，突然出现一个四面描边的框，页面立刻变成后台表单的观感；
   框还把那块内容从正文里"抠"出来，反而显得单薄。
   现在顶部压一条 2px 墨线做锚点，下面是透明底，和正文同一层语言。 */
.dside{ position:sticky; top:120px; }
.dquote{ border:0; border-top:2px solid var(--ink); background:transparent; }
.dquote-h{ padding:24px 0 20px; border-bottom:1px solid var(--line); }
.dquote .lab{ font-size:var(--fs-sm); letter-spacing:.08em; color:var(--ink3); }
.dquote .big{
  margin-top:8px; display:flex; align-items:center; gap:12px;
  font-family:var(--serif); font-size:calc(var(--fs-h3) * var(--k)); font-weight:500; letter-spacing:.02em;
}
.dquote .big::before{ content:""; width:3px; height:23px; background:var(--brand); flex:0 0 auto; }
/* 大号价格后面的单位（2026-10-21）。两个坑一起填：
   ① <em> 浏览器默认是 italic —— 中文伪斜体看着像字体没装好；
   ② 不写字号就会继承 .big 的 h3 尺寸（实测 24px，与数字同高），
      「3.9 元/㎡/天」整段糊成一块，数字反而跳不出来。
   降一号 + --ink3，数字是主角、单位是注脚。 */
.dquote .big em{
  font-style:normal; font-family:var(--sans); font-weight:400;
  font-size:var(--fs-bs); color:var(--ink3); letter-spacing:.02em;
}
.dquote .note{ margin-top:12px; font-size:var(--fs-bs); line-height:1.9; color:var(--ink3); }
/* 面板没有边框了，左右内边距必须归零，否则按钮缩在中间、和顶部墨线不对齐 */
.dquote-b{ padding:20px 0 0; }
.dquote-b .btn{ width:100%; justify-content:center; }
.dquote-b .btn + .btn{ margin-top:8px; }
/* 顾问名片（2026-10-20）：楼页右栏、联系页、关于页共用一套。
   报价卡里原来挂的是「区域顾问 138 xxxx」一行小字，现在换成有职务、有姓名、
   电话与邮箱各一行的名片 —— 客户在页面上先问「打给谁」，再问「多少钱」。

   右栏里沿用报价卡的版式语言（2px 墨线之下、透明底、只有横线）；
   单独出现在版心时（.cp-card）给一条 1px 灰线，否则一段文字悬在纸上看不出是名片。
   电话是主行动：整行 44px 可点，11 位分三组（183 0180 3714）——
   小字号下 11 位连写极易串行，分组后一眼读得出。 */
.dag{ padding:16px 20px; border:1px solid var(--line3); background:var(--paper); }
.dag-h{ display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; }
.dag-k{ font-size:var(--fs-xs); letter-spacing:.1em; color:var(--ink3); }
.dag-n{ font-family:var(--serif); font-size:var(--fs-h3); font-weight:500; letter-spacing:.02em; }
.dag-v{ display:grid; grid-template-columns:4.4em minmax(0,1fr); align-items:center; row-gap:2px; margin-top:8px; }
.dag-v dt{ font-size:var(--fs-xs); letter-spacing:.06em; color:var(--ink3); }
.dag-v dd{ margin:0; min-width:0; }
.dag-v a{ display:inline-flex; align-items:center; gap:8px; min-height:44px;
  color:var(--ink); text-decoration:none; transition:color .2s var(--ease); }
.dag-v a:hover{ color:var(--brand); }
.dag-v svg{ flex:0 0 auto; color:var(--ink3); }
.dag-tel a{ font-size:var(--fs-lg); font-variant-numeric:tabular-nums; letter-spacing:.02em; }
.dag-mail a{ font-size:var(--fs-bs); color:var(--ink2); overflow-wrap:anywhere; }
/* 右栏里的名片：不套框，只压一条横线，跟报价卡是同一层 */
.dquote-b .dag{ margin-top:16px; padding:16px 0 0; border:0; border-top:1px solid var(--line2); background:transparent; }
.cp-card{ margin:24px 0 0; max-width:430px; }
/* 联系页：图与名片并排。名片单独放左半边会留下九成的空白 ——
   183 高的卡挂在 1296 宽的版心左边，看着像没加载完。 */
/* 「名片 + 到访」等宽两列（contact.html 联系方式节）。
   2026-10-26 是「名片 + 一张新外滩中心实拍」——图注写着「代理项目实拍」，
   而公司不做楼盘代理；照片本身也被 620×360 的横框从 1.25 的竖构图里裁掉
   塔尖与前景，只剩一段楼身和右下角的施工围挡。2026-11-02 老板点名这张图：
   「不合理、太丑，我们没有代理项目」。联系页要回答的是「在哪、什么时候来、
   谁来接待」——放任何一栋楼的实拍都会被读成「这是我们代理的楼」，
   所以右列整块换成到访信息，不再有图。
   两列仍等宽、交叉轴 stretch，右列靠 flex 撑到与左列等高；下面的
   .cp-touch 三栏（地址/时间/答复）与此重复，已并入此处一并撤掉。
   左列用 margin-top:auto 把按钮压到列底，两列下缘仍对齐。 */
.cp-two{ display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); gap:56px; align-items:stretch; }
.cp-two .cp-side2{ display:flex; flex-direction:column; }

.cp-visit{ display:flex; flex-direction:column; border:1px solid var(--line3); background:var(--paper); padding:18px 22px; }
.cp-visit-h{ display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; }
.cp-visit-h .k{ font-size:var(--fs-xs); letter-spacing:.1em; color:var(--ink3); }
.cp-visit-h .n{ font-family:var(--serif); font-size:var(--fs-h3); font-weight:500; letter-spacing:.02em; }
/* 四行在卡内均布：卡高由左列决定，内容少也不会都挤在顶上、底下空一截 */
.cp-visit-l{ flex:1 1 auto; display:flex; flex-direction:column; justify-content:space-between; margin:14px 0 0; }
.cp-visit-l > div{ padding:12px 0; border-top:1px solid var(--line2); }
.cp-visit-l > div:first-child{ border-top:0; padding-top:0; }
.cp-visit-l span{ display:block; font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.06em; }
.cp-visit-l b{ display:block; margin-top:6px; font-family:var(--serif); font-size:calc(var(--fs-lg) * var(--k)); font-weight:500; line-height:1.6; letter-spacing:.01em; }
.cp-visit-l em{ display:block; margin-top:4px; font-style:normal; font-size:var(--fs-xs); color:var(--ink3); }
/* beauty.css 给 .cp-acts 的规矩是「通栏顶线 + 按钮右对齐」—— 那是给 services / about
   里「整段话 + 一个按钮」用的，按钮落在右边是为了把整段拉满版心。
   在 contact 的窄栏里，按钮右对齐会漂到列的右端、离开名片与说明的左缘，
   所以这一处改回左对齐；顶线保留，当「联系信息 / 下一步动作」的分界。 */
.cp-two .cp-acts{ margin-top:auto; padding-top:24px; justify-content:flex-start; }
.cp-two .cp-fig figcaption{ flex:none; }
.cp-side2{ padding-top:2px; }
.cp-side2-p{ margin-top:16px; font-size:var(--fs-bs); line-height:1.9; color:var(--ink2); max-width:32em; }

/* 房源节尾：把「十套都能约看」和「打给谁」并排说完的一条带子。
   十行各挂一遍同一个号码只会变成噪音 —— 客户读不出差别，还把每套的节奏打散。
   号码给一次，44px 可点；各行的「问这套」点进去，落到的也是同一个人的名片。 */
.dul-ag{ display:flex; align-items:center; justify-content:space-between; gap:20px; flex-wrap:wrap;
  margin-top:20px; padding:16px 16px; background:var(--paper2); border-left:2px solid var(--ink); }
.dul-ag p{ display:flex; flex-direction:column; gap:4px; }
.dul-ag p b{ font-family:var(--serif); font-size:var(--fs-md); font-weight:500; letter-spacing:.02em; }
.dul-ag p span{ font-size:var(--fs-bs); color:var(--ink2); line-height:1.75; }
.dul-ag-t{ display:inline-flex; align-items:center; gap:8px; min-height:44px; padding:0 16px;
  border:1px solid var(--ink); background:var(--paper); color:var(--ink);
  font-size:var(--fs-md); font-variant-numeric:tabular-nums; text-decoration:none;
  transition:background .2s var(--ease), color .2s var(--ease); }
.dul-ag-t:hover{ background:var(--ink); color:var(--on-dark); }
.dquote .pts{ margin-top:16px; }
.dquote .pts li{ position:relative; padding:4px 0 4px 16px; font-size:var(--fs-bs); color:var(--ink2); line-height:1.75; }
/* 这四条短横原来是品牌红 —— 加上「面议」旁的红竖条，一个面板里就有 5 处红。
   红是点睛不是底色，这里退成中性灰，全页的红留给「面议」和首屏找房按钮。 */
.dquote .pts li::before{ content:""; position:absolute; left:0; top:13px; width:4px; height:1px; background:var(--ink4); }

/* 打印入口：打印样式一直在（见文件末尾 @media print），但页面上从来没有
   触发它的元素 —— 只有知道 Ctrl+P 的人才用得上。
   排在报价卡的三个动作之后、说明清单之前：它不属于「现在就联系」的转化，
   是事后动作（约好时间、把资料带走），所以压低权重，一条文字按钮。 */
.dq-print{ display:inline-flex; align-items:center; gap:8px; min-height:44px; margin-top:8px;
  font-size:var(--fs-bs); color:var(--ink2); border-bottom:1px solid var(--ink4); padding-bottom:2px;
  transition:color .2s var(--ease), border-color .2s var(--ease); }
.dq-print:hover{ color:var(--ink); border-color:var(--ink); }
.dq-print svg{ flex:0 0 auto; }

/* 纸面落款 .pf：屏幕上不存在，只在打印时出现。
   打印版把顶栏、页脚、公司条、吸底条全藏了，纸上只剩这栋楼的资料 ——
   客户拿着这张纸回公司跟老板谈条件，纸上找不到是谁给的、要打给谁，
   这张纸就是匿名的。落款负责把「谁出的这份资料」补回来。 */
.pf{ display:none; }

.dside .dwho{ margin-top:24px; border-top:1px solid var(--line); padding:20px 0 0; }
.dside .dwho h3{ font-family:var(--serif); font-size:var(--fs-base); font-weight:500; letter-spacing:.03em; }
.dside .dwho p{ margin-top:8px; font-size:var(--fs-bs); line-height:1.9; color:var(--ink2); }

/* ---------------- 楼盘详情：相似 / 承接 ---------------- */
.dnear{ background:var(--paper2); padding:var(--sp-band) 0; }
.dnear-h{ display:flex; align-items:flex-end; justify-content:space-between; gap:32px; padding-bottom:var(--sp-h2); }
.dnear-h h2{ font-family:var(--serif); font-size:calc(var(--fs-h2) * var(--k)); font-weight:500; letter-spacing:.04em; }
.dnear-h .more{ display:inline-flex; align-items:center; min-height:32px; font-size:var(--fs-bs); color:var(--ink2); border-bottom:1px solid var(--ink); padding-bottom:4px; }
.dnear-h .more:hover{ color:var(--brand); border-color:var(--brand); }

.dbelt{ background:var(--ink); color:var(--on-dark); padding:var(--sp-band) 0; }
.dbelt .wrap{ display:flex; align-items:center; justify-content:space-between; gap:56px; }
/* 深底白字要够重才不断，这里是真 500（原来写 400 只是被映射成 500）。 */
.dbelt h2{ font-family:var(--serif); font-size:calc(var(--fs-h2) * var(--k)); font-weight:500; letter-spacing:.03em; line-height:1.75; }
.dbelt p{ margin-top:8px; font-size:var(--fs-bs); line-height:1.9; color:var(--on-dark2); max-width:52ch; }
.dbelt .act{ flex:0 0 auto; display:flex; flex-direction:column; gap:8px; align-items:flex-end; }
.dbelt .btn.on-dark{ border-color:var(--on-dark); color:var(--on-dark); }
.dbelt .btn.on-dark:hover{ background:var(--on-dark); color:var(--ink); }

/* ============================================================
   落地页（区域 / 商圈 / 地铁）
   ============================================================ */
.hhead{ padding:var(--sp-head) 0 0; }
.hhead h1{
  font-family:var(--serif); font-weight:500; line-height:var(--lh-h1); letter-spacing:.01em;
  font-size:calc(var(--fs-h1) * var(--k));
}
.hhead .lead{ margin-top:20px; font-size:var(--fs-base); line-height:1.9; color:var(--ink2); max-width:36em; }
/* 中文大标题下的英文译名（只有服务页用）。
   它是「副题」不是眉标：位置在 h1 之下，字号 13px、--ink3（纸上 5.4:1），
   字距 .14em 让一排英文有节奏感而不至于散开。 */
.hsub{ margin-top:8px; font-family:var(--en); font-size:var(--fs-bs); color:var(--ink3); letter-spacing:.14em; }
/* 导语一句一行：按句号切，每句独占一行，落点不会把「步行」劈成「步 / 行」。
   行距用正文的 1.95，所以看上去仍是一段话，不是两条独立陈述。 */
.hlead .ln{ display:block; }
.hlead p + p{ margin-top:12px; }
/* 四项数字原来挤在左边约 700px 内，右边 600px 空着 —— 而它头顶已经有一条
   通栏的墨线，线走到头、数字却只走到一半，看着像没排完。
   改成等分铺满：每格 flex:1，分隔线落在等距位置，整条读起来是一条统计带。 */
.hstat{ display:flex; flex-wrap:wrap; gap:0 48px; margin-top:28px; padding-top:24px; border-top:1px solid var(--ink); }
.hstat div{ flex:1 1 0; min-width:0; padding-right:48px; border-right:1px solid var(--line2); }
.hstat div:last-child{ border-right:0; padding-right:0; }
.hstat .k{ font-size:var(--fs-sm); color:var(--ink3); letter-spacing:.04em; }
.hstat .v{ margin-top:8px; font-family:var(--serif); font-size:calc(var(--fs-h3) * var(--k)); font-weight:500; font-variant-numeric:tabular-nums; line-height:1.5; }
/* 390 下四格平铺会被 flex 压到每格 70px：「累计服务企业」排成一字一行、
   「18 国 · 28 城」断成四行，整条数字读不出内容。手机上改成 2×2。 */
@media (max-width:760px){
  .hstat{ display:grid; grid-template-columns:1fr 1fr; gap:16px 0; }
  .hstat div{ padding-right:24px; }
  .hstat div:nth-child(2n+1){ border-right:1px solid var(--line2); }
  .hstat div:nth-child(2n){ padding-right:0; border-right:0; }
  .hstat div:nth-child(n+3){ padding-top:16px; border-top:1px solid var(--line2); }
}

/* ---------- 找房页首屏（只作用于 .hhead-find）----------
   这一页的 h1 + 导语左对齐、最大 36em，1440 下右边会空出 800px 白纸；
   而紧接着的筛选面板是有边界的"实面"，两者之间没有任何过渡。
   改成两栏：左边说"这一站是什么"，右栏三格统计右对齐说"覆盖面有多大"，
   一排数字收在纸角，往下才是筛选。 */
.hf{ display:grid; grid-template-columns:minmax(0,1fr) 300px; gap:56px; align-items:start; }
/* 三格统计改成右栏的竖排索引：标签在左、数字在右，行间发丝线。
   横排三格塞进 300px 里，「8 个区」只剩一个字宽；竖排既放得下，
   又像一页账目的角标 —— 右栏原来整块是空的。

   ⚠ 2026-10-25 修：这一整组原来写的是 `.hf-stat{display:block}`，
   而 `beauty.css` 的 `.hstat{display:grid;grid-auto-flow:column}` 后加载、
   同优先级 → 竖排被顶掉，退回「右栏 300px 里横排等分 4 格」。
   实测每格 75px、数字 40px 级，「14 个区」直接压住「152 个」、
   「152 个」压住「18 条」，右上角四条数字糊成一团。
   （那行注释明明写着「横排塞进 300px 只剩一个字宽」，写的和跑的不是一回事。）
   全部选择器提到 `.hstat.hf-stat` 两个类，优先级压过 beauty 的单类规则。 */
.hstat.hf-stat{ display:block; margin-top:0; padding-top:0; border-top:1px solid var(--ink); }
/* 行高压到 5px：几行合计尽量与左栏（h1 + 导语）齐平，
   否则右栏比左栏高出一截，hhead 底部会凭空多出空白。 */
.hstat.hf-stat > div{
  display:flex; align-items:baseline; justify-content:space-between; gap:16px;
  padding:4px 0; border-right:0; border-bottom:1px solid var(--line2);
}
.hstat.hf-stat > div:last-child{ border-bottom:0; padding-right:0; }
.hstat.hf-stat .k{ font-size:var(--fs-xs); letter-spacing:.1em; white-space:nowrap; }
.hstat.hf-stat .v{ margin-top:0; white-space:nowrap; letter-spacing:.01em; }

/* 横向切换：同层级其它落地页 */
.hswitch{ margin-top:32px; border-top:1px solid var(--line); border-bottom:1px solid var(--line); }
.hswitch ul{ display:flex; flex-wrap:wrap; gap:0; }
.hswitch li{ border-right:1px solid var(--line2); }
.hswitch a{ display:block; padding:12px 16px; font-size:var(--fs-bs); color:var(--ink2); transition:background .2s var(--ease),color .2s var(--ease); }
.hswitch a:hover{ background:var(--paper2); color:var(--ink); }
.hswitch a.on,.hswitch span.on{ color:var(--ink); font-weight:700; box-shadow:inset 0 -2px 0 var(--brand); }
/* 当前区域/线路原来是 <a>，点它等于把本页重新加载。现在换成 span，
   但它得和 <a> 一样是一整块（否则下划线只有字的宽度，切换条会跳）。 */
.hswitch span.on{ display:block; padding:12px 16px; font-size:var(--fs-bs); }

.hlist{ padding:44px 0 0; }
/* 列表上方的元信息条：三个落地页同一位置、同一句法（共 N 栋 / 按什么排）。
   没有它，读者不知道列表是什么顺序，也不知道这页到底有多少栋。 */

/* 第二段原来用 --ink4(var(--ink4))，在纸底上只有 2.78:1 —— 对比度闸门当场判红。
   12px 的小字不属于"大字号例外"，必须够 4.5。主次改用 ink2 / ink3 拉开。 */


.hlist .pgrid{ grid-template-columns:repeat(3,minmax(0,1fr)); }
/* 同一页里不能再出现第二种卡片尺寸：这两个块原来吃 .pgrid 的默认 4 列（305 宽），
   和上面 415 宽的主列表并排就像两个站。统一 3 列。 */
.hmore .pgrid,.dnear .pgrid{ grid-template-columns:repeat(3,minmax(0,1fr)); }
/* 补楼块只有 2 栋时，3 列网格会右侧空出一整格（415px 空白）。
   2 张卡改 2 列：每张 660×495，源图 750 宽仍是缩小着用。
   只在 ≥1121 生效 —— 窄屏本来就是 2 列 / 1 列。 */
/* 补楼块只有 2 栋时右侧会空一格 —— 这里不靠"把卡放大填满"来解
   （放大 = 同一页两种卡片宽度，闸门当场判红；大屏上还会超过源图像素），
   改由生成器把补充栋数补到 3 的倍数：网格保持三列、卡片始终 415 宽。 */

/* 商圈页补楼：只有两三栋时，把同区域的其它楼接上，页面不至于空半屏 */
.hmore{ padding:var(--sp-band) 0 0; }
.hmore-h{ display:flex; align-items:baseline; gap:16px; padding-bottom:16px; margin-bottom:12px; border-bottom:1px solid var(--ink); }
.hmore-h h2{ font-family:var(--serif); font-size:calc(var(--fs-h2) * var(--k)); font-weight:500; letter-spacing:.04em; }
.hmore-h .side{ font-size:var(--fs-bs); color:var(--ink3); }

/* 空态 */
.hnone{ padding:var(--sp-band) 0; text-align:center; }
.hnone b{ display:block; font-family:var(--serif); font-size:var(--fs-num); font-weight:500; }
.hnone p{ margin-top:8px; font-size:var(--fs-md); color:var(--ink3); }

/* 相关内链矩阵 */
.hrel{ background:var(--paper2); padding:var(--sp-band) 0; }
.hrel-h{ font-family:var(--serif); font-size:calc(var(--fs-h2) * var(--k)); font-weight:500; letter-spacing:.04em; padding-bottom:var(--sp-h2); }
/* 列数跟着「真的有内容」走：某一类只剩两条时，三栏会塌出半屏空白。
   auto-fit 让剩下的两列各占一半，行也跟着变宽，读起来是索引不是清单。 */
.hrel-g{ display:grid; grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); gap:40px; }
.hrel-g h3{ font-size:var(--fs-sm); color:var(--ink3); letter-spacing:.06em; padding-bottom:8px; border-bottom:1px solid var(--line); }
.hrel-g ul{ margin-top:12px; }
.hrel-g li{ padding:4px 0; }
/* 每一行一根发丝线：整块读起来是账本，不是散落的链接 */
.hrel-g ul{ border-top:1px solid var(--line3); }
.hrel-g li + li{ border-top:1px solid var(--line3); }
/* 每行都是「名字 …… 栋数」：用两列栅格把数字推到同一根右边缘，
   原来数字紧跟在名字后面、长短不齐，整块读起来像随手排的清单。 */
/* 原来是「文字 + 右对齐栋数」的两列网格；栋数撤掉以后只剩一列，改回普通块级 */
.hrel-g a{ display:block; font-size:var(--fs-md); color:var(--ink2);
  padding:4px 0; border-bottom:1px solid transparent; }
.hrel-g a:hover{ color:var(--ink); }

/* ---------------- 响应式 ---------------- */
@media (min-width:1800px){
  /* 大屏加密度不加尺寸：4 列之后每张卡仍是 400px 上下，
     图不会因为屏大就被放大到超出源图（这批封面中位只有 750px）。 */
  .hlist .pgrid{ grid-template-columns:repeat(4,minmax(0,1fr)); }
}
/* 断点对齐到 ed.css 那套（1280 / 1120 / 760）。
   原来这里另开 1320 / 1240 两个值，相差 40px —— 在 1290 宽上就会出现
   "列表已经 3 列、正文却还没退两列"的错位。两个差 40px 的档并成一个。 */
@media (max-width:1280px){
  /* 正文栏只剩 848 宽，三格一行每格 253 —— 碰上「流动车位 1,000 元/月
     固定车位 2,000 元/月」这种长值，一行只排得下 14 个字。退成两格。 */
  .dl2{ grid-template-columns:repeat(2,minmax(0,1fr)); gap:0 32px; }
  .dbody{ grid-template-columns:minmax(0,1fr) 320px; gap:48px; }
}
@media (max-width:1120px){
  /* .dtop.nofig 的特异性(0,2,0)高于 .dtop(0,1,0)，不并列写会被它反压 ——
     实测 768 宽下无图页仍是两栏，左 386 / 右 277。 */
  .dtop, .dtop.nofig{ grid-template-columns:1fr; gap:24px; }
  .dkpi.kpi2 > div{ border-bottom:0; border-right:1px solid var(--line2); }
  .dkpi.kpi2 > div:nth-child(2n){ border-right:1px solid var(--line2); padding-right:20px; }
  .dhead .wrap{ flex-direction:column; align-items:flex-start; gap:20px; }
  
  .dkpi{ grid-template-columns:repeat(3,minmax(0,1fr)); }
  .dkpi > div:nth-child(3n){ border-right:0; }
  .dkpi > div{ padding:16px 16px 20px 0; }
  .dbody{ grid-template-columns:1fr; gap:0; margin-bottom:56px; }
  /* ↑ margin-bottom 是 2026-10-26 补的：≤980 时侧栏（需求单卡片）落到正文下方，
     原来整块 .dbody 底边**正好压在页脚顶边**（实测 0px）—— 390 下最后一张卡片
     与页脚之间一点空隙都没有，翻到底看着像被切了一刀。
     audit_compose 的「收尾留白」量的是侧栏里最后一个字到页脚的距离，
     改前只查 .dmain 所以看不见（那时显示 501px 假红），把侧栏算进来才暴露成 15px。 */
  .dside{ position:static; margin-top:32px; }
  .dbelt .wrap{ flex-direction:column; align-items:flex-start; gap:24px; }
  .dbelt .act{ align-items:flex-start; }
  .hlist .pgrid,.hmore .pgrid,.dnear .pgrid{ grid-template-columns:repeat(2,minmax(0,1fr)); }
  .hrel-g{ grid-template-columns:1fr 1fr; gap:32px; }
}
@media (max-width:980px){
  /* 「看某某全部 →」是列表页底部的唯一出口，手机上要 44 */
  .dnear-h .more{ min-height:44px; }
  /* 「同区域其它楼」是详情页底部最主要的横向入口，一条一行，必须 44 */
  /* 手机上要把命中区撑到 44，但两列栅格不能丢 —— 改回 flex 数字就又长短不齐了 */
  .hrel-g a{ display:grid; grid-template-columns:1fr auto; align-items:center; min-height:44px; }
  /* 找房页首屏：980 以下左栏只剩 560 宽，右栏 300 会把导语挤成四行。
     落成单列，统计回到横排（竖排三行在手机上白吃 90px 高度）：
     标签在上、数字在下，与其它内页的 hstat 长得一样。 */
  .hf{ grid-template-columns:minmax(0,1fr); gap:24px; }
  .hf-stat .v{ margin-top:8px; }
}
@media (max-width:760px){
  .dkpi.kpi2 > div:nth-child(2n){ border-right:0; padding-right:0; }
  .dkpi{ grid-template-columns:repeat(2,minmax(0,1fr)); }
  .dkpi > div:nth-child(3n){ border-right:1px solid var(--line2); }
  .dkpi > div:nth-child(2n){ border-right:0; }
  /* 参数表手机上原来落成一列：标签一行、数值一行，8 项就要 887px（一屏半）。
     而这些值大多只有 2–6 个字，竖着排等于把纸上的表格拆成卡片。
     改成「标签定宽 + 数值靠右」的一行式，一行 46px，8 项 380px。
     标签列定 78px（最长「建筑面积」4 字 × 12px = 48px）：
     用 auto 的话每行宽度跟着自己的标签变，几行数值右边缘参差不齐。 */
  .dl2{ grid-template-columns:1fr; }
  .dl2 .i{ display:grid; grid-template-columns:78px minmax(0,1fr); align-items:baseline;
           gap:0 16px; padding:12px 0 12px; }
  .dl2 dd{ text-align:right; }
  /* 手机上落到单列：行容器本来是 flex，竖屏下两列每列只有 160px，
     图里的楼和人全糊了。单列时每张仍用自身比例，零裁切。 */
  .dgal-row{ display:block; }
  .dgal-row figure + figure{ margin-top:16px; }
  .hlist .pgrid,.hmore .pgrid,.dnear .pgrid{ grid-template-columns:minmax(0,1fr); }
  .hrel-g{ grid-template-columns:1fr; }
  .dnear, .hrel{ padding:52px 0; }
  .dbelt{ padding:44px 0; }
  .dnear-h{ flex-direction:column; align-items:flex-start; gap:16px; }
  .hstat div{ padding-right:28px; }
  /* 周边配套的词条在窄屏会折行，中点跟着一起难看 —— 与首页区域快选同一处理：去掉点，用间距分列。 */
  .dperi .chip{ margin-right:16px; }
  .dperi .chip:not(:last-child)::after{ content:none; }
}
@media (max-height:700px){
  /* 图高现在由 aspect-ratio 决定，矮视口只压图宽与上边距，不再写死高度 */
  .dtop{ margin-top:16px; }
  .dhead{ padding:16px 0 0; }
  
}

/* 手机上每一条面包屑都要能单独点中（44px 命中区） */
@media (max-width:760px){
  .crumb a{ min-height:44px; }
}

/* ============================================================
   手机上面包屑与地址行的断行（2026-10-24，390 实测）
   —— 两处都是「分隔符被当成独立的 flex 项目」留下的尾巴：
       面包屑折成「首页 / 找楼 / 写字楼 / 徐汇区 / 中城国际大厦 /」＋「125㎡」，
       行尾挂一个孤零零的「/」；
       地址行「虹桥路500号 | 3/4/10 号线 · 虹桥路站 |」＋「标准交付」，
       行尾留一根竖线。
      为什么不是「让分隔符不许断」：它是独立的 <span>/<i>，CSS 没有办法把它
      粘到**后一个**元素上（只有 `::after` 能粘前一个，那正是现在的错法）。
   做法：
     面包屑 —— 手机上只保留「首页 / 末两级」，中间层级折叠（点「找楼」照样能到）；
     地址行 —— 分隔符整体隐藏，换成每项**前导**的细竖线；它属于后一项，
               换行时跟着后一项走到下一行开头，绝不会留在上一行行尾。
   ============================================================ */
@media (max-width:560px){
  /* 子元素结构是 a·sp·a·sp·…·a·cur，保留第 1、2 个与最后 3 个 */
  .crumb > *:nth-child(n+3):nth-last-child(n+4){ display:none; }
  .dhead .loc .sep{ display:none; }
  .dhead .loc > span:not(:first-child){ position:relative; padding-left:12px; }
  .dhead .loc > span:not(:first-child)::before{
    content:''; position:absolute; left:0; top:50%; width:1px; height:11px;
    transform:translateY(-50%); background:var(--line);
  }
  /* 搜索结果页排序条：390 实测容器 333 / 内容 353，「名称」被切掉半个字。
     五个按钮各收 3px 内边距正好省出 30px —— 一行放得下就不要让它横向滚：
     滚动的提示太弱，切字看着像坏了。 */
  .sort button{ padding:8px 8px; }
}

/* ============================================================
   公司页（about / services / contact）
   —— 三页共用一套语法：两栏正文 + 侧注、事实数字、时间轴、服务清单、
      流程表、联系三格。不新增字号、不新增颜色，全部走 tokens，
      所以这三页和楼盘页看起来还是同一个站，不像另开了一张皮。
   ============================================================ */
/* 内页首屏的 hstat 是全站共用的；区域/商圈页下面紧跟切换条，自带留白，
   公司页下面直接是色块，数字底边正好落在色块边线上，看着像被切了一半。
   只给公司页补这一档，不动内页。 */
.hhead.hhead-co{ padding-bottom:40px; }

/* 通栏横幅：比例一律由 --ar 决定（生成器按源图真实像素写），不写死。
   曾经写死 2.6:1：手里那张城市图是 1600×683（2.34）就切掉 5%，写死 16:9 更狠切两成。
   现在的城市图是 1700×1134（1.499，天际线带江面倒影）——**不要为「扁」再压它**：
   压到 2.34 要上下各切 18%，先没的就是倒影，而那正是这张图唯一的看点。
   宽度封在源图的 1:1（上限 1600）：2560 屏上原来源图宽只有 1364 却铺到 1896，
   等于放大 39% 铺满，远看就是一层毛边；现在只允许缩、不放。 */
.cp-fig{ margin:0; }
/* 横幅比例跟着图走（--ar 由生成器按真实像素写）。原来写死 2.6:1，
   手里唯一那张城市图是 1600×683（2.34）—— 差 11%，等于把左右各切掉 5%。
   写死 16:9 的小屏更狠：2.34 进 1.78，切掉两成，外滩两头的楼全没了。 */
.cp-fig img{ display:block; width:100%; height:auto; background:var(--paper3); aspect-ratio:var(--ar,2.6/1); object-fit:cover; max-width:1700px; margin-inline:auto; }
.cp-fig figcaption{ display:flex; justify-content:space-between; gap:16px; flex-wrap:wrap; padding-top:8px; font-size:var(--fs-sm); color:var(--ink3); letter-spacing:.03em; }
/* 关于页那张上海线稿：整块（图 + 图注）锁到源图原生宽 1700，图注才跟图同框。
   ① 图注对齐 —— 只给 img 限宽居中时，figcaption 仍按 .wrap 全局宽排，
      space-between 会把中英文推到图两端之外，跟图像两条不相干的东西；
   ② 不放 —— 源图就 1700×843，窄屏靠 max-width:100% 缩，2K 屏到 1700 封顶。
   里面的 .wrap 继续吃全局 --w 与 32px 内边距，所以窄屏上图仍与正文列同左缘。 */
.cp-fig.fig-banner{ max-width:1700px; margin-inline:auto; }
/* 线稿的白底用 multiply 叠掉：白 × 纸色 = 纸色，等于这张图没有底。
   换成 object-fit 裁边 / 抠白的话，笔画半透明的抗锯齿边会变成灰毛边；
   不叠的话，纸是 var(--paper)、图是 var(--white)，1296×642 这么大一块白方块，
   那道 2% 的淡边反而比线稿本身更抢眼。 */
.cp-fig.fig-ink img{ background:none; mix-blend-mode:multiply; }
/* 「图 + 文」双栏：一排字、一排图交替，长页面读起来才不闷 */
.cp-duo{ display:grid; grid-template-columns:minmax(0,560px) minmax(0,1fr); gap:64px; align-items:start; }
/* 原来硬写 3/2：全站三处 cp-duo 的图都带了 --ar（1.332 / 1.777），
   硬写会把它盖掉，17:9 的航拍被裁成 3:2 —— 图变高，右栏文字却只有三行，
   `.cp-duo` 取较高的一侧，右栏底下就空出一大块。改成认 --ar、缺省才退回 3/2。 */
.cp-duo .cp-fig img{ aspect-ratio:var(--ar,3/2); }

.cp-head{ margin-bottom:var(--sp-h2); }
.cp-h{ font-family:var(--serif); font-size:calc(var(--fs-h3) * var(--k)); font-weight:500; letter-spacing:var(--ls-h2); line-height:var(--lh-h2); }
.cp-sub{ margin-top:8px; font-size:var(--fs-bs); color:var(--ink3); line-height:1.9; max-width:40em; }

/* 正文 + 右栏。2026-10-23 夜重排：
   原来整块锁 1120，于是「这一节的右岸线」在 1185，而同一页的表格、
   通栏块、色带都在 1361 —— 上下两节右缘差 176，翻页时像没排完
   （process 第 4 节、renovation 第 7 节实测）。
   现在铺满容器，把余量做成**栏间距**而不是右侧空洞：
   正文 700（--measure，与内容页同一把尺）+ 右栏 340 顶到容器右缘，
   中间用 space-between 吃掉剩下的 256。这样两栏各自都有明确边界，
   右侧那条发丝线也终于与上下节的右缘落在同一条竖线上。 */
.cp2{
  display:grid; grid-template-columns:minmax(0,var(--measure)) minmax(280px,1fr);
  justify-content:space-between; gap:96px; align-items:start; max-width:none;
}
/* 关于页那一块本来就要铺满，保留类名以免模板里 300 处调用要改。 */
.cp2-wide{ max-width:none; }
.cp2-l{ min-width:0; }
.cp2-l p{ margin-top:16px; font-size:var(--fs-base); line-height:1.9; color:var(--ink2); max-width:var(--measure); }
.cp2-l p b{ font-weight:700; color:var(--ink); }
.cp2-l h2 + p{ margin-top:20px; }
/* 同一栏里两段之间再起一个小标题（工具页「这个工具做什么 / 现在还没上线」）。
   不给它 44 的上间距，两个 h2 会挤成一段。 */
.cp2-l p + h2{ margin-top:44px; }
/* 引文放在两段正文之间，不放右栏：右栏一挂，文字与引文之间会空出 400px，
   读者的视线要横跨半个屏幕才能接上下一段。文内引用同时也是段落之间的换气口。 */
.cp-quote{ margin:24px 0; padding:4px 0 4px 24px; border-left:2px solid var(--brand); }
.cp-quote p{ margin:0; font-family:var(--serif); font-size:calc(var(--fs-lg) * var(--k)); font-weight:300; line-height:1.9; color:var(--ink); max-width:30em; }
.cp-quote span{ display:block; font-family:var(--sans); font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.06em; margin-top:8px; }

/* 右栏「公司信息 / 承接方」：带发丝线的规格卡。
   比只放两个文字链接有用 —— 客户想知道的是全称、地址、电话，
   这些在每页页脚都有，但在正文里成块出现一次，可信度完全不同。 */
.cp-rail{ border-top:1px solid var(--ink); }
.cp-rail-h{ padding:8px 0; font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.06em; }
.cp-rail > div{ padding:12px 0; border-top:1px solid var(--line2); }
.cp-rail span{ display:block; font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.04em; }
.cp-rail b{ display:block; margin-top:8px; font-weight:400; font-size:var(--fs-bs); color:var(--ink); line-height:1.75; }
.cp-rail b a{ display:inline-flex; align-items:center; min-height:44px; text-decoration:underline; text-decoration-thickness:1px; text-underline-offset:4px; text-decoration-color:var(--line3); transition:color .2s var(--ease), text-decoration-color .2s var(--ease); }
.cp-rail b a:hover{ color:var(--brand); text-decoration-color:currentColor; }
.cp-side .cp-rail-h{ width:100%; }

.cp-facts{ display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:32px; padding-top:24px; border-top:1px solid var(--ink); }
.cp-facts b{ display:block; font-family:var(--serif); font-size:calc(var(--fs-h2) * var(--k)); font-weight:300; line-height:1.1; font-variant-numeric:tabular-nums; }
.cp-facts em{ font-family:var(--sans); font-size:var(--fs-sm); font-style:normal; color:var(--ink3); margin-left:4px; }
.cp-facts i{ font-style:normal; color:var(--ink3); margin:0 4px; font-size:var(--fs-md); }
.cp-facts span{ display:block; margin-top:8px; font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.04em; }
/* 注释行按 40em 限宽：13px 下 1em≈1 字，56em 会排到 56 字一行，
   读者回车时找不到下一行的开头。 */
.cp-note{ margin-top:24px; padding-top:12px; border-top:1px solid var(--line2); font-size:var(--fs-sm); color:var(--ink3); line-height:1.9; max-width:40em; }

.cp-tl{ display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); border-top:1px solid var(--ink); }
.cp-tl li{ padding:24px 28px 24px 0; }
.cp-tl li + li{ padding-left:28px; border-left:1px solid var(--line2); }
.cp-tl .y{ font-family:var(--en); font-size:var(--fs-sm); color:var(--ink3); letter-spacing:.04em; }
.cp-tl b{ display:block; margin-top:8px; font-family:var(--serif); font-size:var(--fs-lg); font-weight:500; letter-spacing:.03em; }
.cp-tl p{ margin-top:8px; font-size:var(--fs-bs); color:var(--ink3); line-height:1.9; }

/* ---------------- 深色块的「纸面厚度」（2026-10-26 全站统一） ----------------
   .co（beauty.css 第 7 节）早就是这么做的，注释写得很准：深底上如果只有纯色，
   会像一块没加载完的黑图；铺一层 .16 不透明度的品牌色径向渐变，纸面才有厚度。
   但 .dbelt / .dquotebar / .vm-lead 一直是 background:var(--ink) 平涂 ——
   同一个站里于是并存两种深色质感：.co 有光有厚度，另三块是死平的色块。
   「黑色背景很丑、没有设计感」指的就是这三块。
   现在统一成同一套：平涂 ink + 右上品牌光晕 + 左下弱光。
   尺寸用 --glow-w / --glow-h 两个变量给出，大带吃默认值，小块自己缩。
   光晕铺在 z-index:0 的伪元素上，内容层必须抬到 1，否则会被半透明层压灰。 */
.dbelt, .dquotebar, .vm-lead{ position:relative; overflow:hidden; isolation:isolate; }
.dbelt::before, .dquotebar::before, .vm-lead::after{
  content:""; position:absolute; inset:0; pointer-events:none; z-index:0;
  background:
    radial-gradient(var(--glow-w,680px) var(--glow-h,320px) at 82% 18%, rgba(var(--brand-rgb), var(--glow-a,.16)), transparent 68%),
    radial-gradient(calc(var(--glow-w,680px) * .76) calc(var(--glow-h,320px) * .8) at 8% 96%, rgba(var(--brand-rgb),.07), transparent 70%);
}
.dbelt > .wrap, .dquotebar > div, .vm-lead > *{ position:relative; z-index:1; }
/* 小块的光晕要跟着块缩：520×326 的块套 680×320 的光斑，中心会跑到块外。
   强度也要降：.co 是 1425×391 的通栏，同样的 .16 落在 520 宽的块里，
   视觉浓度差着近三倍，第一版试过 .16，右上角红得像打了一盏射灯。 */
.vm-lead{ --glow-w:360px; --glow-h:230px; --glow-a:.11; }
.dquotebar{ --glow-w:520px; --glow-h:180px; }

/* ---------------- 愿景与使命（关于页） ----------------
   左栏是一块墨黑底、白字的主愿景声明 —— 全页唯一的深色块。
   左列 440 与下面 .vm-cul 的标签列同宽，两块的左边线才对得齐。
   用 align-items:stretch 让黑块与右栏等高，否则黑块只有文字那么高，
   在一栏说明文字旁边像一张贴歪的标签。 */
.vm{ display:grid; grid-template-columns:minmax(0,520px) minmax(0,1fr); gap:56px; align-items:stretch; }
/* 2026-10-26 三段式重构。原来只有「标签 + 主句」，靠 b{margin-top:auto} 各贴一端，
   440×326 的块中间空 157px —— 实测（_dev/_dark_audit.mjs）判为 D2 空洞。
   现在 grid-template-rows:auto 1fr auto 让主句落在真正的中线上：
   顶线定住起点、落款定住终点、1fr 把剩下全部给主句并居中，块内不再有断层。
   底色也不用平涂：一道 158° 的深墨渐变给块一点体积，内描边收住边缘，
   否则纯 #101215 的实心矩形在白页上就是一张贴纸。 */
.vm-lead{
  display:grid; grid-template-rows:auto 1fr auto;
  padding:32px 40px;
  background:var(--ink);
  color:var(--white);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.07);
  position:relative;
}
.vm-ld-top{ display:flex; align-items:center; gap:16px; }
.vm-ld-top::after{ content:""; flex:1; height:1px; background:rgba(255,255,255,.18); }
.vm-lead .vm-k{ color:var(--on-deep2); }
.vm-ld-main{ display:flex; flex-direction:column; justify-content:center; padding:24px 0; }
/* 30px = --fs-h2。左列加宽到 520 就是为了这一级：14 字 × 30 = 420，
   内容宽 520−80 = 440 装得下；若仍用 440 宽，内容只剩 376，30px 会折成三行。 */
.vm-lead b{ font-family:var(--serif); font-size:var(--fs-h2); font-weight:500; line-height:1.5; letter-spacing:.02em; }
.vm-ld-foot{
  display:flex; justify-content:space-between; align-items:center;
  padding-top:16px; border-top:1px solid rgba(255,255,255,.14);
  font-family:var(--en); font-size:var(--fs-xs); letter-spacing:.12em; color:var(--on-deep3);
}
.vm-body{ display:grid; gap:40px; align-content:start; }
.vm-k{ display:block; font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.08em; }
.vm-item b{ display:block; margin-top:12px; font-family:var(--serif); font-size:calc(var(--fs-h3) * var(--k)); font-weight:500; line-height:1.5; letter-spacing:.03em; }
.vm-item p{ margin-top:16px; font-size:var(--fs-bs); color:var(--ink2); line-height:1.9; max-width:34em; }
/* 企业文化落在两条竖栏之下、用一条通栏发丝线收口 —— 它是三句话，
   做成第三张卡片会显得和上面两级并列，实际是从属。 */
.vm-cul{ display:grid; grid-template-columns:minmax(0,520px) minmax(0,1fr); gap:56px; align-items:baseline; margin-top:48px; padding-top:20px; border-top:1px solid var(--line2); }
.vm-cul p{ font-family:var(--serif); font-size:var(--fs-md); font-weight:500; color:var(--ink); letter-spacing:.04em; line-height:1.9; }

/* ---------------- 六类物业（关于页） ----------------
   3×2 网格，不用卡片、不用阴影 —— 与 .cp-facts / .cp-tl 同一套发丝线语言。
   nth-child(3n+1) 是每行第一格，只有它不带左竖线。 */
.sf{ display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); border-top:1px solid var(--ink); }
.sf li{ padding:24px 28px 24px 0; border-bottom:1px solid var(--line2); }
.sf li:not(:nth-child(3n+1)){ padding-left:28px; border-left:1px solid var(--line2); }
.sf b{ display:block; font-family:var(--serif); font-size:var(--fs-lg); font-weight:500; letter-spacing:.04em; }
.sf span{ display:block; margin-top:4px; font-family:var(--en); font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.06em; }
.sf p{ margin-top:8px; font-size:var(--fs-bs); color:var(--ink3); line-height:1.9; text-wrap:balance; }
/* 2026-11-02：条目数为 3n+2 时（关于页「服务介绍」按品牌手册列五项 = 3+2），
   末项右边会空出一格，那一格既没竖线也没底线，像漏了一块。
   让它从第 2 列起跨两格，把第二行补齐：三列下占 2/3 宽，底线照旧收口。
   ⚠ 必须写 `2 / span 2`，不能写 `span 2` —— 只写 span 时自动放置会从第 2 列
   起再加两列，3 列网格被撑出隐式第 4 列，整块被压成三细条（2026-11-02 实测）。
   窄屏两列下改为整行（见下面的 980 断点）。六项（「六类物业」）最后一个是 3n，
   不落在选择器里，不受影响。 */
.sf li:last-child:nth-child(3n+2){ grid-column:2 / span 2; }

/* ---------- 条目卡片：五项服务 / 四段工序（2026-10-21 重做）-------------
   原来是「左标题 / 右正文」的发丝线表格。问题出在序号上：.no 当时**没有任何
   样式**，默认 inline，而 h3 是 block —— 于是 01 被挤到标题上面一行，
   读起来是「01 / 选址顾问」两行，而不是「01 选址顾问」一行。

   现在整套换成卡片栅格：条目自带 1px 边框（纸白面压在 --paper2 底上），
   序号与标题同一行、中间一道竖发丝线，中文名下面加一行英文名作副题。
   五条并排是一组「面」，不再像五条孤立的横线 —— 这是这页原来显得空的原因：
   版面全是线，没有一个实面。

   为什么序号用 --ink3 而不是 tokens 里那个给「超大装饰数字」的 --ink5：
   12px 的 --ink5 在纸上只有 3.0:1，闸门按小字 4.5:1 判，当场红。
   --ink5 的大字豁免要求 ≥24px，序号不可能那么大。 */
.cp-svc{ display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:16px; }
.cp-svc li{
  min-width:0; padding:24px 28px 24px;
  border:1px solid var(--line3); background:var(--white);
  transition:border-color .18s var(--ease), box-shadow .18s var(--ease);
}
/* 描边用 --line3（不是 --line）：白卡压在 --paper2 上时，--line 的 E5E5E2 与
   底色只差 2%，远看像没有边框。hover 再深一档到 --ink4 并加一档极浅阴影，
   让「这是一张卡」在鼠标移上去时才被强调，静止时不抢文字。 */
.cp-svc li:hover{ border-color:var(--ink4); box-shadow:0 1px 3px rgba(var(--ink-rgb),.05); }
.cp-svc li[id]{ scroll-margin-top:var(--anchor); }
/* 首条通栏：它是这一页的主业务，尺寸上给一层级；内部回到「左标题 / 右正文」，
   与其余四张卡的纵向结构区分开，五张卡才不会像五块一样的砖。 */
.cp-svc li.hi{
  grid-column:1/-1; display:grid;
  grid-template-columns:minmax(0,300px) minmax(0,1fr); gap:48px;
  padding:28px 32px 32px; align-items:start;
}
.cp-svc h3{
  display:flex; align-items:center; margin-top:0;
  font-family:var(--serif); font-size:calc(var(--fs-lg) * var(--k)); font-weight:500; letter-spacing:.04em;
}
/* 英文副题：字号走 --fs-xs（11px），色用 --ink3（纸上 5.4:1）。
   不用大写字母做「眉标」—— 全站禁全大写英文眉标，这里是句首大写的名称。 */
.cp-svc .en{
  display:block; margin-top:8px;
  font-family:var(--en); font-size:var(--fs-xs); color:var(--ink3);
  letter-spacing:.08em; line-height:1.75;
}
.cp-svc .svc-h{ min-width:0; }
.cp-svc .svc-b{ min-width:0; }
.cp-svc li:not(.hi) .svc-b{ margin-top:16px; }
.cp-svc li.hi .svc-b{ padding-top:2px; }
.cp-svc p{ font-size:var(--fs-md); color:var(--ink2); line-height:1.9; max-width:42em; }
.cp-svc .tg{ display:flex; flex-wrap:wrap; gap:8px; margin-top:16px; }
.cp-svc .tg span{ font-size:var(--fs-xs); color:var(--ink2); border:1px solid var(--line); padding:4px 8px; line-height:1.75; }

/* 区块标题的英文副题：接在中文标题后面同一行（不是压在标题上方的眉标）。
   字号 --fs-sm、色 --ink3 —— 12px 在纸上 5.4:1，过 AA。
   折行时 inline-block 会整体落到下一行，不会把「五项服务」劈成两半。 */
.cp-h .en{
  display:inline-block; margin-left:16px; vertical-align:baseline;
  font-family:var(--en); font-size:var(--fs-sm); font-weight:400;
  color:var(--ink3); letter-spacing:.06em;
}

.cp-grid4{ display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:0 64px; border-top:1px solid var(--ink); }
.cp-grid4 > div{ padding:24px 0; border-bottom:1px solid var(--line2); }
.cp-grid4 h3{ font-family:var(--serif); font-size:var(--fs-base); font-weight:500; letter-spacing:.04em; }
.cp-grid4 p{ margin-top:8px; font-size:var(--fs-bs); color:var(--ink3); line-height:1.9; }
/* 业主侧四类业务的英文名：接在中文名下方，11px / --ink3。
   这一组保持「发丝线表格」不改成卡片 —— 五项服务是主体（实面），
   业主侧是附属（线表），两种处理本身就是层级，全做成卡片反而没有重点。 */
.cp-grid4 .en{
  display:block; margin-top:8px;
  font-family:var(--en); font-size:var(--fs-xs); font-weight:400;
  color:var(--ink3); letter-spacing:.06em; line-height:1.75;
}

.cp-chips{ display:flex; flex-wrap:wrap; gap:8px; margin-top:20px; }
.cp-chips li{ font-size:var(--fs-bs); color:var(--ink2); border:1px solid var(--line3); padding:8px 16px; }
/* 六个领域是并列的，就不该缩在左半边：整幅六等分，一眼看完。
   每一格改成「中文名 / 英文名」两行（2026-10-21）：单行六个中文词太薄，
   英文补上第二行之后，这一条从「六个标签」变成「六个词条」。 */
.cp-chips.wide{ display:grid; grid-template-columns:repeat(6,minmax(0,1fr)); gap:8px; margin-top:0; }
.cp-chips.wide li{ display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4px; min-height:76px; font-family:var(--serif); font-size:var(--fs-md); font-weight:500; letter-spacing:.04em; }
.cp-chips.wide .en{ font-family:var(--en); font-size:var(--fs-xs); font-weight:400; color:var(--ink3); letter-spacing:.05em; line-height:1.5; }


.cp-touch{ display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:32px; padding-top:24px; border-top:1px solid var(--ink); }
.cp-touch > div > span{ display:block; font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.06em; }
.cp-touch b{ display:block; margin-top:8px; font-family:var(--serif); font-size:calc(var(--fs-lg) * var(--k)); font-weight:500; line-height:1.75; letter-spacing:.01em; }
.cp-touch b a{ display:inline-flex; align-items:center; min-height:44px; text-decoration:underline; text-decoration-thickness:1px; text-underline-offset:4px; text-decoration-color:var(--line3); transition:color .2s var(--ease), text-decoration-color .2s var(--ease); }
.cp-touch b a:hover{ color:var(--brand); text-decoration-color:currentColor; }
.cp-touch em{ display:block; margin-top:8px; font-style:normal; font-size:var(--fs-xs); color:var(--ink3); }
.cp-acts{ display:flex; flex-wrap:wrap; gap:12px; margin-top:28px; }

@media (max-width:1120px){
  .cp2{ grid-template-columns:minmax(0,1fr); gap:32px; }
  /* 愿景块左列 2026-10-26 从 440 加到 520（为了让 30px 主句不拆行）。
     981–1120 这一档还按两列排，右栏就只剩 384 宽，13px 正文每行不到 30 字，
     两段话会被切成六七行。与 .cp2 同档落单列，深块变成通栏、高度由内容定，
     三段式结构不变。 */
  .vm{ grid-template-columns:minmax(0,1fr); gap:32px; }
  .vm-cul{ grid-template-columns:minmax(0,1fr); gap:8px; }
}
@media (max-width:980px){
  .cp-facts{ grid-template-columns:repeat(2,minmax(0,1fr)); gap:24px 32px; }
  /* 愿景使命与六类物业跟着落到单列 / 两列。
     .sf 的三列复位必须写在 2n 规则之前 —— 两者特异性相同，靠顺序取胜。 */
  .vm{ grid-template-columns:minmax(0,1fr); gap:28px; }
  .vm-cul{ grid-template-columns:minmax(0,1fr); gap:8px; margin-top:36px; }
  .sf{ grid-template-columns:repeat(2,minmax(0,1fr)); }
  .sf li:not(:nth-child(3n+1)){ padding-left:0; border-left:0; }
  .sf li:not(:nth-child(2n+1)){ padding-left:24px; border-left:1px solid var(--line2); }
  /* 两列下末项整行 —— 若沿用三列的「第 2 列起跨两格」，只剩第 2 列可用，
     会撑出隐式第 3 列。 */
  .sf li:last-child:nth-child(3n+2){ grid-column:1 / -1; }
  .cp-tl{ grid-template-columns:repeat(2,minmax(0,1fr)); }
  /* 两列时左列不留白、右列带竖线，第三项起补上横线，否则四块像散开的 */
  .cp-tl li{ padding:20px 24px 20px 0; }
  .cp-tl li:nth-child(2n+1){ padding-left:0; border-left:0; }
  .cp-tl li:nth-child(n+3){ border-top:1px solid var(--line2); }
  .cp-grid4{ grid-template-columns:minmax(0,1fr); gap:0; }
  .cp-touch{ grid-template-columns:minmax(0,1fr); gap:24px; }
  /* 980 下只收第一张通栏卡的两栏：其余四张仍两列并排（每张约 460 宽，
     14px 正文每行 28 字，还在 30–46 的下沿附近，读得动）。
     通栏卡不收到单列的话，左栏 300 + 右栏 300 会把正文挤成「四五个字一行」。 */
  .cp-svc li.hi{ grid-template-columns:minmax(0,1fr); gap:12px; padding:24px 24px 24px; }
  .cp-chips.wide{ grid-template-columns:repeat(2,minmax(0,1fr)); }
  .cp-touch.big{ grid-template-columns:minmax(0,1fr); }
  .cp-duo{ grid-template-columns:minmax(0,1fr); gap:28px; }
  /* 图与名片在窄屏叠成一列：并排时图只剩 200 宽，名片被挤到每行一个字母。
     这两条必须写在这个 980 块里 —— .cp-two / .cp-card 的基础规则在本文件更后面，
     写在页首的 760 块里会被后面的基础规则盖掉（等特异性下后者胜）。 */
  .cp-two{ grid-template-columns:minmax(0,1fr); gap:24px; }
  /* 单列后不再需要"撑到等高"：图回到源图比例（750×600 = 5:4），否则会撑成一条 */
  .cp-two .cp-fig img{ flex:none; min-height:0; aspect-ratio:5 / 4; }
  .cp-card{ max-width:none; }
  /* 窄屏按原比例会压到 149px 高（350 宽 ÷ 2.34），说明文字挤成一条。
     给一个 170 的下限：低于它才裁，而且只裁左右。 */
  .cp-fig img{ aspect-ratio:var(--ar,16/9); min-height:170px; }
}

/* 关于页的两块在手机上落到单列。独立成块而不塞进上面那个 980 —— 
   上一条 .cp-fig img 的 min-height 只该管到 980，760 这里另有规则。 */
@media (max-width:760px){
  /* 卡片在这里才落单列：760 以上两张并排，每张 330–460 宽仍读得动；
     760 以下并排只剩 160 宽，正文要折成每行 8 个字。 */
  .cp-svc{ grid-template-columns:minmax(0,1fr); gap:12px; }
  .cp-svc li{ padding:20px 20px 24px; }
  .cp-svc li.hi{ padding:20px 20px 24px; gap:8px; }
  .cp-chips.wide li{ min-height:68px; }
  .sf{ grid-template-columns:minmax(0,1fr); }
  .sf li:not(:nth-child(3n+1)){ padding-left:0; border-left:0; }
  .sf li:not(:nth-child(2n+1)){ padding-left:0; border-left:0; }
  .sf b{ font-size:var(--fs-md); }
  .vm-body{ gap:32px; }
  .vm-cul p{ font-size:var(--fs-bs); }
  /* 390 下黑块内容宽 282，「做最受信赖的商办地产服务商」12 字按 24px 要 288，
     差 6px 装不进 —— 末行只剩一个「商」字。降一档到 21.6px 装得下；
     360 及以下仍会折行，交给 balance 均分，不会再留孤字。 */
  .vm-lead{ padding:28px 24px; }
  .vm-lead b{ font-size:var(--fs-num); text-wrap:balance; }
}

/* ---------------- 详情页吸底动作条（只给手机） ----------------
   报价卡在右栏最上面，手机上要先滑过图集 + 参数表才看得见（实测 6 屏）。
   与其让客户找按钮，不如把动作钉在拇指够得到的地方。
   原来这里是「拨号 + 预约看楼」两个动作；座机停用后拨号那一格撤掉，
   只留预约看楼并撑满整条 —— 二分之一的宽度按钮反而更难点。
   .dbar-sp 是同一高度、同一断点的占位块 —— 没有它，页脚最后一行会被压在条下面。 */
.dbar{ display:none; }
@media (max-width:760px){
  .dbar{
    display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1.2fr); gap:8px;
    position:fixed; left:0; right:0; bottom:0; z-index: var(--z-chrome);
    padding:8px 12px calc(8px + env(safe-area-inset-bottom, 0px));
    background:var(--paper); border-top:1px solid var(--line);
  }
  .dbar a{ display:flex; align-items:center; justify-content:center; gap:8px; min-height:48px; font-size:var(--fs-bs); }
  .dbar svg{ flex:0 0 auto; }
  .db-tel{ border:1px solid var(--line3); background:var(--paper); color:var(--ink); font-variant-numeric:tabular-nums; }
  .db-go{ background:var(--ink); color:var(--white); }
  /* 占位块高度必须跟条子**算出来一样**：48 按钮 + 8/8 内边距 + 1 发丝线 = 65。
     原来写死 64，滚到底会差 1px；iPhone 上还有 34px 安全区，一并算进去，
     否则页脚最后一行照样被压住。 */
  .dbar-sp{ height:calc(48px + 16px + 1px + env(safe-area-inset-bottom, 0px)); }
}

/* ============================================================
   打印样式
   —— 招商的现场用法是：把详情页打出来，带着去看楼、去谈条件。
      屏幕上负责「导航」和「转化」的东西（顶栏、侧栏报价卡、推荐位、
      深色 CTA、全站公司条、图集）印到纸上全是噪音，还费墨。

   两条原则：
   ① 不逐条去盖颜色，而是把令牌本身改成纸上能用的值 —— tokens.css 里
      全是 var()，重定义一次，整页自动黑白，不用写 !important。
   ② 不留 !important：@media print 在文件末尾，选择器权重相同就靠顺序赢。
      真遇到权重不够的，说明原规则写得比它具体，应该改原规则而不是加 !。
   ============================================================ */
@media print{
  @page{ margin:14mm 12mm; }

  /* 颜色由 tokens.css 末尾的 @media print 统一重定义，这里只管版式 ——
     令牌只该在令牌文件里出现第二次。 */

  /* 屏幕上用于导航与转化的部分：纸上一律不要 */
  .hd,.ft,.skip,.crumb,
  .co,.dbelt,.dside,.dnear,.dgal,.dbar,.dbar-sp,
  .advg,.sform,.hstat,
  .dtop-cta,.dquote-b .btn{ display:none; }

  /* 题头保持「图在左、参数在右」：客户拿着这张纸现场比参数，
     图占 42% 就够认出这栋楼，剩下全给数字。 */
  .dtop, .dtop.nofig{ display:grid; grid-template-columns:minmax(0,42%) minmax(0,1fr);
         gap:8mm; align-items:start; }
  .dtop-r{ min-width:0; }

  /* 留 6mm 内边距兜底：浏览器若把页边距设成 0，内容不至于顶着纸边被裁 */
  .wrap{ max-width:none; width:auto; padding:0 6mm; }
  .dbody{ display:block; }
  .dmain{ width:auto; max-width:none; }

  /* 标题不要单独落在页尾（后面跟着一整页空白） */
  h1,h2,h3{ break-after:avoid; page-break-after:avoid; }

  /* 一个区块、一张表、一段引文尽量不跨页切开 */
  .dsec,.dquote,.dtnote,figure,table,tr{ break-inside:avoid; page-break-inside:avoid; }
  p{ orphans:3; widows:3; }

  a{ text-decoration:none; }

  /* 首图保留（客户要看楼长什么样），但按列宽铺 ——
     只写 max-height 会让宽度按原图比例算出来（563/750 × 70mm ≈ 352px），
     超过 42% 的列宽，图就压到右边参数表的左列上，那一列看着像丢了。 */
  .dfig{ break-inside:avoid; }
  .dfig img{ width:100%; height:auto; max-width:100%; max-height:none; }

  /* 平面图是整页纸里最值得印的东西 —— 带看时客户拿着它圈单元。
     屏幕上 210 宽的缩略图印到纸上等于没有，所以打印时按纸宽单独铺一列，
     一张一张排下去；「看原图」这四个字是屏幕上的提示，纸上没用。 */
  .dplan .dp-list{ display:block; margin-top:6mm; }
  .dplan .dp-list figure{ margin:0 0 7mm; }
  .dp-btn{ border:0; }
  .dp-btn img{ width:100%; height:auto; max-height:none; }
  img{ max-width:100%; }

  /* 落款（见上方 .pf 基础规则）。用 pt 不用 px：纸上一切按印刷单位，
     px 在不同 DPI 的打印机上差得很明显。
     左右 6mm：@page 已经给了 12mm 页边距，.wrap 在纸上又加 6mm，
     落款是 body 直系子元素、不吃 .wrap，必须自己补上这 6mm 才跟正文对齐。 */
  .pf{
    display:flex; justify-content:space-between; align-items:flex-end; gap:10mm;
    margin:9mm 6mm 0; padding-top:4mm; border-top:1px solid var(--line3);
    break-inside:avoid; page-break-inside:avoid;
  }
  .pf-l > b{ display:block; font-size:12pt; letter-spacing:.18em; }
  /* 必须是 > span：写 .pf-l span 会把内层的 .pf-day 这类行内小元素
     也变成块级，一句话被拆成两行。 */
  .pf-l > span{ display:block; font-size:9pt; color:var(--ink3); margin-top:1.5mm; }
  /* 不收缩：右边有电话和地址，被左边两条长句挤扁以后日期会掉到第二行 */
  .pf-r{ flex:0 0 auto; text-align:right; white-space:nowrap; }
  .pf-r > b{ display:block; font-size:11.5pt; letter-spacing:.04em; font-variant-numeric:tabular-nums; }
  .pf-r > span{ display:block; font-size:9pt; color:var(--ink3); line-height:1.75; }
  /* 用 .pf-r > .pf-d 拿权重（2 类 > 1 类 1 元素），不写 !important */
  .pf-r > .pf-d{ font-size:8pt; color:var(--ink4); margin-top:1mm; }
}

/* ============================================================
   租赁流程（process.html）：六步 × 三栏
   ============================================================
   每一步固定三栏：你需要做的 / 注意事项 / 阶段成果。
   三栏顺序不能换 —— 客户先看「我要做什么」，再看「别踩什么坑」，
   最后才是「这一步结束时手里有什么」。
   注意事项是本页真正的价值：写的是可核对的条款与时间点，
   不是「注意沟通」这类放在任何流程里都成立的空话。 */
.flow6{ border-top:1px solid var(--ink); }
.flow6 > li{ display:grid; grid-template-columns:minmax(0,240px) minmax(0,1fr); gap:48px; padding:32px 0; border-bottom:1px solid var(--line2); align-items:start; }
.flow6-l{ min-width:0; }
/* 序号与标题同一行（2026-10-21，与服务页的条目卡同一个手法）：
   原来是 .no 单独一行压在 h3 上面 —— 老板的原话是「序号放在前面不要放在上面」。
   竖线用 align-self:stretch 撑满标题行高，否则只有 12px 的一小截。 */
.flow6-l h3{
  display:flex; align-items:center;
  font-family:var(--serif); font-size:calc(var(--fs-lg) * var(--k)); font-weight:500; letter-spacing:.04em;
}
.flow6-l .when{ display:block; margin-top:8px; font-size:var(--fs-xs); color:var(--ink3); }
.flow6-r{ min-width:0; display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:32px; }
.fr{ min-width:0; }
.fr b,.tall b{ display:block; margin-bottom:8px; font-size:var(--fs-xs); font-weight:700; color:var(--ink3); letter-spacing:.08em; }
.fr p{ font-size:var(--fs-bs); color:var(--ink2); line-height:1.9; }
/* 注意事项用一道左侧细线标记，与另两栏区分；颜色仍是灰阶，不引入第三种色 */
.fr.warn{ padding-left:16px; border-left:1px solid var(--line3); }

/* ============================================================
   承接方（renovation.html 首屏之下）
   ============================================================
   原页面只有 hstat 里一个名字「乐企装」，客户点进来并不知道它和万仕行
   是什么关系 —— 而这恰恰是签约前最该说清的一句。标识按源图 480 宽存、
   240 宽显示（2 倍图），文字列紧随其后，不占整行。 */
.rz-biz{ display:grid; grid-template-columns:240px minmax(0,1fr); gap:20px 64px; align-items:start; max-width:none; }
.rz-biz-l{ display:flex; flex-direction:column; gap:12px; }
.rz-biz-l img{ display:block; width:100%; max-width:240px; height:auto; }
.rz-biz-l span{ font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.06em; }
.rz-biz-r{ min-width:0; max-width:var(--measure); }
/* 2026-10-23：正文原来写 13px / 42em（=546），是全站最窄的一处 ——
   同一页下面几节都是 15px / 700，翻到这一节字会明显变小一号。
   字号与行宽都跟 --fs-base / --measure 走，与其他页同一把尺。 */
.rz-biz-r p{ margin-top:16px; font-size:var(--fs-base); color:var(--ink2); line-height:1.9; max-width:var(--measure); }
@media (max-width:760px){
  .rz-biz{ grid-template-columns:minmax(0,1fr); }
  .rz-biz-l img{ max-width:180px; }
}

/* ============================================================
   装修时间表（renovation.html）
   ============================================================
   乐企装那份《办公装修时间表》是 10593 像素宽的三行流程图：十三个节点、
   三条推进线。缩到版心的 1296 宽，图上的字只剩三像素 —— 所以正文按节点
   重排（可读、可搜索、手机上不横滚），原图留在下面作全貌参考，
   它的价值是「三条线并行」这件事，不是字。

   责任方是这张表真正的用法：客户只关心哪几步要自己拍板。
   三个角色只用灰阶区分（实线 / 细线 / 虚线），不引入第四种颜色。
   ============================================================ */
/* 表宽锁 1120（与 .cp2 同一档）：13 行的正文都只有一行多，铺满 1296 时
   责任方一栏会被推到离正文 500px 之外，读起来像两块不相干的东西。 */
.rzn-key{ display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:8px 32px; margin-top:24px; max-width:1120px; }
.rzn-key li{ display:flex; align-items:baseline; gap:8px; min-width:0; }
.rzn-key li > span:last-child{ font-size:var(--fs-xs); color:var(--ink3); line-height:1.75; }

.rz-who{
  flex:none; display:inline-block; padding:2px 8px; line-height:1.75;
  border:1px solid var(--line3); font-size:var(--fs-xs); color:var(--ink2);
  letter-spacing:.02em; white-space:nowrap;
}
.rz-who.a{ border-color:var(--ink); color:var(--ink); font-weight:700; }
.rz-who.c{ border-style:dashed; color:var(--ink3); }

/* 2026-10-23：去掉 max-width:1120px。
   它让时间表右缘停在 1185，而上面的三条责任方说明（.rzn-key）与整节标题线
   都到 1361 —— 同一条竖线上，一条横线走到头、下一条少了 176px，
   看起来像没排完。实测左右两处都是 l=65，只是右边不齐。 */
.rzn{ margin-top:24px; border-top:1px solid var(--ink); }
.rzn-p + .rzn-p{ border-top:1px solid var(--ink); }
.rzn-ph{ display:flex; align-items:baseline; gap:16px; padding:24px 0 16px; }
.rzn-ph .n{ font-family:var(--serif); font-size:var(--fs-sm); color:var(--ink3); letter-spacing:.16em; }
.rzn-ph h3{ font-family:var(--serif); font-size:calc(var(--fs-lg) * var(--k)); font-weight:500; letter-spacing:.04em; }
.rzn-ph .rz-lead{ margin-left:auto; font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.04em; }

.rzn-n{ border-top:1px solid var(--line2); }
.rzn-n > li{
  display:grid; grid-template-columns:46px minmax(0,1fr) 150px; gap:0 20px;
  align-items:start; padding:16px 0; border-bottom:1px solid var(--line2);
}
.rzn-n .no{ padding-top:2px; font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.08em; font-variant-numeric:tabular-nums; }
.rzn-n h4{ font-size:var(--fs-md); font-weight:700; color:var(--ink); letter-spacing:.02em; line-height:1.75; }
.rzn-n .d{ margin-top:4px; font-size:var(--fs-bs); color:var(--ink3); line-height:1.75; }
.rzn-n .mt{ display:flex; flex-direction:column; align-items:flex-end; gap:4px; text-align:right; }
.rzn-n .cyc{ font-size:var(--fs-xs); color:var(--ink3); font-variant-numeric:tabular-nums; white-space:nowrap; }

/* 终点：图上那只绿框（新址搬迁办公）不是第 14 个节点，是整张表的出口 ——
   所以不编号，用箭头接着排在十三条之后。 */
.rzn-end{
  display:flex; align-items:baseline; gap:12px; flex-wrap:wrap;
  padding:16px 0 16px; border-bottom:1px solid var(--line2);
}
.rzn-end .arw{ color:var(--ink3); font-size:var(--fs-bs); }
.rzn-end b{ font-size:var(--fs-md); font-weight:700; letter-spacing:.02em; }
.rzn-end span:last-child{ font-size:var(--fs-bs); color:var(--ink3); line-height:1.75; }

/* ── 全貌：矢量时序带（2026-10-26 取代原 3200px 位图）─────────────
   原来那张是乐企装《办公装修时间表》的 PPT 截图，橙绿蓝黄四色，字 8px，
   放进 1296 的版心等于一片色块，所以旧版只能做成 360 高的裁切窗加一个
   「查看完整节点图 ↗」把读者送去新窗口。现在按 SCHEDULE 直接渲染：
   三行＝三段推进，一格＝一个节点。图只承担列表讲不清的事 —— 谁主办、周期多长、
   哪几段是并行的。
   编码只用线型，不引入颜色：主办方挂在左边框上（实线深＝企业方、
   实线浅＝承接方、虚线＝第三方），与前文 .rz-who 图例是同一套语义。 */
.rzm{ margin:44px 0 0; }
.rzm-hd{
  display:flex; justify-content:space-between; align-items:baseline;
  gap:12px 32px; flex-wrap:wrap; padding-bottom:12px; border-bottom:1px solid var(--ink);
}
.rzm-hd b{ font-family:var(--serif); font-size:var(--fs-md); font-weight:500; letter-spacing:.02em; }
.rzm-hd span{ font-size:var(--fs-sm); color:var(--ink3); line-height:1.75; }
/* 图例里的三个小色块直接吃 .rzm-n 的边框规则，避免两处各写一套 */
.rzm-hd i{ font-style:normal; padding-left:7px; border-left:3px solid var(--ink3); margin-right:2px; }
.rzm-hd i.who-a{ border-left-color:var(--ink); }
.rzm-hd i.who-c{ border-left:3px dashed var(--ink3); }

.rzm-rows{ margin:0; padding:0; list-style:none; }
.rzm-r{
  display:grid; grid-template-columns:176px minmax(0,1fr); gap:0 28px;
  padding:20px 0; border-bottom:1px solid var(--line2);
}
.rzm-r:last-child{ border-bottom:0; }
.rzm-ph{ display:flex; flex-direction:column; gap:3px; min-width:0; }
/* 序号「一 / 二 / 三」原来是独占一行的 19px serif —— 实测在版面上就是一根横杠，
   和破折号分不出来。改成标题前的领字：与段名同一行，字号降一档。 */
.rzm-ph .n{ font-family:var(--serif); font-size:16px; line-height:1.22; color:var(--ink3); margin-right:7px; }
.rzm-ph b{ font-size:var(--fs-bs); font-weight:700; letter-spacing:.02em; line-height:1.5; }
.rzm-ph i{ font-style:normal; font-size:var(--fs-sm); color:var(--ink3); line-height:1.5; }

/* 三行共用一套列宽（--cols 由生成器按「最多节点的一段」算）。格与格之间
   不插箭头元素：箭头做成元素会占一格宽度，第一行四个格子就比第二行五个宽。
   推进关系改用格缝里的一条细线加三角表达，格宽因此始终一致。 */
.rzm-ln{ display:grid; grid-template-columns:repeat(var(--cols,5),minmax(0,1fr)); gap:0 26px; min-width:0; }
.rzm-n{
  position:relative; min-width:0; min-height:88px;
  display:flex; flex-direction:column; gap:4px;
  padding:10px 12px 9px; border:1px solid var(--line3); border-left-width:3px;
  border-left-color:var(--ink3); background:var(--white);
}
/* 格缝里的推进线：18px 细线 + 一枚小三角，落在两格之间 */
.rzm-n + .rzm-n::before,
.rzm-n + .rzm-go::before{
  content:""; position:absolute; left:-26px; top:50%; width:17px; height:1px;
  background:var(--line3);
}
.rzm-n + .rzm-n::after,
.rzm-n + .rzm-go::after{
  content:""; position:absolute; left:-9px; top:50%; margin-top:-4px;
  border-left:5px solid var(--ink3); border-top:4px solid transparent; border-bottom:4px solid transparent;
  opacity:.55;
}
.rzm-n.who-a{ border-left-color:var(--ink); }
.rzm-n.who-c{ border-left-style:dashed; }
/* 2026-10-27：序号原来是写死的 11px（不是令牌，所以 10-23 抬 --fs-xs 时漏了它）。
   32 处命中「字号过小」。序号是路线图上的编号，认的是位置不是字号，
   但那仍是汉字/数字混排的可读文本，走 --fs-xs（12）。 */
.rzm-n .no{ font-size:var(--fs-xs); line-height:1; color:var(--ink3); font-variant-numeric:tabular-nums; letter-spacing:.06em; }
.rzm-n b{ font-size:var(--fs-bs); font-weight:700; line-height:1.45; letter-spacing:.01em; text-wrap:balance; }
.rzm-n .cyc{ margin-top:auto; font-style:normal; font-size:var(--fs-sm); color:var(--ink3); line-height:1.45; }
.rzm-n .cyc:empty::before{ content:"—"; }
/* 终点格：全页唯一的实心块，正好落在这条线的出口上 */
.rzm-go{ background:var(--ink); border-color:var(--ink); border-left-color:var(--ink); }
.rzm-go .no, .rzm-go .cyc{ color:rgba(255,255,255,.62); }
.rzm-go b{ color:var(--white); }

.rzm figcaption{ padding-top:12px; font-size:var(--fs-sm); color:var(--ink3); line-height:1.75; max-width:62em; }

/* ── 工序图示（2026-10-26 重排）─────────────────────────────────
   旧版是 4 列 × 2 行的方图墙，但整块**锁死** 1328 宽（4×314＋3×24）。
   1440 下刚好贴满版心 1296，看不出问题；1920 屏上版心 1616、这块只有 1328，
   右侧空出 288 —— 图片区与上方标题的右缘不在一条竖线上，看着像没排完；
   2K 屏空得更多。这就是「右边空很多」的来源。
   而图又不能放大（源图 314，放大就糊，check_type 会判），
   所以「铺满」与「不放大」在原结构里无法同时满足。
   解法是三条一起上：① 去掉 1328 的锁，网格铺满容器；② 图仍封顶 314，
   多出来的宽度让它**居中**（原来靠左，才会全部堆在格子左上角）；
   ③ 图注跟图同宽、同样居中 —— 只居中图不居中字，图注的左缘又会跑出 36px。
   八张图在 4 列里正好两行，不缺格。 */
.rzgal{
  display:grid; grid-template-columns:repeat(4,minmax(0,1fr));
  gap:40px 24px; margin-top:32px;
}
.rzgal figure{ margin:0; min-width:0; }
.rzgal img{ display:block; width:100%; max-width:var(--mw,314px); height:auto; aspect-ratio:var(--ar,1); object-fit:cover; background:var(--paper3); margin-inline:auto; }
.rzgal figcaption{ margin-top:12px; max-width:var(--mw,314px); margin-inline:auto; }
.rzgal b{ display:block; font-size:var(--fs-md); font-weight:700; color:var(--ink); letter-spacing:.02em; line-height:1.5; }
.rzgal figcaption span{ display:block; margin-top:6px; font-size:var(--fs-bs); color:var(--ink3); line-height:1.9; }

@media (max-width:980px){
  .rzn-n > li{ grid-template-columns:40px minmax(0,1fr) 128px; gap:0 16px; }
  .rzgal{ grid-template-columns:repeat(2,minmax(0,1fr)); gap:32px 24px; }
  .rzn-key{ grid-template-columns:minmax(0,1fr); gap:8px; }
  /* 时序带：阶段列挪到上面一行，节点仍横排 */
  .rzm-r{ grid-template-columns:minmax(0,1fr); gap:12px; padding:16px 0; }
  .rzm-ph{ flex-direction:row; align-items:baseline; gap:8px; flex-wrap:wrap; }
  .rzm-n{ min-height:82px; padding:9px 10px 8px; }
}
@media (max-width:760px){
  /* 手机上责任方与周期挪到条目下面一行：168 的右栏在 390 屏上会把标题挤成三行 */
  .rzn-n > li{ grid-template-columns:32px minmax(0,1fr); }
  .rzn-n .mt{ grid-column:2; flex-direction:row; align-items:center; justify-content:flex-start; gap:8px; margin-top:8px; text-align:left; }
  .rzn-ph{ flex-wrap:wrap; gap:8px 12px; }
  .rzn-ph .rz-lead{ margin-left:0; }
  /* 工序图两列在手机上放不下，回到单列 */
  .rzgal{ grid-template-columns:minmax(0,1fr); gap:28px; }
  /* 时序带竖排：一行一个节点，推进线转成竖向短箭头 */
  .rzm-ln{ grid-template-columns:minmax(0,1fr); gap:12px 0; }
  .rzm-n + .rzm-n::before, .rzm-n + .rzm-go::before{
    left:50%; top:-12px; width:1px; height:9px;
  }
  .rzm-n + .rzm-n::after, .rzm-n + .rzm-go::after{
    left:50%; top:-3px; margin-left:-4px; margin-top:0;
    border-left:4px solid transparent; border-right:4px solid transparent;
    border-top:5px solid var(--ink3); border-bottom:0;
  }
  .rzm-n{ min-height:0; }
  .rzm-n .cyc{ margin-top:2px; }
  .rzm-hd span{ font-size:var(--fs-xs); }
}

/* ============================================================
   资质清单（renovation.html）
   ============================================================
   两列清单，像证书目录：左边名称，右边等级。
   用网格而不是表格 —— 表格会把 9 行压得很密，且手机上横向溢出。 */
.quals{ display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:0 64px; border-top:1px solid var(--ink); }
.quals > div{ display:flex; align-items:baseline; justify-content:space-between; gap:16px; padding:16px 0; border-bottom:1px solid var(--line2); }
.quals span{ font-size:var(--fs-bs); color:var(--ink2); line-height:1.75; }
.quals b{ flex:none; font-size:var(--fs-xs); font-weight:700; color:var(--ink3); letter-spacing:.04em; white-space:nowrap; }

@media (max-width:980px){
  .flow6 > li{ grid-template-columns:minmax(0,1fr); gap:20px; padding:28px 0; }
  .flow6-r{ gap:24px; }
  .quals{ grid-template-columns:minmax(0,1fr); }
}
@media (max-width:760px){
  .flow6-r{ grid-template-columns:minmax(0,1fr); gap:16px; }
  .fr.warn{ padding-left:16px; }
}

/* ============================================================
   按源图原宽显示的配图（process.html / renovation.html）
   ============================================================
   --srcw 由生成器按图片真实像素写入。通栏时容器 1296，源图只有 838/840 宽，
   会被拉伸 1.5 倍以上 —— 闸门判据是「源宽/显示宽 < 0.85 即必糊」。
   限到源图宽后始终是缩小或原大，图注也跟随同宽，不会出现注比图宽一条街。 */
.cp-fig.fig-src{ max-width:var(--srcw,840px); margin-inline:auto; }

/* ============================================================
   流程节点带（process.html 首屏之下，2026-10-21）
   ============================================================
   原来这一格是写字楼中庭的实拍：好看，但与「流程」无关 —— 客户看完标题
   仍然不知道六步长什么样。现在换成六个节点：圆形图标 + 名称 + 序号与时长，
   背后一条发丝线把六枚串成一条路径。

   图标用描边不用实心：灰阶版面里六个实心图形会变成六个黑点，比文字更抢眼。
   圆底取 --paper2（与本区块底色相同）而不是白色 —— 它要恰好盖住背后那条线，
   多一档色差就会看见六个白斑。 */
.fl-band{ background:var(--paper2); padding:44px 0 40px; }
.fl-steps{ position:relative; display:grid; grid-template-columns:repeat(6,minmax(0,1fr)); }
/* 连接线从第一枚圆心到最后一枚圆心：每格宽 1/6，圆心在格心，
   所以左右各留 1/12（100%/12）的余量。 */
.fl-steps::before{
  content:""; position:absolute; top:23px; left:calc(100% / 12); right:calc(100% / 12);
  height:1px; background:var(--ink4);
}
.fl-steps li{ position:relative; min-width:0; padding:0 12px; text-align:center; }
.fl-ic{
  position:relative; z-index:1;
  display:flex; align-items:center; justify-content:center;
  width:48px; height:48px; margin:0 auto; border-radius:50%;
  border:1px solid var(--line3); background:var(--paper2); color:var(--ink2);
  transition:border-color .18s var(--ease), color .18s var(--ease);
}
.fl-steps li:hover .fl-ic{ border-color:var(--ink); color:var(--ink); }
.fl-steps b{
  display:block; margin-top:16px;
  font-family:var(--serif); font-size:var(--fs-base); font-weight:500; letter-spacing:.04em; color:var(--ink);
}
/* 序号与时长同一行：序号等宽浅灰，时长略深 —— 一眼看到「第几步、多久」 */
.fl-meta{ display:block; margin-top:8px; font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.02em; }
.fl-meta i{ margin-right:8px; font-family:var(--en); font-style:normal; letter-spacing:.08em; font-variant-numeric:tabular-nums; }
.fl-note{ margin-top:24px; font-size:var(--fs-xs); color:var(--ink3); line-height:1.9; text-align:center; }

/* 竖幅窄图 + 文字列（2026-10-21 第三版：抽成公用组件）
   两个地方用它：流程页第三步的「现场记录」、装修页首屏下方的「交付细节」。
   这种版式只有一个难点 —— 图会被自己的固有高度撑开行：
   <img> 一旦参与布局就按固有尺寸占位（760×1058 缩到 260 宽 = 362 高），
   右边的文字比它矮，于是图底下多出一截，「上下对齐」当场就没了。
   所以 picture 绝对定位铺满整列，行高完全由右栏文字决定，图用
   object-fit:cover 去适应这个框 —— 两栏的上下边永远落在同一像素。 */
.tall{ display:grid; grid-template-columns:260px minmax(0,1fr); gap:32px; align-items:stretch; }
/* 流程页那一格只是版位（跨两栏、与上一行留一点空），版式本身走 .tall */
.flow6-r .fr.ph{ grid-column:1/-1; margin-top:8px; }
.tall-col{ display:flex; flex-direction:column; min-width:0; }
.tall-fig{ position:relative; flex:1 1 auto; min-height:200px; margin:0; }
.tall-fig picture{ position:absolute; inset:0; display:block; }
/* 竖幅取景压到右下角（2026-10-24）：水印烧在右下角，而这个框是 flex 撑高的，
   框比例与源图比例只差 2%，居中取景就吃掉下沿 1%。2% 在数字上很小，
   但被吃掉的正是 logo 那一角 —— 判据（probe_dom 的 right/bottom 分解）只看到 2.1%。 */
.tall-fig img{ display:block; width:100%; height:100%; object-fit:cover; object-position:100% 100%; background:var(--paper3); }
.tall-list ol{ list-style:none; margin:0; padding:0; border-top:1px solid var(--line3); }
.tall-list li{
  display:flex; gap:8px; align-items:baseline;
  padding:16px 0; border-bottom:1px solid var(--line2);
  font-size:var(--fs-bs); color:var(--ink2); line-height:1.75;
}
.tall-list li i{ flex:none; font-family:var(--en); font-style:normal; font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.06em; font-variant-numeric:tabular-nums; }
/* 2026-10-27：加 max-width。这条注释原来横跨整个 1004px 容器，
   12px 字一行排到 83.7 个汉字（Butterick 上限 45–90 字符 ≈ 中文 48 字/行），
   眼睛扫到第二行就找不到起点。576px = 48 个 12px 汉字，正好落在上限内
   （判据的上限一档是 48；600px 算出来是 50，紧贴边界，不留余量）。
   它和上面的六条清单左缘对齐，视觉上仍然是一条注脚，不是新的一段正文。 */
.tall-list p{ margin-top:12px; font-size:var(--fs-xs); color:var(--ink3); line-height:1.75; max-width:576px; }

@media (max-width:980px){
  .fl-steps{ grid-template-columns:repeat(3,minmax(0,1fr)); gap:32px 0; }
  /* 三列两行时连接线会横穿第二行，去掉它 —— 两行之间本来就是断的 */
  .fl-steps::before{ display:none; }
}
@media (max-width:980px){
  /* 窄屏放不下两栏：图在上、文字在下。此时下栏撑不开图的高度，
     给图一个 3:4 的固定框，别让它变成一条没有比例的横片。 */
  .tall{ grid-template-columns:minmax(0,1fr); gap:20px; }
  .tall-fig{ display:block; max-width:300px; }
  .tall-fig picture{ display:block; }
  .tall-fig img{ height:auto; aspect-ratio:3/4; }
}
@media (max-width:760px){
  .fl-band{ padding:32px 0 32px; }
  .fl-steps{ grid-template-columns:repeat(2,minmax(0,1fr)); gap:24px 0; }
  .fl-ic{ width:42px; height:42px; }
  .fl-steps b{ margin-top:8px; font-size:var(--fs-md); }
  .fl-note{ margin-top:20px; text-align:left; }
}

/* ============================================================
   通用排期（process.html，2026-10-21）
   ============================================================
   来源是给客户的《项目进程-租赁》Excel：月份逐格排开、红色实心块占格。
   搬上网要改两件事：

   ① 时间轴换成「周次」而不是月份。每个项目的面积、装修深度与报批窗口都不同，
      把 4 月 / 5 月写死，等于替客户承诺了一个日期；换成第 1–15 周，
      模板成立，客户自己往日历上套。
   ② 红块换成墨色。Excel 里的红是「填色」，在这里红只有一个含义：
      终点。所以整张表只有第 14 行（正式入驻）那枚菱形是品牌红，
      其余里程碑是墨色菱形 —— 读图的人一眼就知道要往哪儿看。

   主路径实心、可并行的段落空心（第 11 行室内设计从第 4 周起就与谈判并行）。
   这张表的结论就在这条空心条上：总周期不是十五个节点相加。 */
.gantt{ --gnm:300px; margin:0; border-top:1px solid var(--ink); }
.g-head{
  display:grid; grid-template-columns:var(--gnm) minmax(0,1fr); gap:0 24px;
  padding:12px 0 8px; border-bottom:1px solid var(--line3);
}
.g-hl{ font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.08em; }
/* 周次刻度：数字贴在每一格的左边界，与下面 track 的竖线同一位置。
   刻度不做竖线穿过表体 —— 十四条横线已经够密，再加竖线就是 Excel。 */
.g-axis{ display:grid; grid-template-columns:repeat(15,minmax(0,1fr)); }
.g-axis span{ font-family:var(--en); font-size:var(--fs-xs); color:var(--ink3); font-variant-numeric:tabular-nums; }

.g-body{ list-style:none; margin:0; padding:0; }
/* 阶段带：--paper2 的浅底，从「一」到「四」作为四个分卷。
   ⚠ 左右各外扩 14px（负 margin），再靠 14px 内边距顶回来 —— 这样带子内部的
   轨道仍与下面各行的轨道同一起点。只写 padding 不外扩，阶段条整体右移 14px，
   十四行的条就会和阶段条错开半格，肉眼很难说出哪里不对、但整张表会「歪」。 */
.g-ph{
  display:grid; grid-template-columns:var(--gnm) minmax(0,1fr); gap:0 24px; align-items:center;
  margin:16px -14px 0; padding:8px 16px; background:var(--paper2);
}
.g-ph-l{ display:flex; align-items:center; gap:12px; min-width:0; }
.g-ph-n{
  display:grid; place-items:center; width:22px; height:22px; flex:none;
  border:1px solid var(--ink3); border-radius:50%;
  font-family:var(--serif); font-size:var(--fs-xs); color:var(--ink2);
}
.g-ph-t{ font-family:var(--serif); font-size:var(--fs-md); font-weight:500; letter-spacing:.04em; color:var(--ink); white-space:nowrap; }
/* 周段紧跟在阶段名后面，**不能右对齐**：右对齐落在第 15 周那一格的位置上，
   读起来像「这一段从第 15 周开始」。位置的暗示比文字本身更容易被相信。 */
.g-ph-r{ margin-left:8px; font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.04em; font-variant-numeric:tabular-nums; white-space:nowrap; }
.g-ph-track{ display:grid; grid-template-columns:repeat(15,minmax(0,1fr)); align-items:center; }
.g-ph-bar{ grid-column:var(--s) / span var(--n); height:3px; background:var(--line3); }

.g-row{
  display:grid; grid-template-columns:var(--gnm) minmax(0,1fr); gap:0 24px; align-items:center;
  padding:8px 0; border-bottom:1px solid var(--line2);
}
.g-name{ display:flex; gap:8px; min-width:0; font-size:var(--fs-bs); color:var(--ink2); line-height:1.5; }
.g-name i{ flex:none; margin-top:2px; font-family:var(--en); font-style:normal; font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.04em; font-variant-numeric:tabular-nums; }

/* 轨道：15 等分，竖发丝线只在轨道里出现（重复渐变画格线，不额外加 15 个空元素）。
   min-height 给 16，条 8 居中 —— 条比格线粗一档，才看得出「这一段被占了」。 */
.g-track{
  display:grid; grid-template-columns:repeat(15,minmax(0,1fr)); align-items:center; min-height:16px;
  background-image:repeating-linear-gradient(to right, var(--line) 0 1px, transparent 1px calc(100% / 15));
}
/* --s 起点格、--n 跨几格，直接交给 grid-column 的 span。 */
.g-bar{ position:relative; grid-column:var(--s) / span var(--n); height:8px; background:var(--ink); }
.g-bar.para{ background:transparent; border:1px solid var(--ink2); }
/* 里程碑：条尾一枚菱形。条本身仍是主路径的一段，菱形只说「这里要签字/交钱」。 */
.g-bar.mile::after{
  content:""; position:absolute; right:-3px; top:50%; width:8px; height:8px;
  background:var(--ink); transform:translate(0,-50%) rotate(45deg);
}
.g-bar.end::after{ background:var(--brand); }
.g-wk{ display:none; }
/* 手机版没有条，图例里的墨条就没有对应物 —— 换成跟着行走的文字标签（.g-tag）：
   「可与谈判并行」这件事在文字版里反而更要说清楚，否则十五行看起来是一个接一个。 */
.g-tag{ display:none; }

.g-legend{
  display:flex; flex-wrap:wrap; align-items:center; gap:8px 24px;
  padding-top:16px; font-size:var(--fs-xs); color:var(--ink3);
}
.g-legend .lg{ display:inline-block; width:20px; height:8px; margin-right:8px; vertical-align:middle; background:var(--ink); }
.g-legend .lg-para{ background:transparent; border:1px solid var(--ink2); }
.g-legend .lg-mile{ width:8px; height:8px; margin-right:8px; background:var(--ink); transform:rotate(45deg); }
.g-legend .lg-note{ margin-left:auto; line-height:1.75; }

@media (max-width:1120px){ .gantt{ --gnm:240px; } }
/* 900 以下不再画条：38px 一格在手机上已经是「看得见、读不出」。
   改成同一张表的文字版 —— 每行右侧直接写「第 1–2 周」。
   这不是降级，是换了一种更准确的读法：手机上一行一件事，时间跟着走。 */
@media (max-width:900px){
  .gantt{ --gnm:1fr; }
  .g-head{ grid-template-columns:minmax(0,1fr) auto; }
  .g-axis{ display:none; }
  .g-head::after{ content:"周次"; font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.08em; }
  .g-ph{ grid-template-columns:minmax(0,1fr); margin:20px -12px 0; padding:8px 12px; }
  .g-ph-track{ display:none; }
  .g-ph-r{ margin-left:auto; }
  .g-row{ grid-template-columns:minmax(0,1fr) auto; gap:0 16px; }
  .g-track{ display:none; }
  .g-wk{ display:block; font-size:var(--fs-xs); color:var(--ink3); font-variant-numeric:tabular-nums; white-space:nowrap; }
  .g-tag{ display:inline-block; margin-left:8px; padding:1px 8px; border:1px solid var(--line3); font-size:var(--fs-xs); color:var(--ink3); white-space:nowrap; }
  .g-legend .lg-i{ display:none; }
  .g-legend .lg-note{ margin-left:0; }
}

/* ---------- 落地页「其余 N 栋」文字索引 ----------
   见 _dev/gen_site.js 的 cardList()。浦东 687 栋、2 号线 751 栋，
   全铺成卡片单页接近 900KB、要懒加载七八百张图；但整批砍掉又会让这批楼
   变成孤岛页（站内没有入口，搜索引擎也不给权重）。
   折中：前 48 栋给卡片，其余排成自适应文字栏 —— 一屏能看到几十个楼名，
   一条链接不到 90 字节，六百条也不到 60KB。
   行高 44px 是触控下限，和站内其他列表保持同一个数。 */
/* 2026-11-03 上线前核查：文字索引改成折叠（老板已确认「折叠文字索引」）。
   直出时 xiezilou/index.html 桌面 40,275px / 手机 103,134px，其中这一千到三千个
   楼名就占 31,000px 上下 —— 读者要滚过整份索引才见到下一页入口。
   用原生 <details>：内容不离开 DOM，站内内链与 SEO 一条不丢，默认收起。
   ⚠ summary 必须 display:flex 且 list-style:none：
   ① 浏览器给 summary 的默认 display 是 list-item，会顶掉 .flatidx-h 的 flex，
      「按楼名排列」和「展开全部」会掉到两行；② 不去掉 list-style 会多一个三角，
      和右侧的展开指示重复。 */
.flatidx{ margin-top:44px; padding-top:28px; border-top:1px solid var(--line2); }
.flatidx-h{
  display:flex; align-items:baseline; gap:12px; list-style:none;
  font-family:var(--serif); font-size:var(--fs-md); font-weight:500; letter-spacing:.02em;
  cursor:pointer;
}
.flatidx-h::-webkit-details-marker{ display:none; }
.flatidx-h span{ font-family:var(--sans); font-size:var(--fs-xs); font-weight:400; color:var(--ink3); letter-spacing:.04em; margin-right:auto; }
.flatidx-x{
  flex:none; font-style:normal; white-space:nowrap;
  font-family:var(--sans); font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.04em;
}
.flatidx-x::after{ content:'展开全部 ↓'; }
.flatidx[open] > .flatidx-h .flatidx-x::after{ content:'收起 ↑'; }
.flatidx-h:hover{ color:var(--brand); }
.flatidx-h:hover .flatidx-x{ color:var(--brand); }
.flatidx-l{
  margin-top:16px;
  display:grid; grid-template-columns:repeat(auto-fill, minmax(196px, 1fr));
  column-gap:28px;
}
.flatidx-l a{
  display:flex; justify-content:space-between; align-items:baseline; gap:8px;
  min-height:44px; padding:8px 0; border-bottom:1px solid var(--line2);
}
/* 2026-10-27：楼名不再单行截断。
   原来是 nowrap + ellipsis —— 区域页的「其余 N 栋」索引里，最长的楼名
   （「半岛湾时尚文化创意产业园（北外滩/四川北路）」）在 390 宽下只剩 139px，
   被砍掉 118px，也就是说**后半截楼名和括号里的片区全看不见**。
   而括号里的「（北外滩/四川北路）」正是同名楼之间唯一的区分（全站 34 组同名），
   砍掉它等于把消歧信息删了。改成允许折行：一行放不下就两行，
   这一块本来就是「一屏扫几十个楼名」的密度区，两行仍然比截断强。
   ⚠ 不改成 line-clamp：clamp 仍然会裁，判据（scrollWidth > clientWidth）仍判红，
   而且被裁的正是区分信息。 */
.flatidx-l b{
  font-weight:400; font-size:var(--fs-sm); color:var(--ink);
  overflow-wrap:anywhere;
}
.flatidx-l em{
  flex:none; font-style:normal; font-size:var(--fs-xs);
  color:var(--ink3); font-variant-numeric:tabular-nums;
}
.flatidx-l a:hover b{ color:var(--brand); }
@media (max-width:760px){
  .flatidx-l{ grid-template-columns:repeat(auto-fill, minmax(150px, 1fr)); column-gap:16px; }
}

/* ── AI 答案块「一句话看清这栋楼」（2026-10-22）────────────────
   目的不是好看，是让 AI 能在首屏附近找到「一段能直接抄走的话 + 一张能解析
   的表 + 两组判断」。视觉上只做两件事，不引入新色块：
     · 首句放大一档（读者跳过正文也能读到结论）；
     · 适合/留意两栏并列（桌面）或上下叠（手机）。
   红线：全页只允许一个深色块（首屏主图旁），这里不许加背景色。 */
.ans-lead{ margin-top:16px; font-size:var(--fs-lg); line-height:1.9; color:var(--ink); }
.answ .dl2{ margin-top:16px; }
.ans-fit{ display:grid; grid-template-columns:1fr 1fr; gap:28px; margin-top:24px; }
.ans-fit h3{ font-family:var(--sans); font-size:var(--fs-sm); font-weight:700; letter-spacing:.06em; color:var(--ink3); margin:0 0 4px; }
.ans-fit ul{ margin:0; padding:0; list-style:none; }
.ans-fit li{ position:relative; padding:4px 0 4px 16px; font-size:var(--fs-bs); line-height:1.75; color:var(--ink2); }
.ans-fit li::before{ content:""; position:absolute; left:0; top:15px; width:5px; height:1px; background:var(--ink4); }
@media (max-width:760px){
  .ans-lead{ font-size:var(--fs-base); line-height:1.9; }
  .ans-fit{ grid-template-columns:1fr; gap:16px; }
}

/* ── 问题型内容页（2026-10-22）─────────────────────────────────
   这批页面回答的是「怎么办」，不是「有什么楼」，所以版式要比楼栋页更
   像一篇可以读的答案：表格承载对照，列表承载事实，不做卡片堆叠。
   表格用最朴素的边线表 —— AI 解析表格时，合并单元格和斑马纹都是噪音。 */
/* 2026-10-23：加 tabular-nums。表里这类值最多：「1–2 周」「2–4 周」「3–5 周」
   「4.7 元」「62–70」——比例字下数字宽度不等，"1"窄"8"宽，同一列上下就对不齐，
   远看像表格没排完。等宽数字只改数字，不动中文，零风险。 */
.ctab{ width:100%; border-collapse:collapse; margin-top:16px; font-size:var(--fs-bs); font-variant-numeric:tabular-nums; }
.ctab th,.ctab td{ text-align:left; padding:12px 16px 12px 0; border-bottom:1px solid var(--line); vertical-align:top; }
.ctab th{ font-family:var(--sans); font-size:var(--fs-sm); font-weight:700; color:var(--ink3); letter-spacing:.05em; border-bottom:1px solid var(--ink4); white-space:nowrap; }
.ctab td{ color:var(--ink2); line-height:1.75; }
.ctab td.k{ color:var(--ink); }
.ctab tbody tr:last-child td{ border-bottom:0; }
/* 短值单元格（1–2 周 / 62–70% / 30 天）整格不断行。
   裸写 white-space:nowrap 会让手机上的表格重新撑出视口，所以只在
   「这一格本来就短」时才用（生成器判定后包 .nw），长句格子照常折行。 */
.ctab .nw{ white-space:nowrap; }
@media (max-width:760px){
  .ctab{ font-size:var(--fs-sm); }
  .ctab th,.ctab td{ padding:8px 8px 8px 0; }
}
/* 关键事实清单：一条一句，前面加短横 —— 与「需要留意」同一套视觉语言 */
/* 2026-10-23：这一列原来是 13px / 行高 1.9 / 无 measure —— 于是同一小节里
   段落按 42em（约 42 字）收着，列表却铺满整个主栏：1440 下一行 68 个字、
   1920 下 92 个字，两种节奏并排，读起来像两块不是一套的东西。
   改法与 .dtxt 对齐：同字号（15px）、行高收到 1.8、宽度用同一把尺。
   ⚠ 2026-10-23 夜再改一次：原来这里写 max-width:42em，但 42em 在 15px 的字号下
   算出 630，而 .dtxt 的 42em（基准 17px）算出 714 —— 字/行一样，右缘差 84px。
   改成统一令牌 --measure（700px），两条右缘才真的在同一条线上。 */
.cfl{ margin:20px 0 0; padding:0; list-style:none; max-width:var(--measure); }
.cfl li{ position:relative; padding:8px 0 8px 16px; font-size:var(--fs-base); line-height:1.75; color:var(--ink2); }
.cfl li::before{ content:""; position:absolute; left:0; top:calc(7px + .9em); width:7px; height:1px; background:var(--ink4); }
/* 相关内容链接：两列，锚文本本身就是一句话，不做「点此查看」 */
.clink{ margin:16px 0 0; padding:0; list-style:none; display:grid; grid-template-columns:1fr 1fr; gap:0 32px; }
.clink a{ display:block; padding:12px 0; border-bottom:1px solid var(--line); font-size:var(--fs-bs); color:var(--ink2); }
/* 条目数是奇数时，最后一条会独占左半格，右半格空着 —— 于是那一条的下划线
   停在行中间，看着像表格少画了一截（实测 .clink 每项 424、容器 880，3 项和 5 项都撞）。
   让奇数末项横跨两列：右缘收回容器边界，同时奇数/偶数两种条数自然长出两种版式。 */
.clink li:last-child:nth-child(odd){ grid-column:1 / -1; }
.clink a:hover{ color:var(--brand); }
@media (max-width:760px){ .clink{ grid-template-columns:1fr; } }
/* 内容组索引页 */
.cindex{ margin:16px 0 0; padding:0; list-style:none; }
.cindex li a{ display:block; padding:16px 0; border-bottom:1px solid var(--line); }
.cindex b{ display:block; font-family:var(--serif); font-size:var(--fs-lg); font-weight:500; color:var(--ink); letter-spacing:.01em; }
.cindex span{ display:block; margin-top:4px; font-size:var(--fs-sm); color:var(--ink3); }
.cindex a:hover b{ color:var(--brand); }

/* ── 落地页判断块（2026-10-22）─────────────────────────────────
   区域/商圈/地铁页的列表上方原来只有一句导语加数字，读者看完 300 个楼名
   仍然不知道「这片到底适合我不」。这一块放在列表**之后**：
   先让人看到楼，再给他一个能带走判断的结论。
   视觉沿用答案块（.ans-lead / .ans-fit），不新增语言。 */
.hjudge{ padding:var(--sp-band) 0; border-top:1px solid var(--line); }
.hjudge h2{ font-family:var(--serif); font-size:calc(var(--fs-h2) * var(--k)); font-weight:500; letter-spacing:.04em; display:flex; align-items:baseline; gap:16px; }
.hjudge h2 .side{ font-family:var(--sans); font-size:var(--fs-sm); font-weight:400; color:var(--ink3); letter-spacing:.06em; }
.hjudge .ans-lead{ margin-top:20px; max-width:64ch; }
.hjudge .ans-fit{ max-width:980px; }

/* ── 楼盘首屏报价块（2026-10-22 二轮大改）──────────────────────
   六格小字里塞价格，价格和「总层数」读起来一样重。搜楼把报价做成
   独立一块、字号仅次于 h1 —— 客户点进一栋楼，第一件事就是问多少钱。
   这里只用一个主角数字 + 三个副数，不加色块、不加红条
   （本页的红已经用在 .dsum 与侧栏报价条上了，红只两处）。
   右栏宽约 600，`220–5,000` 这类 9 字数字在 --fs-num 下量得下；
   手机上一列两行，不挤成三格。 */
.dlead{ margin:0 0 24px; padding:16px 0 20px; border-top:1px solid var(--ink); border-bottom:1px solid var(--line); }
.dlead-h .lab{ font-size:var(--fs-sm); letter-spacing:.08em; color:var(--ink3); }
.dlead-h b{
  display:inline-block; margin-top:8px; font-family:var(--serif); font-weight:500;
  font-size:calc(var(--fs-h2) * var(--k)); line-height:1.1; letter-spacing:.01em;
  font-variant-numeric:tabular-nums;
}
.dlead-h em{ font-style:normal; font-family:var(--sans); font-size:var(--fs-bs); color:var(--ink3); margin-left:8px; }
/* 「面议」不是一个数字，不占主角字号（2026-10-22 二轮大改补）。
   主角字号是留给「能被比较、能被反算」的报价的；全库 1,140 栋楼没有挂牌价，
   若沿用 30px，客户点进来第一眼看到的最大一行字就是「面议」两个字 ——
   整页最响的位置在说「没有」。降到副数字号，让视觉重心落到在租套数、
   面积段与右侧的咨询入口上，同时补一行去哪问价的说明。 */
.dlead-h b.is-na{
  font-size:calc(var(--fs-num) * var(--k));
  letter-spacing:.02em; padding-bottom:4px;
}
.dlead-na{ margin:16px 0 0; font-size:var(--fs-sm); color:var(--ink3); max-width:44em; }
.dlead-b{ display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); margin-top:16px; }
.dlead-b > div{ min-width:0; padding-right:16px; }
.dlead-b > div + div{ padding-left:16px; border-left:1px solid var(--line2); }
.dlead-b span{ display:block; font-size:var(--fs-xs); letter-spacing:.06em; color:var(--ink3); }
.dlead-b b{
  display:block; margin-top:4px; font-family:var(--serif); font-weight:500;
  font-size:calc(var(--fs-num) * var(--k)); white-space:nowrap; font-variant-numeric:tabular-nums;
}
.dlead-b em{ font-style:normal; font-family:var(--sans); font-size:var(--fs-xs); color:var(--ink3); margin-left:4px; }

/* ── 同商圈对比表（2026-10-22 二轮大改）────────────────────────
   搜索页与详情页共用一套表格语言：细线、无斑马纹、数字右对齐等宽。
   首列给楼名（可点），所以表格外侧必须能横向滚动 —— 手机上六列塞不下，
   挤成一行行换字比横向滑动更难读。 */
/* position:relative 不是为了定位，是为了给表格里的 .sr（绝对定位的屏读文本）
   一个包含块 —— 否则它按初始包含块算 static 位置，逃出下面的 overflow-x 裁剪，
   在 390 视口把整页撑到 439。max-width 兜住 grid 子项的 min-width:auto。 */
.dtwrap{ margin-top:8px; overflow-x:auto; -webkit-overflow-scrolling:touch; max-width:100%; position:relative; }
.dtable{ width:100%; min-width:560px; border-collapse:collapse; font-size:var(--fs-bs); }
.dtable th{
  padding:0 16px 8px 0; text-align:left; font-weight:400; font-size:var(--fs-xs);
  letter-spacing:.06em; color:var(--ink3); border-bottom:1px solid var(--ink); white-space:nowrap;
  /* top 对齐，不是默认的 baseline：表头多数列是「标签 + 单位」两行（面积/㎡），
     少数列只有一行（装修）。不钉死顶部，单行的那列会被居中，跟邻列的标签错开半行。 */
  vertical-align:top;
}
.dtable th em{ display:block; margin-top:4px; font-style:normal; font-size:var(--fs-xs); letter-spacing:0; color:var(--ink3); }
.dtable th.num{ text-align:right; }
.dtable td{ padding:12px 16px 12px 0; border-bottom:1px solid var(--line); vertical-align:middle; }
.dtable td.num{ text-align:right; white-space:nowrap; font-variant-numeric:tabular-nums; }
.dtable td.na{ color:var(--ink3); }
.dtable .pk-n{ min-width:170px; line-height:1.5; }
/* 周边推荐每行一张楼栋主图（v6.0）。这张图**可以**用楼栋实拍 ——
   周边表一行就是「另一栋楼」，不存在「同一张照片在十行里重复」的问题
   （那正是房源列表不能借楼栋图的原因）。
   76×57 的相框 + contain：不裁图，角标水印就不会被切掉；
   框底 paper3，留白读起来像装裱而不是没铺满。 */
.dtable .pk-t{
  width:76px; height:57px; margin:0 0 0; flex:0 0 auto;
  background:var(--paper3); overflow:hidden;
  display:flex; align-items:center; justify-content:center;
}
.dtable .pk-t img{ display:block; width:auto; height:auto; max-width:100%; max-height:100%; }
.dtable .pk-tph{ color:var(--ink3); font-size:var(--fs-xs); border:1px solid var(--line2); }
/* 图和楼名横排：图在左、名字在右，两行的行高因此对齐 ——
   只有一侧有图的话，整张表的名字会左右错开，扫读时对不上。 */
.dtable .pkn{ display:flex; align-items:center; gap:12px; }
.dtable .pkx{ min-width:0; }
.dtable .pk-tag{
  display:inline-block; margin-left:8px; padding:1px 8px; font-size:var(--fs-xs);
  color:var(--ink3); border:1px solid var(--line); border-radius:var(--r-1); white-space:nowrap;
}
/* 本栋那一行只加底色与加粗，不用品牌红 —— 红在这页已经用完了，
   而且「我在这」用底色表达比用红更准确：红在这里会被读成「推荐」。 */
.dtable tr.pk-self td{ background:var(--paper2); }
.dtable tr.pk-self td:first-child{ padding-left:8px; }
.dtable tr.pk-self td:last-child{ padding-right:8px; }

@media (max-width:760px){
  .dlead-b{ grid-template-columns:1fr 1fr; row-gap:16px; }
  .dlead-b > div + div{ padding-left:0; border-left:0; }
  .dlead-b > div:nth-child(2n){ padding-left:16px; border-left:1px solid var(--line2); }
  .dtable{ min-width:520px; }
  /* 同栋其他单元表在手机上收掉「单价」列（2026-10-22 二轮大改）：
     6 列挤进 390 时右侧刚好切在「精装带家具」中间，看着像页面坏了；
     而单价与月租是同一份数据的两副面孔，月租已经含了面积，手机留月租就够。
     收成 5 列后表格能在 390 内站住，真的还放不下时下面的 overflow-x 仍然兜底。 */
  .dunits-sib .dtable{ min-width:0; }
  .dunits-sib .c-price{ display:none; }
}
.dcost .dl2{ margin-top:0; grid-template-columns:1fr; gap:0; }
.dcost .dl2 .i{
  flex-direction:row; align-items:baseline; justify-content:space-between;
  gap:12px; padding:8px 0; border-top:1px solid var(--line2);
}
.dcost .dl2 dt{ flex:none; }
.dcost .dl2 dd{ font-size:var(--fs-bs); text-align:right; line-height:1.5; }
.dcost .dl2 .i.sum{ border-top:1px solid var(--ink); padding-top:12px; margin-top:2px; }
.dcost .dl2 .i.sum dt{ color:var(--ink); }
.dcost .dl2 .i.sum dd{ font-family:var(--serif); font-weight:500; font-size:var(--fs-lg); color:var(--ink); }

/* 对比表里的报价条（2026-10-22 二轮大改）
   同一张表里最便宜的一档满宽，其余按「最低价 ÷ 最高最低价」等比缩。
   条只有 3px、用墨阶不用品牌红 —— 它的作用是让一排数字有个可比的高度，
   不是抢注意力；本栋那一行条子用更深的墨，读者一眼能定位自己在哪。 */
/* 条与数字的间距 10px（不是 7px）：7px 时 3px 的深色条紧贴在价格数字下方，
   在 1440 截图里读起来像一条**删除线** —— 价格被划掉是灾难性的误读。
   拉开距离 + 保留全宽浅灰底轨，它才像「条形图」而不是「下划线」。 */
.pk-bar{ display:block; margin-top:8px; height:3px; background:var(--line2); }
/* 条身用 --ink3 不用 --ink4：--ink4 在纸底上只有 2.8:1，令牌注释里写明它只配做
   分隔线与描边；3px 的条子是要被读的数据，不是线。
   margin-left:auto 让它从右侧生长、与右对齐的价格数字同一个右端 ——
   从左生长时条的右端和数字的右端差着半个单元格，看着像没对齐的两件事。 */
.pk-bar i{ display:block; height:100%; background:var(--ink3); margin-left:auto; }
.dtable tr.pk-self .pk-bar{ background:#DCDAD5; }
.dtable tr.pk-self .pk-bar i{ background:var(--ink); }

/* ============================================================
   3.0 · 首屏图片带 + 报价横条（2026-10-22 三轮大改）
   ------------------------------------------------------------
   1.0 的首屏是一张图 + 右侧四格数据，病根在 .dfig img 的这一行：
       max-width: min(var(--mw,840px), calc(min(58vh,540px) * var(--ar,1.5)));
   图宽是被「高度上限 × 源图比例」**反算**出来的。竖构图（上海写字楼
   大量是竖拍）比例 0.8，图宽只有 438px，却占着 fit-content(56%) 的 694px 栏，
   中间白出 316px；而右栏四格数据只有 324px 高，图却有 572px 高 ——
   首屏右下半块整片空白。上一轮只是往白带里填了内容，没有动图本身。

   3.0 换结构：不再让「源图比例」决定版面，改成**图片带**——
   主图吃满整行高度，右列两张缩略图，图与图之间 8px 缝（图墙的做法）。
   比例交给 object-fit:cover，高度交给一个视口单位令牌统一控制：
   1440×900 的笔记本上图片带 378px，首屏能同时看到标题、图、和报价横条。
   ============================================================ */
.dhero{
  /* 高度是这一块唯一的旋钮。改它不会连带改比例 —— 这是 1.0 最大的教训：
     比例与高度互相反算，改一个另一个就变形。
     42vh / 下限 320 / 上限 520：900 高的屏 → 378，1080 → 453，4K → 520 封顶。 */
  --dh-h: clamp(320px, 42vh, 520px);
  --dh-g: 8px;
  display:grid; gap:var(--dh-g); margin-top:24px; align-items:stretch;
}
/* n1：整栋只有一张实拍 —— 就这一张，居中放，不跟它凑第二格。
   ⚠️ 2026-10-22 闸门判红后收窄：全库 7,047 张图里 84% 原生宽只有 750–899，
   ≥1,200 的只有 26 张。主图铺到 1,296 是放大 0.58×（必糊，check_type 第 5 步
   直接判红）。宽度封顶 860：750/860 = 0.87，压在闸门 0.85 线上方；
   再宽就糊，再窄就不像主角。 */
/* ── 2026-10-22 四轮修正：n1 从 grid 改 flex ─────────────────────
   3.0 写的是 `.dhero.n1{grid 单列}` + `figure{max-width:860;margin:0 auto}`。
   实测那 860 的封顶**从来没生效过**：网格项一旦有 `margin:auto`，
   它就从 stretch 变成 shrink-to-fit，宽度退回内容宽度 ——
   而内容是一张 aspect-ratio 由 height 反算的竖图，于是 figure 只有 307 宽
   （`_geom.js` 实测：figure 306.8、img 306.8、容器 1,296）。
   左右各空 400 多，客户看到的是「一张图孤零零浮在中间」。

   改成 flex 居中：轴线、竖排图注、图片三者作为一个整体，gap 26 把它们绑在一起。
   竖图不再被要求铺满整行（铺满就要裁掉 64%，一栋楼只剩中间一截），
   而是按源比例站住；高度提到 46vh 让它有主角的分量。
   横图在 440 高下自然到 783 宽，仍低于 860 封顶，放大倍数不变。 */
.dhero.n1{
  display:flex; align-items:center; justify-content:center; gap:24px;
  --dh-h:clamp(360px,46vh,560px);
}
.dhero.n1 figure{ flex:0 0 auto; max-width:860px; margin:0; height:var(--dh-h); }
.dhero.n1 .dh-axis,.dhero.n1 .dh-vd{ height:var(--dh-h); flex:0 0 auto; }
.dh-vd .vd{ font-size:var(--fs-xs); color:var(--ink3); }
/* 首屏主图的内描边：白亮的大堂照片压在纸底上时，边缘会和背景糊在一起，
   1px 的 12% 墨线把它「钉」住。outline 不占布局 —— 见 ed.css 里 W09 的说明。 */
.dhero figure.frm{ outline:1px solid rgba(var(--ink-rgb),.12); outline-offset:-1px; }
/* n2：主图 + 右列。主图列宽由生成器按源图原生宽算好写进 --hw（禁放大，
   小图就窄一点，右列 1fr 自动吃掉剩下的宽）—— 原来给死 340，
   在 1,680 的容器里右边会空出 400 多 px 的纸面，图带断成两截。 */
.dhero.n2{ grid-template-columns:minmax(0,min(100%,var(--hw,860px))) minmax(0,1fr); }
.dhero figure{
  margin:0; position:relative; overflow:hidden;
  background:var(--paper3);
  /* 老浏览器没有 object-fit 时退回一张被拉伸的图也不塌 —— 有 aspect 兜底 */
  height:var(--dh-h);
}
.dhero figure img,
.dhero figure .gal-btn{ width:100%; height:100%; }
/* object-position 偏上（44%）而不是正中：满宽裁切是**只裁上下**，
   一栋 1250×891 的楼景铺到 1,296 宽要裁掉 55% 的高度，正中的话
   裁掉的就是楼顶 —— 白玉兰广场实测只剩中间一截江面。
   楼顶比天空和地面都重要，所以取 44%：留出天际线，压掉前景的地砖。 */
.dhero figure img{ display:block; object-fit:cover; object-position:50% 44%; filter:saturate(.96) contrast(1.02); }
/* 右列两格：均分高度，中间留一条缝。用 grid 而不是 margin-top，
   是因为 n=2 时（只有一张缩略图）它要能自己撑满，不留半格空洞。
   height 必须显式给：1fr 1fr 只平分「容器已有的高度」，
   容器没高度时行高由内容决定 —— 而内容的 figure 各自带 --dh-h，
   于是两张 420 的图把右列撑成 848，主图却被自己的 height 钉在 420，
   图片带整体比主图高一倍（实测 kerry 848 vs 420）。 */
.dh-s{ display:grid; gap:var(--dh-g); grid-template-rows:1fr 1fr; min-width:0; height:var(--dh-h); }
.dh-s.one{ grid-template-rows:1fr; }
/* 右列里的 figure 必须放弃 --dh-h，改跟网格行高走。
   上面那条 .dhero figure{height:var(--dh-h)} 对它同样生效 ——
   两张 420 的图塞进两个 206 的行，多出来的 428 直接溢出图片带、
   压在下面的报价横条上（实测第 5 格「月支出合计」被盖掉）。
   100% 让它们各占自己那一行，正好 206。 */
.dh-s figure{ height:100%; }

/* ── 首屏图窗 v7.0（2026-10-23）────────────────────────────────
   老板：「主图做多张图片可以翻页查看，不然上面空白太多了」。
   结构没有推翻 n1/n2 —— 沿用 n2 的「主图 860 + 右列」骨架，
   改的是**右列装什么**：以前只有「第 2、3 张图」，两张就到底；
   现在右列固定两格，图不够就装速览数据，空白一律变成内容。
   主图宽度仍是 860 封顶（源图原生宽 750–899 占 84%，再宽就是放大）。
   ───────────────────────────────────────────────────────────── */
/* 右列只剩一个孩子时占满两行。没有这条，n=2 的楼会空出下半格 ——
   而「空半格」正是这次要消灭的东西。 */
.dh-s > :only-child{ grid-row:1 / -1; }

/* 主图上的翻页箭头。44px 是触控底线（手机上一根手指点得中）。
   底色 78% 墨与 .frm-no / .dh-more 同一档：底图最亮到纯白时，
   白字仍有约 9:1 —— 对比度闸门按最坏情况算过，不用半透明毛玻璃。 */
/* 箭头放**右上角**，与左上角的图号对称。
   不放右下角：那里是 logo 水印位（老板 2026-10-21 定的），
   44px 的方块压上去，水印就少一半 —— 而水印是图片被单独另存后
   唯一还留在图上的东西。 */
.car-nav{
  position:absolute; z-index:var(--z-raised); right:10px; top:10px;
  display:flex; gap:8px;
}
.car-b{
  width:44px; height:44px; display:flex; align-items:center; justify-content:center;
  padding:0; border:0; cursor:pointer; color:var(--white);
  background:rgba(var(--ink-rgb),.78);
  transition:background .18s var(--ease);
}
.car-b:hover{ background:rgba(var(--ink-rgb),.94); }
.car-b .ic-i{ width:18px; height:18px; }
/* 左箭头就是同一个图标翻过来 —— 多画一条 path 就多一个会漂移的源。 */
.car-b.prev .ic-i{ transform:scaleX(-1); }

/* 右列缩略图：整格可点，点了换主图（不直接弹灯箱 —— 客户在首屏想的是
   「再看看下一张」，而不是「把这张铺满屏」。放大由点主图承担）。 */
.dh-th .car-t{
  display:block; width:100%; height:100%; padding:0; border:0;
  background:none; cursor:pointer;
}
.dh-th .car-t img{
  width:100%; height:100%; object-fit:cover; object-position:50% 44%;
  display:block; transition:opacity .18s var(--ease);
}
.dh-th .car-t:hover img{ opacity:.84; }
/* 同 .gal-btn：环必须画在 img 上。缩略图里也是满幅 img，
   画在 button 上的 outline / inset 阴影都会被图片盖住 + 被 .dh-th 的
   overflow:hidden 裁掉，实测完全不可见。 */
.dh-th .car-t:focus-visible img{
  outline:2px solid var(--brand); outline-offset:-3px;
}

/* 速览格：图不够时补位。纸底 + 1px 线，与右侧缩略图同尺寸 ——
   两种格子在右列交替出现，视觉重量必须一致，否则右列看着是拼的。
   每格两条、标签左值右：单条居中会显得这一格空着没加载完。 */
.dh-gl{
  display:flex; align-items:center;
  padding:16px 24px; background:var(--paper2); border:1px solid var(--line3);
}
.dh-gl div{ width:100%; max-width:340px; margin:0 auto; display:flex; flex-direction:column; gap:16px; }
.dh-gl .gr{ display:flex; align-items:baseline; justify-content:space-between; gap:12px; }
.dh-gl .k{
  font-size:var(--fs-xs); color:var(--ink3);
  letter-spacing:.12em; line-height:1.5; white-space:nowrap;
}
.dh-gl b{
  font-family:var(--serif); font-weight:500;
  font-size:var(--fs-num); letter-spacing:.02em;
  font-variant-numeric:tabular-nums; color:var(--ink); line-height:1.25;
  text-align:right;
}

/* 灯箱池：n 张全在，但不参与布局。元素本身是 <button>，
   只作为 detail.js 收集灯箱序列的锚点，没有自己的视觉。 */
.car-pool{ display:none; }
/* 无实拍（625 栋 / 27.5%）：图片带退化成一整块留白 + 一句话，
   高度压到 200 —— 没有照片就不该占满 378 的高度假装有内容。 */
.dhero.nofig{ --dh-h:200px; grid-template-columns:minmax(0,1fr); }
.dhero .dfig-no{ height:var(--dh-h); aspect-ratio:auto; width:100%; border:1px solid var(--line2); }

/* 图片带下方一条细信息：张数 + 看全部。
   1.0 把这两个数塞在图注里（「照片 10 张 · 平面图 3 张」压在图名后面），
   字号 12px 挤在 438 宽的图下面，等于没有。 */
.dhmeta{
  display:flex; align-items:baseline; justify-content:space-between; gap:20px;
  margin-top:12px; padding-bottom:2px;
  font-size:var(--fs-sm); color:var(--ink3); letter-spacing:.04em;
}
.dhmeta b{ font-weight:700; color:var(--ink); font-variant-numeric:tabular-nums; }
/* 图标与计数的配对（v3.1）：照片 / 平面图 / 位置图三类分开数，
   挂上图标后「照片 12 张 · 平面图 1 张」不再是一串同质的字。
   只用 12px —— 这一行本身是 --fs-sm，再大的图标会把它顶成一块。 */
.dhmeta .dhb{ display:inline-flex; align-items:center; gap:4px; }
.dhmeta .dhb .ic-i{ width:12px; height:12px; color:var(--ink2); }
.dhmeta a .ic-i{ width:12px; height:12px; margin-left:4px; color:inherit; }
/* a 不折行：390 宽下「看全部 9 张」被挤成两行，右边一截掉到第二行去，
   左边那串「照片 8 张 · 平面图 1 张 · 楼栋实拍 · 非本套室内」也跟着折，
   两行读起来像两组不相关的话。给 a 上 nowrap，它就拿走自己需要的那点宽度，
   剩下的全给左边去折 —— 折行只发生在一处，顺序就清楚了。 */
.dhmeta a{ color:var(--ink); border-bottom:1px solid var(--line3); padding-bottom:1px; white-space:nowrap; }
.dhmeta a:hover{ border-bottom-color:var(--ink); }
/* 2026-10-27：图注里那个「看全部 N 张」在手机上是 23–26 高。
   它是整个图区唯一的入口（点进去才是图集），却比正文链接还扁 ——
   之前按「文本行内链接」豁免掉了，但那不是正文：它自成一行、带下划线、是出口。
   30 个楼盘页 × 6 档宽度每次都报（53×23 / 51×26 / 82×23）。
   抬到 40：inline-flex + 居中，下划线的位置交给 padding-bottom，视觉不变。 */
@media (max-width:760px){
  .dhmeta a{ display:inline-flex; align-items:center; min-height:40px; padding-bottom:0; }
}
@media (max-width:600px){
  /* 手机上「· 楼栋实拍 · 非本套室内」这一截挤不下 —— 但它必须留着：
     全库 2.24 万套房源级实拍是 0 张，这些图是大堂和电梯厅，不是这一套。
     删掉它就成了拿大堂照片冒充房源。所以改的是字号与间距，不是删字。 */
  .dhmeta{ gap:12px; font-size:var(--fs-xs); align-items:flex-start; }
  .dhmeta span{ line-height:1.5; }
}

/* ── 报价横条 ──────────────────────────────────────────────
   1.0 的报价在右栏 344px 的卡里：一个「面议」占着 --fs-h2 的主角字号，
   下面三个小字挤成一团，客户要在首屏找到「一个月到底花多少钱」得先找。
   3.0 把它横过来，占满整行：面积 / 单价 / 月租 / 物业费 / 月支出合计。
   格数不写死 —— 房源页很多只有面积与物业费（房源级有价率 49.8%），
   写死 5 列会留三个空格子。grid-auto-flow:column 让有值的格子自己铺满。 */
.dquotebar{
  display:grid; grid-auto-flow:column; grid-auto-columns:minmax(0,1fr);
  margin-top:24px; border-top:1px solid var(--ink); border-bottom:1px solid var(--line);
}
.dquotebar > div{ min-width:0; padding:16px 20px 20px 0; }
.dquotebar > div + div{ padding-left:20px; border-left:1px solid var(--line2); }
/* 标签前挂一个小图标（v3.1）：报价条五格分别读作面积 / 单价 / 月租 /
   物业费 / 合计，全是「金额与数量」，客户在第一眼扫过来时靠图标分区比靠
   读字快。图标 13px、--ink2，比标签略深一档 —— 它是定位用的锚点，
   不是第二个内容，所以不能跟 24px 的数字抢。
   ⚠️ 原来这里是 display:block + text-overflow:ellipsis，改成 flex 之后
      ellipsis 失效（flex 容器不裁文字），所以靠 nowrap + overflow:hidden 兜。 */
.dquotebar .k{
  display:flex; align-items:center; gap:8px;
  font-size:var(--fs-xs); letter-spacing:.06em; color:var(--ink3);
  white-space:nowrap; overflow:hidden;
}
.dquotebar .k .ic-i{ width:13px; height:13px; color:var(--ink2); }
.dquotebar .v{
  display:block; margin-top:8px;
  font-family:var(--serif); font-weight:500;
  font-size:calc(var(--fs-h3) * var(--k)); line-height:1.1;
  color:var(--ink); font-variant-numeric:tabular-nums; white-space:nowrap;
}
.dquotebar .v em{
  font-family:var(--sans); font-style:normal; font-weight:400;
  font-size:var(--fs-sm); color:var(--ink3); margin-left:4px; letter-spacing:0;
}
/* 合计那一格是这一条的重点：左边一条墨线加粗 + 数字用品牌红以外的最深墨。
   不用红色 —— 红色在这套版式里只给两个地方（品牌标记、必要警示），
   一个价格用红，下一页再来一个，红色就贬值了。 */
.dquotebar > div.sum{ box-shadow:inset 2px 0 0 var(--ink); }
.dquotebar > div.sum .k{ color:var(--ink2); }
.dquotebar .v.na{ font-family:var(--sans); font-weight:400; font-size:var(--fs-num); color:var(--ink3); }
.dq-note{
  margin:12px 0 0; font-size:var(--fs-xs); color:var(--ink3); line-height:1.75;
}

@media (min-width:1500px){
  /* 超宽屏上右列会涨到 700+。两格竖着排就是 700×220 的横条，裁掉六成画面，
     一眼看不出是同一栋楼。改成横着并排两格，各自接近原图比例。 */
  .dhero.n2 .dh-s{ grid-template-columns:1fr 1fr; grid-template-rows:1fr; }
  .dhero.n2 .dh-s.one{ grid-template-columns:1fr; }
}
@media (max-width:980px){
  /* 平板：右列收到 240，主图跟着让一点 —— 但**仍然不许超过 --hw**，
     否则 640 宽的小图在 710 的列里又会被放大。 */
  .dhero.n2{ grid-template-columns:minmax(0,min(100%,var(--hw,860px))) 240px; }
  .dquotebar > div{ padding:16px 12px 16px 0; }
  .dquotebar > div + div{ padding-left:12px; }
  .dquotebar .v{ font-size:calc(var(--fs-lg) * var(--k)); }
}
@media (max-width:760px){
  /* 手机：图片带改上下两段（主图 + 一张缩略图），高度 240。
     三格以上缩略图在 390 宽下每格只有 120 宽，看不出是什么。 */
  .dhero{ --dh-h:240px; }
  .dhero.n2{ grid-template-columns:minmax(0,1fr); }
  .dhero.n2 .dh-s{ grid-template-rows:1fr; grid-template-columns:1fr 1fr; height:120px; }
  .dhero.n2 .dh-s.one{ grid-template-columns:1fr; }
  /* 速览格在手机上只有 164 宽：左右对齐会把「45 元/㎡/月」拆成三行。
     改成标签在上、值在下，120 高刚好放两条 —— 手机上一格两行读起来
     比一寸宽的左右对齐清楚得多。 */
  .dh-gl{ padding:8px 12px; }
  .dh-gl div{ gap:8px; max-width:none; }
  .dh-gl .gr{ flex-direction:column; align-items:flex-start; gap:2px; }
  .dh-gl .k{ letter-spacing:.06em; }
  .dh-gl b{ font-size:var(--fs-sm); text-align:left; }
  /* 报价横条在手机上必须折 —— 5 列 × 78px 会把「月支出合计」挤成两行。
     用两列网格，最后一格（合计）横跨两列单独一行，正好是它该有的分量。 */
  .dquotebar{ grid-auto-flow:row; grid-template-columns:1fr 1fr; grid-auto-columns:auto; }
  .dquotebar > div{ padding:12px 8px 16px 0; border-left:0 !important; }
  .dquotebar > div:nth-child(2n){ padding-left:12px; border-left:1px solid var(--line2) !important; }
  .dquotebar > div:nth-child(n+3){ border-top:1px solid var(--line2); }
  .dquotebar > div.sum{ grid-column:1 / -1; padding-left:0; box-shadow:none; border-top:1px solid var(--ink) !important; }
  .dquotebar .v{ font-size:calc(var(--fs-num) * var(--k)); }
}
@media print{
  /* 打印：图带缩成一张主图。纸上两个 340 的缩略图会把正文挤到第二页。 */
  .dhero{ display:block; --dh-h:auto; }
  .dhero figure{ height:auto; }
  .dhero figure img{ height:auto; max-height:72mm; object-fit:contain; }
  .dh-s, .dh-more{ display:none; }
  .dquotebar{ grid-auto-flow:column; }
  .dquotebar .v{ font-size:13pt; }
}

/* 报价横条下面一行：左边结论句，右边动作。
   1.0 这两样都挤在 344px 的右栏里上下堆着 —— 结论句折成四行，
   按钮孤零零浮在右上角。摊平到整行后句子一行读完，按钮落在右端，
   与报价横条的右边界同一条线。 */
.dqfoot{ display:flex; align-items:flex-end; justify-content:space-between; gap:32px; margin-top:16px; }
.dqfoot .dsum{ margin:0; max-width:36em; }
.dqfoot .btn{ flex:none; }
@media (max-width:860px){
  .dqfoot{ flex-direction:column-reverse; align-items:stretch; gap:16px; }
  .dqfoot .btn{ width:100%; text-align:center; }
}

/* 侧栏常驻的一行报价（3.0）。报价主体已经搬到首屏横条，
   但侧栏是 sticky 的 —— 客户滚到页面中段比条件时，抬头还要能看见价钱。
   所以这里留一行「这一套 / 3.83 万元/月」，--fs-lg 级，不抢首屏。
   1.0 这里是一个 --fs-h2 的大字「面议」，一栋没有挂牌价的楼，
   整页最响的位置在说「没有」。 */
.dq-h2{
  display:flex; align-items:baseline; justify-content:space-between; gap:12px;
  padding-bottom:12px; border-bottom:1px solid var(--ink);
}
.dq-h2 span{ font-size:var(--fs-sm); letter-spacing:.06em; color:var(--ink3); white-space:nowrap; }
.dq-h2 b{ font-family:var(--serif); font-weight:500; font-size:var(--fs-lg); color:var(--ink); font-variant-numeric:tabular-nums; white-space:nowrap; }
.dq-h2 b em{ font-family:var(--sans); font-style:normal; font-weight:400; font-size:var(--fs-xs); color:var(--ink3); margin-left:4px; letter-spacing:0; }

/* 报价横条下面那条楼宇参数带（3.0）。1.0 的六格 KPI 排在右栏 2×2，
   客户要一格格读；摊到整行后是 6 列一条，一眼扫完。
   浅底是为了和上面的报价条分层：报价是「要谈的数字」，参数是「要看的事实」，
   两块都用白底连排，会读成同一张表。 */
.dkpi.dkpi-band{ background:var(--paper2); border-top:0; }
.dquotebar + .dkpi.dkpi-band{ border-top:0; }
.dkpi.dkpi-band > div{ padding-top:16px; padding-bottom:16px; }
.dkpi.dkpi-band dd{ font-size:calc(var(--fs-num) * var(--k)); }
@media (max-width:980px){
  .dkpi.dkpi-band{ grid-template-columns:repeat(3,minmax(0,1fr)); }
  .dkpi.dkpi-band > div:nth-child(3n){ border-right:0; }
  .dkpi.dkpi-band > div:nth-child(n+4){ border-top:1px solid var(--line2); }
}
@media (max-width:760px){
  .dkpi.dkpi-band{ grid-template-columns:1fr 1fr; }
  .dkpi.dkpi-band > div:nth-child(3n){ border-right:1px solid var(--line2); }
  .dkpi.dkpi-band > div:nth-child(2n){ border-right:0; }
  .dkpi.dkpi-band > div:nth-child(n+3){ border-top:1px solid var(--line2); }
}

/* ============================================================
   3.0 · AI 选址顾问页 / 行业资讯页
   ============================================================ */

/* 表单：与首页那块同一个骨架（上墨线起头、下划线输入框、无卡片），
   多了一行复选框组。宽度收到 760 —— 表单横跨 1,296 会让四个输入框
   彼此离得太远，眼睛要来回扫。 */
.aip-form{ margin-top:24px; border-top:1px solid var(--ink); padding-top:24px; }
/* 四个字段铺满整幅：1,296 的容器里只填 760、右边空出一大片白，看起来像
   「表单还没做完」。改成 4 列铺满后它是一条「需求条」，和上方报价横条
   （.dquotebar）是同一种横向节奏 —— 客户一眼知道要填几格。 */
.aip-f{ display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:24px 32px; }
@media (max-width:1080px){ .aip-f{ grid-template-columns:1fr 1fr; gap:24px 28px; } }
@media (max-width:600px){ .aip-f{ grid-template-columns:1fr; } }
.aip-f label{ display:block; font-size:var(--fs-sm); color:var(--ink3); letter-spacing:.04em; }
/* 2026-10-27：字段后的「必填 / 可空」从 --ink4 改 --ink3。
   --ink4(#94989E) 在纸底 #FAFAF9 上只有 2.78:1，WCAG AA 要 4.5:1（正文级字号，
   12px 不算大字）。这行字是「这个字段能不能不填」的唯一提示，读不清就等于没有。
   --ink3(#63676E) 是 5.4:1；层级没丢 —— 它仍然是括号后的浅墨小字，
   靠字号和括号与标签本身区分，不靠「浅到看不见」。 */
.aip-f label em{ font-style:normal; font-size:var(--fs-xs); color:var(--ink3); margin-left:8px; }
.aip-f input, .aip-f select{
  width:100%; margin-top:8px; padding:8px 0;
  border:0; border-bottom:1px solid var(--line3); border-radius:0; background:none;
  font-family:var(--sans); font-size:var(--fs-lg); color:var(--ink);
  transition:border-color .25s;
}
.aip-f select{ appearance:none; cursor:pointer;
  background-image:linear-gradient(45deg,transparent 50%,var(--ink3) 50%),linear-gradient(135deg,var(--ink3) 50%,transparent 50%);
  background-position:calc(100% - 13px) 55%,calc(100% - 8px) 55%;
  background-size:5px 5px,5px 5px; background-repeat:no-repeat; padding-right:24px;
}
.aip-f input:focus, .aip-f select:focus{ outline:0; border-bottom-color:var(--ink); }
.aip-f input::placeholder{ color:var(--ink4); }
/* 复选框与按钮同一行：左边是三个选项、右边是动作，中间留白 */
.aip-send{ display:flex; align-items:center; justify-content:space-between; gap:20px 32px; flex-wrap:wrap; margin-top:24px; }
.aip-chk{ display:flex; flex-wrap:wrap; align-items:center; gap:8px 24px; margin:0; padding:0; border:0; min-width:0; }
.aip-chk legend{ float:left; padding:0; margin-right:16px; font-size:var(--fs-sm); color:var(--ink3); letter-spacing:.04em; }
.aip-chk label{ display:inline-flex; align-items:center; gap:8px; font-size:var(--fs-md); color:var(--ink2); cursor:pointer; }
.aip-chk input{ width:15px; height:15px; accent-color:var(--ink); cursor:pointer; }
.aip-form .btn{ flex:none; min-width:200px; }
.aip-hint{ margin:16px 0 0; font-size:var(--fs-sm); color:var(--ink3); line-height:1.75; max-width:52em; }
.aip-hint a{ color:var(--ink); border-bottom:1px solid var(--line3); }

/* 结果区：出来之前不占位（没有骨架屏 —— 现在还没有东西可骨架，
   空骨架比空着更像「坏了」）。 */
.aip-res{ margin-top:44px; padding-top:32px; border-top:1px solid var(--ink); }
.aip-res-h h2{
  margin:0; font-family:var(--serif); font-weight:500;
  font-size:calc(var(--fs-h2) * var(--k)); line-height:1.25; letter-spacing:.01em;
}
.aip-res-h p{ margin:12px 0 0; font-size:var(--fs-md); color:var(--ink3); line-height:1.75; max-width:42em; }
.aip-res .dsec:first-of-type{ margin-top:36px; }
.aip-res .dquotebar{ margin-top:24px; }

/* 候选表里的副行（区 · 商圈 · 需跨层） */
.aip-sub{ display:block; margin-top:4px; font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.02em; }
.aip-dim{ font-size:var(--fs-xs); color:var(--ink3); }

/* 步骤：左边编号用衬线大数字，与右侧标题同一基线。
   编号不做圆形徽章 —— 圆徽章是流程图的语汇，这里是文章里的清单。 */
.aip-steps{ margin:16px 0 0; padding:0; list-style:none; counter-reset:st; }
.aip-steps li{
  position:relative; padding:20px 0 20px 52px; border-top:1px solid var(--line);
  counter-increment:st;
}
.aip-steps li:last-child{ border-bottom:1px solid var(--line); }
.aip-steps li::before{
  content:counter(st,decimal-leading-zero);
  position:absolute; left:0; top:19px;
  font-family:var(--serif); font-weight:400; font-size:var(--fs-num);
  /* 2026-11-02：原来是 --ink4（纸底 2.8:1）。19px 属大字，AA 下限 3:1 —— 2.8 差一点，
     但它是一串连续编号，读不清就等于这段清单没有顺序。提到 --ink3（5.4:1）。
     同时补 tabular-nums：01 与 10 在比例数字下宽度差 1~2px，纵向排下来会抖。 */
  color:var(--ink3); letter-spacing:.02em; font-variant-numeric:tabular-nums;
}
.aip-steps li b{ display:block; font-weight:700; font-size:var(--fs-md); color:var(--ink); line-height:1.75; }
.aip-steps li p{ margin:8px 0 0; font-size:var(--fs-md); color:var(--ink3); line-height:1.75; max-width:44em; }
.aip-steps li a{ display:inline-block; margin-top:8px; font-size:var(--fs-sm); }

/* 注意坑：左侧一条短墨线起头，每条之间不画线 —— 它们是并列的几句提醒，
   不是有序步骤。加分割线会被读成「第 N 步」。 */
.aip-pit{ margin:16px 0 0; padding:0; list-style:none; }
.aip-pit li{
  position:relative; padding:8px 0 8px 20px;
  font-size:var(--fs-md); color:var(--ink2); line-height:1.75;
}
.aip-pit li::before{ content:""; position:absolute; left:0; top:19px; width:8px; height:1px; background:var(--ink3); }
.aip-pit b{ color:var(--ink); font-weight:500; }

.aip-act{ display:flex; flex-wrap:wrap; gap:12px; margin-top:40px; }

/* 方法说明：用浅底整块抬起来，与上面「算出来的结论」分开 ——
   这里是给不信的人看的，不是结论的一部分。 */
.aip-method{ margin-top:52px; padding:32px 36px; background:var(--paper2); }
.aip-method h2{
  margin:0 0 16px; font-family:var(--serif); font-weight:500;
  font-size:calc(var(--fs-h3) * var(--k)); letter-spacing:.01em;
}
.aip-method .dl2{ margin:0; grid-template-columns:repeat(2,minmax(0,1fr)); }
/* 四条说明走 2×2：用通用 .dl2 的 3 列会剩一条单独占半行，右下角空一块。
   这条要盖住 .dl2 在 860 断点里的两列/一列设置，所以自己带断点。 */
@media (max-width:860px){ .aip-method .dl2{ grid-template-columns:1fr; } }
.aip-method .dtnote{ margin-top:16px; }

/* 底部「开放数据」横带：两边对齐，右边 em 是动作。
   与首页那块同一个视觉，客户从首页点进来能认出来是同一样东西。 */
.aip-api{
  display:flex; align-items:center; justify-content:space-between; gap:32px;
  margin-top:44px; padding:24px 0;
  border-top:1px solid var(--line); border-bottom:1px solid var(--line);
  transition:border-color .25s;
}
.aip-api:hover{ border-color:var(--ink3); }
.aip-api div{ min-width:0; }
.aip-api b{ display:block; font-weight:700; font-size:var(--fs-md); color:var(--ink); }
.aip-api span{ display:block; margin-top:8px; font-size:var(--fs-sm); color:var(--ink3); line-height:1.75; max-width:52em; }
.aip-api em{ flex:none; font-style:normal; font-size:var(--fs-sm); color:var(--ink3); }

/* 资讯列表页：分类块 */
.aip-cat{ margin-top:48px; }
.aip-cat h2{
  margin:0; font-family:var(--serif); font-weight:500;
  font-size:calc(var(--fs-h3) * var(--k)); letter-spacing:.01em;
}
.aip-cat-sub{ margin:8px 0 0; font-size:var(--fs-md); color:var(--ink3); line-height:1.75; }
.aip-list{ margin:20px 0 0; padding:0; list-style:none; border-top:1px solid var(--ink); }
.aip-list li{ border-bottom:1px solid var(--line); }
/* 字重用 500 不是随手写的：自托管的 Noto Serif SC 只有 300 与 500 两档
   （assets/fonts/noto-serif-sc.css）。写 400 会被浏览器就近匹配成 500 ——
   渲染结果一样，但「以为这里是常规、那里是标题」的层级根本不存在，
   check_type 第 6 条会把它当「字重落空」判红。要么真有那一档，要么别写。 */
.aip-list a{
  display:flex; align-items:center; justify-content:space-between; gap:20px;
  padding:16px 0; font-size:var(--fs-lg); color:var(--ink2);
  font-family:var(--serif); font-weight:500; line-height:1.5;
  transition:color .22s var(--ease), padding-left .22s var(--ease);
}
.aip-list a:hover{ color:var(--ink); padding-left:8px; }
.aip-list a span{ flex:none; font-family:var(--sans); font-weight:400; color:var(--ink4); font-size:var(--fs-md); }

/* 代码块（开放接口页） */
.aip-code{
  margin:16px 0 0; padding:20px 24px; overflow-x:auto;
  background:var(--ink); color:var(--on-dark);
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:12.5px; line-height:1.75; border-radius:0;
}
.aip-code code{ font:inherit; color:inherit; white-space:pre; }
.aip-code::-webkit-scrollbar{ height:8px; }
.aip-code::-webkit-scrollbar-thumb{ background:#3A3D42; }

@media (max-width:760px){
  .aip-f{ grid-template-columns:1fr; gap:16px; }
  .aip-chk{ gap:8px 16px; }
  .aip-chk legend{ width:100%; margin:0 0 4px; }
  .aip-form .btn{ width:100%; }
  .aip-method{ padding:24px 20px; }
  .aip-steps li{ padding-left:40px; }
  .aip-api{ flex-direction:column; align-items:flex-start; gap:8px; }
  .aip-act .btn{ width:100%; text-align:center; }
}
@media print{
  .aip-form, .aip-act, .aip-api, .aip-method{ display:none; }
  .aip-res{ border-top:0; padding-top:0; margin-top:0; }
}

/* ══════════════════════════════════════════════════════════════════
   v4.0 房源详情页：图册主导（2026-10-22 专项）
   ─────────────────────────────────────────────────────────────────
   老板原话：「客户要的是图片，和美观，简洁，你的在租房源只有表格，
   没有任何展示，这个界面太垃圾了，布局也不合理」。

   改之前先量了：一页 5,227px、9 个区块、图集排第 5 位，
   而 27.7% 的房源页（6,170 套）连一张#gal 都生成不出来。
   所以这不是「加几张图」，是**顺序与层级**的问题：
     图从第 5 块提到第 1 屏 → 参数从 11 行墙拆成 4 个大数 → 两张表变卡片。
   ─────────────────────────────────────────────────────────────────
   四条自限（与 v3.1 同一份，别在这里破例）：
     1. 不新增字号档位：只用 tokens.css 里那 11 个 --fs-*，需要更大就 × --k；
     2. 图不裁不放大：figure 的宽高由生成器按源图比例算好写进 --w/--h，
        object-fit:cover 在框比例 == 图比例时不裁任何东西（角标水印在底部，
        一裁就没了；check_wm 的 W09 判的就是这条）；
     3. 新写的 hover 一律进 @media (hover:hover)；
     4. 线只用 --line / --line2 / --line3 / --ink4 四个。
   ══════════════════════════════════════════════════════════════════ */

/* ── 首屏两列：左图册 / 右信息卡 ───────────────────────────────────
   392 是右卡的固定宽（报价四行 + 两个 44 高的按钮正好放得下），
   左列吃掉剩下的全部 —— 1440 视口下 .wrap 是 1,296，减去 392 与 44 的缝
   正好 860，与 3.0 时代的图片上限同一个数，所以放大倍数没有变化。
   margin-top 22：比原来的 26 小 4px，因为 .dhead 的下沿已经有一条 loc 行，
   再留 26 会显得标题与图之间断层。 */
.dhero.u1{
  display:grid; grid-template-columns:minmax(0,1fr) 392px; gap:0 44px;
  margin-top:24px; align-items:start;
}
.dhero.u1 .ug{ min-width:0; }
.dhero.u1 .ug-t{ display:flex; align-items:flex-end; gap:24px; }
/* 档案跟着图拉平高度：图 520 高、档案只有 4 条数据时，不拉平就是
   一块 200 高的小卡片浮在图旁边，上面空 300px。拉平之后底部署名行
   被 margin-top:auto 推到最下沿，读起来像图纸右下角的图签栏。
   图本身有确定高度，align-items:flex-end 对它们仍然生效（同组内按底边对齐）。 */
.dhero.u1 .ug-t .uarch{ align-self:stretch; }
.dhero.u1.nofig .ug-t{ display:block; }
/* 图行与档案**并排**的那一档（单张竖图、宽度凑不满左列）。
   行宽取生成器写死的 --rw（= sum(--w)），档案吃剩下的 —— 反过来写就出事：
   档案宽度是内容撑出来的，会把图行挤到比 --w 窄，挤多少取决于
   档案里文字怎么换行，也就是**取决于字体加载完成的时间**。
   实测 1-maison-place 的竖图标称 422、实际只画到 408，两次测量差 90px。
   也不能让行按内容自动撑：撑出来的宽度跟着「挑了哪一档图」走（实测 464
   = 声明槽位 = 被图片分辨率反过来影响版面），是个循环。
   所以：行宽有确定值就写死，剩 22px gap 之后全给档案。 */
.dhero.u1 .ug.with-arch .ug-row{ flex:0 0 var(--rw, auto); min-width:0; }
.dhero.u1 .ug.with-arch .uarch{ flex:1 1 0%; min-width:0; }

/* 图行。宽度、比例、原生宽由生成器算好（--w/--g/--mw），这里负责摆位置。
   ⚠️ 三个坑，都踩过：
   1. 不能用 `flex:0 0 auto; width:var(--w)`。那样图在 1281–1440 的视口里
      仍是 818 固定宽，而左列已经窄到 700——图会直接压到右边的信息卡上。
      页面自身不溢出（scrollWidth 没有变），所以只查「横向溢出」的判据
      查不出来，只有量图片与卡片的 x 区间才能发现。**宽度必须是流体。**
   2. 流体又不能只给 flex-basis：让浏览器按比例分宽时行高由宽度反算，
      竖图一行三张会算成 1,100 高。所以配 aspect-ratio:var(--g)，
      高跟着宽走，比例恒等于源图比例 ⇒ 零裁切（角标水印在底部）。
      因为每一张的 flex-grow 正比于 ar，行内高度天然相等。
   3. 必须有 max-width:var(--mw)（源图原生宽）。窄视口里若某张图需求宽度
      小于原生宽，浏览器不会放大；全库实拍原生宽 p05 只有 408，
      不设这条就是 2 倍放大 —— check_type 第 5 步（原图宽/渲染宽 < 0.85）判红。 */
.dhero.u1 .ug-row{ display:flex; align-items:flex-end; gap:8px; }
.dhero.u1 .ug-row figure{
  flex:var(--w,400) 1 1 0%; min-width:0;
  max-width:var(--mw,9999px);
  aspect-ratio:var(--g,1.33);
  height:auto; margin:0; position:relative;
  background:var(--paper3); overflow:hidden;
}
.dhero.u1 .ug-row img{ width:100%; height:100%; object-fit:cover; display:block; }

/* 图下那行说明。比 dhmeta 短：卡里已经写了本套的数字，
   这一条只回答「这些图是不是这一套」，所以「楼栋实拍 · 非本套室内」
   用 ink2 而不是 ink3，它是这一行里唯一必须被读到的话。 */
.dhero.u1 .ug-meta{
  display:flex; align-items:center; flex-wrap:wrap; gap:8px;
  margin-top:12px; font-size:var(--fs-sm); color:var(--ink3); letter-spacing:.04em;
}
.dhero.u1 .ug-meta span{ display:inline-flex; align-items:center; gap:4px; }
.dhero.u1 .ug-meta .ic-i{ width:12px; height:12px; color:var(--ink2); }
.dhero.u1 .ug-meta i{ font-style:normal; color:var(--ink4); }
/* 「本套室内实拍」是这一页最想说的那句好消息，但它排在「照片 N 张」后面，
   不能用一个提示色把它写成警告。用正文色 + 半档字重：比旁边那几项重一点，
   眼睛扫过去知道这一条不一样，又不至于抢掉面积大字的注意力。 */
.dhero.u1 .ug-meta .ug-own{ color:var(--ink); font-weight:700; }
.dhero.u1 .ug-meta .ug-warn{ color:var(--ink2); }
.dhero.u1 .ug-meta a{
  margin-left:auto; display:inline-flex; align-items:center; gap:4px;
  color:var(--ink); border-bottom:1px solid var(--line3); padding-bottom:1px;
  white-space:nowrap; min-height:0;
}
/* 2026-10-27：手机上这一条只有 23 高（`min-height:0` 是 10-2x 为压平行高加的）。
   它是图集唯一的入口，不是正文里的一句话 —— 40 是手指的落点。
   只在窄屏放开，桌面档那一行要和左边四项对齐成一条注释线，不能被撑高。 */
@media (max-width:760px){ .dhero.u1 .ug-meta a{ min-height:40px; padding-bottom:0; } }

/* ── 右：信息卡 ────────────────────────────────────────────────────
   面积是这个卡里最大的一个字，用 display 档（52）—— h1 里的面积是
   标题的一部分（楼名 + 面积 + 在租），读起来是一句话；这里是一个数，
   两者同一个数字但不是一个东西，所以字号也不同步。
   卡片顶部 2px 墨线而不是 1px：它是首屏的右边界，和左图形成对称重量。 */
.ucard{ display:flex; flex-direction:column; border-top:2px solid var(--ink); padding-top:16px; }
.uc-k{ font-size:var(--fs-sm); color:var(--ink3); letter-spacing:.1em; }
.uc-area{ display:flex; align-items:baseline; gap:4px; margin-top:8px; }
.uc-area b{
  font-family:var(--serif); font-weight:500;
  font-size:calc(var(--fs-display) * var(--k)); line-height:1;
  letter-spacing:-.01em; font-variant-numeric:tabular-nums; color:var(--ink);
}
.uc-area em{ font-style:normal; font-family:var(--sans); font-size:var(--fs-lg); color:var(--ink3); }
.uc-sub{ margin-top:8px; font-size:var(--fs-md); line-height:1.75; color:var(--ink2); }

/* 竖向报价条。这里**必须**保留 quoteBar 的 <span class="k">/<span class="v"> 结构：
   check_price 逐字匹配它（`<span class="k">单价</span><span class="v">`），
   换成自己的类名就要改闸门，而这一行改判据的出错率高于改模板。 */
.dquotebar.vert{ display:block; margin-top:16px; border-top:1px solid var(--line2); }
.dquotebar.vert > div{
  display:flex; align-items:baseline; justify-content:space-between; gap:16px;
  padding:12px 0; border-bottom:1px solid var(--line2);
  border-left:0; padding-left:0;
}
.dquotebar.vert > div.sum{ box-shadow:none; }
.dquotebar.vert .k{ font-size:var(--fs-sm); white-space:normal; }
.dquotebar.vert .v{ margin-top:0; font-size:calc(var(--fs-num) * var(--k)); }
.dquotebar.vert .v.na{ font-size:var(--fs-num); }
.dquotebar.vert .dq-note, .dquotebar.vert + .dq-note{
  margin:8px 0 0; font-size:var(--fs-xs); color:var(--ink3); line-height:1.75;
}
.uc-act{ display:grid; gap:8px; margin-top:16px; }
.uc-act .btn{ width:100%; justify-content:center; }

/* ── 无实拍：楼栋档案（6,250 套 / 28.1% 的首屏内容）─────────────────
   原来这一档是「200px 空框 + 暂无实拍」—— 客户点进来第一屏是一片白。
   现在换成图纸图签：边框 + 8 条楼宇参数 + 底部署名行，
   每一格都是数据层真有的字段（缺的整条不出现，不写「暂无」刷屏）。
   这不是占位图，是「没有照片时客户仍然想知道的东西」。 */
.uarch{
  flex:1 1 auto; min-width:0;
  display:flex; flex-direction:column; gap:12px;
  border:1px solid var(--line3); background:var(--paper2);
  padding:16px 16px 16px;
}
.uarch-h{ display:flex; flex-direction:column; gap:4px; }
.uarch-h b{ font-family:var(--serif); font-size:var(--fs-base); font-weight:500; letter-spacing:.03em; }
.uarch-h span{ font-size:var(--fs-sm); color:var(--ink3); }
.uarch-d{ margin:0; display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px 20px; }
.uarch-d > div{ min-width:0; }
.uarch-d dt{ display:flex; align-items:center; gap:4px; font-size:var(--fs-xs); color:var(--ink3); letter-spacing:.04em; }
.uarch-d dt .ic-i{ width:11px; height:11px; color:var(--ink4); }
.uarch-d dd{ margin:4px 0 0; font-size:var(--fs-bs); color:var(--ink); font-variant-numeric:tabular-nums; }
.uarch-f{ margin-top:auto; padding-top:8px; border-top:1px solid var(--line3); font-size:var(--fs-xs); color:var(--ink4); letter-spacing:.06em; }
/* 无图时的楼栋简介与实勘入口 */
.uarch-p{ margin:0; font-family:var(--serif); font-weight:300; font-size:var(--fs-md); line-height:1.75; color:var(--ink2); max-width:34em; }
.uarch-cta{ align-self:flex-start; margin-top:2px; }
/* 整列都是档案时（无图）横向铺开：4 列、参数加大一档，撑住首屏高度。
   ⚠️ 还要**拉平到右卡的高度**：嘉加德必易园那种楼，数据层只有一条「地铁」，
     档案只有 200px 高，而右边卡片 537px —— 不拉平就在首屏中间留一块
     340px 的空白（第一版截图就是这样，比原来那句「暂无实拍」还空）。
     拉平的做法不是给死高度（数据条数会变），而是让 .ug 成为纵向 flex、
     .ug-t 吃满剩余高度，档案自己 flex:1 撑开。 */
.dhero.u1.nofig{ align-items:stretch; }
.dhero.u1.nofig .ug{ display:flex; flex-direction:column; }
.dhero.u1.nofig .ug-t{ flex:1 1 auto; display:flex; }
.dhero.u1.nofig .uarch{ padding:24px 24px 16px; gap:16px; }
.dhero.u1.nofig .uarch-d{ grid-template-columns:repeat(4,minmax(0,1fr)); gap:16px 24px; }
.dhero.u1.nofig .uarch-d dd{ font-size:var(--fs-lg); }
.dhero.u1.nofig .uarch-h b{ font-size:var(--fs-lg); }

/* ── 条件：4 个大数 + 两列清单 ─────────────────────────────────────
   替代原来 3 列 × 4 行的 dl2 参数墙（老板说的「表格」）。
   大数与清单之间用一条 --line 分开：上面是「决定要不要」的数，
   下面是「签约前要确认」的事，两类东西不该同一个重量。 */
.ukpi{
  display:grid; grid-template-columns:repeat(3,minmax(0,1fr));
  margin-top:20px; border-top:1px solid var(--ink); border-bottom:1px solid var(--line);
}
.ukpi > div{ padding:16px 16px 16px 0; min-width:0; }
.ukpi > div + div{ padding-left:16px; border-left:1px solid var(--line2); }
.ukpi .k{ display:flex; align-items:center; gap:8px; font-size:var(--fs-xs); letter-spacing:.06em; color:var(--ink3); }
.ukpi .k .ic-i{ width:13px; height:13px; color:var(--ink2); }
.ukpi b{
  display:inline-block; margin-top:8px;
  font-family:var(--serif); font-weight:500;
  font-size:calc(var(--fs-h2) * var(--k)); line-height:1.1;
  font-variant-numeric:tabular-nums;
}
.ukpi em{ font-style:normal; font-family:var(--sans); font-size:var(--fs-sm); color:var(--ink3); margin-left:4px; }
.uline{ list-style:none; margin:16px 0 0; padding:0; display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:0 44px; }
.uline li{ display:flex; align-items:baseline; justify-content:space-between; gap:16px; padding:8px 0; border-bottom:1px solid var(--line2); }
.uline span{ font-size:var(--fs-sm); color:var(--ink3); letter-spacing:.02em; }
.uline b{ font-size:var(--fs-bs); font-weight:400; color:var(--ink); font-variant-numeric:tabular-nums; text-align:right; }

/* ── 关于这一套：正文 + 判断，左右两栏 ─────────────────────────────
   原来是两块（「这一套」349px + 「这一套适合谁」341px），标题都以
   「这一套」开头。合起来 690px 说一件事，滚轮要转两下。
   左栏 1.15fr：宋体正文行长控制在 28em 以内（.uabout-l p 的 max-width）。 */
.uabout{ display:grid; grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr); gap:44px; margin-top:16px; align-items:start; }
.uabout-l p{ margin:0 0 16px; max-width:28em; font-family:var(--serif); font-weight:300; font-size:var(--fs-lg); line-height:1.9; color:var(--ink); }
.uabout-l p:last-child{ margin-bottom:0; }
.uabout-r h3{ margin:0 0 8px; font-size:var(--fs-sm); font-weight:400; letter-spacing:.1em; color:var(--ink3); }
.uabout-r ul{ margin:0 0 16px; padding:0; list-style:none; }
.uabout-r ul:last-child{ margin-bottom:0; }
.uabout-r li{ position:relative; padding-left:16px; margin-bottom:8px; font-size:var(--fs-md); line-height:1.75; color:var(--ink2); }
.uabout-r li::before{ content:""; position:absolute; left:0; top:.78em; width:5px; height:1px; background:var(--ink4); }

/* ── 图册带：一行横滑 ──────────────────────────────────────────────
   178 是行高：1440 下首屏（900）里能露出 4–5 张，滚轮横滑看完全部。
   折行会占掉 1,000px 以上（8 张以上的房源有 2,230 套），
   而这一块的作用是「一眼看到还有多少图」，不是逐张品鉴 —— 逐张点开放大。
   scroll-snap 用 proximity 不用 mandatory：mandatory 会让小幅滚动
   总是弹到下一张，鼠标拖起来一顿一顿的。 */
.ugal-band{
  display:flex; gap:8px; margin-top:20px; padding-bottom:8px;
  overflow-x:auto; overscroll-behavior-x:contain;
  scroll-snap-type:x proximity;
}
.ugal-band figure{
  flex:0 0 auto; width:var(--w); height:var(--h); margin:0; position:relative;
  background:var(--paper3); scroll-snap-align:start; overflow:hidden;
}
.ugal-band img{ width:100%; height:100%; object-fit:cover; display:block; }
.ugal-band::-webkit-scrollbar{ height:6px; }
.ugal-band::-webkit-scrollbar-track{ background:var(--line2); }
.ugal-band::-webkit-scrollbar-thumb{ background:var(--line3); }
@media (hover:hover){
  .ugal-band::-webkit-scrollbar-thumb:hover{ background:var(--ink4); }
}

/* ── 这栋楼与位置：楼宇参数 + 交通并排 ─────────────────────────────
   原来是两块（「楼里的条件」343px + 「交通」231px），各占一行。
   合并之后一行放下，右栏给地铁 —— 客户看楼宇参数时，下一句问的就是通勤。 */
.ubld{ display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); gap:44px; margin-top:4px; align-items:start; }
.ubld .dl2{ grid-template-columns:repeat(2,minmax(0,1fr)); gap:0 24px; margin-top:0; }

/* ── 窄屏 ──────────────────────────────────────────────────────────
   1,180 是右卡开始挤图的临界点（1,180 − 144 = 1,036 的 .wrap，
   减去 320 的卡还剩 700，三张竖图刚好）。900 以下整块竖排。 */
@media (max-width:1180px){
  .dhero.u1{ grid-template-columns:minmax(0,1fr) 320px; gap:0 28px; }
  .uabout,.ubld{ gap:32px; }
}
@media (max-width:900px){
  .dhero.u1{ grid-template-columns:minmax(0,1fr); gap:24px; }
  /* 手机上不能保留「一行三张 + 横滑」：实测 390 屏里第一张图就有 818 宽，
     客户看到的是半张楼、还得左右拖才能看全 —— 首屏图必须一屏放得下。
     所以窄屏只留第一张，按屏宽铺满，高度由源图比例自然算出。
     其余图不丢：下面「这栋楼的实拍」那条横滑带里全都在。 */
  .dhero.u1 .ug-row{ display:block; overflow:visible; padding-bottom:0; }
  .dhero.u1 .ug-row figure{ width:100%; height:auto; }
  .dhero.u1 .ug-row figure + figure{ display:none; }
  .dhero.u1 .ug-row img{ width:100%; height:auto; }
  .dhero.u1 .ug-t{ display:block; }
  .dhero.u1 .ug-t .uarch{ margin-top:16px; }
  .ucard{ border-top-width:1px; }
  .ukpi{ grid-template-columns:repeat(2,minmax(0,1fr)); }
  .ukpi > div:nth-child(odd){ padding-left:0; border-left:0; }
  .uline{ grid-template-columns:minmax(0,1fr); }
  .uabout,.ubld{ grid-template-columns:minmax(0,1fr); gap:24px; }
  .dhero.u1.nofig .uarch-d{ grid-template-columns:repeat(2,minmax(0,1fr)); }
  .dhero.u1.nofig .uarch-d dd{ font-size:var(--fs-bs); }
}
