/* ─────────────────────────────────────────────────────────────
   LanZ · 供需 Agent 产品页(/products/match/)专属样式

   来源:外部设计交付(供需agent.zip)。页面概念是**撮合场**:需求与供给
   两侧不断相遇、锁定。四段各一套机制,与另外四个 Agent 页不重合。
   只被这一个页面引用。

   集成时做了六处改造, 都是本站硬约束逼出来的, 别改回去:

   1. **所有选择器收进 .matchx 作用域。** 设计稿用的是 .hero / .wrap /
      .btn / .field / .who 这些通用类名, 而 style.css 全站加载、同名类
      全都有。不隔离的话两边互相覆盖, 顶栏会散架。

   2. **.hero → .mt-hero、.field → .mfield、.who → .termwho。**
      光靠作用域压不住这三个:style.css 里 .field 有 11 条规则、.who 有
      19 条, 全是表单与首页分段的排版 —— 那些「我们没声明的属性」会照样
      继承过来。

   3. **动画名加了 mt- 前缀。** 设计稿的 @keyframes breathe / rise 与
      style.css 里的同名, 后加载的那份会整体覆盖前一份。
      ⚠ 溯源页 cx-、招商页 iv-、政策页 pl-、客户页 cl-, 五页各一套,
      不要合并 —— 合并就等于五页共用一份动效, 改一边会静默动到另外四边。

   4. **字体换成站里的系统字体栈。** 原稿引 Google Fonts, 本站 CSP 是
      default-src 'none' 起步, 外链字体会被浏览器直接拦掉, 而且不报错
      —— 只会静默回退。SVG 里的 font-family 属性也一并删掉了, 靠继承
      拿 --font-body, 等宽的那几处用 var(--font-mono)。
      ⚠ 代价:原稿的 font-weight:900 在系统中文字体里没有对应字重,
      会回退到 700, 标题比设计稿略轻。

   5. **设计稿自带的胶囊顶栏与页脚样式整段删掉。** 那两块用站里统一的
      (build.sh 逐页比对, 不一致直接失败)。

   6. **[data-rise] 的隐藏态挂在 html.mt-rise 上。** 原稿直接写
      [data-rise]{opacity:0}, JS 一挂各段标题就永远不显示。本站的规矩
      是「内容默认可见, JS 只负责隐藏」—— 见 style.css 的 .reveal。

   ── 语义约定(全页一致, 首屏图例里明示) ──────────────────────
   紫 = 需求, 青 = 供给, 白 = 已撮合。
   ⚠ 青色只用于区分供给侧, 不作为第二主色 —— 面积、按钮、标题都不用它。
   ⚠ 深底上的青用 --cyan, 浅底上必须换成 --cyan-d(浅底上 --cyan 只有
     1.9:1, 等于隐形)。

   设计系统说明见交付附带的 README;色值是设计稿给的 hex,
   ⚠ 没有转成 OKLCH —— 与 tokens.css 的口径不一致, 是笔已知的账。
   ───────────────────────────────────────────────────────────── */
:root{
  --ink:#12112B;  /* 主文字 */
  --ink-2:#3A3752;  /* 正文 */
  --ink-3:#6B6884;  /* 弱文字 / 等宽标签 */
  --lite:#EFECF9;  /* 浅色段底色 —— ⚠ 平色, 勿改成渐变 */
  --dark:#0B0A1E;
  --dark-2:#08071A;
  --purple:#7B4DEB;  /* 需求 */
  --purple-d:#6D3FE0;  /* 浅底上的紫（文字可用） */
  --purple-l:#8B62F0;
  --purple-lt:#A98CFF;  /* 深底上的紫（文字可用） */
  --purple-pale:#B79EFF;
  --cyan:#3FD2E8;  /* 深底上的青 = 供给 */
  --cyan-d:#0E93A8;  /* 浅底上的青（满足对比度） */
  --on-dark:#EDEBF7;
  --on-dark-2:#B4B1C9;
  --on-dark-3:#9E9BB8;
  --on-dark-4:#8A87A6;
  --grid:rgba(160,150,255,.055);
  --maxw:1280px;
  --pad:40px;
}
body{ background:var(--lite); color:var(--ink) }
.matchx, .matchx *{ box-sizing:border-box }
.matchx a{ color:var(--purple-d); text-decoration:none }
.matchx a:hover{ color:var(--purple-l) }
.matchx button{ font-family:inherit }
.matchx .mono{ font-family:var(--font-mono) }
.matchx .wrap{ max-width:var(--maxw); margin:0 auto; padding:0 var(--pad) }
.matchx .grid-tex{
  position:absolute;
  inset:0;
  pointer-events:none;
  background-image:linear-gradient(var(--grid) 1px,transparent 1px),linear-gradient(90deg,var(--grid) 1px,transparent 1px);
  background-size:64px 64px;
}

/* ---------- 动效基座 ----------
   ⚠ 四套机制全部由**滚入视野驱动、滚出即停**(match.js 的 onView)。
   打字那段是嵌套定时器, 滚出去必须显式清掉, 否则多条时间线会叠在一起。 */
@keyframes mt-breathe{ 0%,100%{ opacity:.4 } 50%{ opacity:1 } }
@keyframes mt-rise{ from{ opacity:0; transform:translateY(26px) } to{ opacity:1; transform:none } }
@keyframes mt-bob{ 0%,100%{ transform:translate(0,0) } 50%{ transform:translate(var(--dx,4px),var(--dy,-7px)) } }
@keyframes mt-railL{ from{ transform:translateX(0) } to{ transform:translateX(-50%) } }
@keyframes mt-railR{ from{ transform:translateX(-50%) } to{ transform:translateX(0) } }
@keyframes mt-seam{ 0%,100%{ opacity:.35; transform:scaleY(.92) } 50%{ opacity:1; transform:scaleY(1) } }
@keyframes mt-pop{
  0%{ opacity:0; transform:translateY(10px) scale(.9) }
  60%{ transform:translateY(0) scale(1.04) }
  100%{ opacity:1; transform:none }
}
@keyframes mt-flyin{ from{ opacity:0; transform:translateX(-14px) } to{ opacity:1; transform:none } }
@keyframes mt-caret{ 0%,49%{ opacity:1 } 50%,100%{ opacity:0 } }
@keyframes mt-spinslow{ to{ transform:rotate(360deg) } }
/* 隐藏态挂在 html.mt-rise 上:只有 JS 确认 IntersectionObserver 可用
   才加这个类。JS 挂了 = 内容照常显示, 不会白屏。 */
html.mt-rise .matchx [data-rise]{ opacity:0 }
.matchx [data-rise="in"]{ animation:mt-rise .9s cubic-bezier(.16,.84,.34,1) both }
.matchx .dot{
  width:6px;
  height:6px;
  border-radius:999px;
  background:var(--purple-l);
  animation:mt-breathe 2.4s ease-in-out infinite;
}

/* ---------- 按钮 ---------- */
.matchx .btn{
  display:inline-block;
  white-space:nowrap;
  padding:19px 46px;
  border-radius:999px;
  background:var(--purple);
  color:#fff;
  font-size:17px;
  font-weight:700;
  box-shadow:0 14px 44px rgba(123,77,235,.5);
}
.matchx .btn:hover{ background:var(--purple-l); color:#fff }

/* ---------- 通用 ---------- */
.matchx .sect-h2{
  margin:0;
  font-size:clamp(34px,3.6vw,46px);
  line-height:1.18;
  font-weight:900;
  letter-spacing:-.025em;
}
.matchx .sect-p{
  margin:24px 0 0;
  font-size:17.5px;
  line-height:1.9;
  color:var(--ink-2);
  max-width:27em;
}
.matchx .card{
  background:#fff;
  border-radius:16px;
  padding:26px 28px 30px;
  box-shadow:0 10px 34px rgba(18,17,43,.07);
}
.matchx .cap{
  display:flex;
  align-items:center;
  gap:10px;
  padding-bottom:16px;
  border-bottom:1px solid rgba(18,17,43,.12);
  font-family:var(--font-mono);
  font-size:11.5px;
  letter-spacing:.1em;
  color:var(--ink-3);
}
.matchx .cap span{ white-space:nowrap }
.matchx .cap .r{ margin-left:auto }
.matchx .stats{ display:flex; flex-wrap:wrap; gap:16px 52px }
.matchx .stats .k{ display:block; font-size:12.5px; color:var(--ink-3) }
.matchx .stats .v{
  display:block;
  font-size:32px;
  font-weight:900;
  letter-spacing:-.03em;
  margin-top:3px;
  color:var(--ink);
}
.matchx .stats .v.hi{ color:var(--purple-d) }

/* ============ 首屏：撮合场（无卡片） ============ */
/* ⚠ 原稿是 margin-top:-88px —— 那是为了钻到它自带的 sticky 胶囊导航
   下面。本站顶栏是 position:fixed, 不占文档流, 首屏本来就从页面顶端
   开始, 再拉 -88px 会把大标题整个顶出屏幕。改成 0, 上边距交给 padding。 */
.matchx .mt-hero{
  position:relative;
  padding:186px 0 120px;
  overflow:hidden;
  color:var(--on-dark);
  background:radial-gradient(1200px 700px at 72% 40%,#24164F 0%,#120D33 46%,#0B0A1E 100%);
}
.matchx .mt-hero .halo{
  position:absolute;
  top:36%;
  right:4%;
  width:820px;
  height:820px;
  transform:translateY(-50%);
  pointer-events:none;
  animation:mt-breathe 8s ease-in-out infinite;
  background:radial-gradient(circle at center,rgba(123,77,235,.3),rgba(11,10,30,0) 62%);
}
.matchx .mt-hero .ring{
  position:absolute;
  top:36%;
  right:4%;
  width:640px;
  height:640px;
  transform:translate(50%,-50%);
  border-radius:999px;
  border:1px dashed rgba(171,140,255,.16);
  pointer-events:none;
  animation:mt-spinslow 80s linear infinite;
}
.matchx .hero-grid{
  position:relative;
  display:grid;
  grid-template-columns:minmax(0,.92fr) minmax(0,1.08fr);
  gap:48px;
  align-items:center;
}
.matchx .mt-hero h1{
  margin:0;
  font-size:clamp(40px,4.2vw,62px);
  line-height:1.12;
  font-weight:900;
  letter-spacing:-.025em;
  color:#fff;
}
/* 「Agent」那一段的渐变字。⚠ 与另外四个 Agent 页逐字相同, 改一处要五处
   一起改。color:transparent 收在 @supports 里:万一 background-clip:text
   不生效, 落回实色标题, 而不是一个看不见的大标题。 */
.matchx .mt-hero h1 em{ font-style:normal }
@supports (-webkit-background-clip:text) or (background-clip:text){
  .matchx .mt-hero h1 em{
    background:linear-gradient(96deg,#fff 18%,var(--purple-lt) 62%,var(--cyan) 100%);
    -webkit-background-clip:text;
    background-clip:text;
    color:transparent;
  }
}
.matchx .mt-hero p{
  margin:28px 0 0;
  font-size:18.5px;
  line-height:1.85;
  color:var(--on-dark-2);
  max-width:25em;
}
.matchx .mt-hero .btn{ margin-top:42px }
.matchx .hero-legend{ display:flex; flex-wrap:wrap; gap:22px; margin-top:34px; font-size:13px; color:var(--on-dark-3) }
.matchx .hero-legend span{ display:flex; align-items:center; gap:9px }
.matchx .hero-legend i{ width:10px; height:10px; border-radius:999px }
/* 撮合场向右出血到视口边缘 —— 场子被版心切断会看着像张图, 铺出去才像个场 */
.matchx .mfield{
  position:relative;
  min-width:0;
  margin-right:calc(-1 * max(var(--pad),(100vw - var(--maxw)) / 2));
}
/* overflow:visible 是给节点标签留的 —— 靠边的标签会探出 viewBox */
.matchx .mfield svg{ width:100%; height:auto; display:block; overflow:visible }
.matchx .nd{ animation:mt-bob 9s ease-in-out infinite }
.matchx .nd .core{ transition:r .4s,filter .4s }
.matchx .nd .lbl{ font-size:17px; transition:fill .4s }
.matchx .nd.hit .core{ r:11; filter:drop-shadow(0 0 12px rgba(171,140,255,.95)) }
.matchx .nd.hit .lbl{ fill:#fff; font-weight:700 }
.matchx .mlink{ fill:none; stroke-width:1.8; stroke-linecap:round }

/* ============ 发布：打字解析 ============ */
.matchx .post{ position:relative; padding:116px 0; background:var(--lite) }
.matchx .post-grid{
  display:grid;
  grid-template-columns:minmax(0,.86fr) minmax(0,1.14fr);
  gap:62px;
  align-items:center;
  margin-top:46px;
}
/* min-height 占住五行:三条示例长短不一, 不占位整张卡会随打字上下跳 */
.matchx .term{
  font-family:var(--font-mono);
  font-size:15.5px;
  line-height:1.8;
  color:var(--ink);
  min-height:5.4em;
  padding:18px 20px;
  border-radius:12px;
  background:#F6F4FC;
  border:1px solid rgba(18,17,43,.07);
}
.matchx .term .termwho{
  color:var(--purple-d);
  letter-spacing:.06em;
  font-size:12px;
  display:block;
  margin-bottom:9px;
}
.matchx .term .cur{
  display:inline-block;
  width:8px;
  height:18px;
  vertical-align:-3px;
  background:var(--purple-d);
  animation:mt-caret 1s steps(1) infinite;
  margin-left:2px;
}
.matchx .slots{ display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:12px; margin-top:20px }
.matchx .slot{
  border-radius:12px;
  padding:14px 15px;
  background:#F6F4FC;
  border:1px dashed rgba(18,17,43,.14);
  min-height:86px;
}
.matchx .slot .k{
  font-family:var(--font-mono);
  font-size:10.5px;
  letter-spacing:.14em;
  color:var(--ink-3);
}
.matchx .slot .v{ font-size:15.5px; font-weight:700; color:var(--ink); margin-top:10px; opacity:0 }
.matchx .slot.on{
  background:rgba(123,77,235,.1);
  border-style:solid;
  border-color:rgba(123,77,235,.35);
}
.matchx .slot.on .v{ animation:mt-pop .5s cubic-bezier(.16,.84,.34,1) both }
.matchx .post-tip{
  margin:22px 0 0;
  font-family:var(--font-mono);
  font-size:12.5px;
  color:var(--purple-d);
  min-height:1.4em;
}

/* ============ 蜂巢 ============ */
.matchx .hive{ position:relative; padding:116px 0; background:var(--lite) }
.matchx .hive-grid{
  display:grid;
  grid-template-columns:minmax(0,1.06fr) minmax(0,.94fr);
  gap:60px;
  align-items:center;
  margin-top:46px;
}
.matchx .hex{ cursor:pointer }
/* ⚠ transform-box:fill-box 必须留着 —— 不写的话 scale 以整个 SVG 画布
   原点为中心, 高亮那格会飞到画面外。 */
.matchx .hex polygon{
  fill:#fff;
  stroke:rgba(18,17,43,.08);
  stroke-width:1;
  transition:fill .45s,stroke .45s,transform .45s;
  transform-origin:center;
  transform-box:fill-box;
}
.matchx .hex text{ transition:fill .45s }
.matchx .hex .nm{ font-size:19px; font-weight:700; fill:var(--ink) }
.matchx .hex .ct{ font-family:var(--font-mono); font-size:16px; fill:var(--ink-3) }
.matchx .hex.on polygon{ fill:var(--purple); stroke:var(--purple-pale); transform:scale(1.06) }
.matchx .hex.on .nm{ fill:#fff }
.matchx .hex.on .ct{ fill:#DCD4FF }
.matchx .hex.warm polygon{ fill:#E3DBFA }
.matchx .hex:focus-visible polygon{ stroke:var(--purple-d); stroke-width:2.5 }
.matchx .hive-panel .t{
  font-family:var(--font-mono);
  font-size:11px;
  letter-spacing:.16em;
  color:var(--ink-3);
}
.matchx .hive-panel h3{ margin:14px 0 0; font-size:30px; font-weight:900; letter-spacing:-.02em }
.matchx .hive-panel .n{ display:flex; align-items:baseline; gap:10px; margin-top:20px }
.matchx .hive-panel .n b{ font-size:42px; font-weight:900; letter-spacing:-.04em; color:var(--purple-d) }
.matchx .hive-panel .n s{ text-decoration:none; font-size:14px; color:var(--ink-3) }
.matchx .egs{ margin-top:24px; border-top:1px solid rgba(18,17,43,.12) }
.matchx .eg{
  display:flex;
  gap:14px;
  align-items:baseline;
  padding:13px 0;
  border-bottom:1px solid rgba(18,17,43,.07);
  font-size:15px;
  color:var(--ink-2);
  animation:mt-flyin .5s cubic-bezier(.16,.84,.34,1) both;
}
.matchx .eg i{ flex:none; width:6px; height:6px; border-radius:999px; background:var(--purple-lt); margin-top:8px }

/* ============ 对撞轨道 ============ */
.matchx .match{ position:relative; padding:116px 0 122px; background:var(--lite) }
/* 两端淡出, 让两条轨看着是从画外开进来的 */
.matchx .rails{
  position:relative;
  margin-top:44px;
  padding:34px 0;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
}
/* ⚠ 两条轨的内容各重复两遍(match.js 里 DEM.concat(DEM)), 位移到 -50%
   正好接回起点。只渲染一遍会在循环点看到明显回跳。 */
.matchx .rail{ display:flex; width:max-content; gap:12px; padding:8px 0 }
.matchx .rail.a{ animation:mt-railR 46s linear infinite }
.matchx .rail.b{ animation:mt-railL 38s linear infinite; margin-top:14px }
.matchx .pin{
  flex:none;
  display:flex;
  align-items:center;
  gap:10px;
  padding:12px 18px;
  border-radius:999px;
  background:#fff;
  box-shadow:0 2px 10px rgba(18,17,43,.06);
  font-size:14.5px;
  color:var(--ink-2);
  white-space:nowrap;
}
.matchx .pin i{ width:8px; height:8px; border-radius:999px; flex:none }
.matchx .pin.d i{ background:var(--purple) }
.matchx .pin.s i{ background:var(--cyan-d) }
.matchx .pin b{ font-weight:700; color:var(--ink) }
.matchx .seam{
  position:absolute;
  left:50%;
  top:0;
  bottom:0;
  width:2px;
  transform:translateX(-50%);
  background:linear-gradient(180deg,rgba(123,77,235,0),var(--purple),rgba(123,77,235,0));
  animation:mt-seam 2.2s ease-in-out infinite;
  pointer-events:none;
}
/* ⚠ 标签的底色必须与段落底色一致, 否则压不住底下那条竖线 */
.matchx .seam::after{
  content:"撮合";
  position:absolute;
  top:-4px;
  left:50%;
  transform:translateX(-50%);
  font-family:var(--font-mono);
  font-size:10.5px;
  letter-spacing:.18em;
  color:var(--purple-d);
  background:var(--lite);
  padding:0 8px;
}
.matchx .match-grid{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:58px;
  align-items:start;
  margin-top:40px;
}
.matchx .hits{ display:flex; flex-direction:column; gap:10px }
.matchx .hit{
  display:grid;
  grid-template-columns:minmax(0,1fr) auto;
  gap:16px;
  align-items:center;
  padding:16px 18px;
  border-radius:13px;
  background:#fff;
  box-shadow:0 6px 22px rgba(18,17,43,.06);
  animation:mt-pop .55s cubic-bezier(.16,.84,.34,1) both;
}
.matchx .hit .pair{ font-size:15px; color:var(--ink-2); min-width:0 }
.matchx .hit .pair b{ color:var(--ink); font-weight:700 }
.matchx .hit .pair s{
  display:block;
  text-decoration:none;
  font-family:var(--font-mono);
  font-size:11.5px;
  color:var(--ink-3);
  margin-top:6px;
}
.matchx .hit .sc{
  font-family:var(--font-mono);
  font-size:14px;
  color:var(--purple-d);
  padding:6px 12px;
  border-radius:999px;
  background:rgba(123,77,235,.12);
  white-space:nowrap;
}

/* ============ CTA ============ */
.matchx .cta-s{
  position:relative;
  padding:118px 0 126px;
  overflow:hidden;
  text-align:center;
  color:var(--on-dark);
  background:radial-gradient(900px 560px at 50% 12%,#1C1244 0%,#0D0A26 52%,#08071A 100%);
}
.matchx .cta-s .halo{
  position:absolute;
  top:-120px;
  left:50%;
  width:900px;
  height:560px;
  transform:translateX(-50%);
  pointer-events:none;
  animation:mt-breathe 7s ease-in-out infinite;
  background:radial-gradient(ellipse at center,rgba(123,77,235,.32),rgba(11,10,30,0) 70%);
}
.matchx .cta-s h2{
  margin:0;
  font-size:clamp(38px,4.4vw,54px);
  line-height:1.16;
  font-weight:900;
  letter-spacing:-.025em;
  color:#fff;
}
.matchx .cta-s p{
  margin:26px auto 0;
  font-size:18px;
  line-height:1.9;
  color:var(--on-dark-2);
  max-width:28em;
}

/* ---------- 响应式 ---------- */
@media (max-width:1080px){
  .matchx .hero-grid,
  .matchx .post-grid,
  .matchx .hive-grid,
  .matchx .match-grid{ grid-template-columns:minmax(0,1fr); gap:46px }
  .matchx .mt-hero{ padding:150px 0 96px }
  .matchx .mfield{ margin-right:0 }
  .matchx .mt-hero .ring{ display:none }
  .matchx .slots{ grid-template-columns:repeat(2,minmax(0,1fr)) }
}
/* ⚠ 手机上这两张 SVG 被压得太扁, 图内文字会掉到看不清的字号 ——
   实测 375px 下撮合场的标签只有 5.5px、蜂巢的类目名只有 8.7px,
   本站的下限是 12px。两张图的处理方式不同:

   · 撮合场:二十个标签挤在 920 宽的画布里, 想上到 12px 得把字号提到
     37 以上, 那个尺寸下标签之间会互相压住。所以窄屏干脆只留节点与
     撮合弧 —— 紫/青/白三色的含义首屏图例里已经讲清楚了, 场子本身
     读的是「谁和谁连上了」, 不是每个标签的字。
   · 蜂巢:只有六格, 有空间, 直接把字号提上去, 再把卡的内边距收紧
     换出一点宽度。 */
@media (max-width:700px){
  .matchx .nd .lbl{ display:none }
  .matchx .nd .core{ r:9 }
  .matchx .hive .card{ padding:18px 14px 22px }
  .matchx .hex .nm{ font-size:25px }
  .matchx .hex .ct{ font-size:22px }
}
@media (prefers-reduced-motion:reduce){
  .matchx .dot,
  .matchx .nd,
  .matchx .mt-hero .halo,
  .matchx .mt-hero .ring,
  .matchx .rail,
  .matchx .seam,
  .matchx .cta-s .halo,
  .matchx .term .cur{ animation:none }
  .matchx [data-rise="in"]{ animation:none }
  html.mt-rise .matchx [data-rise]{ opacity:1 }
  /* 初态一律直接置为终态 —— 不做动画就不能把内容留在初态里 */
  .matchx .slot .v,
  .matchx .eg,
  .matchx .hit{ opacity:1; animation:none; transform:none }
}
