/* ==========================================================================
   BM 居和国际 · JUHE INTERNATIONAL — one-page site
   Light, warm, premium. Desktop + mobile responsive.
   ========================================================================== */

/* --------------------------------------------------------------------------
   PALETTE — aligned to the 2026-09 LOGO (slate blue #4B5A65 + gold #CBA465).

   Two switchable themes, so the client can A/B them before launch:
     (default)        → LOGO palette: slate primary + gold accent
     html.theme-green → the previous deep-green #0E6353 palette, kept intact

   Rule: every surface/text colour on a brand tint must come from a variable
   here. Never hard-code a brand-adjacent hex below this block, or the theme
   switch will leave orphan colours behind.
   -------------------------------------------------------------------------- */
:root{
  /* neutrals — kept warm so wood imagery and the gold accent sit naturally */
  --ink:#1A1A18;
  --ink-2:#5B5751;
  /* muted tier for real (content-bearing) text: spec lines, footnotes, the
     native name beside each language. #8C877E read only 3.57:1 on white and
     3.10:1 on --brand-tint — below WCAG AA for small text. #6F6B65 keeps the
     "whisper" tier visually separate from --ink-2 while clearing 4.5:1 on every
     surface it actually sits on (white 5.29 / warm 4.85 / soft 4.90 / tint 4.59). */
  --ink-3:#6F6B65;
  --line:#E6E1D8;
  --line-2:#F0ECE4;
  --bg:#FFFFFF;
  --bg-soft:#F8F6F2;
  --bg-warm:#F3EFE8;
  /* brand — slate blue sampled from the LOGO wordmark */
  --brand:#4B5A65;
  --brand-d:#333E47;
  --brand-l:#66757F;
  --brand-tint:#EDEFF1;
  --gold:#CBA465;
  --brand-rgb:75,90,101;   /* --brand as R,G,B — for translucent glows/washes */
  /* derived surfaces */
  --hover-line:#C9D2D8;    /* card / tile hover border */
  --on-dark:#DDE3E7;       /* text on dark surfaces */
  --on-dark-dim:#A3AEB5;   /* muted text on dark surfaces */
  --on-dark-mute:#8E9AA2;  /* footnote text on dark surfaces (footer legal line) */
  --ft-bg:#262E35;         /* footer */
  --dot:var(--gold);       /* top-bar bullet dots */
  /* action colours — the LOGO pairs a slate wordmark with a gold arch, so the
     site mirrors that: slate carries surfaces/structure, gold carries action.
     Gold is a LIGHT colour: it may only be used as a fill behind dark text, or
     on a dark surface. As text on white it is 2.3:1 and fails WCAG AA badly. */
  --btn-bg:var(--gold);
  --btn-fg:#2A2E33;
  --btn-bg-h:#D8B47C;
  --stat-fg:var(--gold);        /* stat figures sit on --brand, 3.1:1 — large text only */
  --rule-accent:var(--gold);    /* the 22x2px rule before each .eyebrow */
  --radius:6px;
  --radius-lg:14px;
  --shadow-s:0 1px 2px rgba(26,26,24,.05), 0 2px 8px rgba(26,26,24,.04);
  --shadow-m:0 6px 22px rgba(26,26,24,.08);
  --shadow-l:0 18px 60px rgba(26,26,24,.14);
  --wrap:1240px;
  --hdr-h:70px;
  --font:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Hiragino Sans GB",
         "Microsoft YaHei","Noto Sans SC","Leelawadee UI","Khmer UI","Noto Sans Thai",
         "Noto Sans Khmer","Segoe UI Historic",Roboto,Arial,Helvetica,sans-serif;
}

/* Legacy deep-green palette — only the brand-derived tokens change, so the
   whole site flips with one class. Apply with <html class="theme-green">.
   Kept so the client can compare the two versions side by side. */
html.theme-green{
  --brand:#0E6353;
  --brand-rgb:14,99,83;
  --brand-d:#0A4A3E;
  --brand-l:#14785F;
  --brand-tint:#EAF3F0;
  --gold:#B0894A;
  --hover-line:#CFE2DC;
  --on-dark:#DCE9E5;
  --on-dark-dim:#9DB3AD;
  --on-dark-mute:#87A39C;
  --ft-bg:#14211E;
  --dot:#7FC3AF;
  /* on the green palette the primary button stays white-on-green and the stat
     figures stay white: #B0894A on #0E6353 is only 2.2:1, well under AA. */
  --btn-bg:var(--brand);
  --btn-fg:#fff;
  --btn-bg-h:var(--brand-d);
  --stat-fg:#fff;
  --rule-accent:var(--brand);
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{
  margin:0;font-family:var(--font);color:var(--ink);background:var(--bg);
  font-size:16px;line-height:1.7;-webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
img{max-width:100%;height:auto;display:block}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
ul{margin:0;padding:0;list-style:none}
h1,h2,h3,h4{margin:0;line-height:1.25;font-weight:700;letter-spacing:-.01em}

.wrap{width:100%;max-width:var(--wrap);margin:0 auto;padding:0 22px}
/* Off-canvas via transform, NOT left:-9999px — a negative offset on the
   inline-start side becomes 9999px of scrollable overflow in RTL, which is what
   gave the Arabic page a phantom horizontal scrollbar.  position:fixed never
   contributes to the document's scrollable area. */
.skip{
  position:fixed;top:0;left:50%;transform:translate(-50%,-180%);z-index:99;
  background:#fff;padding:8px 14px;border-radius:0 0 6px 6px;box-shadow:var(--shadow-m);
}
.skip:focus{transform:translate(-50%,0)}

/* ---------- shared type ---------- */
.eyebrow{
  display:inline-flex;align-items:center;gap:9px;
  font-size:12.5px;font-weight:600;letter-spacing:.16em;text-transform:uppercase;
  color:var(--brand);margin-bottom:14px;
}
.eyebrow::before{content:"";width:22px;height:2px;background:var(--rule-accent);flex:none}
.sec{padding:88px 0}
.sec.tight{padding:64px 0}
.sec.soft{background:var(--bg-soft)}
.sec.warm{background:var(--bg-warm)}
.sec-head{max-width:760px;margin-bottom:44px}
.sec-head.center{margin-left:auto;margin-right:auto;text-align:center}
.sec-head.center .eyebrow{justify-content:center}
/* text-wrap:balance keeps two-line headings from dropping a single orphan
   character onto the last line (「…门墙柜解决方 / 案」 in Chinese). Same
   technique already used on .btn > span. */
.sec-title{font-size:clamp(25px,3.4vw,40px);text-wrap:balance}
.sec-sub{margin:14px 0 0;color:var(--ink-2);font-size:16px;line-height:1.85}

/* ---------- buttons ---------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  padding:13px 24px;border-radius:999px;font-size:14.5px;font-weight:600;
  letter-spacing:.02em;max-width:100%;text-align:center;
  /* NOT white-space:nowrap. Button labels are 12-language copy, and German
     compounds ("Zeichnungen und Konfigurationsberatung anfordern", 48 chars)
     have a min-content width of ~390px — wider than a 390px phone. A nowrap
     button cannot shrink below min-content, so it pushed the document 15px
     wide and gave German phones a horizontal scrollbar that no other language
     had. Letting the label wrap, with break-word as the last-resort net, keeps
     the box inside its column in every language. */
  white-space:normal;overflow-wrap:break-word;hyphens:auto;
  border:1px solid transparent;
  transition:background-color .22s ease,color .22s ease,border-color .22s ease,
             transform .22s ease,box-shadow .22s ease;
}
.btn > span{min-width:0;text-wrap:balance}
.btn svg{width:16px;height:16px;flex:none}
.btn-brand{background:var(--btn-bg);color:var(--btn-fg)}
.btn-brand:hover{background:var(--btn-bg-h);transform:translateY(-1px);box-shadow:var(--shadow-m)}
.btn-line{border-color:var(--line);color:var(--ink);background:#fff}
.btn-line:hover{border-color:var(--brand);color:var(--brand)}
.btn-ghost{color:#fff;border-color:rgba(255,255,255,.5)}
.btn-ghost:hover{background:rgba(255,255,255,.14);border-color:#fff}
/* token-based on purpose — a hard-coded WhatsApp green here would orphan the
   same way .ic.wa did as soon as the theme flips */
.btn-wa{background:var(--brand);color:#fff}

/* ---------- topbar ---------- */
.topbar{background:var(--brand-d);color:var(--on-dark);font-size:13px}
.topbar .wrap{display:flex;align-items:center;gap:20px;height:38px;overflow:hidden}
.tb-item{display:flex;align-items:center;gap:7px;white-space:nowrap}
.tb-item i{width:5px;height:5px;border-radius:50%;background:var(--dot);display:inline-block}
.tb-sp{flex:1}
.topbar a{color:var(--on-dark);display:flex;align-items:center;gap:7px;white-space:nowrap}
.topbar a:hover{color:#fff}
.topbar svg{width:14px;height:14px}

/* ---------- header ---------- */
.hdr{
  position:sticky;top:0;z-index:60;background:rgba(255,255,255,.94);
  backdrop-filter:saturate(180%) blur(14px);border-bottom:1px solid var(--line-2);
}
.hdr.scrolled{box-shadow:0 4px 24px rgba(26,26,24,.07)}
.hdr-in{display:flex;align-items:center;gap:26px;height:var(--hdr-h)}
.logo{display:flex;align-items:center;gap:11px;flex:none}
/* Real LOGO artwork (2026-09 lock-up: arch mark + "BM Juhe / International
   Group"). Replaces the old .logo-mark/.logo-txt text build-up — the artwork
   already carries the wordmark, so no adjacent text is needed, and the header
   block ends up ~50px narrower, which buys the nav some breathing room.
   The legacy .logo-mark / .logo-txt rules further down are now unused. */
.logo img{display:block;height:clamp(34px,3.1vw,42px);width:auto}

.nav{display:flex;align-items:center;gap:4px;margin-left:auto}
/* Top-level rows only. The "Products" item owns a dropdown panel whose links
   must NOT inherit the header sizing — otherwise the .fit1/.fit2/.fit3 tiers
   below would also shrink the panel's own rows. */
.nav > a,.nav-item > a{
  padding:9px 13px;border-radius:8px;font-size:14.5px;font-weight:500;color:var(--ink-2);
  transition:color .18s,background-color .18s;white-space:nowrap;
  display:flex;align-items:center;gap:6px;
}
.nav > a:hover,.nav > a.on,
.nav-item > a:hover,.nav-item.on > a{color:var(--brand);background:var(--brand-tint)}

/* ---------- nav dropdown (7 product categories) ---------- */
.nav-item{position:relative;display:flex;align-items:center}
.nav-sub-toggle{
  width:20px;height:20px;border-radius:6px;display:grid;place-items:center;flex:none;
  color:var(--ink-3);margin-inline-start:-5px;
}
.nav-sub-toggle svg{width:10px;height:10px;transition:transform .2s}
.nav-item.open .nav-sub-toggle svg{transform:rotate(180deg)}
.nav-sub-toggle:hover{background:var(--brand-tint);color:var(--brand)}
.nav-sub{
  position:absolute;top:calc(100% + 9px);inset-inline-start:0;width:258px;z-index:5;
  background:#fff;border:1px solid var(--line);border-radius:var(--radius-lg);
  box-shadow:var(--shadow-l);padding:8px;
  opacity:0;visibility:hidden;transform:translateY(-6px);transition:.2s;
}
/* invisible bridge so the pointer can travel from trigger to panel */
.nav-sub::before{content:"";position:absolute;inset-inline:0;top:-11px;height:11px}
.nav-item.open .nav-sub,
.nav-item.has-sub:hover .nav-sub{opacity:1;visibility:visible;transform:none}
.nav-sub a{
  display:flex;align-items:center;gap:10px;padding:9px 11px;border-radius:8px;
  font-size:13.5px;font-weight:500;color:var(--ink-2);white-space:normal;line-height:1.4;
}
.nav-sub a:hover{background:var(--bg-soft);color:var(--brand)}
.nav-sub a em{font-style:normal;font-size:11px;font-weight:600;color:var(--ink-3);
  margin-inline-start:auto;letter-spacing:.03em;flex:none}

/* ---------- level 2 — one row per category, each owning a third level ----------
   The row itself still links to the category page (the name is always one click
   away); landing on it opens a fly-out with that category's own three sub-topics.
   Which three differs per category — see .nav-fly below. */
.sub-item{position:relative;display:flex;align-items:center}
.sub-item > a{flex:1;min-width:0}
.sub-item:hover > a,
.sub-item:focus-within > a,
.sub-item.open > a{background:var(--bg-soft);color:var(--brand)}
/* The chevron is a pure indicator wherever hover exists (the panel opens on
   its own), and a real toggle on touch — see the (hover:none) / drawer blocks. */
.sub-tgl{
  width:22px;height:22px;flex:none;display:grid;place-items:center;border-radius:6px;
  color:var(--ink-3);margin-inline-end:5px;pointer-events:none;
}
.sub-tgl svg{width:9px;height:9px}
[dir="rtl"] .sub-tgl svg{transform:scaleX(-1)}

/* ---------- level 3 — the fly-out ----------
   The offset is measured from the .sub-item, not from the panel, so it has to
   clear the panel's own 8px padding as well as the 6px gutter — otherwise the
   fly-out's left edge lands on top of the panel border. */
.nav-fly{
  position:absolute;top:-9px;inset-inline-start:calc(100% + 14px);width:206px;z-index:6;
  background:#fff;border:1px solid var(--line);border-radius:var(--radius-lg);
  box-shadow:var(--shadow-l);padding:7px;
  opacity:0;visibility:hidden;transform:translateX(-6px);transition:.18s;
}
[dir="rtl"] .nav-fly{transform:translateX(6px)}
/* bridge across the gutter so the pointer can reach the fly-out without a gap */
.nav-fly::before{content:"";position:absolute;inset-block:0;inset-inline-end:100%;width:14px}
.sub-item:hover > .nav-fly,
.sub-item:focus-within > .nav-fly,
.sub-item.open > .nav-fly{opacity:1;visibility:visible;transform:none}
.nav-fly a{padding:8px 10px;border-radius:7px;font-size:12.8px}
.nav-fly a:hover{background:var(--bg-soft);color:var(--brand)}
/* short guide rule per row — the same accent language as .eyebrow */
.nav-fly a::before{
  content:"";width:7px;height:1px;flex:none;background:var(--hover-line);
  transition:background-color .18s;
}
.nav-fly a:hover::before{background:var(--brand)}
/* No hover on touch hardware: the chevron stops being decoration and becomes a
   real toggle, otherwise the third level would be unreachable there. */
@media (hover:none){
  .sub-tgl{pointer-events:auto}
  .sub-tgl:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
}
.hdr-act{display:flex;align-items:center;gap:10px;flex:none}

/* ---------- header auto-fit ------------------------------------------------
   Eight nav labels in twelve languages do not fit one 1240px row at a single
   type size: Latin translations are 1.6–1.9× longer than Chinese, so en/fr/de/
   it/no/vi/km/ms/lt all pushed the CTA out of the container and gave the page a
   horizontal scrollbar.  fitHeader() in app.js measures the row and steps down
   through these tiers only as far as it has to, so short-label languages
   (zh, th) keep the full-size navigation. */
.hdr.fit1 .nav > a,.hdr.fit1 .nav-item > a{padding:9px 10px;font-size:13.5px}
.hdr.fit1 .hdr-in{gap:18px}

.hdr.fit2 .nav > a,.hdr.fit2 .nav-item > a{padding:9px 8px;font-size:12.6px}
.hdr.fit2 .hdr-in{gap:15px}
.hdr.fit2 .hdr-act{gap:7px}
.hdr.fit2 .lang-btn{padding:8px 10px;font-size:12.8px}

/* last resort — the brand lock-up loses its English subline before anything
   is allowed to spill outside the container */
.hdr.fit3 .nav > a,.hdr.fit3 .nav-item > a{padding:8px 7px;font-size:12px}
.hdr.fit3 .logo-txt i{display:none}
.hdr.fit3 .hdr-act .btn-brand{padding:10px 14px;font-size:13.5px}

/* while fitHeader() measures the row the transitions must be off: a running
   transition makes getComputedStyle report the *starting* value, so every
   measurement looked like an overflow and the header fell through to fit3. */
.hdr.measuring,.hdr.measuring *{transition:none!important}

/* language picker */
.lang{position:relative}
.lang-btn{
  display:flex;align-items:center;gap:7px;padding:9px 12px;border:1px solid var(--line);
  border-radius:999px;font-size:13.5px;font-weight:600;color:var(--ink-2);
}
.lang-btn:hover{border-color:var(--brand);color:var(--brand)}
.lang-btn svg{width:13px;height:13px;transition:.2s}
.lang.open .lang-btn svg{transform:rotate(180deg)}
.lang-menu{
  position:absolute;top:calc(100% + 8px);inset-inline-end:0;width:210px;max-height:60vh;
  overflow:auto;background:#fff;border:1px solid var(--line);border-radius:var(--radius-lg);
  box-shadow:var(--shadow-l);padding:7px;opacity:0;visibility:hidden;transform:translateY(-6px);
  transition:.2s;
}
.lang.open .lang-menu{opacity:1;visibility:visible;transform:none}
.lang-menu button{
  display:flex;width:100%;text-align:start;padding:9px 11px;border-radius:8px;
  font-size:14px;gap:9px;align-items:center;
}
.lang-menu button:hover{background:var(--bg-soft)}
.lang-menu button.on{background:var(--brand-tint);color:var(--brand);font-weight:600}
.lang-menu em{font-style:normal;font-size:11px;color:var(--ink-3);margin-inline-start:auto}

.burger{display:none;width:42px;height:42px;border:1px solid var(--line);border-radius:10px;
  place-items:center}
.burger span{display:block;width:18px;height:2px;background:var(--ink);position:relative}
.burger span::before,.burger span::after{
  content:"";position:absolute;left:0;width:18px;height:2px;background:var(--ink);transition:.2s}
.burger span::before{top:-6px}.burger span::after{top:6px}

/* ---------- hero ---------- */
.hero{position:relative;background:linear-gradient(180deg,#FBF9F6 0%,var(--bg-soft) 100%);overflow:hidden}
.hero::after{
  content:"";position:absolute;inset-inline-end:-160px;top:-160px;width:520px;height:520px;
  background:radial-gradient(circle,rgba(var(--brand-rgb),.07),transparent 66%);border-radius:50%;
}
.hero-in{
  position:relative;z-index:1;display:grid;grid-template-columns:1fr 1fr;gap:56px;
  align-items:center;padding:64px 22px 72px;
}
.badge{
  display:inline-flex;align-items:center;gap:8px;background:#fff;border:1px solid var(--line);
  border-radius:999px;padding:7px 15px 7px 9px;font-size:12.5px;font-weight:600;
  color:var(--ink-2);box-shadow:var(--shadow-s);margin-bottom:22px;
}
.badge b{background:var(--brand);color:#fff;border-radius:999px;padding:3px 9px;font-size:11px;
  letter-spacing:.04em}
.hero h1{font-size:clamp(30px,4.6vw,54px);letter-spacing:-.02em}
.hero h1 em{font-style:normal;color:var(--brand);display:block}
.hero-sub{margin:20px 0 0;font-size:clamp(15px,1.5vw,17.5px);color:var(--ink-2);line-height:1.9;
  max-width:540px}
.hero-cta{display:flex;gap:12px;flex-wrap:wrap;margin-top:32px}
.hero-tags{display:flex;flex-wrap:wrap;gap:10px;margin-top:34px}
.hero-tags li{
  display:flex;align-items:center;gap:8px;font-size:13.5px;color:var(--ink-2);
  background:#fff;border:1px solid var(--line);border-radius:10px;padding:9px 13px;
}
.hero-tags svg{width:15px;height:15px;color:var(--brand);flex:none}
.hero-media{position:relative}
.hero-media picture,.hero-media img{display:block;width:100%}
.hero-media img{
  width:100%;aspect-ratio:4/4.6;object-fit:cover;object-position:center 42%;
  border-radius:var(--radius-lg);box-shadow:var(--shadow-l);
}
.hero-float{
  position:absolute;inset-inline-start:-18px;bottom:34px;background:#fff;border-radius:var(--radius-lg);
  padding:15px 19px;box-shadow:var(--shadow-m);border:1px solid var(--line-2);
}
.hero-float b{display:block;font-size:21px;color:var(--brand);letter-spacing:-.01em}
.hero-float span{font-size:11.5px;color:var(--ink-3);letter-spacing:.06em;text-transform:uppercase;
  font-weight:600}

/* ---------- stats strip ---------- */
.stats{background:var(--brand);color:#fff}
.stats .wrap{
  display:grid;grid-template-columns:repeat(4,1fr);gap:0;
}
.stat{padding:30px 20px;text-align:center;border-inline-end:1px solid rgba(255,255,255,.13)}
.stat:last-child{border:0}
.stat b{display:block;font-size:clamp(24px,2.8vw,34px);font-weight:800;letter-spacing:-.02em;color:var(--stat-fg)}
/* The unit suffix (+ / %) renders at .55em = 13–18.7px, which is NOT "large
   text" under WCAG (large needs >=24px, or >=18.66px AND bold). Gold on the
   slate band is only 3.06:1, so the glyph used to fail AA. The figure itself
   stays LOGO gold; the suffix takes the light on-dark neutral (5.4:1). */
.stat b i{font-style:normal;font-size:.55em;font-weight:600;margin-inline-start:2px;color:var(--on-dark)}
.stat span{display:block;margin-top:6px;font-size:12.5px;color:rgba(255,255,255,.72);
  letter-spacing:.05em}

/* ---------- grids ---------- */
.grid{display:grid;gap:20px}
.g2{grid-template-columns:repeat(2,1fr)}
.g3{grid-template-columns:repeat(3,1fr)}
.g4{grid-template-columns:repeat(4,1fr)}

/* ---------- feature cards ---------- */
.fcard{
  background:#fff;border:1px solid var(--line-2);border-radius:var(--radius-lg);padding:26px 24px;
  transition:.25s;position:relative;overflow:hidden;
}
.fcard:hover{border-color:var(--hover-line);box-shadow:var(--shadow-m);transform:translateY(-3px)}
.fcard .ic{
  width:44px;height:44px;border-radius:11px;background:var(--brand-tint);color:var(--brand);
  display:grid;place-items:center;margin-bottom:16px;
}
.fcard .ic svg{width:22px;height:22px}
.fcard h3{font-size:16.5px;margin-bottom:8px}
.fcard p{margin:0;font-size:14px;color:var(--ink-2);line-height:1.75}
.fcard .no{
  position:absolute;inset-inline-end:18px;top:14px;font-size:34px;font-weight:800;
  color:var(--line-2);line-height:1;
}

/* ---------- tech block ---------- */
.tech-split{display:grid;grid-template-columns:1.05fr 1fr;gap:52px;align-items:center}
.tech-img{border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-m);background:#fff}
.tech-img img{width:100%;aspect-ratio:4/3;object-fit:cover}
.layers{display:flex;flex-direction:column;gap:12px;margin-top:26px}
.layer{
  display:flex;gap:14px;align-items:flex-start;background:#fff;border:1px solid var(--line-2);
  border-radius:12px;padding:16px 18px;
}
.layer .n{
  width:30px;height:30px;border-radius:8px;background:var(--brand);color:#fff;font-size:13px;
  font-weight:700;display:grid;place-items:center;flex:none;
}
.layer h4{font-size:15px;margin-bottom:4px}
.layer p{margin:0;font-size:13.5px;color:var(--ink-2)}
.metric-row{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-top:24px}
.metric{background:var(--brand-tint);border-radius:12px;padding:18px 16px;text-align:center}
.metric b{display:block;font-size:clamp(22px,2.4vw,30px);color:var(--brand);font-weight:800;
  letter-spacing:-.02em;line-height:1.1}
.metric span{display:block;margin-top:6px;font-size:12.5px;color:var(--ink-2)}

/* ---------- gallery / filters ---------- */
.filters{display:flex;flex-wrap:wrap;gap:9px;margin-bottom:30px}
.filters button{
  padding:9px 17px;border:1px solid var(--line);border-radius:999px;font-size:13.5px;
  font-weight:600;color:var(--ink-2);background:#fff;transition:.2s;
}
.filters button:hover{border-color:var(--brand);color:var(--brand)}
.filters button.on{background:var(--brand);border-color:var(--brand);color:#fff}

.gallery{display:grid;grid-template-columns:repeat(4,1fr);gap:18px}
.pcard{
  background:#fff;border:1px solid var(--line-2);border-radius:var(--radius-lg);overflow:hidden;
  transition:.28s;cursor:pointer;
}
.pcard:hover{box-shadow:var(--shadow-m);transform:translateY(-3px);border-color:var(--hover-line)}
.pcard .ph{position:relative;background:var(--bg-soft);overflow:hidden}
.pcard .ph img{width:100%;aspect-ratio:3/4;object-fit:cover;object-position:center center;
  transition:.5s}
.pcard:hover .ph img{transform:scale(1.04)}
.pcard .tags{
  position:absolute;inset-inline-start:12px;bottom:12px;display:flex;gap:6px;flex-wrap:wrap;
}
.pcard .tags span{
  background:rgba(255,255,255,.92);backdrop-filter:blur(6px);border-radius:6px;
  padding:4px 9px;font-size:11px;font-weight:600;color:var(--ink-2);
}
.pcard .meta{padding:15px 16px 17px}
.pcard .meta h3{font-size:14.5px;font-weight:600}
.pcard .meta p{margin:4px 0 0;font-size:12px;color:var(--ink-3)}
.pcard .more{
  margin-top:11px;display:flex;align-items:center;gap:5px;font-size:12.5px;font-weight:600;
  color:var(--brand);
}
.pcard .more svg{width:13px;height:13px;transition:.2s}
.pcard:hover .more svg{transform:translateX(3px)}
.ghost{
  grid-column:1/-1;border:1px dashed var(--line);border-radius:var(--radius-lg);padding:22px;
  text-align:center;color:var(--ink-2);font-size:14px;background:var(--bg-soft);
}
.ghost b{color:var(--brand)}

/* ---------- swatches ---------- */
.swatches{display:grid;grid-template-columns:repeat(5,1fr);gap:16px}
.sw{background:#fff;border:1px solid var(--line-2);border-radius:12px;overflow:hidden;
  transition:.25s}
.sw:hover{box-shadow:var(--shadow-m);transform:translateY(-3px)}
.sw img{width:100%;aspect-ratio:16/10;object-fit:cover}
.sw .cap{display:flex;align-items:center;justify-content:space-between;padding:10px 12px;
  font-size:12px;color:var(--ink-3);font-weight:600}
.sw .cap code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px}
.sw .cap i{width:13px;height:13px;border-radius:50%;border:1px solid rgba(0,0,0,.12);display:block}

/* ---------- scenes ---------- */
.scenes{display:grid;grid-template-columns:repeat(2,1fr);gap:18px}
.scene{position:relative;border-radius:var(--radius-lg);overflow:hidden;background:#111;
  display:block;width:100%;padding:0;text-align:start}
.scene img{width:100%;aspect-ratio:16/9;object-fit:cover;transition:.5s}
.scene:hover img{transform:scale(1.03)}
.scene .ov{
  position:absolute;inset-inline:0;bottom:0;padding:44px 22px 20px;color:#fff;
  background:linear-gradient(transparent,rgba(22,27,33,.82));
}
.scene .ov b{display:block;font-size:17.5px}
.scene .ov span{display:block;margin-top:3px;font-size:13px;color:rgba(255,255,255,.8)}
.scene .kk{
  position:absolute;top:16px;inset-inline-start:16px;background:rgba(255,255,255,.9);
  border-radius:999px;padding:5px 12px;font-size:11.5px;font-weight:700;color:var(--brand);
  letter-spacing:.04em;
}

/* ---------- wide band / ambassador ---------- */
.band{position:relative;background:var(--brand-d);color:#fff;overflow:hidden}
.band .wrap{position:relative;z-index:2}
.band-in{display:grid;grid-template-columns:1.15fr .85fr;gap:48px;align-items:center;
  padding:70px 22px}
.band h2{font-size:clamp(24px,3.2vw,38px);margin-bottom:16px}
.band p{margin:0;color:rgba(255,255,255,.78);font-size:15.5px;line-height:1.9;max-width:560px}
.band-img{border-radius:var(--radius-lg);overflow:hidden;box-shadow:0 24px 60px rgba(0,0,0,.3)}
.band-img img{width:100%;aspect-ratio:4/4.3;object-fit:cover;object-position:center 22%}
.band .bt{margin-top:26px;display:flex;gap:12px;flex-wrap:wrap}
/* chips sitting on the dark brand surface — colours come from tokens so they
   follow the theme switch (gold reads as the LOGO accent on dark).
   Selectors are qualified with .hero-tags on purpose: `.hero-tags li` is
   0,1,1 and would otherwise out-specify a bare `.band-chip`. */
.band-eyebrow{color:var(--gold)}
.hero-tags li.band-chip{background:rgba(255,255,255,.08);border-color:rgba(255,255,255,.18);color:var(--on-dark)}
.hero-tags svg.band-tick{color:var(--gold)}

/* wide banner */
.wideband{position:relative;min-height:340px;display:grid;place-items:center;text-align:center;
  color:#fff;overflow:hidden;background:var(--ft-bg)}
.wideband img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.wideband::after{content:"";position:absolute;inset:0;background:rgba(22,27,33,.62)}
.wideband .inner{position:relative;z-index:2;padding:56px 22px;max-width:820px}
.wideband h2{font-size:clamp(22px,3vw,34px)}
.wideband p{margin:12px 0 0;color:rgba(255,255,255,.82);font-size:15px}

/* ---------- process ---------- */
.steps{display:grid;grid-template-columns:repeat(6,1fr);gap:0;position:relative}
.steps::before{
  content:"";position:absolute;top:23px;left:8%;right:8%;height:2px;background:var(--line);
}
.step{position:relative;text-align:center;padding:0 8px}
.step .dot{
  width:46px;height:46px;border-radius:50%;background:#fff;border:2px solid var(--line);
  display:grid;place-items:center;margin:0 auto 14px;font-weight:800;color:var(--brand);
  position:relative;z-index:1;font-size:15px;
}
.step:hover .dot{border-color:var(--brand);background:var(--brand);color:#fff}
.step h4{font-size:14px;margin-bottom:5px}
.step p{margin:0;font-size:12.5px;color:var(--ink-2);line-height:1.65}

/* ---------- about ---------- */
.about-split{display:grid;grid-template-columns:1fr 1fr;gap:52px;align-items:center}
.about-img{border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-m)}
.about-img img{width:100%;aspect-ratio:4/3;object-fit:cover}
.facts{display:grid;grid-template-columns:repeat(2,1fr);gap:14px;margin-top:26px}
.fact{background:#fff;border:1px solid var(--line-2);border-radius:12px;padding:16px 18px}
.fact b{display:block;font-size:19px;color:var(--brand);margin-bottom:3px}
.fact span{font-size:12.5px;color:var(--ink-2)}
/* product-line digest under the about block — one row per category, the name
   bound to cat.<k>.name so it renames itself with the nav */
.ab-lines{margin-top:46px}
.abline{list-style:none;margin:14px 0 0;padding:0;border-top:1px solid var(--line-2)}
.abline li{display:grid;grid-template-columns:198px minmax(0,1fr);gap:24px;align-items:baseline;
  padding:14px 0;border-bottom:1px solid var(--line-2)}
.abline b{font-size:14.5px;font-weight:700;color:var(--ink);
  display:flex;align-items:baseline;gap:9px;min-width:0;overflow-wrap:break-word}
.abline b::before{content:"";flex:none;width:14px;height:2px;background:var(--rule-accent);
  transform:translateY(-4px)}
.abline span{font-size:13.5px;color:var(--ink-2);line-height:1.68;min-width:0;overflow-wrap:break-word}
/* on a category page, the row for that category is tinted */
.abline li.on b{color:var(--brand)}
.abline li.on b::before{width:22px}
.abline li.on span{color:var(--ink)}
@media(max-width:760px){
  .abline li{grid-template-columns:1fr;gap:5px;padding:13px 0}
}

/* ---------- quote / contact ---------- */
.quote{display:grid;grid-template-columns:.95fr 1.05fr;gap:52px;align-items:start}
.qcard{background:#fff;border:1px solid var(--line);border-radius:var(--radius-lg);padding:30px;
  box-shadow:var(--shadow-m)}
.frow{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.field{margin-bottom:14px}
.field label{display:block;font-size:12.5px;font-weight:600;color:var(--ink-2);margin-bottom:6px}
.field input,.field select,.field textarea{
  width:100%;padding:12px 14px;border:1px solid var(--line);border-radius:10px;font-size:14.5px;
  font-family:inherit;color:var(--ink);background:#fff;transition:.2s;
}
.field textarea{min-height:104px;resize:vertical}
.field input:focus,.field select:focus,.field textarea:focus{
  outline:none;border-color:var(--brand);box-shadow:0 0 0 3px rgba(var(--brand-rgb),.1)}
.qnote{font-size:12.5px;color:var(--ink-3);margin:14px 0 0;line-height:1.7}
.qok{background:var(--brand-tint);border:1px solid var(--hover-line);color:var(--brand-d);border-radius:12px;
  padding:14px 16px;font-size:14px;margin-top:14px}

.cta-list{display:flex;flex-direction:column;gap:12px;margin-top:26px}
.cta-item{display:flex;gap:14px;align-items:center;background:#fff;border:1px solid var(--line-2);
  border-radius:12px;padding:15px 17px;transition:.2s}
.cta-item:hover{border-color:var(--hover-line);box-shadow:var(--shadow-s)}
.cta-item .ic{width:40px;height:40px;border-radius:11px;display:grid;place-items:center;flex:none;
  background:var(--brand-tint);color:var(--brand)}
.cta-item .ic svg{width:19px;height:19px}
/* The WhatsApp tile used to carry its own brand green (#E4F8EC bg / #128C4A
   glyph). That was the last orphan colour in the set: it ignored the theme
   switch, so in the LOGO palette three tiles went slate and the fourth stayed
   green, reading as a different component. All four now share the token pair
   above; recognition comes from the glyph + the "WhatsApp" label, not colour. */
.cta-item .ic.wa{background:var(--brand-tint);color:var(--brand)}
.cta-item b{display:block;font-size:14.5px}
.cta-item span{font-size:12.5px;color:var(--ink-3)}

/* ---------- footer ---------- */
.ft{background:var(--ft-bg);color:var(--on-dark-dim);font-size:13.5px;padding:56px 0 26px}
.ft a:hover{color:#fff}
.ft-grid{display:grid;grid-template-columns:1.5fr 1fr 1fr 1.2fr;gap:36px;padding-bottom:34px;
  border-bottom:1px solid rgba(255,255,255,.1)}
.ft h4{color:#fff;font-size:14px;margin-bottom:16px;letter-spacing:.04em}
.ft li{margin-bottom:9px}
.ft .brandrow{display:flex;align-items:center;gap:11px;margin-bottom:16px}
.ft .brandrow img{display:block;height:32px;width:auto}   /* white LOGO on dark */
.ft .brandrow b{color:#fff;font-size:16px;letter-spacing:.05em}
.ft-bottom{display:flex;justify-content:space-between;gap:18px;flex-wrap:wrap;padding-top:22px;
  font-size:12.5px;color:var(--on-dark-mute)}

/* ---------- lightbox ---------- */
.lb{position:fixed;inset:0;z-index:200;background:rgba(19,23,28,.94);display:grid;
  place-items:center;padding:22px;opacity:0;visibility:hidden;transition:.25s}
.lb.on{opacity:1;visibility:visible}
.lb-in{max-width:min(940px,94vw);max-height:90vh;display:flex;flex-direction:column;gap:14px}
.lb img{max-height:74vh;width:auto;margin:0 auto;border-radius:var(--radius-lg);object-fit:contain;
  background:#fff}
.lb .cap{text-align:center;color:#fff}
.lb .cap b{display:block;font-size:17px}
.lb .cap span{font-size:13px;color:rgba(255,255,255,.66)}
.lb .x{position:absolute;top:18px;inset-inline-end:20px;width:44px;height:44px;border-radius:50%;
  background:rgba(255,255,255,.14);color:#fff;display:grid;place-items:center;font-size:22px}
.lb .x:hover{background:rgba(255,255,255,.26)}

/* ---------- reveal ---------- */
.rv{opacity:0;transform:translateY(22px);transition:opacity .7s ease,transform .7s ease}
.rv.in{opacity:1;transform:none}

/* ==========================================================================
   Responsive — tablets
   ========================================================================== */
@media (max-width:1100px){
  /* three credentials + two contacts no longer fit the utility bar once the
     container narrows — the longest locales were clipping the e-mail */
  .topbar .tb-item:nth-child(3){display:none}
  .gallery,.swatches{grid-template-columns:repeat(3,1fr)}
  .g4{grid-template-columns:repeat(2,1fr)}
  .steps{grid-template-columns:repeat(3,1fr);gap:30px 0}
  .steps::before{display:none}
}

/* --------------------------------------------------------------------------
   The inline navigation needs the full 1240px container: eight labels in twelve
   languages run up to 1130px wide, so between ~990px and 1240px it cannot fit
   even at the smallest .fit tier.  Collapse it into the menu button before that
   happens, instead of letting it push the CTA off the edge.
   -------------------------------------------------------------------------- */
@media (max-width:1279px){
  /* the nav is out of flow now, so the actions need their own push to the right */
  .hdr-act{margin-left:auto}
  /* the utility bar carries the longest strings of all — tighten before clipping */
  .topbar{font-size:12.4px}
  .topbar .wrap{gap:12px}
  .nav{
    position:fixed;inset:calc(var(--hdr-h) + 0px) 0 auto 0;background:#fff;flex-direction:column;
    align-items:stretch;gap:2px;padding:14px 18px 22px;border-bottom:1px solid var(--line);
    box-shadow:var(--shadow-m);transform:translateY(-120%);transition:.28s;
    max-height:calc(100vh - var(--hdr-h));overflow:auto;margin:0;
  }
  .nav.on{transform:none}
  .nav > a,.nav-item > a{padding:13px 12px;font-size:16px;border-radius:10px}
  /* inside the drawer the dropdown turns into an inline accordion */
  .nav-item{position:static;display:flex;align-items:center;flex-wrap:wrap;gap:2px}
  .nav-item > a{flex:1;min-width:0}
  .nav-sub-toggle{width:42px;height:42px;margin:0;border-radius:10px}
  .nav-sub-toggle svg{width:12px;height:12px}
  .nav-sub{
    position:static;flex:0 0 100%;width:auto;padding:0 0 6px 12px;background:none;
    border:0;border-radius:0;box-shadow:none;opacity:1;visibility:visible;transform:none;
    display:none;
  }
  .nav-item.open .nav-sub{display:block}
  .nav-sub a{padding:11px 12px;font-size:14.5px;border-radius:9px}
  /* ---- third level becomes an inline accordion inside the drawer ----
     There is no hover in a drawer, so the chevron turns into a real 40px tap
     target and the fly-out simply indents below its own category row. */
  .sub-item{flex-wrap:wrap;align-items:center}
  .sub-tgl{pointer-events:auto;width:40px;height:40px;margin:0;border-radius:10px}
  .sub-tgl svg{width:12px;height:12px}
  .sub-item.open .sub-tgl svg{transform:rotate(90deg)}
  [dir="rtl"] .sub-item.open .sub-tgl svg{transform:scaleX(-1) rotate(90deg)}
  .nav-fly{
    position:static;flex:0 0 100%;width:auto;padding:0 0 4px 14px;background:none;
    border:0;border-radius:0;box-shadow:none;opacity:1;visibility:visible;
    transform:none;display:none;
  }
  .sub-item.open > .nav-fly{display:block}
  .nav-fly::before{display:none}
  .nav-fly a{padding:10px 12px;font-size:14px;border-radius:9px}
  .burger{display:grid}
}

@media (max-width:980px){
  /* the quote button stays in the header while there is room for it (see the
     1279px block) and only moves into the hero below this width */
  .hdr-act .btn-brand{display:none}
  /* Second top-bar selling point goes too: at 641–980px the bar still shows
     the email + WhatsApp links, and long languages (Vietnamese) ran the
     WhatsApp link 6px past the edge, where overflow:hidden silently cut a
     character off the phone number. Dropping one bullet frees ~150px. */
  .topbar .tb-item:nth-child(2){display:none}
  .topbar .wrap{gap:12px}
  .hero-in{grid-template-columns:1fr;gap:34px;padding:42px 22px 54px}
  .hero-media img{aspect-ratio:4/4.1}
  .hero-float{inset-inline-start:14px;bottom:16px;padding:12px 15px}
  .tech-split,.about-split,.quote,.band-in{grid-template-columns:1fr;gap:32px}
  .band-in{padding:52px 22px}
  .band-img img{aspect-ratio:4/3.4}
  .stats .wrap{grid-template-columns:repeat(2,1fr)}
  .stat{border-bottom:1px solid rgba(255,255,255,.13)}
  .stat:nth-child(2n){border-inline-end:0}
  .stat:nth-child(n+3){border-bottom:0}
  .sec{padding:62px 0}
  .ft-grid{grid-template-columns:1fr 1fr;gap:28px}
  .scenes{grid-template-columns:1fr}
}

/* ==========================================================================
   Responsive — phones  (mobile-first image crops kick in here)
   ========================================================================== */
@media (max-width:640px){
  :root{--hdr-h:62px}
  .wrap{padding:0 16px}
  .hero-in{padding:32px 16px 44px;gap:28px}
  .gallery{grid-template-columns:repeat(2,1fr);gap:12px}
  .swatches{grid-template-columns:repeat(2,1fr);gap:12px}
  .g2,.g3,.g4,.metric-row,.facts,.frow{grid-template-columns:1fr}
  .metric-row{grid-template-columns:repeat(2,1fr)}
  .steps{grid-template-columns:repeat(2,1fr)}
  .sec{padding:48px 0;scroll-margin-top:calc(var(--hdr-h) + 10px)}
  .sec-sub{font-size:15px}
  .topbar .wrap{height:34px;font-size:11.5px;gap:10px}
  /* phones: keep one credential + one contact; the rest move into the header/footer */
  .topbar .tb-item:nth-child(2),.topbar .tb-item:nth-child(3),
  .topbar .tb-sp,.topbar a[data-wa]{display:none}
  .topbar a span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  /* the contact links must stay whole; let the credential tagline ellipsise first */
  .topbar a{flex:none}
  .topbar .tb-item{flex:0 1 auto;min-width:0}
  .topbar .tb-item span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .hdr-in{gap:10px}
  .logo-txt i{display:none}
  .logo-mark{width:36px;height:36px}
  .lang-btn{padding:8px 10px;font-size:12.5px}
  .lang-menu{width:min(240px,86vw)}
  .qcard{padding:20px 17px}
  .btn{padding:12px 20px;font-size:14px}
  .hero-cta{gap:10px}
  .hero-cta .btn{flex:1 1 100%}
  .pcard .meta{padding:12px 12px 14px}
  .pcard .more{font-size:12px}
  .scene img{aspect-ratio:4/3.1}          /* portrait-ish on phones: full scene readable */
  .wideband{min-height:290px}
  .ft{padding:40px 0 22px}
  .ft-grid{grid-template-columns:1fr;gap:24px}
  .lb img{max-height:66vh}
  .swatches{gap:10px}
  .sw .cap{font-size:11px;padding:8px 9px}
}

@media (max-width:400px){
  .gallery{grid-template-columns:1fr 1fr;gap:10px}
  .swatches{grid-template-columns:1fr 1fr}
}

/* ---------- RTL (Arabic) ---------- */
[dir="rtl"] .eyebrow::before{order:2}
[dir="rtl"] .hero-media img{object-position:center 42%}
[dir="rtl"] .hero-float{inset-inline-start:auto;inset-inline-end:-18px}

/* The header keeps the SAME arrangement as every other language — brand on the
   left, language switch + CTA on the right.  Only the Arabic text inside each
   block stays right-to-left, so the nav still reads naturally from the right.
   (Mirroring the whole row would move the logo to the right and the language
   switch to the left, which reads as "flipped" next to the other 11 locales.) */
[dir="rtl"] .hdr-in{direction:ltr}
[dir="rtl"] .nav{direction:rtl}
[dir="rtl"] .nav a{text-align:right}

/* ...and the utility bar above it, so the whole header block reads the same way
   as the other eleven locales (tagline on the left, contacts on the right).
   Each item keeps its own right-to-left flow, so the bullet / icon still leads
   the Arabic text. */
[dir="rtl"] .topbar .wrap{direction:ltr}
[dir="rtl"] .tb-item,[dir="rtl"] .topbar a{direction:rtl}

/* arrows drawn as SVG must mirror in RTL */
[dir="rtl"] .arw{transform:scaleX(-1)}

/* --------------------------------------------------------------------------
   Bidi isolation for Latin / numeric runs.
   Arabic is RTL: a bare "+86 153 5062 8725" or "950 × 2400 mm" sitting in an
   RTL paragraph gets visually reordered by the Unicode bidi algorithm
   (renders as "8725 5062 153 86+" / "mm 2400 × 950").  Any element holding
   phone numbers, e-mails, model codes, dimensions or units must be pinned to
   LTR and isolated from the surrounding Arabic run.
   -------------------------------------------------------------------------- */
[dir="rtl"] .ltr{direction:ltr;unicode-bidi:isolate;text-align:inherit}
[dir="rtl"] .ltr.ta-s{text-align:start}

/* ==========================================================================
   Product categories (2026-09) — the 7-card grid on the home page and the
   seven /products/<key>.html pages it links to.
   ========================================================================== */

/* ---------- home page: category entry grid ---------- */
.catgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:18px}
.catcard{
  display:block;position:relative;background:#fff;border:1px solid var(--line-2);
  border-radius:var(--radius-lg);overflow:hidden;transition:.28s;
}
.catcard:hover{box-shadow:var(--shadow-m);transform:translateY(-3px);border-color:var(--hover-line)}
.catcard .ph{position:relative;background:var(--bg-soft);overflow:hidden}
.catcard .ph img{width:100%;aspect-ratio:3/4;object-fit:cover;transition:.5s}
.catcard:hover .ph img{transform:scale(1.04)}
.catcard .kk{
  position:absolute;inset-inline-start:12px;top:12px;background:rgba(255,255,255,.93);
  backdrop-filter:blur(6px);border-radius:999px;padding:4px 11px;font-size:11px;font-weight:700;
  color:var(--brand);letter-spacing:.04em;
}
.catcard .mt{padding:16px 17px 18px}
.catcard .mt h3{font-size:16px;margin-bottom:4px}
.catcard .mt em{
  display:block;font-style:normal;font-size:10.5px;font-weight:700;color:var(--ink-3);
  letter-spacing:.07em;text-transform:uppercase;margin-bottom:9px;
}
.catcard .mt p{
  margin:0;font-size:13px;color:var(--ink-2);line-height:1.7;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;
}
.catcard .more{
  margin-top:12px;display:flex;align-items:center;gap:5px;font-size:12.5px;font-weight:600;
  color:var(--brand);
}
.catcard .more svg{width:13px;height:13px;transition:.2s}
.catcard:hover .more svg{transform:translateX(3px)}
/* eighth cell: keeps the 4x2 grid square and doubles as the catalogue CTA */
.catcard.ghost{
  display:grid;place-content:center;text-align:center;gap:10px;padding:24px;
  background:var(--bg-soft);border-style:dashed;
}
.catcard.ghost svg{width:30px;height:30px;color:var(--brand);margin:0 auto}
.catcard.ghost b{font-size:14.5px;display:block}
.catcard.ghost span{font-size:12.5px;color:var(--ink-2);line-height:1.65}

/* ---------- category page hero ----------
   Full-bleed band cut from the series' OWN catalogue imagery.

   The first build reused a 3:4 product tile as the background; blown up into a
   1440x330 band it just read as a dark rectangle, so it was replaced by a two
   column layout with a portrait shot on the right. That fixed the rectangle but
   the hero was still generic. The real fix is upstream: _tools/make_hero.py now
   renders a purpose-made 2400x1000 (2.4:1) plate plus a 1200x800 mobile plate
   out of that series' own catalogue page, and the scrim below is tuned to them
   (the scrim is what makes full-bleed safe — see the contrast note). */
.pagehero{position:relative;background:var(--brand-d);color:#fff;overflow:hidden}
.pagehero .ph-bg{position:absolute;inset:0;z-index:0}
.pagehero .ph-bg img{display:block;width:100%;height:100%;object-fit:cover;object-position:center}
/* Scrim: heavy wherever the copy can sit, light on the far right so the product
   still reads. NOT cosmetic — it is what makes gold safe: the eyebrow and the
   info-pill numbers are 12.5px gold, and gold needs a backdrop of L<=.05 to
   reach 4.5:1. Over a pure-white photo that means alpha >= .84, so the copy
   column is held at .86-.90 and only the last 40% ramps away.
   (Earlier this ramp was .70 at 42% -> gold read 2.9:1 there.) */
.pagehero .ph-bg::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(100deg,rgba(17,22,27,.90) 0%,rgba(17,22,27,.86) 58%,rgba(17,22,27,.28) 100%);
}
/* RTL: mirror the ramp so the copy column keeps the heavy end behind it */
[dir=rtl] .pagehero .ph-bg::after{
  background:linear-gradient(260deg,rgba(17,22,27,.90) 0%,rgba(17,22,27,.86) 58%,rgba(17,22,27,.28) 100%);
}
/* 821-1099px: --wrap is clamped to the viewport, so the 740px copy column
   already reaches ~74% of the width — past the point where a horizontal ramp
   can still be dark underneath it. Switch to a near-uniform scrim; the hero
   photo only glows through, and the product itself is right below in the grid. */
@media (max-width:1099px){
  .pagehero .ph-bg::after,[dir=rtl] .pagehero .ph-bg::after{
    background:linear-gradient(180deg,rgba(17,22,27,.90) 0%,rgba(17,22,27,.84) 100%);
  }
}
.pagehero::before{
  content:"";position:absolute;inset-inline-end:-140px;top:-170px;width:580px;height:580px;z-index:1;
  background:radial-gradient(circle,rgba(203,164,101,.17),transparent 68%);border-radius:50%;
}
.pagehero .wrap{
  position:relative;z-index:2;max-width:var(--wrap);padding:76px 22px 82px;
}
.ph-copy{min-width:0;max-width:740px}
/* the copy sits on a photograph now — a soft shadow carries the white text
   wherever the scrim has already faded out (RTL right edge, narrow viewports) */
.pagehero h1,.pagehero .lead,.pagehero .en,.pagehero .crumb{text-shadow:0 2px 16px rgba(0,0,0,.5)}
.crumb{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:12.5px;
  color:rgba(255,255,255,.7);margin-bottom:20px;
}
.crumb a:hover{color:#fff}
.crumb svg{width:12px;height:12px;opacity:.65;flex:none}
.pagehero .eyebrow{color:var(--gold)}
.pagehero h1{font-size:clamp(27px,3.8vw,44px);letter-spacing:-.02em}
.pagehero .en{
  display:block;margin-top:9px;font-size:11.5px;font-weight:700;letter-spacing:.16em;
  text-transform:uppercase;color:rgba(255,255,255,.6);
}
.pagehero .slogan{margin:16px 0 0;font-size:clamp(15px,1.6vw,18px);font-weight:600;color:var(--gold)}
.pagehero .lead{
  margin:16px 0 0;font-size:15.5px;line-height:1.9;color:rgba(255,255,255,.84);max-width:780px;
}
.pagehero .pmeta{display:flex;flex-wrap:wrap;gap:10px;margin-top:26px}
/* the pills read as dark glass, not light glass: a translucent WHITE fill would
   lift the backdrop under the gold number to ~3.5:1, and over the photo's bright
   side it gets worse. Darkening the fill keeps the gold at 5.9:1. */
.pagehero .pmeta span{
  background:rgba(17,22,27,.28);border:1px solid rgba(255,255,255,.18);border-radius:999px;
  padding:7px 14px;font-size:12.5px;color:var(--on-dark);
}
.pagehero .pmeta span em{font-style:normal;font-weight:700;color:var(--gold);margin-inline-end:6px}

/* ---------- category page: selling points (.pitch) ----------
   Everything in here is quoted from that series' own printed catalogue
   (see _review/series_spec.md). Numbers use --brand, never --gold: gold is
   2.3:1 on white and .pitem sits on white. */
.pitch{display:grid;gap:18px;grid-template-columns:repeat(3,1fr)}
.pitem{
  background:#fff;border:1px solid var(--line);border-radius:var(--radius-lg);
  padding:24px 22px 26px;position:relative;overflow:hidden;transition:.22s;
}
.pitem::before{
  content:"";position:absolute;inset-inline-start:0;top:0;width:100%;height:3px;
  background:linear-gradient(90deg,var(--brand),var(--brand-l));transform:scaleX(0);
  transform-origin:inline-start;transition:transform .3s;
}
.pitem:hover{border-color:var(--hover-line);box-shadow:var(--shadow-m)}
.pitem:hover::before{transform:scaleX(1)}
.pitem .no{
  display:block;font-size:13px;font-weight:800;letter-spacing:.14em;line-height:1;
  margin-bottom:12px;color:var(--brand);
}
.pitem h3{font-size:15.5px;font-weight:700;color:var(--ink)}
.pitem p{margin:9px 0 0;font-size:13.5px;line-height:1.85;color:var(--ink-2)}

/* ---------- category page: product card meta band ----------
   Model code + colour name, both lifted from the catalogue label strip that
   sits under each product. The code is ASCII, so it must be bidi-isolated
   (class="ltr") or Arabic reorders it. */
.pcard .meta .code{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin-bottom:9px}
.pcard .meta .code b{
  font-size:11.5px;font-weight:700;letter-spacing:.04em;color:var(--brand);
  background:var(--brand-tint);border-radius:6px;padding:3px 8px;
}
.pcard .meta .code em{
  font-style:normal;font-size:11.5px;font-weight:600;color:var(--ink-2);
  border:1px solid var(--line);border-radius:999px;padding:3px 9px;
}
/* a product whose catalogue label carries no code/colour must not leave a
   blank row behind — the generator omits the span, this is the belt-and-braces */
.pcard .meta .code:empty{display:none}
.pcard .meta h3 small{
  display:block;margin-top:3px;font-size:11px;font-weight:500;color:var(--ink-3);letter-spacing:.02em;
}

/* ---------- category page body ---------- */
.catnote{
  background:var(--brand-tint);border:1px solid var(--hover-line);border-radius:var(--radius-lg);
  padding:20px 22px;font-size:14px;color:var(--ink-2);line-height:1.85;
}
.catnote b{color:var(--brand-d)}
.catnav{display:flex;flex-wrap:wrap;gap:9px;margin-top:32px}
.catnav a{
  display:flex;align-items:center;gap:7px;background:#fff;border:1px solid var(--line);
  border-radius:999px;padding:9px 16px;font-size:13px;font-weight:600;color:var(--ink-2);
  transition:.2s;
}
.catnav a:hover{border-color:var(--brand);color:var(--brand)}
.catnav a.on{background:var(--brand);border-color:var(--brand);color:#fff}

/* On the English page cat.<K>.en is deliberately an empty string (the name
   already IS the English name) — collapse it rather than leave a blank line */
.catcard .mt em:empty,.pagehero .en:empty{display:none}

@media (max-width:1100px){
  .catgrid{grid-template-columns:repeat(3,1fr)}
}
@media (max-width:980px){
  .catgrid{grid-template-columns:repeat(2,1fr)}
  .pitch{grid-template-columns:repeat(2,1fr)}
  .pagehero .wrap{padding:60px 22px 66px}
  .ph-copy{max-width:none}
}
/* phone: the copy spans the full width, so a horizontal ramp would leave its
   right half unprotected — switch to a vertical scrim instead */
@media (max-width:820px){
  .pagehero .ph-bg::after,[dir=rtl] .pagehero .ph-bg::after{
    background:linear-gradient(180deg,rgba(17,22,27,.88) 0%,rgba(17,22,27,.93) 100%);
  }
  .pagehero h1,.pagehero .lead,.pagehero .en,.pagehero .crumb{
    text-shadow:0 1px 10px rgba(0,0,0,.55);
  }
}
@media (max-width:640px){
  .catgrid{gap:12px}
  .catcard .mt{padding:12px 13px 14px}
  .catcard .mt p{-webkit-line-clamp:2}
  .catcard .mt h3{font-size:14.5px}
  .catcard.ghost{padding:16px}
  .pitch{grid-template-columns:1fr;gap:14px}
  .pitem{padding:20px 18px 22px}
  .pitem .no{font-size:12px;margin-bottom:10px}
  .pagehero .wrap{padding:42px 16px 48px}
  .pagehero .pmeta span{font-size:12px;padding:6px 12px}
}

/* ==========================================================================
   category page — specification table
   A definition list, not a <table>: it has to reflow to one column on phones
   without the horizontal-scroll dodge, and <dl> carries the label/value
   semantics for screen readers for free.
   ========================================================================== */
.spectable{
  border:1px solid var(--line);border-radius:var(--radius-lg);overflow:hidden;
  background:var(--bg);box-shadow:var(--shadow-s);
}
.spectable>div{
  display:grid;grid-template-columns:minmax(110px,190px) 1fr;gap:10px 22px;
  padding:15px 22px;border-bottom:1px solid var(--line-2);
}
.spectable>div:last-child{border-bottom:0}
.spectable>div:nth-child(odd){background:var(--bg-soft)}
.spectable dt{
  font-size:12.5px;font-weight:700;letter-spacing:.04em;color:var(--ink-3);
  text-transform:uppercase;line-height:1.7;
}
.spectable dd{margin:0;font-size:14.5px;color:var(--ink-2);line-height:1.8}

/* ==========================================================================
   category page — application scenes
   ========================================================================== */
.scard{
  background:var(--bg);border:1px solid var(--line);border-radius:var(--radius-lg);
  overflow:hidden;display:flex;flex-direction:column;box-shadow:var(--shadow-s);
}
.scard .im{aspect-ratio:4/3;overflow:hidden;background:var(--brand-tint)}
.scard .im img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .55s ease}
.scard:hover .im img{transform:scale(1.045)}
.scard .bd{padding:18px 20px 20px;display:flex;flex-direction:column;flex:1}
.scard h3{margin:0;font-size:16.5px;font-weight:700;color:var(--ink);letter-spacing:-.01em}
.scard p{margin:9px 0 0;font-size:13.5px;line-height:1.85;color:var(--ink-2)}

@media (max-width:640px){
  .spectable>div{grid-template-columns:1fr;gap:4px;padding:13px 16px}
  .spectable dt{font-size:11.5px}
  .spectable dd{font-size:13.5px}
  .scard .bd{padding:15px 16px 17px}
  .scard h3{font-size:15px}
  .scard p{font-size:13px}
}

@media print{
  .hdr,.topbar,.lb,.hero-cta{display:none}
}
