/* ═══════════════════════════════════════════════════════════════════════════
   阡视科技 QIANSHI TECH — Landing Page
   Design language: Deep-space precision. Slate-navy void, mint signal.
   Palette derived from the brand marks:
     · #222E3A  corporate mark ink      → surface family
     · #7F9EB1 → #AEBECC mark gradient  → steel neutrals
     · #8AEFDC  WYLON accent dot        → signature accent
   ═══════════════════════════════════════════════════════════════════════════ */

/* ───────────────────────────────── TOKENS ───────────────────────────────── */
:root {
  /* surfaces */
  --void:       #05080d;
  --bg:         #070b11;
  --surface:    #0a1018;
  --panel:      #0e1621;
  --card:       #121b27;
  --card-hi:    #18232f;

  /* hairlines */
  --hair:       rgba(var(--steel-rgb), .10);
  --hair-2:     rgba(var(--steel-rgb), .17);
  --hair-3:     rgba(var(--steel-rgb), .28);

  /* ink */
  --ink:        #eef3f9;
  --ink-2:      #9dadc0;
  --ink-3:      #64748b;

  /* brand */
  --mint:       #8aefdc;
  --mint-deep:  #34c9ac;
  --steel:      #a8bfd0;
  --steel-dim:  #7f9eb1;
  --blue:       #3d7bff;
  --blue-hi:    #6b9bff;

  /* type */
  /* Latin resolves to Inter; every CJK glyph the site uses is in the self-hosted
     MiSans subset, so the fallbacks only ever catch a stray character.
     No PingFang / YaHei anywhere in the chain — by request. */
  --sans: 'Inter', 'MiSans VF', 'MiSans', 'HarmonyOS Sans SC', 'Noto Sans SC',
          'Source Han Sans SC', sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas,
          'Liberation Mono', monospace;

  /* rhythm */
  --gut:        clamp(20px, 4vw, 48px);
  --maxw:       1440px;   /* matches wylon.cn */
  --sec-y:      clamp(88px, 11vw, 168px);
  --r-sm:       4px;
  --r:          8px;
  --r-lg:       14px;

  /* triplets so every rgba(...) below can flip with the theme */
  --mint-rgb:   138, 239, 220;
  --steel-rgb:  160, 190, 214;
  --blue-rgb:   61, 123, 255;
  --tint-rgb:   255, 255, 255;   /* the "lift" overlay: white on dark, ink on light */
  --shadow-rgb: 0, 0, 0;

  --ease:       cubic-bezier(.22, 1, .36, 1);

  /* where an anchored heading should land, measured from the viewport top
     (68px nav + 28px breathing room) */
  --anchor-y:   96px;
  --cta-y:      clamp(88px, 10vw, 150px);
}


/* ═══════════════════════════════ LIGHT THEME ══════════════════════════════
   Same structure, inverted ground. Only tokens change — every component reads
   from them, so no component rules are duplicated here.
   ═══════════════════════════════════════════════════════════════════════════ */
[data-theme="light"] {
  --void:       #eef1f6;
  --bg:         #f6f8fb;
  --surface:    #ffffff;
  --panel:      #f4f7fa;
  --card:       #ffffff;
  --card-hi:    #eef3f8;

  --hair:       rgba(19, 42, 71, .12);
  --hair-2:     rgba(19, 42, 71, .20);
  --hair-3:     rgba(19, 42, 71, .32);

  --ink:        #0c1722;
  --ink-2:      #45586d;
  --ink-3:      #6f8296;

  /* the signature mint is far too light on white — darken it for anything that
     has to read as text or a line, and keep a bright one for glows/fills */
  --mint:       #0b8f74;
  --mint-rgb:   11, 143, 116;
  --mint-deep:  #06705b;
  --steel:      #4a6076;
  --steel-dim:  #5d7288;
  --steel-rgb:  74, 100, 130;
  --blue:       #2563eb;
  --blue-hi:    #1d4ed8;
  --blue-rgb:   37, 99, 235;

  /* overlays darken instead of lifting, and shadows go slate rather than black */
  --tint-rgb:   16, 34, 56;
  --shadow-rgb: 24, 45, 74;

  color-scheme: light;
}
[data-theme="light"] .line__shot--split .line__half:first-child,
/* the Token-factory figure is a canvas (main.js tokenfab) that reads the
   palette from the theme tokens, so it needs no light-ground swap */
/* product renders are dark hardware on transparent — give them a soft plate
   so they do not float unanchored on white */
[data-theme="light"] .line__shot::after,
[data-theme="light"] .fam__shot::after,
[data-theme="light"] .spec__shot::after {
  background: radial-gradient(closest-side, rgba(var(--shadow-rgb), .16), transparent 74%);
}
/* pieces that are explicitly "glow on a dark ground" need a light counterpart */
[data-theme="light"] body { background: var(--bg); }
[data-theme="light"] .hero {
  background:
    radial-gradient(120% 80% at 78% 30%, rgba(var(--blue-rgb), .10) 0%, transparent 62%),
    linear-gradient(180deg, #ffffff 0%, #f4f8fc 55%, var(--bg) 100%);
}
[data-theme="light"] .page-hero {
  background:
    radial-gradient(90% 120% at 22% 0%, rgba(var(--blue-rgb), .10) 0%, transparent 58%),
    radial-gradient(60% 90% at 88% 30%, rgba(var(--mint-rgb), .10) 0%, transparent 62%),
    linear-gradient(180deg, #ffffff, var(--surface));
}
[data-theme="light"] .cta {
  background:
    radial-gradient(90% 120% at 50% 0%, rgba(var(--blue-rgb), .10) 0%, transparent 58%),
    radial-gradient(60% 80% at 78% 110%, rgba(var(--mint-rgb), .09) 0%, transparent 60%),
    var(--surface);
}
[data-theme="light"] .nav.is-stuck { background: rgba(255,255,255,.82); }
[data-theme="light"] .mobile-menu { background: rgba(255,255,255,.97); }
[data-theme="light"] .submenu,
[data-theme="light"] .jd {
  background: linear-gradient(180deg, #ffffff, #f4f7fa);
  border-color: rgba(19,42,71,.16);
  box-shadow: 0 30px 70px -28px rgba(var(--shadow-rgb), .28), 0 1px 0 rgba(255,255,255,.9) inset;
}
[data-theme="light"] .vinds li { background: var(--card); }
/* the saturated royal blue reads loud against a soft light ground; on white the
   primary action goes to the brand mark's own slate ink (#222E3A family), which
   keeps the mint free to stay the one accent */
[data-theme="light"] .btn--primary {
  color: #fff;
  background: linear-gradient(180deg, #2a3f55, #1a2c3e);
  box-shadow: 0 1px 0 rgba(255,255,255,.16) inset, 0 6px 18px -8px rgba(26,44,62,.55);
}
[data-theme="light"] .btn--primary:hover {
  background: linear-gradient(180deg, #334b63, #223649);
  box-shadow: 0 1px 0 rgba(255,255,255,.22) inset, 0 10px 26px -8px rgba(26,44,62,.65);
}
/* keep the hero highlight gradient on blue — it is type, not a control */
[data-theme="light"] .grad {
  background: linear-gradient(96deg, var(--mint) 0%, #2f7fb8 52%, #2b4d7e 100%);
  -webkit-background-clip: text; background-clip: text;
}
/* vendor marks are solid black artwork — do not invert them on a light ground */
[data-theme="light"] .eco__logos img { filter: none; opacity: .55; }
[data-theme="light"] .eco__logos li:hover img { opacity: 1; }
/* the corporate mark is white artwork; swap to the dark-ink version */
[data-theme="light"] .nav__brand img,
[data-theme="light"] .foot__brand img { content: url('../img/logos/qianshi-on-light.png'); }

/* ────────────────────────────────── RESET ───────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  background: var(--void);
}

body {
  font-family: var(--sans);
  font-weight: 450;   /* between Regular and Medium — the variable font allows the in-between */
  font-size: 16px;
  line-height: 1.75;
  color: var(--ink-2);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}
body.is-locked { overflow: hidden; }

img, svg { display: block; max-width: 100%; }
img { height: auto; }
ul, ol { list-style: none; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
sup { font-size: .5em; vertical-align: super; line-height: 0; letter-spacing: 0; }
/* the ® must not inherit the wide tracking of mono runs */
/* the wylon wordmark: always lowercase, always in its own face, set at a
   semibold instance of the variable font so it holds its own beside CJK */
.wm {
  font-family: 'Wylon', var(--sans); font-weight: 650; font-style: normal;
  text-transform: lowercase; letter-spacing: .01em; font-size: 1.02em;
}

::selection { background: rgba(var(--mint-rgb), .24); color: #fff; }

:focus-visible {
  outline: 2px solid var(--mint);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip-link {
  position: fixed; top: 8px; left: 8px; z-index: 999;
  padding: 10px 18px; background: var(--mint); color: #04120f;
  font-weight: 600; border-radius: var(--r-sm);
  transform: translateY(-160%); transition: transform .2s var(--ease);
}
.skip-link:focus { transform: none; }


/* ─────────────────────────────── PRIMITIVES ─────────────────────────────── */
.container { width: 100%; max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gut); }
.section   {
  padding-block: var(--sec-y); position: relative;
  scroll-margin-top: calc(var(--anchor-y) - var(--sec-y));
}

.mono {
  font-family: var(--mono);
  font-size: .6875rem;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  font-feature-settings: 'ss01';
}

.h2 {
  font-size: clamp(2rem, 3.9vw, 3.4rem);
  font-weight: 800;
  line-height: 1.14;
  letter-spacing: -.022em;
  color: var(--ink);
}
/* status qualifier inside a display heading — at full h2 size it would read as
   part of the product name rather than a state */
.h2__status {
  font-size: .4em; font-weight: 600; letter-spacing: 0;
  vertical-align: .22em; margin-left: .18em;
  color: var(--steel-dim);
}
.h2__status--ship { color: var(--mint); }

.h3 {
  font-size: clamp(1.25rem, 1.9vw, 1.75rem);
  font-weight: 700; line-height: 1.35; letter-spacing: -.015em;
  color: var(--ink);
}
.lede {
  font-size: 1.0625rem;
  line-height: 1.8;
  color: var(--ink-2);
  max-width: 60ch;
  margin-top: 22px;
  text-wrap: pretty;          /* avoids single-word orphans on the last line */
}
.grad {
  background: linear-gradient(96deg, var(--mint) 0%, #b9e4ff 48%, var(--blue-hi) 100%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
}

.sec-head { margin-bottom: clamp(48px, 6vw, 76px); }
.sec-head--center { text-align: center; margin-inline: auto; max-width: 780px; }
/* centred copy is short enough for the balancer — evens the ragged last line */
.sec-head--center .lede { margin-inline: auto; text-wrap: balance; }

/* buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .55em;
  height: 46px; padding-inline: 24px;
  font-size: .9375rem; font-weight: 600; letter-spacing: .01em;
  border-radius: var(--r-sm);
  border: 1px solid transparent;
  white-space: nowrap;
  transition: background .22s var(--ease), border-color .22s var(--ease),
              color .22s var(--ease), box-shadow .28s var(--ease), transform .22s var(--ease);
}
.btn svg { width: 15px; height: 15px; transition: transform .28s var(--ease); }
.btn:hover svg { transform: translateX(3px); }

.btn--primary {
  background: linear-gradient(180deg, #4b86ff, var(--blue));
  color: #fff;
  box-shadow: 0 1px 0 rgba(255,255,255,.22) inset, 0 6px 20px -8px rgba(var(--blue-rgb), .7);
}
.btn--primary:hover {
  background: linear-gradient(180deg, #5c91ff, #3f7dff);
  box-shadow: 0 1px 0 rgba(255,255,255,.28) inset, 0 10px 30px -8px rgba(var(--blue-rgb), .85);
  transform: translateY(-1px);
}
.btn--ghost {
  border-color: var(--hair-2);
  color: var(--ink);
  background: rgba(var(--tint-rgb), .02);
}
.btn--ghost:hover {
  border-color: rgba(var(--mint-rgb), .5);
  background: rgba(var(--mint-rgb), .06);
  color: #fff;
}
.btn--sm { height: 36px; padding-inline: 16px; font-size: .8125rem; }
.btn--lg { height: 54px; padding-inline: 32px; font-size: 1rem; }

/* chips / tags */
.tag {
  display: inline-block; padding: 4px 9px;
  border: 1px solid var(--hair-2); border-radius: 3px;
  color: var(--steel-dim); background: rgba(var(--tint-rgb), .02);
}
.tag--accent { color: var(--mint); border-color: rgba(var(--mint-rgb), .32); background: rgba(var(--mint-rgb), .06); }

.chips { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 20px; }
.chips li {
  font-size: .75rem; font-weight: 500; color: var(--steel-dim);
  padding: 4px 10px; border-radius: 999px;
  border: 1px solid var(--hair); background: rgba(var(--tint-rgb), .02);
}

/* reveal */
.reveal { opacity: 0; transform: translateY(18px); }
.reveal.in {
  opacity: 1; transform: none;
  transition: opacity .85s var(--ease), transform .85s var(--ease);
  transition-delay: calc(var(--d, 0) * 90ms);
}

/* ────────────────────────────────── NAV ─────────────────────────────────── */
.nav {
  position: fixed; inset: 0 0 auto; z-index: 100;
  transition: background .35s var(--ease), backdrop-filter .35s var(--ease),
              border-color .35s var(--ease);
  border-bottom: 1px solid transparent;
}
.nav.is-stuck {
  background: rgba(7, 11, 17, .78);
  backdrop-filter: saturate(160%) blur(16px);
  -webkit-backdrop-filter: saturate(160%) blur(16px);
  border-bottom-color: var(--hair);
}
.nav__inner {
  max-width: var(--maxw); margin-inline: auto;
  padding: 0 var(--gut);
  height: 68px;
  /* 1fr | auto | 1fr keeps the links dead-centre in the viewport whatever the
     brand mark and CTA measure — a flex row would centre them between the two. */
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 24px;
}
.nav__brand img { height: 26px; width: auto; }
.nav__brand { flex: none; opacity: .96; transition: opacity .2s; }
.nav__brand:hover { opacity: 1; }

.nav__links { display: flex; align-items: center; justify-content: center; gap: clamp(20px, 2.2vw, 32px); }
.nav__item, .nav__trigger {
  position: relative; display: inline-flex; align-items: center; gap: 5px;
  font-size: .875rem; font-weight: 500; color: var(--ink-2);
  padding-block: 6px; white-space: nowrap;
  transition: color .2s var(--ease);
}
.nav__item::after, .nav__trigger::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: var(--mint);
  transform: scaleX(0); transform-origin: left;
  transition: transform .34s var(--ease);
}
a.nav__item:hover, .nav__trigger:hover { color: var(--ink); }
a.nav__item:hover::after, .nav__trigger:hover::after,
.nav__item--has-menu.is-open .nav__trigger::after { transform: scaleX(1); }
.nav__item[aria-current="page"] { color: var(--ink); }
.nav__item[aria-current="page"]::after { transform: scaleX(1); background: var(--hair-3); }

.nav__trigger svg { width: 9px; height: 6px; opacity: .7; transition: transform .3s var(--ease); }
/* the wrapper is a div around the trigger button — if it keeps .nav__item
   padding it stacks on the button's own and the item sits 6px taller than
   its siblings, pushing its underline out of line */
.nav__item--has-menu { position: relative; padding: 0; }
.nav__item--has-menu::after { display: none; }
.nav__item--has-menu.is-open .nav__trigger svg { transform: rotate(180deg); }

.submenu {
  position: absolute; top: calc(100% + 18px); left: 50%;
  transform: translate(-50%, -6px);
  min-width: 384px; padding: 10px;
  border: 1px solid rgba(var(--steel-rgb), .22); border-radius: var(--r-lg);
  /* a clearly lighter panel — at rgba(10,16,24,.96) it read as a hole in the
     page rather than a surface floating above it */
  background: linear-gradient(180deg, rgba(32, 46, 62, .97), rgba(23, 34, 47, .97));
  backdrop-filter: saturate(160%) blur(18px);
  -webkit-backdrop-filter: saturate(160%) blur(18px);
  box-shadow: 0 30px 70px -28px rgba(var(--shadow-rgb), .9), 0 1px 0 rgba(var(--tint-rgb), .06) inset;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .24s var(--ease), transform .24s var(--ease), visibility .24s;
}
.nav__item--has-menu.is-open .submenu {
  opacity: 1; visibility: visible; pointer-events: auto; transform: translate(-50%, 0);
}
/* keeps the pointer inside the item while travelling down to the panel */
.nav__item--has-menu::before {
  content: ''; position: absolute; top: 100%; left: 0; right: 0; height: 20px;
}
.submenu a {
  display: block; padding: 14px 18px; border-radius: var(--r);
  transition: background .2s var(--ease);
}
.submenu a:hover { background: rgba(var(--mint-rgb), .10); }
.submenu__t { display: block; font-size: .9375rem; font-weight: 600; color: var(--ink); }
.submenu__d { display: block; margin-top: 5px; font-size: .8125rem; line-height: 1.55; color: var(--ink-2); }
.submenu a:hover .submenu__t { color: var(--mint); }

.nav__actions { display: flex; align-items: center; justify-content: flex-end; gap: 14px; }
/* secondary entry — sits with the CTA, not in the main nav */
.nav__aux {
  position: relative; font-size: .875rem; font-weight: 500; color: var(--ink-2);
  padding-block: 6px; white-space: nowrap; transition: color .2s var(--ease);
}
.nav__aux::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: var(--mint); transform: scaleX(0); transform-origin: left;
  transition: transform .34s var(--ease);
}
.nav__aux:hover { color: var(--ink); }
.nav__aux:hover::after, .nav__aux[aria-current="page"]::after { transform: scaleX(1); }
.nav__aux[aria-current="page"] { color: var(--ink); }


/* ── theme toggle ───────────────────────────────────────────────────────── */
.themetog {
  flex: none; width: 34px; height: 34px; display: grid; place-items: center;
  border: 0; border-radius: var(--r-sm);
  color: var(--ink-2); background: transparent;
  transition: color .2s var(--ease), background .2s var(--ease);
}
.themetog:hover { color: var(--mint); background: rgba(var(--mint-rgb), .07); }
.themetog svg { width: 16px; height: 16px; grid-area: 1 / 1; transition: opacity .2s var(--ease), transform .3s var(--ease); }
/* the icon names the theme a click switches TO: a sun on the dark page, a moon on the light one */
.themetog__sun  { opacity: 1; }
.themetog__moon { opacity: 0; transform: rotate(40deg) scale(.7); }
[data-theme="light"] .themetog__sun  { opacity: 0; transform: rotate(-40deg) scale(.7); }
[data-theme="light"] .themetog__moon { opacity: 1; transform: none; }
@media (max-width: 620px) { .themetog { width: 30px; height: 30px; }}

.nav__toggle {
  display: none; width: 40px; height: 40px;
  align-items: center; justify-content: center; flex-direction: column; gap: 5px;
  margin-right: -8px;
}
.nav__toggle span {
  display: block; width: 20px; height: 1.5px; background: var(--ink);
  transition: transform .3s var(--ease), opacity .2s var(--ease);
}
.nav__toggle[aria-expanded="true"] span:first-child { transform: translateY(3.25px) rotate(45deg); }
.nav__toggle[aria-expanded="true"] span:last-child  { transform: translateY(-3.25px) rotate(-45deg); }

.nav__progress {
  height: 1px; width: 100%;
  background: linear-gradient(90deg, var(--mint), var(--blue));
  transform: scaleX(0); transform-origin: left;
}

/* mobile menu */
[hidden] { display: none !important; }
.mobile-menu {
  position: fixed; inset: 68px 0 0; z-index: 99;
  background: rgba(5, 8, 13, .97);
  backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
  padding: 40px var(--gut) 32px;
  display: flex; flex-direction: column; justify-content: space-between;
  animation: mmIn .3s var(--ease);
}
@keyframes mmIn { from { opacity: 0; transform: translateY(-8px); } }
.mobile-menu nav { display: flex; flex-direction: column; }
.mobile-menu a, .mobile-menu .mm__label {   /* the 产品 heading is a label, not a link: its two items sit under it */
  display: flex; align-items: baseline; gap: 16px;
  padding: 20px 0;
  font-size: 1.5rem; font-weight: 700; letter-spacing: -.02em; color: var(--ink);
  border-bottom: 1px solid var(--hair);
}
.mm__idx { font-family: var(--mono); font-size: .6875rem; color: var(--mint); letter-spacing: .12em; }
.mm__sub { display: flex; flex-direction: column; padding: 4px 0 14px 38px; }
.mobile-menu .mm__sub a {
  padding: 9px 0; font-size: .9375rem; font-weight: 500;
  color: var(--ink-2); border-bottom: 0;
}
.mobile-menu .mm__sub a:hover { color: var(--mint); }
.mobile-menu__foot { display: flex; justify-content: space-between; color: var(--ink-3); }

/* ────────────────────────────────── HERO ────────────────────────────────── */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex; flex-direction: column; justify-content: center;
  padding-top: 104px;
  overflow: hidden;
  background:
    radial-gradient(120% 80% at 78% 30%, rgba(21, 42, 66, .55) 0%, transparent 62%),
    linear-gradient(180deg, #060a10 0%, #070c13 55%, var(--bg) 100%);
}
/* The fabric is dimmed — not erased — behind the headline: it keeps the depth
   without ever competing with the type for contrast. */
.hero__canvas {
  position: absolute; inset: 0; width: 100%; height: 100%;
  /* the headline sits bottom-left, so fade the lattice out towards that corner
     and let it fill the rest of the frame */
  mask-image: linear-gradient(90deg, transparent 6%, rgba(var(--shadow-rgb), .4) 30%, #000 54%);
  -webkit-mask-image: linear-gradient(90deg, transparent 6%, rgba(var(--shadow-rgb), .4) 30%, #000 54%);
}
.hero__grid {
  position: absolute; inset: 0;
  background-image:
    linear-gradient(to right, rgba(var(--steel-rgb), .045) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(var(--steel-rgb), .045) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(110% 85% at 50% 35%, #000 20%, transparent 78%);
  -webkit-mask-image: radial-gradient(110% 85% at 50% 35%, #000 20%, transparent 78%);
}
.hero__glow {
  position: absolute; left: -12%; top: 4%;
  width: 780px; height: 780px; max-width: 90vw;
  background: radial-gradient(circle, rgba(var(--blue-rgb), .16) 0%, transparent 66%);
  filter: blur(20px);
  pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
  .hero__glow { animation: glowDrift 26s ease-in-out infinite alternate; }
  @keyframes glowDrift { to { transform: translate(6%, 5%) scale(1.08); } }
}

.hero__inner {
  position: relative; z-index: 2;
  /* headline sits at the vertical centre, left; the lattice owns the right —
     smaller type than the first cut so the visual has room */
  padding-block: clamp(32px, 5vh, 72px);
  flex: 1; display: flex; flex-direction: column; justify-content: center;
}
.hero__title {
  font-size: clamp(2.6rem, 6.9vw, 6rem);
  font-weight: 550;
  line-height: 1.06;
  letter-spacing: -.03em;
  color: var(--ink);
  max-width: 17ch;
  text-wrap: balance;
}
.hero__lede {
  margin-top: 32px;
  font-size: clamp(1.0625rem, 1.5vw, 1.375rem);
  line-height: 1.85;
  color: var(--ink-2);
  max-width: 52ch;
}
.hero__cta { display: flex; flex-wrap: wrap; gap: 14px; margin-top: clamp(40px, 4vw, 56px); }

/* rack */
.rack { display: flex; flex-direction: column; }
@keyframes bus { from { background-position: 120% 0; } to { background-position: -120% 0; } }
@keyframes meshBreathe {
  0%, 100% { opacity: .5; transform: scale(.9); }
  50%      { opacity: 1;  transform: scale(1.06); }
}
@keyframes meshBeam { to { stroke-dashoffset: -200; } }
@keyframes osDrop {
  0%        { transform: translateY(0);   opacity: 0; }
  25%       { opacity: 1; }
  70%, 100% { transform: translateY(16px); opacity: 0; }
}
@keyframes sink {
  0%, 12%   { transform: translateY(0);   opacity: 1; }
  33%, 45%  { transform: translateY(28px); opacity: .85; }
  66%, 78%  { transform: translateY(56px); opacity: .6; }
  92%, 100% { transform: translateY(84px); opacity: 0; }
}
@keyframes coreGlow { 0%,100% { opacity: .6; } 50% { opacity: 1; } }

/* ──────────────────────────────── PRODUCTS ──────────────────────────────── */
.products { background: var(--surface); border-top: 1px solid var(--hair); }
.vh { position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; }
.line {
  position: relative; display: flex; flex-direction: column;
  padding: 32px 32px 28px;
  border: 1px solid var(--hair); border-radius: var(--r-lg);
  background: linear-gradient(180deg, rgba(var(--tint-rgb), .022), transparent 38%), var(--card);
  overflow: hidden;
  transition: border-color .35s var(--ease), transform .35s var(--ease), box-shadow .35s var(--ease);
}
.line::before {
  content:''; position:absolute; inset:0; pointer-events:none; opacity:0;
  background: radial-gradient(85% 55% at 50% 0%, rgba(var(--mint-rgb), .10), transparent 62%);
  transition: opacity .4s var(--ease);
}
.line:hover { transform: translateY(-4px); border-color: var(--hair-2); box-shadow: 0 28px 64px -42px rgba(var(--shadow-rgb), .95); }
.line:hover::before { opacity: 1; }
.eco__logos {
  margin-top: 8px;
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  background: var(--hair);
  overflow: hidden;
}
.eco__logos li {
  display: grid; place-items: center;
  padding: 34px 26px;
  background: var(--panel);
  transition: background .3s var(--ease);
}
.eco__logos li:hover { background: var(--card-hi); }
.eco__logos img {
  width: auto; max-width: 100%;
  filter: brightness(0) invert(1);   /* every mark is solid black → uniform white */
  opacity: .42;
  transition: opacity .3s var(--ease);
}
/* Optical sizing: these lockups differ in aspect and in how much of the box the
   wordmark occupies, so a single height would make them read at unequal weight. */
.eco__logos img[data-v="cambricon"] { height: 42px; }
.eco__logos img[data-v="metax"]     { height: 27px; }
.eco__logos img[data-v="biren"]     { height: 38px; }
.eco__logos img[data-v="sunrise"]   { height: 27px; }
/* two-line lockups need more height for their latin row to match the others */
.eco__logos img[data-v="moorethreads"] { height: 38px; }
.eco__logos img[data-v="hygon"]        { height: 42px; }
.eco__logos li:hover img { opacity: .95; }

/* ── full-bleed photo bands ─────────────────────────────────────────────── */
/* GE's move: a photograph the full width of the viewport with a statement set
   over it, cut hard against the light sections either side. The band is dark
   in both themes on purpose — the photo is the ground, not the token palette. */
.band {
  position: relative; overflow: hidden; isolation: isolate;
  min-height: clamp(520px, 78vh, 840px);
  display: flex; align-items: center;
  background: #060a10; color: #fff;
}
/* The photo is taller than its band and slides through it as you scroll
   (parallax, set by main.js on --py), while a slow push-in with a diagonal
   drift runs on top. The two use different transform channels — `translate`
   for the parallax, `transform` for the drift — so they compose instead of
   fighting. Both are switched off under reduced motion. */
.band__img {
  position: absolute; left: 0; right: 0; top: -10%; z-index: -2;
  width: 100%; height: 120%; object-fit: cover; object-position: 30% 50%;
  translate: 0 var(--py, 0);
}
@media (prefers-reduced-motion: no-preference) {
  .band__img { animation: kenburns 18s ease-in-out infinite alternate; will-change: transform, translate; }
  @keyframes kenburns {
    from { transform: scale(1.04) translate3d(-1.6%, -1%, 0); }
    to   { transform: scale(1.16) translate3d(1.6%, 1%, 0); }
  }
}
.band__shade {
  position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(90deg, rgba(6,10,16,.62) 0%, rgba(6,10,16,.34) 45%, rgba(6,10,16,.66) 100%),
    linear-gradient(180deg, rgba(6,10,16,.35) 0%, transparent 28%, transparent 68%, rgba(6,10,16,.6) 100%);
}
.band__shade--center {
  background:
    radial-gradient(70% 90% at 50% 50%, rgba(6,10,16,.82) 0%, rgba(6,10,16,.55) 60%, rgba(6,10,16,.35) 100%),
    linear-gradient(180deg, rgba(6,10,16,.45), transparent 30%, transparent 70%, rgba(6,10,16,.6));
}
/* ── company band: two photos, one scan line ─────────────────────────────── */
/* The dark cabinet is clipped from --cut rightwards over the bright appliance
   stack; --cut sweeps 14% ↔ 86% on an 18 s cycle, so the cabinet is scanned
   out of the scene and back. Pure CSS, identical on every device. --cut is
   registered so keyframes can drive it. */
@property --cut { syntax: '<percentage>'; inherits: true; initial-value: 34%; }
.band--company { --cut: 34%; }
.band--company .band__img { object-position: 50% 50%; }
.band__img--over { clip-path: inset(0 0 0 var(--cut)); }
.band__scan {
  position: absolute; top: 0; bottom: 0; left: var(--cut); z-index: 0;
  width: 2px; margin-left: -1px; pointer-events: none;
  background: linear-gradient(180deg, transparent, rgba(var(--mint-rgb), .95) 12%, rgba(var(--mint-rgb), .95) 88%, transparent);
  box-shadow: 0 0 22px 4px rgba(var(--mint-rgb), .35);
}
/* a soft glow trailing onto the revealed cabinet, and a fine raster ahead of
   the edge — the two cues that make it read as a scan rather than a wipe */
.band__scan::before {
  content: ''; position: absolute; top: 0; bottom: 0; left: 2px; width: 220px;
  background: linear-gradient(90deg, rgba(var(--mint-rgb), .20), rgba(var(--mint-rgb), .06) 45%, transparent);
}
.band__scan::after {
  content: ''; position: absolute; top: 0; bottom: 0; right: 2px; width: 56px;
  background: repeating-linear-gradient(90deg, rgba(255,255,255,.10) 0 1px, transparent 1px 7px);
  mask-image: linear-gradient(90deg, transparent, #000);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000);
}
@media (prefers-reduced-motion: no-preference) {
  .band--company { animation: cutSweep 18s ease-in-out infinite alternate; }
  @keyframes cutSweep { from { --cut: 14%; } to { --cut: 86%; } }
}
/* the statement now meets the bright photo for part of every cycle, so the
   ground is pulled down evenly rather than only on the dark side */
.band--company .band__shade {
  background:
    linear-gradient(90deg, rgba(6,10,16,.70) 0%, rgba(6,10,16,.56) 50%, rgba(6,10,16,.68) 100%),
    linear-gradient(180deg, rgba(6,10,16,.40) 0%, transparent 30%, transparent 70%, rgba(6,10,16,.62) 100%);
}
.band--cta .band__img { object-position: 50% 45%; }
.band__inner {
  width: 100%; padding-block: clamp(72px, 9vw, 140px);
  display: grid; grid-template-columns: minmax(0, .7fr) minmax(0, 1.3fr);
  gap: clamp(24px, 4vw, 72px); align-items: start;
}
.band__k { font-size: .625rem; letter-spacing: .18em; color: rgba(255,255,255,.62); padding-top: .9em; }
.band__statement {
  font-size: clamp(1.5rem, 3vw, 2.875rem); font-weight: 550;
  line-height: 1.38; letter-spacing: -.02em; color: #fff;
  text-wrap: pretty; max-width: 26ch;
}
/* with no label beside it, the statement takes the full width so it can read
   large and on one line (~23em of headline, ~38em of the line under it) */
.band--company .band__copy { grid-column: 1 / -1; }
.band--company .band__statement { font-size: clamp(1.75rem, 3.4vw, 3.375rem); max-width: none; }
.band--company .band__lede { font-size: clamp(1rem, 1.45vw, 1.3125rem); max-width: none; }
@media (min-width: 768px) {
  .band--company .band__statement, .band--company .band__lede { white-space: nowrap; }
}
.band__inner--center { display: grid; grid-template-columns: 1fr; justify-items: center; text-align: center; gap: 0; }
.band__title {
  font-size: clamp(2.25rem, 5.2vw, 4.5rem); font-weight: 550;
  line-height: 1.12; letter-spacing: -.03em; color: #fff;
}
.band__lede { margin-top: 24px; font-size: clamp(1rem, 1.3vw, 1.1875rem); line-height: 1.8; color: rgba(255,255,255,.72); max-width: 44ch; }
.band .cta__actions { margin-top: 40px; }
/* buttons have to read on a photograph, whatever the theme */
.band .btn--primary { background: #fff; color: #0c1722; border-color: #fff; }
.band .btn--primary:hover { background: #e9eef4; color: #0c1722; }
.band .btn--ghost { color: #fff; border-color: rgba(255,255,255,.45); background: rgba(255,255,255,.06); }
.band .btn--ghost:hover { border-color: #fff; background: rgba(255,255,255,.12); color: #fff; }
.band .btn svg { color: currentColor; }
@media (max-width: 860px) {
  .band { min-height: clamp(440px, 70vh, 640px); }
  .band__inner { grid-template-columns: 1fr; gap: 18px; }
}

/* ── narrative: the two things the company does ─────────────────────────── */
/* Same no-card grammar as the product bands below: a statement in display type,
   then the two halves of it side by side, held apart by a hairline instead of
   a border box. */
.narr { background: var(--bg); padding-block: clamp(88px, 11vw, 180px); }
/* the statement stands alone now; the two business bands follow it directly,
   so its bottom padding is short and the bands' own padding sets the gap */
.narr--lead { padding-bottom: clamp(8px, 1.5vw, 24px); }
@media (max-width: 720px) {
  /* the hand-set break strands "架构，" on a line of its own at this width — let the browser balance it instead */
  .narr__lead br { display: none; }
  .narr__lead { text-wrap: balance; }
}
/* the hero's grid, much fainter, under the light sections — ties the page to
   one drawing. It slides one cell every 40 s: a conveyor, not a twinkle. */
.narr, .duo { isolation: isolate; overflow: hidden; }
.narr::before, .duo::before {
  content: ''; position: absolute; inset: -64px 0; z-index: -1; pointer-events: none;
  background-image:
    linear-gradient(to right, rgba(var(--steel-rgb), .07) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(var(--steel-rgb), .07) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(75% 70% at 68% 45%, #000 0%, transparent 78%);
  -webkit-mask-image: radial-gradient(75% 70% at 68% 45%, #000 0%, transparent 78%);
}
@media (prefers-reduced-motion: no-preference) {
  .narr::before, .duo::before { animation: gridDrift 40s linear infinite; }
  @keyframes gridDrift { to { background-position: 64px 64px; } }
}
/* the two display statements are revealed by a left → right wipe rather than
   the plain fade the rest of the page uses; negative insets keep glyph
   overhangs from being shaved. The clip lives on an inner span, never on the
   .reveal element itself: IntersectionObserver counts clip-path towards the
   intersection area, so a fully clipped target can never cross the threshold. */
.narr__wipe { display: block; }
.narr__wipe, .duo__card .duo__name { clip-path: inset(-.2em 101% -.2em -.1em); }
.narr__lead.in .narr__wipe, .duo__card.in .duo__name {
  clip-path: inset(-.2em -.1em -.2em -.1em);
  transition: clip-path 1.2s var(--ease) .1s;
}
@media (prefers-reduced-motion: reduce) {
  .narr__wipe, .duo__card .duo__name { clip-path: none; }
}
.narr__lead {
  font-size: clamp(2rem, 4.4vw, 4.25rem); font-weight: 550;
  line-height: 1.2; letter-spacing: -.03em; color: var(--ink);
  /* the <br> in the markup sets the break; ch is measured on Inter and runs
     ~40% narrower than a CJK glyph, so a tight ch cap strands a word */
  max-width: 32ch;
}
/* the rule draws itself left → right as the block scrolls in — a line being
   set on a drawing, not a border that was always there */
.duo__card::before,
.duo__card:last-child::after {
  content: ''; position: absolute; left: 0; right: 0; height: 1px;
  background: var(--hair);
  transform-origin: left center; transform: scaleX(0);
  transition: transform 1.1s var(--ease) .12s;
}
.duo__card::before { top: 0; }
.duo__card:last-child::after { bottom: 0; transition-delay: .5s; }
.duo__card.in::before, .duo__card.in:last-child::after { transform: scaleX(1); }
@media (prefers-reduced-motion: reduce) {
  .duo__card::before, .duo__card:last-child::after { transform: none; transition: none; }
}

/* ── token factory canvas ─────────────────────────────────────────────────── */
.tokenfab { display: block; width: 100%; aspect-ratio: 420 / 250; }
/* inside the products card the shot is a fixed-height box: fill it and let
   the scene letterbox itself. The shot's ::after is a bottom fade meant for
   product photographs — it must not sit on top of a live scene. */
.fam__shot .tokenfab { position: absolute; inset: 0; width: 100%; height: 100%; aspect-ratio: auto; z-index: 2; }
.fam__shot:has(.tokenfab)::after { display: none; }

/* ── two product lines ──────────────────────────────────────────────────── */
/* No cards. Each line is a band sitting straight on the page, separated by a
   hairline and a lot of air — the quiet reads as confidence, where a boxed
   card reads as a tile in a catalogue. */
.duo { background: var(--bg); padding-block: 0; }
.duo__list { display: grid; }
.duo__card {
  position: relative;
  display: grid; grid-template-columns: minmax(0, .86fr) minmax(0, 1.14fr);
  gap: clamp(28px, 4vw, 80px); align-items: center;
  padding-block: clamp(72px, 9vw, 150px);
}

.duo__copy { display: grid; justify-items: start; }
.duo__name {
  font-size: clamp(2.25rem, 4.6vw, 4.5rem); font-weight: 550;
  letter-spacing: -.035em; line-height: 1.08; color: var(--ink);
}
/* the kind heads the whole card, above the picture — a step between the
   section statement and the product name, so it sits a size up from body */
.duo__kind {
  order: -2; font-size: clamp(1.125rem, 1.6vw, 1.5rem); font-weight: 600;
  line-height: 1.3; color: var(--mint); letter-spacing: -.015em;
}
.duo__card--local .duo__kind { color: var(--steel); }
.duo__uses { display: grid; gap: 11px; margin-top: clamp(26px, 3vw, 40px); }
.duo__uses li {
  position: relative; padding-left: 20px;
  font-size: clamp(.9375rem, 1.15vw, 1.0625rem); line-height: 1.7; color: var(--ink-2);
}
.duo__uses li::before {
  content: ''; position: absolute; left: 0; top: .62em;
  width: 7px; height: 7px; border-radius: 2px; background: var(--mint);
}
.duo__card--local .duo__uses li::before { background: var(--steel); }
.duo__aud { margin-top: 24px; font-size: .875rem; color: var(--ink-3); }
/* plain labels rather than bordered pills — the last boxed thing in the band */
.duo__models { display: flex; flex-wrap: wrap; align-items: center; gap: 0 14px; margin-top: 10px; }
.duo__models li {
  font-family: var(--mono); font-size: .75rem; letter-spacing: .06em;
  color: var(--ink-2);
}
.duo__models li + li::before {
  content: ''; display: inline-block; vertical-align: middle;
  width: 1px; height: 11px; margin-right: 14px;
  background: var(--hair-3);
}
.duo__go { margin-top: clamp(28px, 3.2vw, 44px); }

.duo__shot { position: relative; display: grid; place-items: center; }
.duo__shot img { max-width: 100%; max-height: min(400px, 38vw); width: auto; object-fit: contain; }
/* the cloud band's figure is one statement: three tags above the cluster,
   the cluster, a centred caption below — and the token stream parts around
   the whole group (main.js measures the union of the three), not the photo */
.duo__shot--cluster { grid-template-columns: minmax(0, 1fr); }
/* the cluster is a wide row of cabinets: keep it a size down from the old
   single cabinet so tags, picture and caption read as one quiet group */
.duo__shot--cluster img { max-width: min(560px, 82%); max-height: min(300px, 24vw); }
.duo__tags {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 8px;
  margin-bottom: clamp(14px, 1.6vw, 22px); max-width: 100%;
}
.duo__tags li {
  font-size: .8125rem; line-height: 1; padding: 8px 13px; white-space: nowrap;
  color: var(--ink-2); border: 1px solid var(--hair-2); border-radius: 999px;
  background: rgba(var(--tint-rgb), .04);
}
.duo__tags li::before { content: ''; display: inline-block; width: 5px; height: 5px; border-radius: 50%; background: var(--mint); margin: 0 8px 1px 0; vertical-align: middle; }
.duo__cap {
  margin-top: clamp(12px, 1.4vw, 18px); text-align: center;
  font-size: .9375rem; letter-spacing: .04em; color: var(--ink-2);
}
.duo__cap .wm { color: var(--ink); }
@media (max-width: 720px) {
  .duo__tags li { font-size: .75rem; padding: 7px 11px; }
}
/* the cloud band: the token stream fills the whole band behind everything,
   faded out under the copy so the words stay clean, and the cabinet stands in
   front of it with a soft dark halo so it reads as an object in the stream */
.duo__card--cloud { overflow: hidden; }
.duo__bg {
  position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; aspect-ratio: auto;
  pointer-events: none;
  /* a quiet ground, not a feature: held well down so it never competes with the words */
  opacity: .3;
  /* clear under the kind at the top, strongest around the picture, gone under
     the copy; the second gradient feathers the side edges so the stream never
     ends on a hard line */
  mask-image: linear-gradient(180deg, transparent 0%, transparent 12%, #000 24%, #000 38%, rgba(0,0,0,.08) 48%, transparent 58%),
              linear-gradient(90deg, transparent 0%, #000 7%, #000 90%, transparent 100%);
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, transparent 12%, #000 24%, #000 38%, rgba(0,0,0,.08) 48%, transparent 58%),
              linear-gradient(90deg, transparent 0%, #000 7%, #000 90%, transparent 100%);
  mask-composite: intersect; -webkit-mask-composite: source-in;
}
.duo__card--cloud .duo__kind, .duo__card--cloud .duo__copy, .duo__card--cloud .duo__shot { position: relative; z-index: 1; }
.duo__card--cloud .duo__shot img { max-width: 76%; }   /* leave two channels beside the cluster for the stream to pass */
/* a soft halo in the page colour lifts the cluster out of the stream */
.duo__card--cloud .duo__shot::before {
  content: ''; position: absolute; inset: -4% -6%; z-index: -1;
  background: radial-gradient(52% 58% at 50% 52%, var(--bg) 0%, rgba(var(--shadow-rgb), 0) 70%);
  opacity: .9;
}

/* Each card is picture over copy. From 941px the two cards sit side by side
   in one row — cloud left, local right, a hairline between — instead of two
   full-width bands stacked: the pair reads at a glance and costs half the
   height. The picture stages share a min-height so the two copies start on
   the same line. */
.duo__card { grid-template-columns: minmax(0, 1fr); gap: clamp(24px, 2.4vw, 36px); align-items: start; align-content: start; padding-block: clamp(52px, 6vw, 88px); }
.duo__shot { order: -1; }
.duo__shot img { max-height: 240px; }
.duo__shot--cluster img { max-height: 200px; }
@media (min-width: 941px) {
  .duo__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .duo__card { padding-inline: 0 clamp(28px, 3.4vw, 64px); }
  .duo__card--local { padding-inline: clamp(28px, 3.4vw, 64px) 0; border-left: 1px solid var(--hair); }
  .duo__shot { min-height: clamp(300px, 23vw, 350px); align-content: center; }
  .duo__name { font-size: clamp(2rem, 3.3vw, 3.25rem); }
  .duo__uses { margin-top: clamp(20px, 2vw, 28px); }
  .duo__card:last-child::after { display: none; }   /* the bottom rule only closes the stacked layout */
}

/* ────────────────────────────────── NEWS ────────────────────────────────── */
.nw { background: var(--bg); }
.nw + .nw { border-top: 1px solid var(--hair); }

/* shared card chrome — the featured item and the grid items differ only in scale */
.nw__card {
  display: grid; gap: 18px; align-content: start;
  color: inherit; text-decoration: none;
}
.nw__shot {
  position: relative; overflow: hidden;
  aspect-ratio: 16 / 9;
  border: 1px solid var(--hair); border-radius: var(--r-lg);
  background: var(--panel);
}
.nw__shot img {
  width: 100%; height: 100%; display: block; object-fit: cover;
  transition: transform .6s var(--ease);
}
.nw__card:hover .nw__shot { border-color: var(--hair-3); }
.nw__card:hover .nw__shot img { transform: scale(1.035); }

.nw__txt { display: grid; gap: 12px; align-content: start; }
.nw__meta { display: flex; align-items: center; gap: 12px; }
.nw__cat {
  font-size: .625rem; letter-spacing: .14em; color: var(--mint);
  padding: 4px 10px; border-radius: 999px;
  border: 1px solid rgba(var(--mint-rgb), .28); background: rgba(var(--mint-rgb), .06);
}
.nw__date { font-size: .75rem; color: var(--ink-3); }
.nw__card h3 {
  font-size: 1.0625rem; font-weight: 700; line-height: 1.65;
  letter-spacing: -.01em; color: var(--ink);
  transition: color .2s var(--ease);
}
.nw__card:hover h3 { color: var(--mint); }
.nw__deck { font-size: .875rem; line-height: 1.85; color: var(--ink-2); }
.nw__go { display: inline-flex; align-items: center; gap: 7px; font-size: .8125rem; color: var(--mint); }
.nw__go svg { width: 15px; height: 15px; transition: transform .25s var(--ease); }
.nw__card:hover .nw__go svg { transform: translateX(3px); }

.nw__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(20px, 2.4vw, 34px); }

/* index list: one bookmark-style card per item, newest first. A row scales to
   any number of entries, which a 3-up grid does not — four items would leave
   one stranded on its own row. */
/* no section heading above the list, so the full section padding would read as
   a hole between the hero and the first card */
.nw--flush { padding-top: clamp(40px, 4vw, 64px); }
/* the about page carries the list under its own heading */
.nw--about { border-top: 1px solid var(--hair); }

/* the three standing honours, folded into the about hero rather than given a
   section of their own — hairline-separated labels, no card */
.ab-honors {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 12px clamp(18px, 2.2vw, 30px);
  margin-top: clamp(30px, 3.4vw, 48px);
}
.ab-honors li {
  position: relative; font-size: clamp(.875rem, 1.05vw, 1rem);
  font-weight: 600; color: var(--ink-2); letter-spacing: -.005em;
}
.ab-honors li + li::before {
  content: ''; position: absolute; left: calc(-1 * clamp(18px, 2.2vw, 30px) / 2);
  top: 50%; transform: translateY(-50%);
  width: 1px; height: 13px; background: var(--hair-3);
}
@media (max-width: 620px) {
  .ab-honors { display: grid; gap: 10px; }
  .ab-honors li + li::before { display: none; }}
.nw__list { display: grid; gap: clamp(14px, 1.8vw, 22px); list-style: none; }
.nw__row {
  display: grid; grid-template-columns: minmax(0, 340px) minmax(0, 1fr);
  gap: clamp(20px, 2.6vw, 40px); align-items: center;
  padding: clamp(14px, 1.6vw, 20px);
  border: 1px solid var(--hair); border-radius: var(--r-lg); background: var(--panel);
  color: inherit; text-decoration: none;
  transition: border-color .25s var(--ease), background .25s var(--ease);
}
.nw__row:hover { border-color: var(--hair-3); background: var(--card-hi); }
.nw__row .nw__shot { border: 0; }          /* the card already carries the frame */
.nw__row:hover .nw__shot img { transform: scale(1.035); }
.nw__row h3 { font-size: 1.125rem; }
.nw__row:hover h3 { color: var(--mint); }

@media (max-width: 760px) {
  .nw__row { grid-template-columns: 1fr; }}

/* ── article ─────────────────────────────────────────────────────────────── */
.art { background: var(--bg); }
/* a comfortable measure for long-form Chinese copy, centred in the container */
.art__wrap { width: min(100%, 760px); margin-inline: auto; }
.art__fig { margin-bottom: clamp(28px, 3.4vw, 46px); }
.art__fig img {
  width: 100%; height: auto; display: block;
  border: 1px solid var(--hair); border-radius: var(--r-lg); background: var(--panel);
}
.art__cap { margin-top: 12px; font-size: .75rem; color: var(--ink-3); text-align: center; }
/* figures set between paragraphs need air on both sides */
.art__body .art__fig { margin: clamp(28px, 3.4vw, 44px) 0; }
/* a portrait shot at full column width would run ~1140px tall and swamp the
   copy — cap the height and centre it instead */
.art__fig--tall img { max-height: 620px; width: auto; margin-inline: auto; }
.art__body p { font-size: 1rem; line-height: 2.05; color: var(--ink-2); }
.art__body p + p,
.art__body blockquote + p { margin-top: 1.35em; }
.art__quote {
  display: block; margin-top: 1.35em;
  padding: 22px clamp(20px, 2.4vw, 30px);
  border-left: 2px solid rgba(var(--mint-rgb), .5); border-radius: 0 var(--r) var(--r) 0;
  background: rgba(var(--mint-rgb), .045);
}
.art__quote p { color: var(--ink); font-size: 1.0625rem; line-height: 1.95; }
.art__who { margin-top: 12px; font-size: .8125rem; color: var(--ink-3); }
.art__body h2 {
  margin-top: clamp(34px, 3.6vw, 52px);
  font-size: clamp(1.125rem, 1.7vw, 1.375rem); font-weight: 800;
  line-height: 1.5; letter-spacing: -.015em; color: var(--ink);
  padding-left: 14px; border-left: 3px solid var(--mint);
}
.art__body h2 + p { margin-top: 1.1em; }
.art__link {
  margin-top: clamp(26px, 3vw, 40px); padding-top: 20px; border-top: 1px solid var(--hair);
  font-size: .875rem; color: var(--ink-3);
}
.art__link a { color: var(--mint); word-break: break-all; }
.art__link a:hover { text-decoration: underline; }

.art__head { display: grid; gap: 16px; }
.art__title { font-size: clamp(1.75rem, 3.4vw, 2.75rem); font-weight: 800; line-height: 1.32; letter-spacing: -.02em; color: var(--ink); }
.art__deck { font-size: 1.0625rem; line-height: 1.85; color: var(--ink-2); max-width: 60ch; }

@media (max-width: 1000px) {
  .nw__grid { grid-template-columns: repeat(2, 1fr); }}
@media (max-width: 620px) {
  .nw__grid { grid-template-columns: 1fr; }}

/* ── pagination ──────────────────────────────────────────────────────────── */
/* real paged URLs rather than a JS toggle: each page is crawlable, linkable,
   and works with scripting off */
.pager {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: 8px; margin-top: clamp(28px, 3.2vw, 44px);
}
.pager__btn, .pager__num {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 38px; height: 38px; padding: 0 14px;
  border: 1px solid var(--hair); border-radius: var(--r-sm);
  font-size: .8125rem; color: var(--ink-2); background: var(--panel);
  transition: color .2s var(--ease), border-color .2s var(--ease), background .2s var(--ease);
}
a.pager__btn:hover, a.pager__num:hover { color: var(--ink); border-color: var(--hair-3); background: var(--card-hi); }
.pager__num.is-on {
  color: var(--mint); border-color: rgba(var(--mint-rgb), .4);
  background: rgba(var(--mint-rgb), .07); cursor: default;
}
.pager__btn.is-off { color: var(--ink-3); opacity: .45; cursor: default; }
.pager__sep { width: 6px; }

/* ───────────────────────────────── ABOUT ────────────────────────────────── */
.about { background: var(--bg); border-top: 1px solid var(--hair); }

/* ────────────────────────────────── CTA ─────────────────────────────────── */
.cta {
  position: relative; overflow: hidden;
  scroll-margin-top: calc(var(--anchor-y) - var(--cta-y));
  padding-block: var(--cta-y);
  border-top: 1px solid var(--hair);
  background:
    radial-gradient(90% 120% at 50% 0%, rgba(var(--blue-rgb), .13) 0%, transparent 58%),
    radial-gradient(60% 80% at 78% 110%, rgba(var(--mint-rgb), .08) 0%, transparent 60%),
    var(--surface);
  text-align: center;
}
.cta__grid {
  position: absolute; inset: 0;
  background-image:
    linear-gradient(to right, rgba(var(--steel-rgb), .05) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(var(--steel-rgb), .05) 1px, transparent 1px);
  background-size: 56px 56px;
  mask-image: radial-gradient(70% 70% at 50% 40%, #000, transparent 75%);
  -webkit-mask-image: radial-gradient(70% 70% at 50% 40%, #000, transparent 75%);
}
.cta__inner { position: relative; z-index: 1; }
.cta__title { font-size: clamp(2.1rem, 4.6vw, 3.75rem); letter-spacing: -.03em; }
.cta .lede { margin-inline: auto; }
.cta__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 14px; margin-top: 40px; }

/* ───────────────────────────────── FOOTER ───────────────────────────────── */
/* The footer is the last part of each page's last section, not a strip of its
   own: no ground, no top border — it sits on whatever that section draws
   (photo band, CTA glow, or the plain section ground). */
.foot { position: relative; z-index: 2; background: none; padding-top: clamp(40px, 5vw, 72px); text-align: left; }
/* plain sections and CTAs: the footer supplies the bottom padding */
.section.has-foot, .cta.has-foot { padding-bottom: 0; }
.section.has-foot > .foot, .cta.has-foot > .foot { margin-top: clamp(56px, 7vw, 110px); }
/* photo bands: the statement keeps the vertical centre, the footer takes the
   bottom edge over a rising shade; the photo is always dark, so the footer
   keeps its light inks and the on-dark logo in both themes */
.band.has-foot { flex-direction: column; align-items: stretch; }
.band.has-foot > .band__inner { flex: 1; align-content: center; }
.band.has-foot > .foot {
  padding-top: clamp(64px, 8vw, 120px);
  background: linear-gradient(180deg, rgba(4, 7, 12, 0) 0%, rgba(4, 7, 12, .62) 46%, rgba(4, 7, 12, .86) 100%);
  --hair: rgba(255, 255, 255, .16);
}
.band.has-foot .foot__bottom { color: rgba(255, 255, 255, .66); }
.band.has-foot .foot__icp a:hover { color: #fff; }
.band.has-foot .foot__brand img { content: url('../img/logos/qianshi-on-dark.png'); opacity: .95; }
.foot__inner {
  display: flex; justify-content: flex-end;
  padding-bottom: clamp(44px, 5vw, 64px);
}
.foot__brand { max-width: 46ch; text-align: right; }
.foot__brand img { height: 28px; width: auto; opacity: .85; margin-left: auto; }

.foot__bottom {
  /* copyright left, filing info right; both fall back to left once they wrap */
  display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline;
  gap: 10px 22px;
  padding-block: 24px;
  border-top: 1px solid var(--hair);
  font-size: .75rem; color: var(--ink-3); text-align: left;
}
.foot__icp { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px 18px; justify-content: flex-end; text-align: right; }
.foot__icp a { transition: color .2s; }
.foot__icp a:hover { color: var(--ink-2); }
/* the 公安备案 emblem is an official colour mark — never invert or tint it */
.foot__gov { display: inline-flex; align-items: center; gap: 6px; }
.foot__gov img { width: 18px; height: 20px; flex: none; }
@media (max-width: 620px) {
  /* stacked on phones — keep both lines on the same left edge */
  .foot__bottom { justify-content: flex-start; }
  .foot__icp { justify-content: flex-start; text-align: left; }}


.vcaps { display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(14px, 1.6vw, 22px); }
.vcap { padding: 26px 24px; border: 1px solid var(--hair); border-radius: var(--r-lg); background: var(--card); }
.vcap h3 { font-size: 1rem; font-weight: 700; color: var(--ink); }
.vcap p { margin-top: 10px; font-size: .8125rem; line-height: 1.75; color: var(--ink-3); }

/* ── vertical-agent stack (solutions) ───────────────────────────────────── */
.vstack { display: grid; gap: 0; }
.vlayer {
  display: grid; grid-template-columns: 210px minmax(0, 1fr);
  gap: clamp(18px, 2.6vw, 36px); align-items: center;
  padding: clamp(22px, 2.6vw, 30px) clamp(20px, 2.6vw, 32px);
  border: 1px solid var(--hair); border-radius: var(--r-lg); background: var(--panel);
}
.vlayer__side > .mono { display: block; color: var(--ink-3); font-size: .625rem; letter-spacing: .14em; }
.vlayer__side b { display: block; margin-top: 8px; font-size: 1.125rem; font-weight: 700; color: var(--ink); letter-spacing: -.015em; }

/* the industry layer is what the customer buys — give it the weight */
.vlayer--apps {
  border-color: rgba(var(--mint-rgb), .34);
  background: linear-gradient(120deg, rgba(var(--mint-rgb), .10), transparent 58%), var(--card-hi);
}
.vlayer--apps .vlayer__side > .mono { color: var(--mint); }
.vlayer--apps .vlayer__side b { font-size: 1.375rem; font-weight: 800; }
.vinds { display: grid; grid-template-columns: repeat(5, 1fr); gap: 1px; background: var(--hair); border: 1px solid var(--hair); border-radius: var(--r); overflow: hidden; }
.vinds li { padding: 16px 14px; background: rgba(18,27,39,.94); transition: background .3s var(--ease); }
.vinds li:hover { background: var(--card-hi); }
.vinds b { display: block; font-size: .9375rem; font-weight: 700; color: var(--ink); }
.vinds span { display: block; margin-top: 6px; font-size: .6875rem; line-height: 1.6; color: var(--ink-3); }
.vinds__more b { color: var(--steel-dim); }

.vlayer--os { border-color: rgba(var(--mint-rgb), .22); background: linear-gradient(100deg, rgba(var(--mint-rgb), .06), transparent 60%), var(--card); }
.vlayer--os .vlayer__side > .mono { color: var(--mint); }
.vcaps2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px 20px; }
.vcaps2 b { display: block; font-size: .875rem; font-weight: 700; color: var(--ink); }
.vcaps2 span { display: block; margin-top: 5px; font-size: .75rem; line-height: 1.65; color: var(--ink-3); }

.vhw { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px 20px; }
.vhw b { display: block; font-size: .875rem; font-weight: 700; color: var(--ink); }
.vhw span { display: block; margin-top: 5px; font-size: .75rem; line-height: 1.65; color: var(--ink-3); }

/* connector between layers */
.vflow { display: flex; justify-content: center; gap: 8px; padding: 10px 0; }
.vflow span { width: 5px; height: 5px; border-radius: 50%; background: var(--mint); opacity: .35; animation: vflow 1.8s ease-in-out infinite; }
.vflow span:nth-child(2) { animation-delay: .2s; }
.vflow span:nth-child(3) { animation-delay: .4s; }
@keyframes vflow { 0%,100% { opacity: .2; transform: translateY(-2px); } 50% { opacity: 1; transform: translateY(2px); } }


/* outbound link inside the workbench endpoints */
.wb__link-out { display: inline-flex; align-items: center; gap: 7px; margin-top: 14px; font-size: .75rem; font-weight: 600; color: var(--mint); }
.wb__link-out svg { width: 13px; height: 13px; transition: transform .3s var(--ease); }
.wb__link-out:hover svg { transform: translateX(3px); }

@media (max-width: 1000px) {
  .vlayer { grid-template-columns: 1fr; gap: 16px; }
  .vinds { grid-template-columns: repeat(2, 1fr); }
  .vcaps2, .vhw { grid-template-columns: 1fr; }}
@media (max-width: 560px) { .vinds { grid-template-columns: 1fr; }}

/* ═══════════════════════════ PRODUCTS PAGE ════════════════════════════════ */
.page-hero--lean { padding-block: calc(68px + clamp(56px, 6.5vw, 96px)) clamp(48px, 5.5vw, 78px); }
.prod--cloud { background: var(--surface); border-top: 1px solid var(--hair); }
.prod--local { background: var(--bg);      border-top: 1px solid var(--hair); }

.spec {
  display: grid; grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr);
  gap: clamp(28px, 4vw, 64px); align-items: center;
  padding: clamp(28px, 3.4vw, 44px);
  border: 1px solid var(--hair); border-radius: var(--r-lg);
  background: linear-gradient(150deg, rgba(var(--mint-rgb), .04), transparent 52%), var(--panel);
}
.spec + .spec { margin-top: clamp(18px, 2vw, 28px); }
.spec--flip .spec__shot { order: 2; }
.spec__shot { position: relative; display: grid; place-items: center; min-height: 180px; }
.spec__shot::after {
  content:''; position:absolute; left:50%; bottom:2%; width:80%; height:24%;
  transform: translateX(-50%);
  background: radial-gradient(closest-side, rgba(var(--mint-rgb), .15), transparent 74%);
  filter: blur(14px);
}
/* Appliance renders: keep the subtle floor light behind the chassis. */
.spec__shot--soft-light { isolation: isolate; }
.spec__shot--soft-light::after {
  z-index: 0; bottom: 0; height: 16%; opacity: .5;
  pointer-events: none;
}
.spec__shot--soft-light img { z-index: 1; }
/* the 1000 is a portrait tower render — cap the height so it does not
   tower over the landscape rack/chassis shots in the sibling blocks */
.spec__shot img { position: relative; max-width: 100%; max-height: clamp(220px, 26vw, 330px); width: auto; height: auto; }
.spec__name { font-size: clamp(1.375rem, 2.2vw, 1.875rem); font-weight: 800; letter-spacing: -.02em; color: var(--ink); }
.spec__name span { display: block; margin-top: 6px; font-size: .875rem; font-weight: 500; letter-spacing: 0; color: var(--steel-dim); }
.spec__lead { margin-top: 16px; font-size: .9375rem; line-height: 1.8; color: var(--ink-2); }

.feats { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; margin-top: 24px; }
.feats li { padding: 16px 18px; border: 1px solid var(--hair); border-radius: var(--r); background: rgba(var(--tint-rgb), .018); }
.feats b { display: block; font-size: .9375rem; font-weight: 700; color: var(--ink); }
.feats span { display: block; margin-top: 6px; font-size: .8125rem; line-height: 1.7; color: var(--ink-3); }

.hilite { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px; margin-top: 22px; background: var(--hair); border: 1px solid var(--hair); border-radius: var(--r); overflow: hidden; }
.hilite > div { padding: 18px; background: var(--card); }
.hilite b { display: block; font-size: 1.0625rem; font-weight: 800; letter-spacing: -.015em; color: var(--mint); }
.hilite span { display: block; margin-top: 6px; font-size: .8125rem; color: var(--ink-3); }

.twocol { display: grid; grid-template-columns: repeat(2, 1fr); gap: clamp(20px, 2.6vw, 40px); margin-top: 26px; }
.twocol h4 { color: var(--mint); opacity: .85; font-size: .625rem; margin-bottom: 12px; }
.twocol > :only-child { grid-column: 1 / -1; }   /* with the spec column gone, the capability list takes the row */
.ticks { display: grid; gap: 10px; }
.ticks li { position: relative; padding-left: 20px; font-size: .8125rem; line-height: 1.7; color: var(--ink-2); }
.ticks li::before {
  content:''; position:absolute; left:0; top:.42em; width:9px; height:5px;
  border-left: 1.5px solid var(--mint); border-bottom: 1.5px solid var(--mint);
  transform: rotate(-45deg);
}
.specs-dl { display: grid; gap: 0; }
.specs-dl > div { display: grid; grid-template-columns: 76px 1fr; gap: 12px; padding: 9px 0; border-bottom: 1px solid var(--hair); }
.specs-dl > div:first-child { border-top: 1px solid var(--hair); }
.specs-dl dt { font-size: .75rem; color: var(--ink-3); }
.specs-dl dd { font-size: .8125rem; color: var(--ink-2); font-weight: 500; }
.scenes { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 24px; }
.scenes li { padding: 5px 13px; border-radius: 999px; font-size: .75rem; color: var(--steel-dim); border: 1px solid var(--hair-2); }

.factory { margin-top: clamp(24px, 3vw, 40px); max-width: 68ch; }

.modes { display: grid; grid-template-columns: repeat(2, 1fr); gap: clamp(16px, 1.8vw, 24px); margin-top: clamp(18px, 2vw, 28px); }
.mode { padding: 28px; border: 1px solid var(--hair); border-radius: var(--r-lg); background: var(--panel); }
.mode--partner { border-color: rgba(138,130,255,.28); background: linear-gradient(150deg, rgba(120,130,255,.08), transparent 55%), var(--panel); }
.mode > .mono { color: var(--mint); font-size: .625rem; }
.mode--partner > .mono { color: #9aa2ff; }
.mode b { display: block; margin-top: 10px; font-size: 1.0625rem; font-weight: 700; color: var(--ink); }
.mode ul { margin-top: 16px; display: grid; gap: 9px; }
.mode li { position: relative; padding-left: 17px; font-size: .8125rem; color: var(--ink-2); }
.mode li::before { content:''; position:absolute; left:0; top:.62em; width:5px; height:5px; border-radius:1px; background: var(--mint); opacity:.65; transform: rotate(45deg); }
.mode--partner li::before { background: #9aa2ff; }
.modes__note { margin-top: 18px; text-align: center; font-size: .8125rem; color: var(--ink-3); }

/* ═══════════════════════════ SOLUTIONS PAGE ═══════════════════════════════ */
.sol--general  { background: var(--bg); }
.sol--vertical { background: var(--surface); border-top: 1px solid var(--hair); }
.sol--cases    { background: var(--bg);      border-top: 1px solid var(--hair); }

.scen { display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(14px, 1.6vw, 22px); }
.scen__item { padding: 26px 24px; border: 1px solid var(--hair); border-radius: var(--r-lg); background: linear-gradient(180deg, rgba(var(--tint-rgb), .022), transparent 42%), var(--card); transition: border-color .35s var(--ease), transform .35s var(--ease); }
.scen__item:hover { border-color: rgba(var(--mint-rgb), .3); transform: translateY(-3px); }
.scen__n { color: var(--mint); opacity: .8; font-size: .625rem; }
.scen__item h3 { margin-top: 10px; font-size: 1.0625rem; font-weight: 700; color: var(--ink); }
.scen__item p { margin-top: 10px; font-size: .8125rem; line-height: 1.75; color: var(--ink-3); }

/* workbench → compatible API → endpoints */
.wb {
  display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1.15fr);
  gap: clamp(16px, 2vw, 28px); align-items: center;
  margin-top: clamp(24px, 3vw, 40px); padding: clamp(24px, 3vw, 40px);
  border: 1px solid var(--hair); border-radius: var(--r-lg); background: var(--panel);
}
.wb__bench { padding: 26px; border: 1px solid rgba(var(--mint-rgb), .22); border-radius: var(--r); background: linear-gradient(160deg, rgba(var(--mint-rgb), .06), transparent 55%), var(--card); }
.wb__bench h3 { font-size: 1.125rem; font-weight: 700; color: var(--mint); }
.wb__bench > p { margin-top: 8px; font-size: .8125rem; color: var(--ink-3); }
.wb__apps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-top: 20px; }
.wb__apps li { padding: 10px 6px; text-align: center; border: 1px solid rgba(var(--mint-rgb), .26); border-radius: var(--r-sm); font-size: .75rem; font-weight: 600; color: var(--ink-2); background: rgba(var(--tint-rgb), .02); }
.wb__link { display: grid; justify-items: center; gap: 8px; color: var(--mint); }
.wb__link .mono { font-size: .5625rem; color: var(--steel-dim); white-space: nowrap; }
.wb__link svg { width: 56px; height: 16px; }
.wb__ends { display: grid; gap: 14px; }
.wb__end { padding: 22px; border-radius: var(--r); border: 1px solid var(--hair-2); background: var(--card); }
.wb__end--cloud { border-style: dashed; border-color: rgba(154,162,255,.42); }
.wb__end--local { border-color: rgba(var(--mint-rgb), .3); background: linear-gradient(150deg, rgba(var(--mint-rgb), .05), transparent 60%), var(--card); }
.wb__end > .mono { font-size: .625rem; color: var(--mint); }
.wb__end--cloud > .mono { color: #9aa2ff; }
.wb__end b { display: block; margin-top: 8px; font-size: 1.0625rem; font-weight: 700; color: var(--ink); }
.wb__end > p { margin-top: 8px; font-size: .75rem; line-height: 1.7; color: var(--ink-3); }
.wb__chain { display: grid; grid-template-columns: 1fr auto 1fr; gap: 10px; align-items: center; margin-top: 16px; }
.wb__box { padding: 12px; border: 1px solid var(--hair-2); border-radius: var(--r-sm); background: rgba(var(--tint-rgb), .02); }
.wb__box b { margin-top: 0; font-size: .8125rem; }
.wb__box span { display: block; margin-top: 5px; font-size: .6875rem; color: var(--ink-3); }
.wb__arrow { width: 34px; height: 12px; color: var(--mint); }

.cases { display: grid; grid-template-columns: repeat(2, 1fr); gap: clamp(16px, 1.8vw, 24px); }
.case { padding: 30px; border: 1px solid var(--hair); border-radius: var(--r-lg); background: linear-gradient(180deg, rgba(var(--tint-rgb), .022), transparent 40%), var(--card); transition: border-color .35s var(--ease), transform .35s var(--ease); }
.case:hover { border-color: var(--hair-2); transform: translateY(-3px); }
.case__top { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 18px; }
.case h3 { font-size: 1.25rem; font-weight: 700; letter-spacing: -.015em; color: var(--ink); }
.case > p { margin-top: 12px; font-size: .875rem; line-height: 1.8; color: var(--ink-3); }
.case__list { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--hair); display: grid; gap: 9px; }
.case__list li { position: relative; padding-left: 17px; font-size: .8125rem; color: var(--ink-2); }
.case__list li::before { content:''; position:absolute; left:0; top:.62em; width:5px; height:5px; border-radius:1px; background: var(--mint); opacity:.7; transform: rotate(45deg); }

@media (max-width: 1100px) {
  .spec { grid-template-columns: 1fr; }
  .spec--flip .spec__shot { order: 0; }
  .scen, .vcaps { grid-template-columns: repeat(2, 1fr); }
  .wb { grid-template-columns: 1fr; }
  .wb__link { flex-direction: row; }
  .wb__link svg { transform: rotate(90deg); }}
@media (max-width: 720px) {
  .feats, .twocol, .hilite, .modes,  .scen, .vcaps, .cases { grid-template-columns: 1fr; }
  .wb__apps { grid-template-columns: repeat(2, 1fr); }
  .wb__chain { grid-template-columns: 1fr; }
  .wb__arrow { transform: rotate(90deg); justify-self: center; }}

.ilink { color: var(--mint); border-bottom: 1px solid rgba(var(--mint-rgb), .35); transition: border-color .2s; }
.ilink:hover { border-bottom-color: var(--mint); }

/* ── product family hub cards (products.html) ───────────────────────────── */
.fam { background: var(--bg); }
/* full-width rows rather than three narrow columns: each product gets a large
   photo and room to breathe, and the image side alternates so the three read
   as a sequence instead of a table */
.fam__list { display: grid; gap: clamp(18px, 2vw, 30px); }
.fam__card {
  display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: clamp(26px, 4vw, 72px); align-items: center;
  padding: clamp(26px, 3vw, 46px);
  border: 1px solid var(--hair); border-radius: var(--r-lg); background: var(--card);
  color: inherit; text-decoration: none;
  transition: border-color .3s var(--ease), transform .3s var(--ease), box-shadow .3s var(--ease);
}
.fam__card:nth-child(even) .fam__shot { order: 2; }
.fam__body { display: grid; justify-items: start; }
.fam__card:hover { border-color: rgba(var(--mint-rgb), .32); transform: translateY(-4px); box-shadow: 0 26px 60px -42px rgba(var(--shadow-rgb), .95); }
.fam__card h3 { margin-top: 16px; font-size: clamp(1.75rem, 2.6vw, 2.5rem); font-weight: 800; letter-spacing: -.025em; color: var(--ink); }
.fam__sub { margin-top: 8px; font-size: .9375rem; color: var(--ink-3); }
.fam__shot { position: relative; display: grid; place-items: center; height: clamp(200px, 22vw, 320px); margin: 0; }
.fam__shot::after {
  content:''; position:absolute; left:50%; bottom:4%; width:74%; height:24%; z-index:0;
  transform: translateX(-50%);
  background: radial-gradient(closest-side, rgba(var(--mint-rgb), .16), transparent 74%);
  filter: blur(12px);
}
.fam__shot img { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; object-fit: contain; }
.fam__models { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 20px; }
.fam__models li {
  padding: 5px 12px; border-radius: 999px; font-size: .75rem; font-weight: 600; color: var(--mint);
  border: 1px solid rgba(var(--mint-rgb), .28); background: rgba(var(--mint-rgb), .06);
}
.fam__desc { margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--hair); font-size: .875rem; line-height: 1.85; color: var(--ink-3); max-width: 46ch; }
.fam__go { display: inline-flex; align-items: center; gap: 8px; margin-top: 24px; font-size: .875rem; font-weight: 600; color: var(--ink); }
.fam__go svg { width: 14px; height: 14px; color: var(--mint); transition: transform .3s var(--ease); }
.fam__card:hover .fam__go svg { transform: translateX(4px); }

/* ── layered stack diagram (supernode / cloud / appliance) ──────────────── */
.arch { background: var(--surface); border-top: 1px solid var(--hair); }
.stack { display: grid; gap: 8px; }
.stack__row {
  display: grid; grid-template-columns: 110px minmax(0, 1fr);
  align-items: center; gap: clamp(14px, 2.4vw, 30px);
  padding: 20px clamp(18px, 2.4vw, 28px);
  border: 1px solid var(--hair); border-radius: var(--r); background: var(--panel);
}
.stack__row > .mono { color: var(--ink-3); font-size: .625rem; letter-spacing: .14em; }
.stack__row b { font-size: .9375rem; font-weight: 600; color: var(--ink-2); }
.stack__row small { display: block; margin-top: 6px; font-size: .75rem; color: var(--ink-3); }
.stack__row--rt, .stack__row--hw,
.stack--lit .stack__row { border-color: rgba(var(--mint-rgb), .28); background: linear-gradient(100deg, rgba(var(--mint-rgb), .07), transparent 62%), var(--card); }
.stack__row--rt > .mono, .stack__row--hw > .mono,
.stack--lit .stack__row > .mono { color: var(--mint); }
.stack__row--rt b, .stack__row--hw b,
.stack--lit .stack__row b { color: var(--ink); }

.axes { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(14px, 1.6vw, 22px); margin-top: clamp(16px, 1.8vw, 24px); }
/* the layer diagram and its three axes read as one figure side by side */
.arch2 { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: clamp(20px, 2.6vw, 40px); align-items: stretch; }
.arch2 .axes { grid-template-columns: 1fr; margin-top: 0; }
/* the two columns are one figure, so let the shorter one grow to match rather
   than leaving a ragged 90px gap under the diagram */
.arch2 .stack { align-content: stretch; }
.arch2 .stack__row { align-content: center; }
@media (max-width: 1000px) {
  .arch2 { grid-template-columns: 1fr; }
  .arch2 .axes { grid-template-columns: repeat(3, 1fr); margin-top: clamp(16px, 1.8vw, 24px); }}
.axis { padding: 24px; border: 1px solid var(--hair); border-radius: var(--r-lg); background: var(--card); }
.axis b { display: block; font-size: 1rem; font-weight: 700; color: var(--ink); }
.axis p { margin-top: 10px; font-size: .8125rem; line-height: 1.75; color: var(--ink-3); }
.axis--os { border-color: rgba(var(--mint-rgb), .26); background: linear-gradient(150deg, rgba(var(--mint-rgb), .06), transparent 58%), var(--card); }
.axis--os b { color: var(--mint); }

@media (max-width: 940px) {
  /* stack the row: photo on top, copy below, and drop the zigzag */
  .fam__card { grid-template-columns: 1fr; gap: 22px; }
  .fam__card:nth-child(even) .fam__shot { order: 0; }
  .axes { grid-template-columns: 1fr; }}
@media (max-width: 620px) { .stack__row { grid-template-columns: 1fr; gap: 10px; }}


/* ═══════════════════ HERO STAGES (per-page 3-D visuals) ═══════════════════
   All five share the .stage3d perspective rig defined with the about-page
   dial; only the layer geometry differs, so the pages read as one family. */
.stage3d__layer svg * { vector-effect: non-scaling-stroke; }

/* ── supernode: stacked GPU lattice planes ──────────────────────────────── */
.sn-mesh line { stroke: currentColor; stroke-width: 1; opacity: .16; }
.sn-die rect  { fill: currentColor; opacity: .34; }
.sn-die--hot rect:nth-child(4n) { opacity: .95; }
.sn-ring { stroke: currentColor; stroke-width: 1.6; opacity: .5; animation: spin 44s linear infinite; transform-origin: 260px 260px; stroke-dasharray: 120 40; }
.sn-ring--in { stroke-width: 2.2; opacity: .85; animation-duration: 26s; animation-direction: reverse; stroke-dasharray: 74 30; }
.sn-core { fill: currentColor; stroke: none; filter: drop-shadow(0 0 12px rgba(var(--mint-rgb), .95)); }
@keyframes spin { to { transform: rotate(360deg); } }

/* ── cloud: a mass of nodes with token pills streaming out of the hub ───── */
.cl-p { fill: currentColor; stroke: none; opacity: .5; }
.cl-tok {
  fill: currentColor; stroke: none; opacity: 0;
  transform-box: fill-box; transform-origin: center;
  filter: drop-shadow(0 0 6px rgba(var(--mint-rgb), .8));
  animation: tokOut 2.8s ease-out infinite;
}
.cl-tok--1 { animation-delay: .7s; }
.cl-tok--2 { animation-delay: 1.4s; }
.cl-tok--3 { animation-delay: 2.1s; }
/* each pill already carries rotate() aiming it outward, so translating along
   its own local X is radial by construction */
@keyframes tokOut {
  0%   { opacity: 0; translate: -30px 0; }
  25%  { opacity: 1; }
  100% { opacity: 0; translate: 60px 0; }
}
.cl-hub { fill: rgba(var(--mint-rgb), .18); stroke: currentColor; stroke-width: 2.6; }
.cl-hub-t { fill: #eef3f9; font-family: var(--mono); font-size: 22px; font-weight: 600; letter-spacing: 2.5px; }
.cl-pulse { fill: none; stroke: currentColor; stroke-width: 1.6; transform-origin: 260px 260px; animation: hpulse 3.2s ease-out infinite; }
@keyframes hpulse { 0%{transform:scale(.5);opacity:.8} 70%,100%{transform:scale(1.9);opacity:0} }

/* ── appliance: the compute field (canvas, main.js apfield) ─────────────── */
/* An isometric floor of compute tiles breathing with load, beams rising from
   the busy ones, a horizon with output flowing along it — the Token-factory
   study's "算力场", moved here. Wider than the square stages, so it gets its
   own box; the shared radial mask still feathers its edge. */

/* ── recruiting: a crowd of wireframe figures, upright, in depth ─────────── */
/* This stage is not tilted: the deck lies flat and does not drift, the four
   layers stand upright at their own depth (the viz box's perspective scales
   the far ones down), and each layer floats gently on its own period. Quiet
   figures are steel outlines; the three in front are mint and lit. No links
   between them — the depth and the lighting carry the picture. */
.stage3d--rc .stage3d__deck { transform: none; animation: none; }
.stage3d--rc .stage3d__layer { transform: translateZ(var(--z)); animation: rcFloat 11s ease-in-out infinite alternate; }
.stage3d--rc .stage3d__layer:nth-child(2) { animation-duration: 14s; animation-delay: -5s; }
.stage3d--rc .stage3d__layer:nth-child(3) { animation-duration: 9s;  animation-delay: -2s; }
.stage3d--rc .stage3d__layer:nth-child(4) { animation-duration: 12s; animation-delay: -7s; }
@keyframes rcFloat { from { transform: translateZ(var(--z)) translateY(-6px); } to { transform: translateZ(var(--z)) translateY(6px); } }
/* a soft pool of light on the ground under the crowd instead of the disc behind a dial */
.stage3d--rc .stage3d__floor { top: 68%; width: 90%; transform: translate(-50%, -50%) translateZ(-300px) scaleY(.38); }
.stage3d--rc { color: var(--steel); }
.rc-fig { fill: none; stroke: var(--steel); stroke-width: 1.4; stroke-linecap: round; opacity: .72; }
.rc-fig--lit {
  stroke: var(--mint); stroke-width: 1.7; opacity: 1;
  filter: drop-shadow(0 0 7px rgba(var(--mint-rgb), .55));
  animation: rcBreathe 4.2s ease-in-out infinite;
}
.rc-fig--lit circle { fill: rgba(var(--mint-rgb), .16); }
.rc-fig--lit:nth-of-type(2) { animation-delay: -1.4s; }
.rc-fig--lit:nth-of-type(3) { animation-delay: -2.8s; }
@keyframes rcBreathe { 0%, 100% { opacity: .78; } 50% { opacity: 1; } }
/* the lean hero is shorter than the 780px stage, so the crowd sits higher and a
   little smaller here; on phones it is the page's one idea, so it is dimmed less */
@media (min-width: 1020px) { .page-hero__viz.stage3d--rc { top: 46%; width: min(780px, 58vw); } }
@media (max-width: 1019px) { .page-hero__viz.stage3d--rc { opacity: .62; top: 6%; } }
@media (prefers-reduced-motion: reduce) { .rc-fig--lit, .stage3d--rc .stage3d__layer { animation: none; } }

/* ── products: one base plate, three solid forms rising ─────────────────── */
.pr-plate { fill: rgba(var(--mint-rgb), .05); stroke: currentColor; stroke-width: 1.4; opacity: .5; }
.pr-form  { fill: rgba(var(--mint-rgb), .12); stroke: currentColor; stroke-width: 1.8; opacity: .85; }
.pr-base  { fill: rgba(var(--mint-rgb), .16); stroke: currentColor; stroke-width: 2.4; }
.pr-pulse { fill: none; stroke: currentColor; stroke-width: 1.4; transform-origin: 260px 260px; animation: hpulse 3.8s ease-out infinite; }
.pr-core  { fill: currentColor; stroke: none; filter: drop-shadow(0 0 14px rgba(var(--mint-rgb), .95)); }

/* ── solutions: agent task graph ────────────────────────────────────────── */
.so-edge line { stroke: currentColor; stroke-width: 2; opacity: .38; }
.so-node { fill: currentColor; stroke: none; opacity: .85; }


/* ═══════════════════════════ RECRUITING PAGE ══════════════════════════════ */
.roles { background: var(--bg); }
/* vertical directory — the auto-fit row read as a button bar, not a contents list */
.roles__nav { border-top: 1px solid var(--hair); }
.roles__nav li { border-bottom: 1px solid var(--hair); }
.roles__nav a {
  display: grid; grid-template-columns: 44px minmax(0, 20rem) minmax(0, 1fr) 20px;
  align-items: center; gap: clamp(14px, 2.4vw, 32px);
  padding: 22px 8px;
  transition: background .28s var(--ease), padding-left .28s var(--ease);
}
.roles__nav a:hover { background: rgba(var(--mint-rgb), .05); padding-left: 18px; }
.roles__n { color: var(--mint); opacity: .7; font-size: .625rem; }
.roles__t { font-size: 1.0625rem; font-weight: 700; color: var(--ink); letter-spacing: -.01em; }
.roles__d { font-size: .8125rem; line-height: 1.7; color: var(--ink-3); }
.roles__nav svg { width: 16px; height: 16px; color: var(--mint); opacity: .55; justify-self: end; transition: transform .28s var(--ease), opacity .28s var(--ease); }
.roles__nav a:hover svg { transform: translateX(4px); opacity: 1; }
.roles__nav a:hover .roles__t { color: var(--mint); }
@media (max-width: 820px) {
  .roles__nav a { grid-template-columns: 34px minmax(0, 1fr) 18px; gap: 12px; padding: 18px 6px; }
  .roles__d { grid-column: 2; margin-top: 4px; }
  .roles__nav a { row-gap: 0; }}
.roles__mail { margin-top: 20px; font-size: .875rem; color: var(--ink-3); }
.roles__mail a { color: var(--mint); border-bottom: 1px solid rgba(var(--mint-rgb), .35); }
.roles__mail a:hover { border-bottom-color: var(--mint); }

.job { border-top: 1px solid var(--hair); }
.job:nth-of-type(odd)  { background: var(--surface); }
.job:nth-of-type(even) { background: var(--bg); }
.job__head { margin-bottom: clamp(28px, 3.4vw, 44px); }
.job__tag { margin-top: 12px; font-size: 1rem; font-weight: 600; color: var(--mint); }
.job__body { display: grid; grid-template-columns: repeat(2, 1fr); gap: clamp(22px, 3vw, 44px); align-items: start; }
.job__block { padding: 26px 28px; border: 1px solid var(--hair); border-radius: var(--r-lg); background: var(--card); }
.job__h { font-size: .9375rem; font-weight: 700; color: var(--ink); margin-bottom: 16px; }
.job__list { display: grid; gap: 11px; }
.job__list li { position: relative; padding-left: 18px; font-size: .875rem; line-height: 1.8; color: var(--ink-2); }
.job__list li::before {
  content:''; position:absolute; left:0; top:.72em; width:5px; height:5px;
  border-radius:1px; background: var(--mint); opacity:.65; transform: rotate(45deg);
}
.job__list--plus li::before { background: var(--steel-dim); }
.job__apply { margin-top: clamp(20px, 2.4vw, 30px); font-size: .875rem; color: var(--ink-3); }
.job__apply a { color: var(--mint); border-bottom: 1px solid rgba(var(--mint-rgb), .35); }
.job__apply a:hover { border-bottom-color: var(--mint); }

@media (max-width: 860px) { .job__body { grid-template-columns: 1fr; }}


/* ── job drawer ─────────────────────────────────────────────────────────── */
/* .has-jd is set by jobs.js, so without JS the sections stay tiled and readable */
.has-jd .job { display: none; }
.has-jd .roles__nav a[aria-current="true"] { background: rgba(var(--mint-rgb), .08); }
.has-jd .roles__nav a[aria-current="true"] .roles__t { color: var(--mint); }

.jd {
  position: fixed; right: clamp(16px, 2.4vw, 32px); bottom: clamp(16px, 2.4vw, 32px);
  z-index: 120; width: min(440px, calc(100vw - 32px)); max-height: min(76vh, 720px);
  display: flex; flex-direction: column;
  border: 1px solid rgba(var(--steel-rgb), .22); border-radius: var(--r-lg);
  background: linear-gradient(180deg, rgba(32,46,62,.98), rgba(19,28,39,.98));
  backdrop-filter: saturate(160%) blur(18px);
  -webkit-backdrop-filter: saturate(160%) blur(18px);
  box-shadow: 0 40px 90px -30px rgba(var(--shadow-rgb), .92), 0 1px 0 rgba(var(--tint-rgb), .06) inset;
  opacity: 0; transform: translateY(14px) scale(.985);
  transition: opacity .26s var(--ease), transform .26s var(--ease);
}
.jd.is-open { opacity: 1; transform: none; }

.jd__bar {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  padding: 20px 20px 16px; border-bottom: 1px solid var(--hair);
}
.jd__t { font-size: 1.0625rem; font-weight: 700; color: var(--ink); letter-spacing: -.01em; }
.jd__tag { margin-top: 6px; font-size: .75rem; line-height: 1.55; color: var(--mint); }
.jd__x {
  flex: none; width: 30px; height: 30px; display: grid; place-items: center;
  border-radius: var(--r-sm); color: var(--ink-3);
  transition: background .2s var(--ease), color .2s var(--ease);
}
.jd__x svg { width: 15px; height: 15px; }
.jd__x:hover { background: rgba(var(--tint-rgb), .06); color: var(--ink); }

.jd__body { overflow-y: auto; padding: 18px 20px 4px; overscroll-behavior: contain; }
.jd__lede { font-size: .8125rem; line-height: 1.8; color: var(--ink-2); margin-bottom: 18px; }
/* the cloned blocks arrive with .job__block — flatten them inside the panel */
.jd__body .job__block { padding: 0; border: 0; background: none; margin-bottom: 20px; }
.jd__body .job__h { font-size: .8125rem; margin-bottom: 10px; }
.jd__body .job__list { gap: 9px; }
.jd__body .job__list li { font-size: .8125rem; line-height: 1.75; }

.jd__foot {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 16px 20px; border-top: 1px solid var(--hair);
}
.jd__apply { height: 40px; padding-inline: 20px; font-size: .875rem; }
.jd__mail { color: var(--ink-3); font-size: .5625rem; }

@media (max-width: 620px) {
  .jd { right: 0; bottom: 0; left: 0; width: auto; max-height: 82vh;
        border-radius: var(--r-lg) var(--r-lg) 0 0; border-bottom: 0; }
  .jd__foot { flex-direction: column; align-items: stretch; }
  .jd__apply { justify-content: center; }
  .jd__mail { text-align: center; }}
.jd__mail { text-transform: none; }   /* .mono uppercases; an address is case-sensitive to the eye */
@media (prefers-reduced-motion: reduce) { .jd { transition: none; }}


/* ═══════════════════════════════ ABOUT PAGE ═══════════════════════════════ */
.page-hero {
  position: relative; overflow: hidden;
  padding: calc(68px + clamp(72px, 9vw, 132px)) 0 clamp(64px, 8vw, 110px);
  border-bottom: 1px solid var(--hair);
  background:
    radial-gradient(90% 120% at 22% 0%, rgba(var(--blue-rgb), .14) 0%, transparent 58%),
    radial-gradient(60% 90% at 88% 30%, rgba(var(--mint-rgb), .08) 0%, transparent 62%),
    linear-gradient(180deg, #060a10, var(--surface));
}
.page-hero__grid {
  position: absolute; inset: 0;
  background-image:
    linear-gradient(to right, rgba(var(--steel-rgb), .045) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(var(--steel-rgb), .045) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(100% 80% at 30% 30%, #000 10%, transparent 76%);
  -webkit-mask-image: radial-gradient(100% 80% at 30% 30%, #000 10%, transparent 76%);
}
.page-hero__inner { position: relative; z-index: 2; max-width: var(--maxw); }
@media (min-width: 1020px) {
  .page-hero__inner > * { max-width: 58%; }}

/* ── instrument dial (3-D stage) ────────────────────────────────────────── */
.page-hero__viz {
  position: absolute; z-index: 1; pointer-events: none;
  top: 50%; right: calc(3% + 100px);
  width: min(780px, 60vw); aspect-ratio: 1;
  transform: translateY(-50%);
  color: var(--mint);
  perspective: 1400px;
  perspective-origin: 50% 42%;
  /* feathered edge — the dial now reaches into the headline column, so it has
     to dissolve rather than stop. Applied here, not on .dial3d, so the inner
     preserve-3d stage is not flattened. */
  mask-image: radial-gradient(closest-side, #000 40%, rgba(var(--shadow-rgb), .5) 70%, transparent 100%);
  -webkit-mask-image: radial-gradient(closest-side, #000 40%, rgba(var(--shadow-rgb), .5) 70%, transparent 100%);
}
/* the appliance field is a canvas in the same slot: wider box, lower, no tilt */
.page-hero__viz--field { width: min(760px, 54vw); aspect-ratio: 9 / 5; top: 60%; right: calc(3% + 60px); display: block; }
@media (max-width: 1019px) {
  .page-hero__viz--field { width: 130vw; right: -26%; top: 0; transform: none; aspect-ratio: 9 / 5; opacity: .5; }
}
/* the stage is tilted, so the rings read as discs stacked in space */
.dial3d, .stage3d__deck {
  position: absolute; inset: 0;
  transform-style: preserve-3d;
  transform: rotateX(58deg) rotateZ(-16deg);
  animation: dialDrift 26s ease-in-out infinite alternate;
}
@keyframes dialDrift {
  from { transform: rotateX(58deg) rotateZ(-16deg); }
  to   { transform: rotateX(50deg) rotateZ(6deg); }
}
.dial3d__layer, .stage3d__layer {
  position: absolute; inset: 0;
  transform: translateZ(var(--z));
  filter: blur(var(--blur));
  opacity: var(--op);
}
.dial3d__layer svg, .stage3d__layer svg { width: 100%; height: 100%; overflow: visible; fill: none; stroke: currentColor; }

.dl-tick { opacity: .5; }
.dl-hair { opacity: .16; stroke-width: 1; }
.dl-arc  { opacity: .62; }
.dl-arc--hot { opacity: 1; filter: drop-shadow(0 0 7px rgba(var(--mint-rgb), .75)); }
.dl-sat {
  fill: var(--mint); stroke: none;
  filter: drop-shadow(0 0 8px rgba(var(--mint-rgb), .95));
}
.dl-sat--sm { opacity: .75; }
.dl-core {
  fill: var(--mint); stroke: none;
  filter: drop-shadow(0 0 14px rgba(var(--mint-rgb), 1));
}
.dl-pulse {
  stroke: var(--mint); stroke-width: 1.2;
  transform-origin: 260px 260px;
  animation: dialPulse 3.6s ease-out infinite;
}
@keyframes dialPulse {
  0%   { transform: scale(.4); opacity: .85; }
  70%,
  100% { transform: scale(3);  opacity: 0; }
}

/* each ring turns at its own rate and direction — the offsets are what make
   it read as an instrument rather than a spinner */
.spin-a, .spin-b, .spin-c, .spin-d, .spin-e, .spin-f, .spin-g { transform-origin: 260px 260px; }
.spin-a { animation: dialSpin 150s linear infinite; }
.spin-b { animation: dialSpin  72s linear infinite reverse; }
.spin-c { animation: dialSpin  96s linear infinite; }
.spin-d { animation: dialSpin  26s linear infinite reverse; }
.spin-e { animation: dialSpin  19s linear infinite; }
.spin-f { animation: dialSpin  40s linear infinite reverse; }
.spin-g { animation: dialSpin  13s linear infinite; }
@keyframes dialSpin { to { transform: rotate(360deg); } }

/* pool of light on the stage floor — sells the tilt */
.dial3d__shadow, .stage3d__floor {
  position: absolute; left: 50%; top: 50%;
  width: 76%; aspect-ratio: 1;
  transform: translate(-50%, -50%) translateZ(-190px);
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(var(--mint-rgb), .16), rgba(var(--blue-rgb), .06) 55%, transparent 78%);
  filter: blur(18px);
}
/* vertical column through the core */
.dial3d__beam, .stage3d__beam {
  position: absolute; left: 50%; top: 50%;
  width: 2px; height: 86%;
  transform: translate(-50%, -50%);
  background: linear-gradient(to bottom, transparent, rgba(var(--mint-rgb), .34) 48%, transparent);
  filter: blur(1.5px);
  animation: dialBeam 5.5s ease-in-out infinite;
}
@keyframes dialBeam { 0%,100% { opacity: .35; } 50% { opacity: .85; } }

@media (max-width: 1019px) {
  /* behind the copy on narrow screens, dialled right back */
  .page-hero__viz {
    top: 2%; right: -20%; width: 118vw; transform: none; opacity: .42;
  }}
.crumb { display: flex; align-items: center; gap: 10px; color: var(--ink-3); margin-bottom: 24px; }
.crumb a { color: var(--steel-dim); transition: color .2s; }
.crumb a:hover { color: var(--mint); }
.crumb span { opacity: .45; }
.page-hero__title {
  font-size: clamp(2.4rem, 5.4vw, 4.4rem);
  font-weight: 800; line-height: 1.1; letter-spacing: -.03em; color: var(--ink);
}
.page-hero__lede { margin-top: 24px; max-width: 56ch; font-size: 1.0625rem; line-height: 1.8; color: var(--ink-2); }
/* Sized rather than transform-scaled. Two reasons: the figure carries .reveal
   and `.reveal.in { transform: none }` (0,2,0) silently wipes any transform put
   there; and a real width lets the layout account for the height, so the plate
   cannot ride up over the section heading. */
.ab-geo__plate { position: relative; width: 98%; margin-inline: auto; }
@keyframes geoFlow { to { stroke-dashoffset: -16; } }
@keyframes geoPulse { 0%,100% { opacity: .5; transform: scale(.86); } 50% { opacity: 1; transform: scale(1.12); } }


/* ── about page runs a tighter rhythm than the homepage ─────────────────────
   The homepage earns its air from full-bleed visuals between sections; this
   page is mostly text-and-card blocks, so the same spacing reads as loose. */
.page-about {
  --sec-y: clamp(56px, 6.2vw, 96px);
}
.page-about .sec-head { margin-bottom: clamp(30px, 3.4vw, 46px); }
.page-about .lede { margin-top: 16px; }
.page-about .page-hero {
  padding: calc(68px + clamp(56px, 6.5vw, 96px)) 0 clamp(48px, 5.5vw, 78px);
}
.page-about .page-hero__lede { margin-top: 20px; }
.page-about.page-about .cta { padding-block: clamp(64px, 7vw, 104px); }

@media (max-width: 920px) {
  .nav__links { display: none; }
  /* collapse to brand | actions once the centre column is empty */
  .nav__inner { grid-template-columns: auto 1fr; }
  .nav__actions { grid-column: 2; }
  .nav__toggle { display: flex; }
  .card { min-height: 0; }

  .eco__logos { grid-template-columns: repeat(2, 1fr); }}

@media (max-width: 620px) {
  body { font-size: 15px; }
  .nav__aux { display: none; }   /* the mobile menu already carries it */
  .nav__inner { gap: 16px; }
  .nav__brand img { height: 22px; }
  .hero { padding-top: 96px; }
  /* on phones the fabric sits behind the whole column, so lift the mask */
  .hero__canvas {
    mask-image: radial-gradient(120% 62% at 60% 34%, #000 10%, transparent 82%);
    -webkit-mask-image: radial-gradient(120% 62% at 60% 34%, #000 10%, transparent 82%);
  }
  /* 3rem × 8 字 = 384px, wider than a phone — scale with the viewport so
     「让万亿参数大模型」 stays on one line and the <br> keeps the break */
  .hero__title { font-size: clamp(1.95rem, 9.3vw, 2.65rem); letter-spacing: -.025em; }
  .hero__cta .btn { flex: 1 1 100%; }
  .cta__actions .btn { flex: 1 1 100%; }}

/* ────────────────────────────── REDUCED MOTION ──────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .reveal { opacity: 1; transform: none; }
  .hero__scanline { display: none; }}