/* ==========================================================================
   GPTECH — 吉派环境技术(浙江)有限公司
   Global stylesheet.  Brand indigo #313D95 sampled from the official logo.
   Drop Barlow / Archivo webfonts into assets/fonts and fill the @font-face
   block below to match the original comps exactly; the stack degrades
   gracefully to system faces until then.
   ========================================================================== */

/* ---------- tokens ---------- */
:root{
  /* brand */
  --brand:#313d95;            /* logo indigo */
  --brand-700:#28327c;
  --brand-500:#3f4db2;
  --blue:#1e5fd6;             /* action blue */
  --blue-600:#1a52ba;
  --blue-400:#4c8cf5;
  --cyan:#35c3f3;             /* telemetry / tech accent */

  /* neutrals */
  --ink-900:#050b1a;
  --ink-800:#0a1631;
  --ink-700:#10203f;
  --ink-600:#1b2c4f;
  --slate-700:#334155;
  --slate-500:#64748b;
  --slate-400:#94a3b8;
  --line:#e3e8ef;
  --line-soft:#eef1f6;
  --paper:#f4f6fa;
  --paper-2:#eaeef5;
  --white:#fff;

  /* type */
  --font:-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue",Helvetica,Arial,
         "PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",sans-serif;
  --font-display:var(--font);
  --font-mono:"SFMono-Regular",Consolas,"Liberation Mono",Menlo,monospace;

  /* metrics */
  --wrap:1240px;
  --gut:32px;
  --r-sm:4px;
  --r:8px;
  --r-lg:14px;
  --header-h:72px;
  --shadow-sm:0 1px 2px rgba(10,22,49,.06),0 2px 8px rgba(10,22,49,.05);
  --shadow:0 4px 14px rgba(10,22,49,.08),0 12px 32px rgba(10,22,49,.07);
  --shadow-lg:0 18px 48px rgba(10,22,49,.14);
  --ease:cubic-bezier(.22,.61,.36,1);

  /* arrow glyph reused as a CSS mask so it can inherit colour and animate
     without another inline SVG in the markup */
  --arrow:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12h15'/%3E%3Cpath d='m13 6 6 6-6 6'/%3E%3C/svg%3E");
}

/* ---------- reset ---------- */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{
  margin:0;background:var(--white);color:var(--ink-800);
  font-family:var(--font);font-size:16px;line-height:1.65;
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
  overflow-x:hidden;
}
img,svg,video{max-width:100%;height:auto;display:block}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
input,textarea,select{font:inherit;color:inherit}
h1,h2,h3,h4,h5,p,figure,ul,ol{margin:0}
ul,ol{padding:0;list-style:none}
table{border-collapse:collapse;width:100%}
:focus-visible{outline:2px solid var(--blue);outline-offset:3px;border-radius:2px}
::selection{background:var(--brand);color:#fff}

/* ---------- layout ---------- */
.wrap{width:100%;max-width:var(--wrap);margin-inline:auto;padding-inline:var(--gut)}
.wrap-wide{width:100%;max-width:1480px;margin-inline:auto;padding-inline:var(--gut)}
.sec{padding-block:84px}
.sec-sm{padding-block:60px}
.sec-tight{padding-block:56px}
.bg-paper{background:var(--paper)}
.bg-ink{background:var(--ink-800);color:#fff}
.grid{display:grid;gap:24px}
.center{text-align:center}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}
.skip{position:absolute;left:16px;top:-60px;z-index:200;background:var(--blue);color:#fff;
  padding:10px 18px;border-radius:var(--r);transition:top .2s}
.skip:focus{top:12px}

/* ---------- type ---------- */
.h-display{
  font-family:var(--font-display);font-weight:800;line-height:1.06;
  letter-spacing:-.022em;text-transform:uppercase;
  font-size:clamp(30px,4.4vw,52px);margin:0;
}
.h1{font-weight:800;font-size:clamp(28px,3.6vw,42px);line-height:1.12;letter-spacing:-.02em;text-transform:uppercase}
.h2{font-weight:800;font-size:clamp(24px,2.7vw,32px);line-height:1.2;letter-spacing:-.015em;text-transform:uppercase}
.h3{font-weight:700;font-size:19px;line-height:1.3;letter-spacing:-.01em}
.h4{font-weight:700;font-size:16px;line-height:1.35}
.lede{font-size:17px;line-height:1.7;color:var(--slate-500)}
.lede-light{font-size:17px;line-height:1.7;color:rgba(255,255,255,.78)}
.muted{color:var(--slate-500)}
.eyebrow{font-size:12px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--blue)}
.rule{width:52px;height:3px;background:var(--blue);border-radius:2px;margin-top:14px}
.rule-c{margin-inline:auto}
/* CJK reads better slightly looser and without forced caps */
:lang(zh) .h-display,:lang(zh) .h1,:lang(zh) .h2{text-transform:none;letter-spacing:.005em;line-height:1.22}
:lang(zh) body,:lang(zh) .lede{line-height:1.8}

.sec-head{margin-bottom:38px}
.sec-head .h2{margin:0}
.sec-head.center .rule{margin-inline:auto}

/* ---------- buttons ---------- */
.btn{
  display:inline-flex;align-items:center;gap:10px;
  padding:13px 24px;border-radius:var(--r-sm);
  font-size:14px;font-weight:700;letter-spacing:.03em;
  transition:background .18s var(--ease),color .18s,border-color .18s,transform .18s var(--ease),box-shadow .18s;
  white-space:nowrap;border:1.5px solid transparent;
}
.btn svg{width:15px;height:15px;flex:none;transition:transform .22s var(--ease)}
.btn:hover{transform:translateY(-2px)}
.btn:hover svg{transform:translateX(3px)}
.btn-primary{background:var(--blue);color:#fff;box-shadow:0 4px 14px rgba(30,95,214,.28)}
.btn-primary:hover{background:var(--blue-600);box-shadow:0 8px 24px rgba(30,95,214,.34)}
.btn-ghost{background:rgba(255,255,255,.9);color:var(--ink-800);border-color:rgba(255,255,255,.9)}
.btn-ghost:hover{background:#fff}
.btn-outline{border-color:var(--line);color:var(--ink-800);background:#fff}
.btn-outline:hover{border-color:var(--blue);color:var(--blue)}
.btn-outline-light{border-color:rgba(255,255,255,.45);color:#fff}
.btn-outline-light:hover{border-color:#fff;background:rgba(255,255,255,.1)}
.btn-white{background:#fff;color:var(--blue);box-shadow:var(--shadow-sm)}
.btn-white:hover{box-shadow:var(--shadow)}
.btn-sm{padding:10px 18px;font-size:13px}

.link-arrow{display:inline-flex;align-items:center;gap:7px;font-size:14px;font-weight:700;color:var(--blue)}
.link-arrow svg{width:14px;height:14px;transition:transform .22s var(--ease)}
.link-arrow:hover svg{transform:translateX(4px)}

/* circular arrow chip used on every image card */
.chip{
  width:34px;height:34px;border-radius:50%;flex:none;
  display:grid;place-items:center;
  border:1.5px solid rgba(255,255,255,.75);color:#fff;
  transition:background .2s,border-color .2s,transform .2s var(--ease);
}
.chip svg{width:13px;height:13px}
.chip-dark{border-color:var(--line);color:var(--slate-500)}

/* ==========================================================================
   HEADER
   ========================================================================== */
.header{
  position:sticky;top:0;z-index:100;background:#fff;
  border-bottom:1px solid var(--line-soft);
  transition:box-shadow .25s,background .25s;
}
.header.is-stuck{box-shadow:0 2px 18px rgba(10,22,49,.09)}
.header-in{display:flex;align-items:center;gap:26px;height:var(--header-h)}
.brand{display:flex;align-items:center;flex:none}
.brand img{height:26px;width:auto}
.nav{display:flex;align-items:center;gap:4px;margin-inline:auto}
.nav a{
  position:relative;padding:8px 14px;font-size:14.5px;font-weight:600;color:var(--ink-700);
  border-radius:var(--r-sm);transition:color .18s;
}
.nav a::after{
  content:"";position:absolute;left:14px;right:14px;bottom:1px;height:2px;
  background:var(--blue);border-radius:2px;transform:scaleX(0);transform-origin:left;
  transition:transform .24s var(--ease);
}
.nav a:hover{color:var(--blue)}
.nav a:hover::after,.nav a[aria-current="page"]::after{transform:scaleX(1)}
.nav a[aria-current="page"]{color:var(--blue)}
.header-act{display:flex;align-items:center;gap:14px;flex:none}
/* CTA duplicated inside the collapsed menu; only one of the two is ever shown */
.nav-cta{display:none}
.lang{
  display:inline-flex;align-items:center;gap:6px;font-size:13.5px;font-weight:600;
  color:var(--slate-500);padding:7px 10px;border-radius:var(--r-sm);transition:color .18s,background .18s;
}
.lang:hover{color:var(--blue);background:var(--paper)}
/* a touch larger than the surrounding text icons: the continents need the
   extra pixels to stay legible as shapes */
.lang svg{width:17px;height:17px}
.burger{display:none;width:40px;height:40px;border-radius:var(--r-sm);place-items:center}
.burger span{display:block;width:19px;height:2px;background:var(--ink-800);border-radius:2px;
  position:relative;transition:transform .25s var(--ease),background .2s}
.burger span::before,.burger span::after{content:"";position:absolute;left:0;width:19px;height:2px;
  background:var(--ink-800);border-radius:2px;transition:transform .25s var(--ease),top .2s}
.burger span::before{top:-6px}.burger span::after{top:6px}
.burger[aria-expanded="true"] span{background:transparent}
.burger[aria-expanded="true"] span::before{top:0;transform:rotate(45deg)}
.burger[aria-expanded="true"] span::after{top:0;transform:rotate(-45deg)}

/* ==========================================================================
   HERO — home
   ========================================================================== */
.hero{position:relative;min-height:620px;display:flex;align-items:center;
  background:var(--ink-900);overflow:hidden;isolation:isolate}
.hero-media{position:absolute;inset:0;z-index:-2;background:var(--ink-900)}
/* hold the ceiling unit and the airflow in frame as the viewport narrows */
.hero-media img{width:100%;height:100%;object-fit:cover;object-position:62% center}
/* Light enough to keep the plant floor readable, dark enough under the
   headline to hold contrast. The photograph is already low-key. */
.hero-media::after{
  content:"";position:absolute;inset:0;
  background:
    linear-gradient(100deg,rgba(5,11,26,.86) 0%,rgba(6,14,32,.66) 30%,rgba(8,18,40,.24) 58%,rgba(8,18,40,.06) 100%),
    linear-gradient(0deg,rgba(5,11,26,.62),rgba(5,11,26,0) 42%);
}
.hero-in{width:100%;padding-block:96px 120px}
.hero-copy{max-width:620px}
.hero h1{color:#fff}
.hero .lede-light{margin-top:20px;max-width:520px}
.hero-cta{display:flex;flex-wrap:wrap;gap:14px;margin-top:34px}

/* ---------- telemetry strip: a live plant readout ---------- */
.telemetry{display:flex;gap:30px;margin-top:64px;flex-wrap:wrap}
.tele{
  display:flex;flex-direction:column;gap:3px;position:relative;
  padding:6px 12px 12px;border-radius:var(--r-sm);
  transition:background .3s var(--ease),transform .3s var(--ease);
}
.tele::after{content:"";position:absolute;left:12px;bottom:4px;width:0;height:1.5px;border-radius:2px;
  background:linear-gradient(90deg,var(--cyan),rgba(53,195,243,0));transition:width .4s var(--ease)}
.telemetry dt{font-size:10.5px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;
  color:rgba(255,255,255,.5);transition:color .3s}
.telemetry dd{margin:0;display:flex;align-items:baseline;gap:5px;
  font-family:var(--font-mono);font-size:21px;font-weight:600;color:var(--cyan);
  font-variant-numeric:tabular-nums;transition:text-shadow .3s}

/* Width is reserved from the widest rendering, so a digit changing never
   shifts the unit that follows it. */
.tele-v{display:inline-block;min-width:var(--w);text-align:right}
.tele-u{font-size:15px;opacity:.72}

/* value swap: the new reading rises into place */
.tele-v.is-new{animation:teleIn .34s var(--ease)}
@keyframes teleIn{
  0%{opacity:0;transform:translateY(-6px)}
  60%{opacity:1}
  100%{opacity:1;transform:none}
}

.tele:hover,.tele:focus-visible{background:rgba(53,195,243,.07);transform:translateY(-2px)}
.tele:hover dt,.tele:focus-visible dt{color:rgba(255,255,255,.8)}
.tele:hover dd,.tele:focus-visible dd{text-shadow:0 0 18px rgba(53,195,243,.5)}
.tele:hover::after,.tele:focus-visible::after{width:44px}

@media (prefers-reduced-motion:reduce){
  .tele-v.is-new{animation:none}
}

/* ---------- page hero (inner pages) ---------- */
.phero{position:relative;background:var(--ink-900);overflow:hidden;isolation:isolate;
  padding-block:64px 62px}
.phero-media{position:absolute;inset:0;z-index:-2}
.phero-media img{width:100%;height:100%;object-fit:cover;object-position:center right}
.phero-media::after{content:"";position:absolute;inset:0;
  background:linear-gradient(95deg,rgba(5,11,26,.96) 0%,rgba(7,16,38,.9) 40%,rgba(10,22,49,.5) 78%,rgba(10,22,49,.35) 100%)}
.crumb{display:flex;align-items:center;gap:8px;font-size:13px;color:rgba(255,255,255,.55);margin-bottom:26px}
.crumb a:hover{color:#fff}
.crumb svg{width:11px;height:11px;opacity:.6}
/* Headlines are pre-broken with <br> in the markup, so let each line run its
   natural width instead of wrapping again inside a narrow measure. */
.phero h1{color:#fff;max-width:none}
.phero .lede-light{margin-top:18px;max-width:560px}
/* the marker-swipe under the second headline line */
.swipe{position:relative;display:inline-block}
.swipe::after{content:"";position:absolute;left:-2px;right:-2px;bottom:.1em;height:.3em;
  background:linear-gradient(90deg,rgba(53,195,243,.55),rgba(30,95,214,.15));z-index:-1;border-radius:2px}

/* hero stat row (inner pages) */
.phero-stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:26px;margin-top:44px;max-width:800px}
.phero-stats .ic{width:34px;height:34px;border-radius:var(--r-sm);display:grid;place-items:center;
  background:rgba(255,255,255,.09);border:1px solid rgba(255,255,255,.14);margin-bottom:12px}
.phero-stats .ic svg{width:17px;height:17px;color:#fff}
.phero-stats b{display:block;font-size:27px;font-weight:800;color:var(--blue-400);line-height:1.1;letter-spacing:-.02em}
.phero-stats span{display:block;font-size:12.5px;color:rgba(255,255,255,.62);margin-top:5px}
/* feature variant (Solutions hero) */
.phero-feats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:26px;margin-top:44px;max-width:760px}
.phero-feats b{display:block;font-size:14.5px;font-weight:700;color:#fff;margin-top:12px}
.phero-feats span{display:block;font-size:12.5px;color:rgba(255,255,255,.6);margin-top:4px;line-height:1.5}
.phero-feats .ic{width:36px;height:36px;display:grid;place-items:center;color:var(--blue-400)}
.phero-feats .ic svg{width:26px;height:26px}
/* contact variant */
.phero-contact{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:26px;margin-top:40px;max-width:820px}
.phero-contact .ic{width:34px;height:34px;border-radius:50%;display:grid;place-items:center;
  background:rgba(255,255,255,.09);border:1px solid rgba(255,255,255,.16);margin-bottom:12px}
.phero-contact .ic svg{width:16px;height:16px;color:#fff}
.phero-contact b{display:block;font-size:12.5px;font-weight:600;color:rgba(255,255,255,.6)}
.phero-contact span{display:block;font-size:14.5px;color:#fff;margin-top:4px;font-weight:600}

/* ==========================================================================
   CAPABILITY STORIES — one slide at a time, card left, paired images right
   ========================================================================== */
/* The section is tall — one screenful of scroll per story — and the stage
   inside it is pinned. Scrolling past the section is what advances the story;
   the height here is the timeline.

   Dark ground, white card, image butted up against it: the pair reads as one
   panel rather than two floating objects. */
/* Pale ground, the same paper tone the rest of the page uses. */
.story{--story-count:4;position:relative;background:var(--paper);
  height:calc((var(--story-count) + 0.25) * 100vh)}
.story-stage{position:sticky;top:var(--header-h);height:calc(100vh - var(--header-h));
  display:grid;align-items:stretch;padding-block:44px;overflow:hidden}
.story-grid{display:grid;grid-template-columns:minmax(0,.52fr) minmax(0,1fr);
  gap:10px;align-items:stretch;height:100%;max-height:820px;align-self:center}

/* Copy sits at the top of a full-height card; the space below it is deliberate
   — it is what makes the panel feel like a page rather than a box. */
/* White against the pale ground — an off-white card would go muddy on it. */
.story-card{position:relative;background:#fff;border-radius:10px;
  padding:52px 46px;display:grid;overflow:hidden;
  box-shadow:0 1px 2px rgba(10,22,49,.04),0 14px 36px rgba(10,22,49,.06)}

/* Blocks share one cell and cross-fade. Nothing is display:none — swapping
   that would snap, and the point is that only the words move. Visibility is
   held back until the fade finishes so the outgoing block stays readable
   while it leaves. */
.story-copy{
  grid-area:1/1;align-self:start;
  opacity:0;transform:translateY(16px);visibility:hidden;pointer-events:none;
  transition:opacity .5s var(--ease),transform .5s var(--ease),visibility 0s .5s;
}
.story-copy.is-on{
  opacity:1;transform:none;visibility:visible;pointer-events:auto;
  transition:opacity .55s .12s var(--ease),transform .55s .12s var(--ease),visibility 0s;
}
/* The reference sets the eyebrow as plain small text, not a coloured all-caps
   label — the heading below is what carries the emphasis, so the line above it
   stays quiet. */
/* Near-neutral ink on the off-white card, not the site's blue-blacks. */
.story-eyebrow{display:block;font-size:14px;font-weight:600;color:var(--slate-700)}
.story-card h2{margin-top:26px;font-size:clamp(28px,2.7vw,40px);font-weight:800;
  line-height:1.15;letter-spacing:-.02em;color:var(--ink-900)}
:lang(zh) .story-card h2{letter-spacing:.01em;line-height:1.3}
/* rule between the name and the words, as in the reference */
.story-quote{margin:22px 0 0;padding-top:26px;border-top:1px solid var(--line)}
.story-quote p{font-size:18px;line-height:1.62;color:var(--ink-800)}
:lang(zh) .story-quote p{font-size:18px;line-height:1.78}
/* the quotation marks belong to the setting, not to the copy */
.story-quote p::before{content:"\201C"}
.story-quote p::after{content:"\201D"}
.story-by{margin-top:24px;font-size:13.5px;line-height:1.6;font-style:italic;
  color:var(--slate-500)}
/* solid block, the way the reference ends the card */
.story-more{display:inline-flex;align-items:center;gap:8px;margin-top:26px;
  padding:13px 20px;border-radius:var(--r-sm);
  background:var(--brand);color:#fff;font-size:14px;font-weight:700;
  transition:background .2s,transform .2s var(--ease)}
.story-more svg{width:14px;height:14px;transition:transform .22s var(--ease)}
.story-more:hover{background:var(--brand-700);transform:translateY(-2px)}
.story-more:hover svg{transform:translateX(3px)}

/* Matches the card's height rather than its own aspect ratio, so the two
   halves square off against each other. */
.story-media{position:relative;border-radius:10px;overflow:hidden;background:var(--ink-800);
  box-shadow:0 1px 2px rgba(10,22,49,.04),0 14px 36px rgba(10,22,49,.06)}
/* Each photograph waits below the frame and slides up over the one before it.
   z-index ascends with the running order, so the arriving image covers the
   outgoing one instead of the two blending — and reversing simply drops it
   back down to reveal what was underneath. */
.story-shot{
  position:absolute;inset:0;display:block;width:100%;height:100%;object-fit:cover;
  transform:translateY(101%);
  transition:transform .78s cubic-bezier(.33,0,.15,1);
  will-change:transform;
}
.story-shot.is-on{transform:translateY(0)}
@media (prefers-reduced-motion:reduce){
  .story-shot{transition:none}
  .story-copy,.story-copy.is-on{transition:opacity .01s,visibility 0s}
}

@media (prefers-reduced-motion:reduce){.story-slide.is-on{animation:none}}

/* ==========================================================================
   CUSTOMER STRIP
   Hairline grid, no cards: the logos already sit on white, so a border box
   around each one would just double the outline.
   ========================================================================== */
.trust{background:#fff;border-bottom:1px solid var(--line-soft);padding-block:46px 16px;overflow:hidden}
.trust-head{text-align:center;font-size:12.5px;font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;color:var(--slate-400);margin-bottom:30px}
.trust-head b{font-weight:800;color:var(--brand)}
:lang(zh) .trust-head{letter-spacing:.06em;text-transform:none;font-size:14px}

/* Runs edge to edge rather than inside the content column, so marks drift in
   and out of frame instead of appearing at a hard boundary. The mask feathers
   both ends; without it the loop reads as a filmstrip being yanked past. */
.trust-marquee{
  overflow:hidden;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
}
.trust-track{
  display:flex;width:max-content;
  animation:trustRun 52s linear infinite;
}
/* pause so a visitor can actually look at a mark they recognise */
.trust-marquee:hover .trust-track{animation-play-state:paused}
/* Spacing lives on the items, not on a flex gap: a gap would also fall
   between the two runs and break the half-width offset. */
.trust-track li{flex:none;display:grid;place-items:center;padding:20px 40px}
/* Each mark is trimmed to its own ink, so the aspect ratios differ. Capping
   both dimensions keeps a wide wordmark and a square glyph at the same
   visual weight — capping only one would make the wide ones dominate. */
.trust-track img{
  width:auto;height:auto;max-width:132px;max-height:42px;
  /* settle the mixed brand colours to one weight, then restore on hover */
  filter:grayscale(1) opacity(.55);
  transition:filter .3s var(--ease);
}
.trust-track li:hover img{filter:none}
@keyframes trustRun{from{transform:translateX(0)}to{transform:translateX(-50%)}}

@media (prefers-reduced-motion:reduce){
  /* no travel — show one run, centred and wrapped */
  .trust-marquee{-webkit-mask-image:none;mask-image:none}
  .trust-track{animation:none;width:auto;flex-wrap:wrap;justify-content:center}
  .trust-track li[aria-hidden]{display:none}
}

/* ==========================================================================
   IMAGE CARDS  (scenario / category tiles)
   ========================================================================== */
.tile{position:relative;display:block;overflow:hidden;border-radius:var(--r);background:var(--ink-800);
  isolation:isolate}
.tile img{width:100%;height:100%;object-fit:cover;transition:transform .7s var(--ease)}
.tile::after{content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(5,11,26,.12) 0%,rgba(5,11,26,.34) 45%,rgba(5,11,26,.8) 100%);
  transition:background .3s}
.tile:hover img{transform:scale(1.055)}
.tile:hover::after{background:linear-gradient(180deg,rgba(5,11,26,.2) 0%,rgba(8,17,40,.45) 45%,rgba(6,12,30,.86) 100%)}
.tile:hover .chip{background:var(--blue);border-color:var(--blue)}
.tile-body{position:absolute;inset:auto 0 0 0;z-index:1;padding:28px;display:flex;
  flex-direction:column;align-items:center;gap:18px;text-align:center}
/* Line breaks are set in the content with "|", so no width cap is needed here.
   All-caps needs positive tracking — the display face's default negative
   tracking closes the counters up and hurts legibility over a photograph.
   text-wrap:balance is the safety net if a title ever wraps on its own. */
.tile-body h3{
  color:#fff;font-size:19px;font-weight:800;text-transform:uppercase;
  letter-spacing:.02em;line-height:1.3;text-wrap:balance;
  text-shadow:0 1px 2px rgba(5,11,26,.5),0 4px 18px rgba(5,11,26,.45);
}
.tiles-2 .tile-body h3{font-size:clamp(18px,1.55vw,22px);line-height:1.28}
:lang(zh) .tile-body h3{text-transform:none;letter-spacing:.06em;line-height:1.45}
.tiles-2{display:grid;grid-template-columns:1fr 1fr;gap:22px}
.tiles-2 .tile{aspect-ratio:16/9.4}
.tiles-3{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}
.tiles-3 .tile{aspect-ratio:16/10.6}
/* rule under the heading, drawn on hover — the same gesture the stat bar and
   telemetry strip use, so the whole page responds in one accent */
.tiles-3 .tile-body h3{position:relative;padding-bottom:12px}
.tiles-3 .tile-body h3::after{content:"";position:absolute;left:50%;bottom:0;
  width:0;height:2px;border-radius:2px;transform:translateX(-50%);
  background:linear-gradient(90deg,var(--cyan),var(--blue));
  transition:width .36s var(--ease)}
.tiles-3 .tile:hover h3::after{width:40px}

/* ==========================================================================
   SECTION HEAD with an optional action on the right
   ========================================================================== */
.band-head{display:flex;align-items:flex-end;justify-content:space-between;gap:30px;
  flex-wrap:wrap;margin-bottom:30px}
.band-head .h2{margin:0}
.band-head p{margin-top:10px;font-size:14.5px;color:var(--slate-500);max-width:62ch}
.band-head .link-arrow{padding-bottom:3px}

/* ==========================================================================
   SOLUTION CARDS — photo, eyebrow, title, blurb, corner action
   ========================================================================== */
.solcards{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}
.solcard-lg{
  position:relative;display:block;overflow:hidden;border-radius:var(--r);
  aspect-ratio:16/12.4;background:var(--ink-800);isolation:isolate;
}
.solcard-lg>img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  transition:transform .7s var(--ease)}
/* Weighted to the lower half: that is where the copy lands, and the top stays
   open so the photograph still reads. */
.solcard-lg::after{content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,
    rgba(5,11,26,.34) 0%,rgba(5,11,26,.4) 26%,rgba(5,11,26,.78) 56%,rgba(3,8,20,.95) 100%);
  transition:background .32s}
.solcard-lg:hover>img{transform:scale(1.055)}
.solcard-lg:hover::after{
  background:linear-gradient(180deg,
    rgba(5,11,26,.3) 0%,rgba(6,14,32,.44) 26%,rgba(4,10,24,.82) 56%,rgba(2,6,16,.97) 100%)}
/* the ring used to sit under the copy; without it the block needs its own
   breathing room at the foot of the card */
.solcard-lg-body{position:absolute;inset:auto 0 0 0;z-index:1;padding:26px 26px 30px;
  display:flex;flex-direction:column;align-items:flex-start}
.solcard-lg-eyebrow{font-size:11px;font-weight:700;letter-spacing:.15em;text-transform:uppercase;
  color:rgba(255,255,255,.5);margin-bottom:10px}
.solcard-lg h3{font-size:20px;font-weight:800;color:#fff;line-height:1.28;letter-spacing:-.005em;
  text-shadow:0 1px 2px rgba(5,11,26,.5)}
:lang(zh) .solcard-lg h3{letter-spacing:.02em}
.solcard-lg p{margin-top:9px;font-size:13px;line-height:1.65;color:rgba(255,255,255,.7);
  max-width:32ch}
/* What's actually in this family — collapsed until you hover. Animating
   grid-template-rows lets it expand from nothing to its natural height
   without hard-coding a value; the body is bottom-anchored so the copy grows
   upward and the ring below never moves. */
.solcard-lg-more{
  display:grid;grid-template-rows:0fr;opacity:0;
  transition:grid-template-rows .34s var(--ease),opacity .26s var(--ease);
}
.solcard-lg-more>span{
  overflow:hidden;font-size:12px;line-height:1.5;letter-spacing:.01em;
  color:var(--cyan);
}
.solcard-lg:hover .solcard-lg-more,
.solcard-lg:focus-visible .solcard-lg-more{grid-template-rows:1fr;opacity:1;padding-top:10px}

/* ==========================================================================
   PRODUCT MATRIX — tabbed
   ========================================================================== */
.tablist{display:flex;gap:4px;border-bottom:1px solid var(--line);margin-bottom:26px;
  overflow-x:auto;scrollbar-width:none}
.tablist::-webkit-scrollbar{display:none}
.tab{
  position:relative;padding:12px 18px 14px;font-size:14.5px;font-weight:600;
  color:var(--slate-500);white-space:nowrap;background:none;border:0;cursor:pointer;
  transition:color .2s;
}
.tab::after{content:"";position:absolute;left:14px;right:14px;bottom:-1px;height:2px;
  background:var(--blue);border-radius:2px;transform:scaleX(0);
  transition:transform .26s cubic-bezier(.32,0,.24,1)}
.tab:hover{color:var(--ink-800)}
.tab[aria-selected="true"]{color:var(--blue)}
.tab[aria-selected="true"]::after{transform:scaleX(1)}

/* Always four tracks, whatever the panel holds. A family with three products
   leaves the last cell empty rather than stretching its cards — otherwise the
   tiles resize every time you switch tabs. */
.matrix{display:grid;grid-template-columns:repeat(4,1fr);gap:18px}
.mcard{display:flex;flex-direction:column;background:#fff;border:1px solid var(--line);
  border-radius:var(--r);overflow:hidden;
  transition:border-color .22s,box-shadow .26s,transform .26s var(--ease)}
.mcard:hover{border-color:#c9d6ea;box-shadow:var(--shadow);transform:translateY(-4px)}
.mcard-fig{display:grid;place-items:center;aspect-ratio:4/3;padding:14px;position:relative;
  overflow:hidden;background:linear-gradient(160deg,#f8fafc,#eef2f8)}
.mcard-fig::before{content:"";position:absolute;inset:0;opacity:.5;
  background-image:linear-gradient(rgba(49,61,149,.05) 1px,transparent 1px),
                   linear-gradient(90deg,rgba(49,61,149,.05) 1px,transparent 1px);
  background-size:22px 22px}
.mcard-fig img{position:relative;width:100%;height:100%;object-fit:contain;
  transition:transform .5s var(--ease)}
.mcard:hover .mcard-fig img{transform:scale(1.05)}
.mcard-body{padding:15px 16px 17px;border-top:1px solid var(--line-soft);
  display:flex;flex-direction:column;gap:4px;position:relative}
/* an arrow that slides in from the edge, rather than sitting there unused */
.mcard-body::after{content:"";position:absolute;right:16px;bottom:18px;
  width:14px;height:14px;opacity:0;transform:translateX(-6px);
  background:currentColor;color:var(--blue);
  -webkit-mask:var(--arrow) center/contain no-repeat;mask:var(--arrow) center/contain no-repeat;
  transition:opacity .22s,transform .26s var(--ease)}
.mcard:hover .mcard-body::after{opacity:1;transform:none}
/* Reserve two lines for the name. Some families run to two-line titles and
   others don't; without this the cards change height as you switch tabs. */
.mcard-body b{font-size:14.5px;font-weight:700;line-height:1.35;color:var(--ink-800);
  min-height:2.7em}
/* keep the last line clear of the arrow that appears on hover */
.mcard-body em{font-style:normal;font-size:12.5px;line-height:1.5;color:var(--slate-500);
  padding-right:22px}

/* panels fade in when their tab is chosen */
.tabpanel[hidden]{display:none}
.tabpanel.is-switching .matrix{animation:panelIn .3s var(--ease)}
@keyframes panelIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){
  .tabpanel.is-switching .matrix{animation:none}
}

/* ==========================================================================
   PRODUCT CARDS
   ========================================================================== */
.pcards{display:grid;grid-template-columns:repeat(4,1fr);gap:22px}
.pcard{
  display:flex;flex-direction:column;background:#fff;border:1px solid var(--line);
  border-radius:var(--r);overflow:hidden;transition:border-color .22s,box-shadow .28s,transform .28s var(--ease);
}
.pcard:hover{border-color:#c9d6ea;box-shadow:var(--shadow);transform:translateY(-4px)}
.pcard-fig{aspect-ratio:4/3.15;background:linear-gradient(160deg,#f7f9fc 0%,#eef2f8 100%);
  display:grid;place-items:center;padding:16px;position:relative;overflow:hidden}
.pcard-fig::before{content:"";position:absolute;inset:0;opacity:.5;
  background-image:linear-gradient(rgba(49,61,149,.05) 1px,transparent 1px),
                   linear-gradient(90deg,rgba(49,61,149,.05) 1px,transparent 1px);
  background-size:26px 26px}
.pcard-fig img{position:relative;width:100%;height:100%;object-fit:contain;
  transition:transform .5s var(--ease)}
.pcard:hover .pcard-fig img{transform:scale(1.05)}
.pcard-body{display:flex;align-items:center;justify-content:space-between;gap:14px;
  padding:18px 20px;border-top:1px solid var(--line-soft);margin-top:auto}
.pcard-body h3{font-size:14px;font-weight:700;text-transform:uppercase;letter-spacing:.015em;line-height:1.35}
:lang(zh) .pcard-body h3{text-transform:none;font-size:15px}
.pcard:hover .chip-dark{border-color:var(--blue);color:var(--blue)}

/* ==========================================================================
   CAPABILITY BAND (dark, home)
   ========================================================================== */
.cap{color:#fff;position:relative;overflow:hidden;isolation:isolate;background:#040a18}
/* The artwork is a 2.9:1 banner built for exactly this slot — rack centred,
   dark field either side — so it runs full bleed rather than sitting in the
   middle as an object. No feathering needed: the plate is dark to its edges. */
.cap-media{position:absolute;inset:0;z-index:-2;pointer-events:none}
.cap-media img{width:100%;height:100%;object-fit:cover;object-position:center}
/* Weighted to the outer thirds, where the copy sits. The middle is left almost
   untouched so the rack keeps its contrast. */
.cap-media::after{
  content:"";position:absolute;inset:0;
  background:
    linear-gradient(90deg,
      rgba(4,10,26,.9) 0%,   rgba(5,12,32,.74) 20%,
      rgba(6,16,42,.22) 36%, rgba(6,16,42,.06) 50%,
      rgba(6,16,42,.24) 64%, rgba(5,12,32,.72) 80%,
      rgba(4,10,26,.9) 100%),
    linear-gradient(0deg,rgba(4,10,26,.5),rgba(4,10,26,0) 22%,rgba(4,10,26,0) 80%,rgba(4,10,26,.4) 100%);
}
/* The empty middle column is the machine's breathing room. The side columns
   are sized so their inner edges stop clear of the chassis. min-height tracks
   the plate's 2.9:1 ratio, so cover crops it as little as possible. */
.cap-in{position:relative;display:grid;
  grid-template-columns:minmax(0,.92fr) minmax(0,1.16fr) minmax(0,.78fr);
  gap:44px;align-items:center;padding-block:84px;min-height:min(34vw,520px)}
.cap-copy{grid-column:1}
.cap-specs{grid-column:3}
/* Broken by hand into two balanced lines, so no width cap is needed. Slightly
   smaller and tighter than the default h2: a stacked display line wants less
   leading than a single-line heading, or the lines drift apart. */
.cap h2{color:#fff;max-width:none;
  font-size:clamp(23px,2.35vw,30px);line-height:1.16;letter-spacing:-.018em;
  text-wrap:balance}
:lang(zh) .cap h2{line-height:1.32;letter-spacing:.01em}
/* Static by intent — these three read as a list, not as controls. Only the
   entrance stagger applies; there is nothing here to hover. */
.cap-feats{margin-top:32px;display:flex;flex-direction:column;gap:22px}
.cap-feat{display:flex;gap:15px;align-items:flex-start}
.cap-feat .ic{width:38px;height:38px;flex:none;border-radius:50%;display:grid;place-items:center;
  background:var(--blue);box-shadow:0 4px 14px rgba(30,95,214,.4)}
.cap-feat .ic svg{width:18px;height:18px;color:#fff}
.cap-feat b{display:block;font-size:13px;font-weight:800;letter-spacing:.09em;text-transform:uppercase}
:lang(zh) .cap-feat b{letter-spacing:.02em;text-transform:none;font-size:15px}
.cap-feat p{font-size:13.5px;line-height:1.6;color:rgba(255,255,255,.62);margin-top:5px}
/* Spec list reads as an instrument panel: the rule at the left is the handle,
   and hovering runs it top-to-bottom like a channel being selected. No glow,
   no scaling — the response is a short, mechanical shift. */
.cap-specs{display:flex;flex-direction:column;gap:24px}
/* Shifts on padding, not transform: these rows are also reveal targets, and
   transform is already spoken for by the entrance animation. Declaring the
   reveal's own properties here too keeps this rule from replacing them. */
.cap-specs div{
  position:relative;padding-left:18px;
  transition:padding-left .2s cubic-bezier(.32,0,.24,1),
             opacity .66s var(--ease),
             transform .66s var(--ease);
}
.cap-specs div::before,
.cap-specs div::after{content:"";position:absolute;left:0;top:0;bottom:0;width:2px}
.cap-specs div::before{background:rgba(255,255,255,.15)}
.cap-specs div::after{
  background:var(--blue-400);
  transform:scaleY(0);transform-origin:top;
  transition:transform .26s cubic-bezier(.32,0,.24,1);
}
.cap-specs dt{font-size:12.5px;color:rgba(255,255,255,.55);margin-bottom:4px;
  transition:color .2s}
.cap-specs dd{margin:0;font-size:23px;font-weight:800;color:var(--blue-400);letter-spacing:-.02em;
  font-variant-numeric:tabular-nums;transition:color .2s}
/* the unit sits a size down and a shade back, so the figure carries the line */
.cap-specs .u{font-style:normal;font-size:.66em;font-weight:700;
  opacity:.6;margin-left:.14em;letter-spacing:.01em}

.cap-specs div:hover{padding-left:24px}
.cap-specs div:hover::after{transform:scaleY(1)}
.cap-specs div:hover dt{color:rgba(255,255,255,.85)}
.cap-specs div:hover dd{color:#7ba8ff}

@media (prefers-reduced-motion:reduce){
  .cap-specs div:hover{padding-left:18px}
  .cap-specs div::after{transition:none}
}

/* ==========================================================================
   CTA BANDS
   ========================================================================== */
.cta{position:relative;overflow:hidden;background:linear-gradient(100deg,#1b4fc4 0%,#2560dd 46%,#1747b0 100%);
  color:#fff}
.cta-in{position:relative;display:flex;align-items:center;justify-content:space-between;gap:40px;
  padding-block:56px;flex-wrap:wrap}

/* ---------- video variant ----------
   The loop runs behind the copy. It is decoration, not content: muted, no
   controls, hidden from assistive tech, and it falls back to its own poster
   frame whenever autoplay is refused. */
/* Base and wash are pulled toward the logo indigo rather than a neutral navy,
   so the band, the button and the mark all sit on the same hue. */
.cta-video{background:#070a24;isolation:isolate}
.cta-media{position:absolute;inset:0;z-index:-2}
/* Taller band means cover crops less, so the framing can sit near centre and
   keep the whole unit rather than a slice of it. */
.cta-media video{width:100%;height:100%;object-fit:cover;object-position:center 50%;display:block}
/* Dark on the left where the type sits, open on the right where the unit is.
   Top and bottom edges fade so the band meets its neighbours cleanly. */
.cta-media::after{
  content:"";position:absolute;inset:0;
  background:
    linear-gradient(100deg,
      rgba(8,11,38,.94) 0%,  rgba(11,15,48,.88) 26%,
      rgba(16,22,66,.55) 46%, rgba(18,26,74,.16) 64%,
      rgba(18,26,74,.1) 100%),
    linear-gradient(0deg,rgba(7,10,32,.55),rgba(7,10,32,0) 24%,rgba(7,10,32,0) 78%,rgba(7,10,32,.45) 100%);
}
/* Headline · strapline · action, stacked hard against the left edge.
   Still flex, but a single column — the copy block centres in the band.
   Height tracks the viewport so the loop keeps more of its frame on wide
   screens instead of being cropped to a letterbox. */
.cta-video .cta-in{flex-direction:column;align-items:flex-start;justify-content:center;
  gap:0;padding-block:104px;min-height:min(40vw,580px)}
/* Hard stop before the machine, which starts around 45% of the frame. The
   room available is actually 0.45·vw − ((vw−1240)/2 + 32): because `.wrap`
   centres, a wider viewport pushes the copy right faster than it pushes the
   machine, so the gap narrows as the screen grows. A fixed cap is therefore
   safer than a percentage, and the type is sized to fit inside it on two
   lines rather than spilling to three. */
.cta-copy{max-width:min(480px,100%)}
.cta-video h2{
  font-size:clamp(32px,3.6vw,52px);font-weight:800;line-height:1.05;
  letter-spacing:-.024em;text-transform:uppercase;color:#fff;
  text-shadow:0 2px 24px rgba(3,8,22,.5);
}
:lang(zh) .cta-video h2{text-transform:none;letter-spacing:.012em;line-height:1.18}
.cta-sub{margin-top:20px;font-size:clamp(14.5px,1.25vw,18px);line-height:1.6;
  color:rgba(255,255,255,.75);font-weight:400}
:lang(zh) .cta-sub{letter-spacing:.02em}

/* ---------- action ----------
   White block carrying the logo indigo. On hover the pair inverts to indigo
   on white — the brand colour does the work, so no glow is needed to make it
   read against the video. */
.cta-btn{
  margin-top:42px;padding:19px 34px;gap:18px;
  background:#fff;color:var(--brand);
  font-size:15px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;
  box-shadow:0 6px 22px rgba(3,9,24,.34);
  transition:background .22s,color .22s,box-shadow .24s,transform .22s var(--ease);
}
:lang(zh) .cta-btn{letter-spacing:.1em;text-transform:none;font-size:16px}
.cta-btn svg{width:17px;height:17px}
.cta-btn:hover{background:var(--brand);color:#fff;
  box-shadow:0 12px 30px rgba(49,61,149,.5)}
.cta-btn:focus-visible{outline:2px solid #fff;outline-offset:4px}

/* Below this the machine would sit under the copy. Pan the frame right and
   deepen the wash so the stack keeps its contrast. */
@media (max-width:900px){
  /* stacked now, nothing beside the copy to avoid — let it use the width */
  .cta-copy{max-width:min(80%,560px)}
  .cta-video .cta-in{padding-block:76px;min-height:430px}
  .cta-media video{object-position:72% 52%}
  .cta-media::after{
    background:
      linear-gradient(100deg,rgba(8,11,38,.95) 0%,rgba(11,15,48,.9) 38%,rgba(16,22,66,.55) 72%,rgba(18,26,74,.3) 100%),
      linear-gradient(0deg,rgba(7,10,32,.6),rgba(7,10,32,0) 30%,rgba(7,10,32,.4) 100%);
  }
}
@media (max-width:560px){
  .cta-copy{max-width:100%}
  .cta-btn{margin-top:28px;padding:16px 22px;font-size:13.5px;letter-spacing:.05em;
    width:100%;justify-content:space-between}
  :lang(zh) .cta-btn{font-size:14.5px;letter-spacing:.08em}
}
.cta h2{color:#fff;max-width:22ch}
.cta p{margin-top:10px;color:rgba(255,255,255,.82);font-size:15.5px;max-width:44ch}
.cta-acts{display:flex;gap:14px;flex-wrap:wrap}
.cta-art{position:absolute;right:-20px;top:50%;transform:translateY(-50%);width:min(430px,40%);
  opacity:.3;pointer-events:none}
.cta-art svg{width:100%;height:auto}
.cta-dark{background:linear-gradient(115deg,#08132c 0%,#0e2049 55%,#0a1734 100%);border-radius:var(--r-lg)}
.cta-dark .cta-in{padding-inline:52px}
.cta-dark .cta-art{opacity:.42;width:min(360px,36%)}

/* ==========================================================================
   FOOTER
   ========================================================================== */
.footer{background:var(--ink-900);color:rgba(255,255,255,.62);font-size:13.5px}

/* ---------- reveal-on-scroll ----------
   The footer is pinned to the bottom of the viewport underneath the page, and
   <main> slides up off it — so the last band lifts away like a card being
   pulled back rather than the footer scrolling into place.

   Two things make it work: <main> needs an opaque background (any transparent
   section would let the pinned footer show through mid-page), and it needs a
   bottom margin exactly as tall as the footer, which is the gap the footer
   shows through at the end. The class and the height are both set by script,
   because the footer's height depends on how its columns wrap. */
.footer-reveal main{
  position:relative;z-index:1;background:var(--white);
  margin-bottom:var(--footer-h,0px);
  /* the lifting edge casts onto the footer, which sells the layering */
  box-shadow:0 24px 54px rgba(0,0,0,.5);
}
/* Fill the screen exactly. A footer shorter than the viewport leaves the tail
   of the band above it still showing once you reach the bottom — a stripe of
   the video peeking over the edge. Stretching it to 100vh means the last
   screenful is footer and nothing else, and the spare height goes into the
   gap around the closing statement rather than into dead padding. */
.footer-reveal .footer{position:fixed;left:0;right:0;bottom:0;z-index:0;min-height:100vh}
.footer-reveal .footer>.wrap{min-height:100vh;display:flex;flex-direction:column}
.footer-reveal .footer-mark{margin-top:auto;margin-bottom:auto}
.footer-in{display:grid;grid-template-columns:minmax(230px,1.5fr) repeat(5,minmax(0,1fr));
  gap:38px;padding-block:60px 44px}
.footer-brand img{height:26px;width:auto;filter:brightness(0) invert(1)}
.footer-brand p{margin-top:18px;line-height:1.72;max-width:30ch}
/* Solid white tiles rather than tinted circles: on a near-black footer the
   filled shape is what carries, and each mark stays in its own recognisable
   silhouette instead of dissolving into the background. */
.social{display:flex;gap:12px;margin-top:24px}
.social a{
  width:44px;height:44px;border-radius:10px;display:grid;place-items:center;
  background:#fff;
  transition:background .22s,transform .22s var(--ease),box-shadow .22s;
}
.social svg{width:20px;height:20px;color:var(--ink-900);transition:color .22s}
/* inverts to the logo indigo — the same swap the primary button makes */
.social a:hover{background:var(--brand);transform:translateY(-3px);
  box-shadow:0 8px 20px rgba(49,61,149,.45)}
.social a:hover svg{color:#fff}
.social a:focus-visible{outline:2px solid #fff;outline-offset:3px}
.footer h4{color:#fff;font-size:14px;font-weight:700;margin-bottom:16px}
.footer nav li+li{margin-top:9px}
/* The link steps to the right and brightens — no underline. Reads as the item
   being picked out of the column rather than decorated. */
.footer nav a,.footer address a{display:inline-block;
  transition:color .18s,transform .24s cubic-bezier(.32,0,.24,1)}
.footer nav a:hover,.footer address a:hover{color:#fff;transform:translateX(9px)}
.footer address{font-style:normal;display:flex;flex-direction:column;gap:9px}
.footer address span{display:flex;gap:9px;align-items:flex-start;line-height:1.55}
.footer address svg{width:14px;height:14px;flex:none;margin-top:3px;opacity:.75}
/* ---------- closing statement ----------
   Deliberately the biggest type anywhere on the site. The reference sets it
   in a condensed grotesque; without that face, tight tracking and a short
   leading get close to the same density. */
/* Sized against viewport height as well as width. This statement is what
   makes the footer tall, and the footer only gets pinned behind the page
   while it still fits on screen — so on a short display it has to give way
   rather than cost the reveal. */
.footer-mark{
  margin:44px 0 38px;color:#fff;
  font-size:clamp(30px,min(7.2vw,13vh),100px);font-weight:800;line-height:.94;
  letter-spacing:-.035em;text-transform:uppercase;
}
/* Negative tracking pulls the last glyph tight against the edge of the box —
   at 375px the longest line was within 28px of being clipped. The trailing
   pad gives that final letter its sidebearing back. */
.footer-mark span{display:block;padding-right:.08em}
:lang(zh) .footer-mark{text-transform:none;letter-spacing:.01em;line-height:1.08;
  font-size:clamp(28px,min(6.2vw,11.5vh),86px)}
:lang(zh) .footer-mark span{padding-right:0}

/* On a short display the statement is what tips the footer past the height
   where pinning still makes sense. Rein it in there rather than lose the
   reveal — a smaller closing line costs less than a footer that cannot be
   uncovered. */
@media (max-height:820px){
  .footer-mark{margin:26px 0 22px;font-size:clamp(28px,min(5.9vw,10vh),76px)}
  :lang(zh) .footer-mark{font-size:clamp(26px,min(5.2vw,9vh),66px)}
}

.footer-bar{border-top:1px solid rgba(255,255,255,.09);padding-block:20px;
  display:flex;align-items:center;justify-content:space-between;gap:24px;flex-wrap:wrap;font-size:12.5px}
.footer-bar .certs{display:flex;gap:10px;align-items:center;opacity:.55}
.footer-bar .certs span{border:1px solid rgba(255,255,255,.3);border-radius:50%;
  width:30px;height:30px;display:grid;place-items:center;font-size:8.5px;font-weight:700;
  letter-spacing:.02em;color:#fff}

/* ==========================================================================
   PROJECTS PAGE
   ========================================================================== */
.catcards{display:grid;grid-template-columns:repeat(4,1fr);gap:22px}
.catcard{background:#fff;border:1px solid var(--line);border-radius:var(--r);overflow:hidden;
  display:flex;flex-direction:column;transition:box-shadow .28s,transform .28s var(--ease),border-color .22s}
.catcard:hover{box-shadow:var(--shadow);transform:translateY(-4px);border-color:#c9d6ea}
.catcard-fig{position:relative;aspect-ratio:16/9.6;overflow:hidden;background:var(--ink-700)}
.catcard-fig img{width:100%;height:100%;object-fit:cover;transition:transform .65s var(--ease)}
.catcard:hover .catcard-fig img{transform:scale(1.06)}
.catcard-fig::after{content:"";position:absolute;inset:0;background:rgba(8,17,40,.28)}
.catcard .badge{position:absolute;left:20px;bottom:-19px;z-index:1;width:38px;height:38px;border-radius:50%;
  background:var(--blue);display:grid;place-items:center;box-shadow:0 5px 16px rgba(30,95,214,.42)}
.catcard .badge svg{width:18px;height:18px;color:#fff}
.catcard-body{padding:32px 22px 24px;display:flex;flex-direction:column;gap:10px;flex:1}
.catcard-body h3{font-size:16px;font-weight:800;text-transform:uppercase;line-height:1.3}
:lang(zh) .catcard-body h3{text-transform:none;font-size:17px}
.catcard-body p{font-size:13.5px;line-height:1.65;color:var(--slate-500);flex:1}
.catcard-body .link-arrow{margin-top:6px}

/* featured project rows */
.projrow{display:grid;grid-template-columns:270px minmax(0,1.25fr) minmax(0,1fr) minmax(0,1fr) 46px;
  gap:0;background:#fff;border:1px solid var(--line);border-radius:var(--r);overflow:hidden;
  transition:box-shadow .28s,border-color .22s}
.projrow+.projrow{margin-top:18px}
.projrow:hover{box-shadow:var(--shadow);border-color:#c9d6ea}
.projrow-fig{overflow:hidden;background:var(--ink-700);min-height:196px}
.projrow-fig img{width:100%;height:100%;object-fit:cover;transition:transform .65s var(--ease)}
.projrow:hover .projrow-fig img{transform:scale(1.06)}
.projrow-main{padding:26px 28px;display:flex;flex-direction:column;gap:8px}
.tag{font-size:11px;font-weight:800;letter-spacing:.13em;text-transform:uppercase;color:var(--blue)}
.projrow-main h3{font-size:19px;font-weight:800}
.projrow-loc{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--slate-500)}
.projrow-loc svg{width:13px;height:13px;color:var(--blue)}
.projrow-main p{font-size:13.5px;line-height:1.65;color:var(--slate-500);margin-top:4px}
.projrow-col{padding:26px 22px;display:flex;flex-direction:column;gap:20px;border-left:1px solid var(--line-soft)}
.projrow-col h4{font-size:12.5px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-800);margin-bottom:7px}
:lang(zh) .projrow-col h4{letter-spacing:.01em;text-transform:none;font-size:13.5px}
.projrow-col li,.projrow-col p{font-size:13px;line-height:1.6;color:var(--slate-500)}
.projrow-col li{padding-left:12px;position:relative}
.projrow-col li+li{margin-top:4px}
.projrow-col li::before{content:"";position:absolute;left:0;top:8.5px;width:4px;height:4px;
  border-radius:50%;background:var(--blue-400)}
.projrow-go{display:grid;place-items:center;border-left:1px solid var(--line-soft);color:var(--slate-400);
  transition:background .22s,color .22s}
.projrow-go svg{width:17px;height:17px;transition:transform .24s var(--ease)}
.projrow:hover .projrow-go{background:var(--blue);color:#fff}
.projrow:hover .projrow-go svg{transform:translateX(3px)}

/* why-partner strip */
.whystrip{background:linear-gradient(115deg,#08132c,#0e2049 55%,#0a1734);color:#fff;position:relative;overflow:hidden}
.whystrip::before{content:"";position:absolute;inset:0;opacity:.4;
  background:radial-gradient(600px 300px at 20% 0%,rgba(30,95,214,.3),transparent 60%)}
.whystrip .wrap{position:relative}
.whystrip h2{color:#fff;margin-bottom:34px}
.whygrid{display:grid;grid-template-columns:repeat(5,1fr);gap:26px}
.whygrid .ic{width:36px;height:36px;border-radius:var(--r-sm);display:grid;place-items:center;
  background:rgba(255,255,255,.09);border:1px solid rgba(255,255,255,.14);margin-bottom:14px}
.whygrid .ic svg{width:18px;height:18px;color:var(--blue-400)}
.whygrid b{display:block;font-size:14.5px;font-weight:700;color:#fff}
.whygrid p{font-size:12.5px;line-height:1.6;color:rgba(255,255,255,.6);margin-top:6px}

/* world map */
.mapsec{display:grid;grid-template-columns:minmax(0,.72fr) minmax(0,1.6fr);gap:52px;align-items:center}
.worldmap{position:relative}
.worldmap svg{width:100%;height:auto}
/* keep region labels legible where they cross the dot field */
.worldmap .pin text{paint-order:stroke;stroke:#fff;stroke-width:3.2px;stroke-linejoin:round}
.pin{fill:var(--blue);animation:pin 2.6s var(--ease) infinite}
.pin:nth-of-type(2){animation-delay:.35s}.pin:nth-of-type(3){animation-delay:.7s}
.pin:nth-of-type(4){animation-delay:1.05s}.pin:nth-of-type(5){animation-delay:1.4s}
.pin:nth-of-type(6){animation-delay:1.75s}
@keyframes pin{0%,72%,100%{opacity:1;transform:translateY(0)}82%{opacity:.65;transform:translateY(-3px)}}

/* ==========================================================================
   SOLUTIONS PAGE
   ========================================================================== */
.solblock{display:grid;grid-template-columns:270px minmax(0,1fr);background:#fff;
  border-radius:var(--r);box-shadow:var(--shadow-sm);overflow:hidden;border:1px solid var(--line)}
.solblock+.solblock{margin-top:26px}
.solside{background:linear-gradient(160deg,#0a1631 0%,#0e2049 100%);color:#fff;padding:38px 30px;
  display:flex;flex-direction:column}
.solside .num{font-size:13px;font-weight:800;color:var(--blue-400);letter-spacing:.1em}
.solside h2{color:#fff;font-size:23px;margin-top:8px;line-height:1.2}
.solside .rule{background:var(--blue-400);margin-block:16px 18px}
.solside p{font-size:13.5px;line-height:1.68;color:rgba(255,255,255,.66);flex:1}
.solside .link-arrow{color:var(--blue-400);margin-top:20px}
.solmain{padding:26px 26px 22px}
.solgrid{display:grid;gap:16px}
.solgrid[data-n="5"]{grid-template-columns:repeat(5,1fr)}
.solgrid[data-n="4"]{grid-template-columns:repeat(4,1fr)}
.solgrid[data-n="3"]{grid-template-columns:repeat(3,1fr)}
.solcard{display:flex;flex-direction:column;border-radius:var(--r);overflow:hidden;background:#fff;
  border:1px solid var(--line-soft);transition:border-color .22s,box-shadow .26s,transform .26s var(--ease)}
.solcard:hover{border-color:#c9d6ea;box-shadow:var(--shadow-sm);transform:translateY(-3px)}
.solcard-fig{position:relative;aspect-ratio:4/3;background:linear-gradient(160deg,#f7f9fc,#e9eef6);
  display:grid;place-items:center;padding:10px;overflow:hidden}
.solcard-fig img{width:100%;height:100%;object-fit:contain;transition:transform .5s var(--ease)}
.solcard:hover .solcard-fig img{transform:scale(1.06)}
.solcard .badge{position:absolute;left:12px;bottom:-15px;z-index:1;width:30px;height:30px;border-radius:50%;
  background:var(--blue);display:grid;place-items:center;box-shadow:0 4px 12px rgba(30,95,214,.4)}
.solcard .badge svg{width:15px;height:15px;color:#fff}
.solcard-body{padding:24px 14px 16px}
.solcard-body h3{font-size:13.5px;font-weight:700;line-height:1.35}
.solcard-body p{font-size:12px;line-height:1.5;color:var(--slate-500);margin-top:5px}
.keyapps{display:flex;align-items:center;gap:16px;flex-wrap:wrap;margin-top:22px;padding-top:18px;
  border-top:1px solid var(--line-soft)}
.keyapps>b{font-size:12.5px;font-weight:700;color:var(--blue);flex:none}
.keyapps ul{display:flex;gap:18px;flex-wrap:wrap}
.keyapps li{display:flex;align-items:center;gap:8px;font-size:12.5px;color:var(--slate-500);line-height:1.35}
.keyapps li svg{width:19px;height:19px;color:var(--blue);flex:none;opacity:.85}

/* ==========================================================================
   PRODUCTS PAGE / DETAIL
   ========================================================================== */
.catnav{position:sticky;top:var(--header-h);z-index:60;background:rgba(255,255,255,.94);
  backdrop-filter:blur(10px);border-bottom:1px solid var(--line-soft)}
.catnav ul{display:flex;gap:6px;overflow-x:auto;padding-block:12px;scrollbar-width:none}
.catnav ul::-webkit-scrollbar{display:none}
.catnav a{padding:9px 16px;border-radius:100px;font-size:13.5px;font-weight:600;color:var(--slate-500);
  white-space:nowrap;transition:background .2s,color .2s}
.catnav a:hover{background:var(--paper);color:var(--ink-800)}
.catnav a.is-on{background:var(--brand);color:#fff}

.catband{display:flex;align-items:flex-end;justify-content:space-between;gap:30px;flex-wrap:wrap;
  padding-bottom:22px;margin-bottom:32px;border-bottom:2px solid var(--line)}
.catband .num{font-size:12.5px;font-weight:800;letter-spacing:.16em;color:var(--blue)}
.catband h2{margin-top:8px}
.catband p{margin-top:10px;font-size:15px;color:var(--slate-500);max-width:60ch}

.prodgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:22px}
.prodgrid[data-n="3"]{grid-template-columns:repeat(3,1fr)}
.prodcard{display:flex;flex-direction:column;background:#fff;border:1px solid var(--line);
  border-radius:var(--r);overflow:hidden;transition:border-color .22s,box-shadow .28s,transform .28s var(--ease)}
.prodcard:hover{border-color:#c9d6ea;box-shadow:var(--shadow);transform:translateY(-4px)}
.prodcard-fig{aspect-ratio:4/3;background:linear-gradient(160deg,#f7f9fc,#eaeff7);position:relative;
  overflow:hidden;padding:14px;display:grid;place-items:center}
.prodcard-fig::before{content:"";position:absolute;inset:0;opacity:.55;
  background-image:linear-gradient(rgba(49,61,149,.05) 1px,transparent 1px),
                   linear-gradient(90deg,rgba(49,61,149,.05) 1px,transparent 1px);
  background-size:24px 24px}
.prodcard-fig img{position:relative;width:100%;height:100%;object-fit:contain;transition:transform .5s var(--ease)}
.prodcard:hover .prodcard-fig img{transform:scale(1.05)}
.prodcard-body{padding:20px;display:flex;flex-direction:column;gap:8px;flex:1}
.prodcard-body h3{font-size:16px;font-weight:700;line-height:1.3}
.prodcard-body .sub{font-size:12.5px;color:var(--blue);font-weight:600}
.prodcard-body p{font-size:13px;line-height:1.6;color:var(--slate-500);flex:1}
.prodcard-body .link-arrow{margin-top:4px;font-size:13px}

/* detail */
.pdetail{display:grid;grid-template-columns:minmax(0,1.02fr) minmax(0,1fr);gap:56px;align-items:start}
.pdetail-fig{background:linear-gradient(160deg,#f7f9fc,#e9eef6);border:1px solid var(--line);
  border-radius:var(--r-lg);padding:34px;position:relative;overflow:hidden}
.pdetail-fig::before{content:"";position:absolute;inset:0;opacity:.6;
  background-image:linear-gradient(rgba(49,61,149,.055) 1px,transparent 1px),
                   linear-gradient(90deg,rgba(49,61,149,.055) 1px,transparent 1px);
  background-size:30px 30px}
.pdetail-fig img{position:relative;width:100%}
.pdetail .tag{margin-bottom:10px;display:block}
.pdetail h1{font-size:clamp(26px,3.1vw,36px)}
.pdetail .lede{margin-top:16px}
.pdetail-acts{display:flex;gap:12px;margin-top:26px;flex-wrap:wrap}
.featlist{margin-top:32px;display:grid;gap:16px}
.featlist li{display:flex;gap:13px;align-items:flex-start}
.featlist .ic{width:30px;height:30px;flex:none;border-radius:var(--r-sm);display:grid;place-items:center;
  background:rgba(30,95,214,.09)}
.featlist .ic svg{width:15px;height:15px;color:var(--blue)}
.featlist b{display:block;font-size:14.5px;font-weight:700}
.featlist p{font-size:13.5px;line-height:1.6;color:var(--slate-500);margin-top:3px}

.spectable{border:1px solid var(--line);border-radius:var(--r);overflow:hidden;background:#fff}
.spectable tr+tr{border-top:1px solid var(--line-soft)}
.spectable th,.spectable td{padding:14px 20px;text-align:left;font-size:14px;vertical-align:top}
.spectable th{width:42%;font-weight:600;color:var(--slate-500);background:var(--paper)}
.spectable td{font-weight:600;font-variant-numeric:tabular-nums}
.chips{display:flex;flex-wrap:wrap;gap:9px}
.chips span{padding:7px 14px;border:1px solid var(--line);border-radius:100px;font-size:13px;
  color:var(--slate-700);background:#fff}

/* ==========================================================================
   ABOUT PAGE
   ========================================================================== */
.about-split{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);gap:56px;align-items:center}
.about-split p+p{margin-top:16px}
.about-fig{border-radius:var(--r);overflow:hidden;box-shadow:var(--shadow);aspect-ratio:16/10.5;background:var(--ink-700)}
.about-fig img{width:100%;height:100%;object-fit:cover}

.mvv{background:linear-gradient(115deg,#08132c,#0e2049 55%,#0a1734);color:#fff;position:relative;overflow:hidden}
.mvv::before{content:"";position:absolute;inset:0;opacity:.4;
  background:radial-gradient(700px 340px at 50% 0%,rgba(30,95,214,.3),transparent 62%)}
.mvv .wrap{position:relative}
.mvvgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:36px;text-align:center}
.mvvgrid .ic{width:56px;height:56px;margin:0 auto 18px;border-radius:50%;display:grid;place-items:center;
  border:1.5px solid rgba(255,255,255,.2);background:rgba(255,255,255,.05)}
.mvvgrid .ic svg{width:25px;height:25px;color:var(--blue-400)}
.mvvgrid h3{font-size:15px;font-weight:800;letter-spacing:.09em;text-transform:uppercase;color:#fff}
:lang(zh) .mvvgrid h3{letter-spacing:.02em;text-transform:none;font-size:17px}
.mvvgrid p{font-size:13px;line-height:1.65;color:rgba(255,255,255,.66);margin-top:12px}

/* timeline */
.timeline{position:relative;padding-top:14px}
.timeline::before{content:"";position:absolute;left:0;right:0;top:20px;height:2px;background:var(--line)}
.tl-items{display:grid;grid-template-columns:repeat(7,1fr);gap:12px}
.tl-item{position:relative;padding-top:38px;text-align:center}
.tl-item::before{content:"";position:absolute;left:50%;top:13px;transform:translateX(-50%);
  width:15px;height:15px;border-radius:50%;background:var(--blue);border:3px solid #fff;
  box-shadow:0 0 0 2px var(--blue);transition:transform .22s var(--ease)}
.tl-item:hover::before{transform:translateX(-50%) scale(1.22)}
.tl-item b{display:block;font-size:19px;font-weight:800;color:var(--ink-800);letter-spacing:-.01em}
.tl-item p{font-size:12.5px;line-height:1.6;color:var(--slate-500);margin-top:7px}

/* manufacturing tiles */
.mfg{display:grid;grid-template-columns:repeat(4,1fr);gap:20px}
.mfg .tile{aspect-ratio:4/3.05;border-radius:var(--r)}
.mfg .tile-body{align-items:flex-start;text-align:left;padding:22px;gap:10px}
.mfg .tile-body .ic{width:32px;height:32px;border-radius:50%;background:rgba(255,255,255,.16);
  border:1px solid rgba(255,255,255,.24);display:grid;place-items:center}
.mfg .tile-body .ic svg{width:15px;height:15px;color:#fff}
.mfg .tile-body h3{font-size:15px;max-width:none}
.mfg .tile-body p{font-size:12.5px;line-height:1.55;color:rgba(255,255,255,.78)}

/* application fields (products page) */
.fieldgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}
.fieldgrid .tile{aspect-ratio:4/3}
.fieldgrid .tile-body{align-items:flex-start;text-align:left;padding:22px;gap:6px}
.fieldgrid .tile-body h3{font-size:16px;max-width:none}
.fieldgrid .tile-body p{font-size:12.5px;line-height:1.55;color:rgba(255,255,255,.78)}

/* production equipment (about page) */
.eqgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:18px}
.eqcard{margin:0;background:#fff;border:1px solid var(--line);border-radius:var(--r);
  overflow:hidden;transition:border-color .22s,box-shadow .26s,transform .26s var(--ease)}
.eqcard:hover{border-color:#c9d6ea;box-shadow:var(--shadow-sm);transform:translateY(-3px)}
.eqcard img{width:100%;aspect-ratio:4/2.8;object-fit:cover;transition:transform .55s var(--ease)}
.eqcard:hover img{transform:scale(1.05)}
.eqcard figcaption{padding:15px 16px 17px;display:flex;flex-direction:column;gap:5px}
.eqcard b{font-size:14px;font-weight:700;line-height:1.3}
.eqcard span{font-size:12.5px;line-height:1.55;color:var(--slate-500)}

/* certifications */
.certgrid{display:grid;grid-template-columns:repeat(6,1fr);gap:18px}
.certcard{border:1px solid var(--line);border-radius:var(--r);background:#fff;padding:22px 14px;
  display:flex;flex-direction:column;align-items:center;gap:14px;text-align:center;
  transition:border-color .22s,box-shadow .26s,transform .26s var(--ease)}
.certcard:hover{border-color:#c9d6ea;box-shadow:var(--shadow-sm);transform:translateY(-3px)}
.certcard .mark{height:56px;display:grid;place-items:center;color:var(--brand)}
.certcard .mark svg{height:52px;width:auto}
.certcard span{font-size:12.5px;color:var(--slate-500);line-height:1.4}

.certshelf{margin:26px 0 0;border:1px solid var(--line);border-radius:var(--r);background:#fff;
  padding:22px 22px 16px;text-align:center}
.certshelf img{width:100%;border-radius:var(--r-sm)}
.certshelf figcaption{margin-top:14px;font-size:12.5px;color:var(--slate-500)}

/* customer logos */
.logogrid{display:grid;grid-template-columns:repeat(6,1fr);gap:14px}
.logocell{border:1px solid var(--line);border-radius:var(--r);background:#fff;height:82px;
  display:grid;place-items:center;padding:12px;transition:border-color .22s,box-shadow .24s}
.logocell:hover{border-color:#c9d6ea;box-shadow:var(--shadow-sm)}
.logocell img{width:auto;height:auto;max-width:118px;max-height:44px;
  filter:grayscale(1) opacity(.6);transition:filter .3s var(--ease)}
.logocell:hover img{filter:none}

/* ==========================================================================
   CONTACT PAGE
   ========================================================================== */
.contact-split{display:grid;grid-template-columns:minmax(0,1.25fr) minmax(0,.8fr);gap:44px;align-items:start}
.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.field{display:flex;flex-direction:column}
.field.full{grid-column:1/-1}
.field input,.field textarea{
  width:100%;padding:13px 16px;border:1px solid var(--line);border-radius:var(--r-sm);
  background:#fff;font-size:14.5px;transition:border-color .2s,box-shadow .2s;
}
.field textarea{min-height:130px;resize:vertical}
.field input::placeholder,.field textarea::placeholder{color:var(--slate-400)}
.field input:focus,.field textarea:focus{outline:none;border-color:var(--blue);
  box-shadow:0 0 0 3px rgba(30,95,214,.12)}
.field .err{font-size:12.5px;color:#d92d20;margin-top:6px;display:none}
.field.is-bad input,.field.is-bad textarea{border-color:#d92d20}
.field.is-bad .err{display:block}
.form-note{margin-top:16px;font-size:12.5px;color:var(--slate-400);line-height:1.6}
.form-ok{display:none;margin-top:18px;padding:14px 18px;border-radius:var(--r-sm);
  background:rgba(16,185,129,.1);border:1px solid rgba(16,185,129,.3);color:#047857;font-size:14px}
.form-ok.is-on{display:block}

.infocard{background:var(--paper);border-radius:var(--r);padding:34px 30px}
.infocard h2{font-size:21px}
.inforow{display:flex;gap:15px;align-items:flex-start;margin-top:26px}
.inforow .ic{width:38px;height:38px;flex:none;border-radius:50%;background:#fff;display:grid;
  place-items:center;box-shadow:var(--shadow-sm)}
.inforow .ic svg{width:17px;height:17px;color:var(--blue)}
.inforow b{display:block;font-size:14.5px;font-weight:700}
.inforow p,.inforow a{font-size:13.5px;line-height:1.6;color:var(--slate-500);margin-top:4px;display:block}
.inforow a:hover{color:var(--blue)}

.offices{display:grid;grid-template-columns:repeat(4,1fr);gap:22px}
.office{background:#fff;border:1px solid var(--line);border-radius:var(--r);overflow:hidden;
  display:flex;flex-direction:column;transition:box-shadow .26s,transform .26s var(--ease),border-color .22s}
.office:hover{box-shadow:var(--shadow);transform:translateY(-4px);border-color:#c9d6ea}
.office-fig{aspect-ratio:16/9.4;overflow:hidden;background:var(--ink-700)}
.office-fig img{width:100%;height:100%;object-fit:cover;transition:transform .6s var(--ease)}
.office:hover .office-fig img{transform:scale(1.06)}
.office-body{padding:20px;display:flex;flex-direction:column;gap:7px;font-size:13.5px;color:var(--slate-500)}
.office-body h3{font-size:15px;font-weight:800;color:var(--blue);text-transform:uppercase;letter-spacing:.02em}
:lang(zh) .office-body h3{text-transform:none}
.office-body .role{font-size:13px;font-weight:600;color:var(--ink-800)}
.office-body a:hover{color:var(--blue)}

/* ==========================================================================
   REVEAL / MOTION
   ========================================================================== */
/* Short travel and a brisk curve: the point is a sense of arrival, not a
   performance. A long slow rise on every block is what makes a page feel
   padded out. */
[data-reveal]{opacity:0;transform:translateY(14px);
  transition:opacity .52s var(--ease),transform .52s var(--ease)}
[data-reveal].is-in{opacity:1;transform:none}
[data-reveal][data-d="1"]{transition-delay:.07s}
[data-reveal][data-d="2"]{transition-delay:.14s}
[data-reveal][data-d="3"]{transition-delay:.21s}
[data-reveal][data-d="4"]{transition-delay:.28s}
[data-reveal][data-d="5"]{transition-delay:.35s}
[data-reveal][data-d="6"]{transition-delay:.42s}
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important}
  [data-reveal]{opacity:1;transform:none}
}

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */
@media (max-width:1180px){
  .footer-in{grid-template-columns:minmax(200px,1.4fr) repeat(3,1fr)}
  /* No room for a clear lane down the middle. The render fades back to a
     texture behind the copy; the machine is the subject only on wide screens. */
  .cap-in{grid-template-columns:minmax(0,1fr) minmax(0,.82fr);gap:40px;padding-block:72px}
  .cap-copy{grid-column:1}
  .cap-specs{grid-column:2}
  /* Cover crops hard into the rack at this width and it collides with the
     copy, so the plate steps back to a texture and legibility wins. */
  .cap-media img{opacity:.4}
  .cap-media::after{
    background:
      linear-gradient(90deg,rgba(4,10,26,.94) 0%,rgba(5,12,32,.9) 52%,rgba(6,16,42,.82) 100%),
      linear-gradient(0deg,rgba(4,10,26,.5),rgba(4,10,26,.2) 50%,rgba(4,10,26,.45) 100%);
  }
  .projrow{grid-template-columns:220px minmax(0,1.2fr) minmax(0,1fr) minmax(0,1fr) 42px}
  .certgrid{grid-template-columns:repeat(3,1fr)}
  .eqgrid{grid-template-columns:repeat(3,1fr)}
  .logogrid{grid-template-columns:repeat(4,1fr)}
  /* the hairline pattern is tied to the column count, so it is restated
     wherever the grid changes */
  /* fewer marks visible at once, so shorten the loop to keep the pace even */
  .trust-track{animation-duration:38s}
  .trust-track li{padding:20px 32px}
  .tl-items{grid-template-columns:repeat(4,1fr);row-gap:30px}
  .timeline::before{display:none}
  .tl-item{padding-top:34px}
  .tl-item::before{top:6px}
}
@media (max-width:1024px){
  :root{--gut:24px}
  .nav{display:none;position:absolute;left:0;right:0;top:var(--header-h);flex-direction:column;
    align-items:stretch;gap:0;background:#fff;border-bottom:1px solid var(--line);
    box-shadow:0 14px 34px rgba(10,22,49,.12);padding:10px 16px 18px}
  .nav.is-open{display:flex}
  .nav a{padding:14px 10px;border-radius:0;font-size:15.5px}
  .nav a+a{border-top:1px solid var(--line-soft)}
  .nav a::after{display:none}
  /* the header CTA is too wide for a phone header bar — show it in the menu */
  .header-cta{display:none}
  .nav-cta{
    display:flex;align-items:center;justify-content:center;gap:8px;
    margin-top:14px;padding:14px 18px;border:0;border-radius:var(--r-sm);
    background:var(--blue);color:#fff;font-size:15px;font-weight:700;
  }
  .nav-cta svg{width:15px;height:15px}
  .nav a.nav-cta{color:#fff}
  .burger{display:grid}
  .pcards,.catcards,.prodgrid,.offices,.mfg,.fieldgrid,.eqgrid{grid-template-columns:repeat(2,1fr)}
  .prodgrid[data-n="3"]{grid-template-columns:repeat(2,1fr)}
  /* Same pinned behaviour, stacked: the card on top, the photograph beneath
     it. Both shrink so the pair still clears the viewport. */
  .story-stage{padding-block:24px}
  .story-grid{grid-template-columns:1fr;grid-template-rows:auto 1fr;gap:0;
    max-height:none}
  .story-card{padding:30px 28px 34px;border-radius:10px 10px 0 0}
  .story-card h2{margin-top:16px;font-size:clamp(24px,3.4vw,30px)}
  .story-quote{margin-top:16px;padding-top:18px}
  .story-quote p{font-size:15.5px}
  :lang(zh) .story-quote p{font-size:16px}
  .story-by{margin-top:16px}
  .story-more{margin-top:18px}
  .story-media{border-radius:0 0 10px 10px;min-height:180px}
  .solcards{grid-template-columns:1fr;gap:18px}
  .solcard-lg{aspect-ratio:16/6.4}
  .solcard-lg p{max-width:52ch}
  .matrix{grid-template-columns:repeat(3,1fr)}
  .tiles-3{grid-template-columns:1fr}
  .solblock{grid-template-columns:1fr}
  .solgrid[data-n="5"],.solgrid[data-n="4"]{grid-template-columns:repeat(3,1fr)}
  .whygrid{grid-template-columns:repeat(3,1fr);row-gap:30px}
  .mvvgrid{grid-template-columns:repeat(2,1fr);row-gap:38px}
  .mapsec,.about-split,.contact-split,.pdetail{grid-template-columns:1fr;gap:36px}
  .projrow{grid-template-columns:1fr 1fr;grid-template-areas:"fig fig" "main main" "c1 c2"}
  .projrow-fig{grid-area:fig;aspect-ratio:16/6.5;min-height:0}
  .projrow-main{grid-area:main}
  .projrow-col{border-left:0;border-top:1px solid var(--line-soft)}
  .projrow-col:nth-of-type(3){grid-area:c1}
  .projrow-col:nth-of-type(4){grid-area:c2;border-left:1px solid var(--line-soft)}
  .projrow-go{display:none}
  .cta-art{display:none}
  .cta-dark .cta-in{padding-inline:34px}
}
@media (max-width:760px){
  :root{--gut:20px}
  .sec{padding-block:56px}
  .sec-sm{padding-block:44px}
  .hero{min-height:0}
  .hero-in{padding-block:64px 72px}
  /* Portrait crops tightly around the ceiling unit, and white type over a
     white machine loses contrast. Pan left onto the darker plant floor —
     the airflow trails run through there too, so the story survives. */
  .hero-media img{object-position:34% center}
  .hero-media::after{
    background:
      linear-gradient(100deg,rgba(5,11,26,.9) 0%,rgba(6,14,32,.78) 42%,rgba(8,18,40,.5) 100%),
      linear-gradient(0deg,rgba(5,11,26,.66),rgba(5,11,26,0) 46%);
  }
  .telemetry{gap:22px;margin-top:40px}
  .phero{padding-block:44px 46px}
  .phero-stats,.phero-feats,.phero-contact{grid-template-columns:1fr 1fr;gap:22px}
  .tiles-2,.pcards,.catcards,.prodgrid,.offices,.mfg,.fieldgrid,.form-grid{grid-template-columns:1fr}
  .prodgrid[data-n="3"]{grid-template-columns:1fr}
  .solcard-lg{aspect-ratio:16/11}
  .solcard-lg-body{padding:22px}
  .solcard-lg h3{font-size:18px}
  .matrix{grid-template-columns:repeat(2,1fr)}
  .tab{padding:11px 14px 13px;font-size:13.5px}
  .tab::after{left:10px;right:10px}
  .solgrid[data-n="5"],.solgrid[data-n="4"],.solgrid[data-n="3"]{grid-template-columns:1fr 1fr}
  .whygrid{grid-template-columns:1fr 1fr}
  .certgrid,.logogrid,.eqgrid{grid-template-columns:repeat(2,1fr)}
  .trust{padding-block:36px 10px}
  .trust-head{margin-bottom:18px;font-size:11.5px;letter-spacing:.1em}
  .trust-track{animation-duration:28s}
  .trust-track li{padding:14px 24px}
  .trust-track img{max-width:104px;max-height:34px}
  .tl-items{grid-template-columns:1fr 1fr}
  .cap-in{grid-template-columns:1fr;padding-block:56px;gap:34px}
  .cap-copy,.cap-specs{grid-column:1}
  .cap-specs{flex-direction:column;gap:20px}
  .cap-media img{opacity:.32}
  .projrow{grid-template-columns:1fr;grid-template-areas:"fig" "main" "c1" "c2"}
  .projrow-col:nth-of-type(4){border-left:0}
  .cta-in{flex-direction:column;align-items:flex-start;gap:26px}
  .cta-dark .cta-in{padding-inline:26px}
  .footer-in{grid-template-columns:1fr 1fr;gap:30px}
  .footer-brand{grid-column:1/-1}
  .spectable th,.spectable td{padding:12px 14px;font-size:13.5px}
}
@media (max-width:460px){
  .solgrid[data-n="5"],.solgrid[data-n="4"],.solgrid[data-n="3"]{grid-template-columns:1fr}
  .whygrid,.certgrid,.logogrid,.tl-items{grid-template-columns:1fr}
  .phero-stats,.phero-feats,.phero-contact{grid-template-columns:1fr}
  .hero-cta .btn,.cta-acts .btn{width:100%;justify-content:center}
}

/* ---------- print ---------- */
@media print{
  .header,.footer,.cta,.catnav,.skip{display:none}
  body{color:#000}
  .phero,.hero{background:#fff;color:#000;min-height:0;padding-block:20px}
  .phero-media,.hero-media,.hero-beams{display:none}
  .phero h1,.hero h1{color:#000}
}
