/* ==========================================================================
   REPLAS HUB — design system, v1.0
   ==========================================================================
   Brand colours are sampled from the supplied logo artwork rather than
   specified from memory:

     --navy   #0F244E   hsl(220, 68%, 18%)   the wordmark
     --olive  #4C8036   hsl(103, 40%, 36%)   the swoosh and pellet dots

   The earlier "#4F9D5D signature green" was a mint at 129° — a different
   hue from the mark it sat beside, which is why the palette read wrong
   next to the logo. Do not revert it.

   Two derived steps exist for contrast, not for style:
     --olive-700 #3E6A2C  white on #4C8036 measures 4.9:1 — already AA, but
                          the darker step is used for small text and hovers
     --olive-300 #9BC183  olive on navy is far under AA; accent text on the
                          navy sections uses this lighter step instead

   Structure: tokens → reset → type → buttons → header → hero → sections →
   cards → offers → forms → footer → motion → responsive.
   ========================================================================== */

:root {
  --navy: #0F244E;
  --navy-dark: #0A1937;
  --olive: #4C8036;
  --olive-700: #3E6A2C;
  --olive-300: #9BC183;
  --olive-soft: #EDF3E8;

  --ink: #2B3440;
  /* Was #6E7682 — measured 4.59:1 on white (passes AA) but only 4.21:1 on
     --paper-tint (fails). Every .sec-intro sits on a tinted section, and
     every "On request" spec value uses .pending, which shares this token —
     so the failure was sitewide, not a one-off. This value clears AA on
     both grounds: 5.45:1 white, 5.00:1 tint. */
  --muted: #5F6B76;
  --line: #E0DFD8;
  --line-soft: #EEEDE7;
  --line-dark: #24365C;
  --paper: #FFFFFF;
  --paper-tint: #F6F5F1;
  --on-navy: #DCE4F0;
  --on-navy-dim: #93A2BC;
  --danger: #A33A2E;
  --danger-soft: #FBEEEC;

  --f-head: 'Manrope', 'Noto Sans TC', 'Segoe UI', system-ui, sans-serif;
  --f-body: 'Inter', 'Noto Sans TC', 'Segoe UI', system-ui, sans-serif;

  --wrap: 1220px;
  --wrap-narrow: 860px;
  --nav-h: 74px;
  --r: 3px;
  --r-lg: 5px;
  --gutter: 24px;

  color-scheme: light;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--f-body);
  font-size: 16px;
  line-height: 1.68;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, svg { display: block; max-width: 100%; }
img { height: auto; }
[hidden] { display: none !important; }

a { color: var(--navy); text-decoration-color: rgba(76, 128, 54, .5); text-underline-offset: 3px; }
a:hover { color: var(--olive-700); }
:focus-visible { outline: 2px solid var(--olive); outline-offset: 3px; border-radius: 2px; }

.skip {
  position: absolute; left: 12px; top: -100px; z-index: 200;
  background: var(--navy); color: #fff; padding: 12px 18px; border-radius: var(--r);
  font: 600 14px/1 var(--f-body); text-decoration: none; transition: top .15s ease;
}
.skip:focus { top: 12px; color: #fff; }

/* ---------- layout ------------------------------------------------------ */
.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter); }
.wrap-narrow { max-width: var(--wrap-narrow); }
/* Three weights, not one. Every section previously used the same 92px block
   padding, so a small supplier footnote occupied the page with exactly the
   same authority as the product grid — which is the mechanical reason the
   homepage read as "everything is the same thing". Major sections keep the
   full measure; secondary asides get .sec-note and visibly step down. */
.sec { padding-block: 92px; }
.sec-tight { padding-block: 66px; }
.sec-note { padding-block: 46px; }
.sec-tint { background: var(--paper-tint); }
.sec-navy { background: var(--navy); color: var(--on-navy); }
.sec-navy h2, .sec-navy h3 { color: #fff; }
.sec-navy .eyebrow { color: var(--olive-300); }
.sec-navy .sec-intro, .sec-navy p { color: var(--on-navy); }
.sec-navy .ticks li { color: var(--on-navy); }
.sec-navy .ticks li::before { background: var(--olive-300); }

/* ---------- type -------------------------------------------------------- */
h1, h2, h3, h4 {
  font-family: var(--f-head); color: var(--navy);
  margin: 0 0 .5em; letter-spacing: -.015em; text-wrap: balance;
}
h1 { font-size: clamp(32px, 4.2vw, 50px); line-height: 1.12; font-weight: 800; letter-spacing: -.026em; }
h2 { font-size: clamp(24px, 2.5vw, 33px); line-height: 1.2; font-weight: 700; }
h3 { font-size: 18px; line-height: 1.35; font-weight: 700; }
p { margin: 0 0 1.1em; max-width: 68ch; }
p:last-child { margin-bottom: 0; }

.eyebrow {
  font-family: var(--f-head); font-size: 12px; font-weight: 700;
  letter-spacing: .15em; text-transform: uppercase; color: var(--olive-700); margin: 0 0 14px;
}
.lede { font-size: clamp(17px, 1.5vw, 19px); line-height: 1.62; color: var(--ink); }

.sec-head { margin-bottom: 42px; max-width: 760px; }
.sec-head-narrow { max-width: 100%; }
.sec-intro { color: var(--muted); font-size: 17px; }
.sec-foot { margin-top: 40px; }
.prose h2 { margin-top: 2em; font-size: 21px; }
.prose h2:first-child { margin-top: 0; }

/* ---------- buttons ----------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-family: var(--f-head); font-size: 15px; font-weight: 700; letter-spacing: .01em;
  padding: 13px 24px; border: 1px solid transparent; border-radius: var(--r);
  text-decoration: none; cursor: pointer; white-space: nowrap;
  transition: background-color .16s ease, border-color .16s ease, color .16s ease, transform .16s ease;
}
.btn:active { transform: translateY(1px); }
.btn-primary { background: var(--olive); color: #fff; }
.btn-primary:hover { background: var(--olive-700); color: #fff; }
.btn-outline { background: transparent; color: var(--navy); border-color: var(--line); }
.btn-outline:hover { border-color: var(--navy); background: var(--paper-tint); color: var(--navy); }
.btn-on-navy { background: #fff; color: var(--navy); }
.btn-on-navy:hover { background: var(--olive-soft); color: var(--navy-dark); }
.btn-sm { padding: 9px 14px; font-size: 13.5px; }
.btn-lg { padding: 16px 30px; font-size: 16px; }
.btn-block { display: flex; width: 100%; }

/* ---------- header ------------------------------------------------------ */
.site-header {
  position: sticky; top: 0; z-index: 100;
  background: rgba(255, 255, 255, .94);
  backdrop-filter: saturate(1.3) blur(8px);
  border-bottom: 1px solid transparent;
  transition: border-color .2s ease, box-shadow .2s ease;
}
.site-header.scrolled { border-bottom-color: var(--line); box-shadow: 0 1px 16px rgba(15, 36, 78, .06); }
.header-inner { display: flex; align-items: center; gap: 18px; min-height: var(--nav-h); }
.brand { flex: none; display: block; line-height: 0; }
.brand img { width: 170px; height: auto; }

.site-nav { margin-left: auto; display: flex; align-items: center; gap: 22px; }
.site-nav ul { display: flex; align-items: center; gap: 20px; list-style: none; margin: 0; padding: 0; }
.site-nav ul a {
  position: relative; white-space: nowrap;
  font-family: var(--f-head); font-size: 13px; font-weight: 700;
  letter-spacing: .09em; text-transform: uppercase;
  color: var(--navy); text-decoration: none; padding-block: 4px;
}
.site-nav ul a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: var(--olive); transform: scaleX(0); transform-origin: left; transition: transform .2s ease;
}
.site-nav ul a:hover::after, .site-nav ul a[aria-current="page"]::after { transform: scaleX(1); }
/* One signal, not two. The current page used to turn olive AND gain a rule;
   a green word sitting in a row of navy ones reads as a different kind of
   element rather than as "you are here". The text stays navy and the rule
   alone carries the state. */
.site-nav ul a[aria-current="page"] { color: var(--navy); }

.nav-cta { display: flex; align-items: center; gap: 10px; }

/* Header CTA vs. the hero's own CTA. Only the homepage (body.has-hero) has
   a "Request a Quote" button of its own above the fold — showing the same
   button a second time in the header at that exact moment is redundant.
   Starts hidden here; app.js's headerCta() block adds .header-cta-on once
   the hero button scrolls out from under the sticky header, and removes it
   again on the way back up. opacity+visibility (not display) so the
   language switch / hamburger never shift position as this fades in.
   Pages without .has-hero never opt in, so the header CTA there is simply
   always visible — unchanged from before.

   .mobile-cta-group .btn is the persistent one next to the hamburger and
   is scoped at every width (harmless above 980px — the group itself is
   display:none there). .nav-cta .btn is deliberately scoped to desktop
   only: below 980px that same button also lives inside the collapsible
   drawer, and a visitor who has opened the drawer asked to see it — that
   button must not disappear just because they have not scrolled yet. */
@media (min-width: 981px) {
  body.has-hero .nav-cta .btn { opacity: 0; visibility: hidden; pointer-events: none; transition: opacity .18s ease; }
  body.has-hero.header-cta-on .nav-cta .btn { opacity: 1; visibility: visible; pointer-events: auto; }
}
body.has-hero .mobile-cta-group .btn {
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .18s ease;
}
body.has-hero.header-cta-on .mobile-cta-group .btn {
  opacity: 1; visibility: visible; pointer-events: auto;
}
@media (prefers-reduced-motion: reduce) {
  body.has-hero .nav-cta .btn, body.has-hero .mobile-cta-group .btn { transition: none; }
}
.lang-switch {
  font-family: var(--f-head); font-size: 13px; font-weight: 700; color: var(--navy);
  text-decoration: none; padding: 8px 11px; border: 1px solid var(--line);
  border-radius: var(--r); white-space: nowrap;
  transition: border-color .15s ease, background-color .15s ease;
}
.lang-switch:hover { border-color: var(--navy); background: var(--paper-tint); color: var(--navy); }

/* Grouped with the toggle so both sit flush right on mobile; margin-left:
   auto moved here from .nav-toggle since the group is now what needs to
   push right, not the button alone. */
.mobile-cta-group { display: none; }

.nav-toggle {
  display: none; width: 44px; height: 44px;
  background: transparent; border: 1px solid var(--line); border-radius: var(--r); padding: 0; cursor: pointer;
}
.nav-toggle span { display: block; width: 20px; height: 2px; margin: 4px auto; background: var(--navy); transition: transform .2s ease, opacity .2s ease; }
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* ---------- hero --------------------------------------------------------
   Two columns from 900px up, stacked below. The copy column is capped at
   the same 62ch the rest of the site uses for reading width; the photograph
   takes the space that was previously empty gradient. */
.hero {
  background: linear-gradient(180deg, var(--paper-tint) 0%, var(--paper) 100%);
  border-bottom: 1px solid var(--line-soft);
  padding-block: 84px 76px;
}
.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: 56px;
  align-items: center;
}
.hero-inner { max-width: 620px; }
.hero-inner h1 { margin-bottom: 20px; }
.hero-inner .lede { max-width: 62ch; }
.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 30px; }

.hero-media { line-height: 0; }
.hero-media img, .hero-media svg {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--r-lg);
  /* A flat edge against a flat tint reads as a pasted rectangle. The
     hairline and lift give it the same physical presence the product cards
     already have, so it belongs to the same design system. */
  border: 1px solid var(--line);
  box-shadow: 0 18px 44px rgba(15, 36, 78, .10);
}

@media (max-width: 900px) {
  /* Stacked, and the image goes second: on a phone the headline and the
     quote button must clear the fold before any decoration does. */
  .hero-grid { grid-template-columns: 1fr; gap: 34px; }
  .hero-inner { max-width: 100%; }
  .hero-media img, .hero-media svg { aspect-ratio: 16 / 9; }
}

/* ---------- page head --------------------------------------------------- */
.page-head { background: var(--paper); border-bottom: 1px solid var(--line-soft); padding-block: 64px 56px; }
.page-head h1 { margin-bottom: 16px; }
.page-head .lede { color: var(--muted); max-width: 64ch; }
.crumbs { font-size: 13px; color: var(--muted); margin-bottom: 22px; display: flex; gap: 8px; flex-wrap: wrap; }
.crumbs a { color: var(--muted); text-decoration: none; }
.crumbs a:hover { color: var(--olive-700); text-decoration: underline; }

/* ---------- grids ------------------------------------------------------- */
.grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px; }
.grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 22px; }

/* ---------- generic card ------------------------------------------------ */
.card { background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-lg); padding: 26px; }
.sec-tint .card { background: var(--paper); }
.card-lg { padding: 32px; }
.card h2 { font-size: 21px; margin-bottom: 10px; }
.card h3 { margin-bottom: 10px; }
.card p { font-size: 15.5px; color: var(--muted); }
.card .btn { margin-top: 18px; }

/* ---------- material index tiles (homepage) ------------------------------
   Deliberately imageless. These sit above the offers grid, which carries the
   photography; giving both sections 4:3 images made the homepage repeat the
   same pictures twice. The polymer code does the work here — a buyer
   scanning for "do you handle PC?" finds it faster in a row of codes than
   in photo cards. auto-fit rather than a fixed count: v1.0 has seven
   categories, but the brief is explicit that more can be added later
   without a template change — a hardcoded repeat(6, …) or repeat(7, …)
   would need editing again the next time a category is added. */
.cat-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 12px;
}
.cat-tile {
  display: flex; flex-direction: column; gap: 3px;
  padding: 20px 18px 18px;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-lg);
  text-decoration: none;
  transition: border-color .18s ease, transform .18s ease, box-shadow .18s ease;
}
.cat-tile:hover {
  border-color: var(--olive); transform: translateY(-2px);
  box-shadow: 0 8px 20px rgba(15, 36, 78, .07);
}
.ct-code {
  font-family: var(--f-head); font-size: 27px; font-weight: 800;
  letter-spacing: -.02em; line-height: 1; color: var(--navy);
}
.ct-name { font-size: 13px; line-height: 1.35; color: var(--muted); }
.ct-count {
  /* auto, not a fixed step: ABS and PET carry no second line, so a fixed
     margin would leave their count sitting higher than the other four. */
  margin-top: auto; padding-top: 11px; border-top: 1px solid var(--line-soft);
  font-family: var(--f-head); font-size: 12px; font-weight: 700;
  letter-spacing: .03em; color: var(--olive-700);
}

/* ---------- material category card -------------------------------------- */
.cat-card {
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-lg);
  transition: border-color .18s ease, transform .18s ease, box-shadow .18s ease;
}
.cat-card:hover { border-color: #C9CCD4; transform: translateY(-2px); box-shadow: 0 10px 26px rgba(15, 36, 78, .07); }
.cat-media { display: block; position: relative; line-height: 0; }
.cat-media img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.cat-body { padding: 22px 22px 24px; display: flex; flex-direction: column; flex: 1; }
.cat-body h3 { font-size: 17px; margin-bottom: 8px; }
.cat-body h3 a { color: var(--navy); text-decoration: none; }
.cat-body h3 a:hover { color: var(--olive-700); }
.cat-body p { font-size: 14.5px; color: var(--muted); }
.cat-count {
  margin-top: auto; padding-top: 14px;
  font-family: var(--f-head); font-size: 12.5px; font-weight: 700;
  letter-spacing: .04em; color: var(--olive-700);
}

/* ---------- offer card --------------------------------------------------- */
.offer-card {
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-lg);
  transition: border-color .18s ease, transform .18s ease, box-shadow .18s ease;
}
.offer-card:hover { border-color: #C9CCD4; transform: translateY(-2px); box-shadow: 0 10px 26px rgba(15, 36, 78, .07); }
.offer-media { display: block; position: relative; line-height: 0; }
/* 1:1 (2026-09-12) — the real PP product photos are square, shot with the
   pellet pile centred and clear margin on all sides, so cover-fit at 1:1
   never crops it. Applies to every offer card, not just PP's, so the grid
   stays visually uniform whether a card shows a real photo or the pending
   placeholder above. */
.offer-media img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; }
.badge-japan {
  position: absolute; left: 12px; top: 12px;
  background: var(--navy); color: #fff;
  font-family: var(--f-head); font-size: 11px; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
  padding: 5px 10px; border-radius: 2px;
}
.badge-inline { position: static; display: inline-block; margin-left: 8px; vertical-align: 2px; }
/* Illustrative-image label (2026-09-11 brief, P0-A) — visible on the card
   itself, not only in a figcaption a buyer has to scroll to on the detail
   page. Muted rather than the navy badge-japan treatment: this is a
   disclosure, not a selling point, and should not compete with it. */
.badge-illustrative {
  position: absolute; right: 12px; bottom: 12px;
  background: rgba(15, 36, 78, .78); color: #fff;
  font-family: var(--f-head); font-size: 10.5px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase;
  padding: 4px 9px; border-radius: 2px;
}
/* Neutral placeholder for a category with no honest photo to show — see
   photoStatusOf() in build.js. A designed panel, not a stock photo and not
   an AI-generated stand-in, so it cannot be mistaken for the material. */
.photo-pending {
  display: flex; align-items: center; justify-content: center; text-align: center;
  width: 100%; aspect-ratio: 4 / 3;
  background:
    repeating-linear-gradient(135deg, var(--paper-tint) 0 14px, var(--paper) 14px 28px);
  border: 1px dashed var(--line); border-radius: var(--r-lg);
  font-family: var(--f-head); font-size: 13px; font-weight: 700;
  letter-spacing: .04em; color: var(--muted);
  padding: 20px;
}
.photo-pending-card { border-radius: 0; border-width: 0 0 1px; }
/* Product cards and detail pages went 1:1 on 2026-09-12 (owner-supplied
   real PP photos are square, shot centred with generous margin so cover
   never crops the pellet pile) — .photo-pending-card matches that ratio so
   a placeholder card sits in the same grid as a real-photo card without a
   visible seam. .cat-head-fig keeps the wider default: that is a category
   overview banner, not a product card or detail page. */
.photo-pending-card, .fig-offer.photo-pending { aspect-ratio: 1 / 1; }
.offer-body { padding: 20px 22px 24px; display: flex; flex-direction: column; flex: 1; }
.offer-code {
  font-family: var(--f-head); font-size: 12px; font-weight: 700;
  letter-spacing: .1em; color: var(--muted); margin: 0 0 8px;
}
.offer-card h3 { font-size: 16px; line-height: 1.4; margin-bottom: 14px; }
.offer-card h3 a { color: var(--navy); text-decoration: none; }
.offer-card h3 a:hover { color: var(--olive-700); }
.offer-meta { margin: 0 0 16px; display: grid; gap: 6px; }
.offer-meta > div { display: flex; gap: 10px; font-size: 13.5px; }
.offer-meta dt { color: var(--muted); flex: 0 0 96px; }
.offer-meta dd { margin: 0; color: var(--ink); }
.link-arrow {
  margin-top: auto; padding-top: 14px; border-top: 1px solid var(--line-soft);
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--f-head); font-size: 13.5px; font-weight: 700;
  color: var(--olive-700); text-decoration: none;
}
.link-arrow span { transition: transform .18s ease; }
.offer-card:hover .link-arrow span, .link-arrow:hover span { transform: translateX(4px); }

/* ---------- category / offer heads --------------------------------------- */
.cat-head { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr); gap: 44px; align-items: center; }
.cat-head-fig img { border-radius: var(--r-lg); }
.offer-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 24px; }
.offer-head h1 { font-size: clamp(26px, 3vw, 38px); margin-bottom: 0; }
.offer-panel { background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-lg); padding: 28px; }
.offer-panel .btn { margin-top: 22px; }

.foot-brand { min-width: 0; }
.cat-head-copy h1 { margin-bottom: 14px; }
.fig-offer img { aspect-ratio: 1 / 1; }

/* ---------- figures ------------------------------------------------------ */
.fig { margin: 0; position: relative; }
.fig img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--r-lg); border: 1px solid var(--line); }
/* Wide band figure: a single photograph carrying a section on its own, so
   it is capped and centred rather than filling the 1220px wrap edge to edge. */
.fig-band { max-width: 900px; margin-inline: auto; }
.fig-band img { aspect-ratio: 16 / 9; }
.fig figcaption { margin-top: 9px; font-size: 12.5px; line-height: 1.5; color: var(--muted); }

/* ---------- split -------------------------------------------------------- */
.split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 48px; align-items: start; }

/* ---------- ticks -------------------------------------------------------- */
.ticks { list-style: none; margin: 20px 0 0; padding: 0; display: grid; gap: 10px; }
.ticks li { position: relative; padding-left: 24px; font-size: 15.5px; }
.ticks li::before { content: ""; position: absolute; left: 0; top: .62em; width: 8px; height: 8px; border-radius: 50%; background: var(--olive); }
.ticks-neutral li::before { background: var(--muted); opacity: .45; }
.card .ticks { margin-top: 14px; }
.card .ticks li { font-size: 15px; }

/* ---------- steps -------------------------------------------------------- */
/* auto-fit rather than a class per length: the English flow has four steps
   (no Trial Order — overseas business is FCL, per the brief), the Chinese
   flow has five (an extra price-acceptance step, since a Taiwan buyer
   confirms price before material). A fixed 5-column grid squeezed four
   items into five slots and left a visible gap; auto-fit divides evenly
   for either count without a class per length. */
.steps { display: grid; gap: 0; list-style: none; margin: 0; padding: 0; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
.steps li { position: relative; padding: 28px 26px 0 0; border-top: 2px solid var(--line); }
.steps li::before { content: ""; position: absolute; left: 0; top: -5px; width: 8px; height: 8px; border-radius: 50%; background: var(--olive); }
.step-n { display: block; font-family: var(--f-head); font-size: 12px; font-weight: 800; letter-spacing: .14em; color: var(--muted); margin-bottom: 9px; }
.steps h3 { font-size: 16px; margin-bottom: 7px; }
.steps p { font-size: 14.5px; color: var(--muted); margin: 0; }

/* ---------- route strip (homepage process summary) ----------------------
   Labelled stops with a connecting rule, not copy blocks — four on the
   English homepage, five on the Chinese one (see steps, above, for why the
   counts differ). auto-fit rather than a fixed column count so neither
   language leaves a visible gap in the row. The full step descriptions
   belong on How We Work; repeating them here was what made that page feel
   like something the reader had already seen. */
.route {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 0;
  counter-reset: route;
}
.route li {
  position: relative; padding: 22px 16px 0 0;
  border-top: 2px solid var(--line);
  font-family: var(--f-head); font-size: 15px; font-weight: 700; color: var(--navy);
}
.route li::before {
  content: ""; position: absolute; left: 0; top: -5px;
  width: 8px; height: 8px; border-radius: 50%; background: var(--olive);
}
.route-n {
  display: block; font-size: 11.5px; font-weight: 800; letter-spacing: .14em;
  color: var(--muted); margin-bottom: 6px;
}
@media (max-width: 900px) { .route { grid-template-columns: repeat(3, minmax(0, 1fr)); row-gap: 24px; } }
@media (max-width: 560px) { .route { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* ---------- japan block --------------------------------------------------- */

/* ---------- inline bands -------------------------------------------------- */
.band-rfq, .band-supplier { border-left: 3px solid var(--olive); padding-left: 30px; }
.band-rfq h2, .band-supplier h2 { margin-bottom: 12px; }
.band-rfq p, .band-supplier p { color: var(--muted); }

/* Secondary asides — the Regrind route and the supplier entry. Both are
   real routes the brief asks for, but neither is what the buyer came for,
   so they are set at body scale with a muted rule instead of the accent,
   and read as notes rather than as another headline section competing with
   the product grid. */
.band-note { border-left: 2px solid var(--line); padding-left: 24px; }
.band-note h2 { font-size: 19px; margin-bottom: 8px; }
.band-note p { color: var(--muted); font-size: 15.5px; }
.band-note .sec-foot { margin-top: 20px; }

/* ---------- filters ------------------------------------------------------- */
.filters { margin-bottom: 32px; }
.filters-label { font-family: var(--f-head); font-size: 12px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--muted); margin: 0 0 12px; }
.pills { display: flex; flex-wrap: wrap; gap: 8px; }
.pill {
  font-family: var(--f-head); font-size: 13.5px; font-weight: 700;
  background: var(--paper); color: var(--ink); border: 1px solid var(--line);
  border-radius: 999px; padding: 8px 17px; cursor: pointer;
  transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
.pill:hover { border-color: var(--navy); }
.pill.is-on { background: var(--navy); color: #fff; border-color: var(--navy); }
.empty { margin-top: 26px; font-size: 15px; color: var(--muted); }

/* ---------- definition list ----------------------------------------------- */
.dl { margin: 0; }
.dl-row { display: grid; grid-template-columns: minmax(150px, 34%) 1fr; gap: 18px; padding: 13px 0; border-bottom: 1px solid var(--line-soft); }
.dl-row:first-child { border-top: 1px solid var(--line-soft); }
.dl dt { font-family: var(--f-head); font-size: 13.5px; font-weight: 700; color: var(--navy); }
.dl dd { margin: 0; font-size: 14.5px; color: var(--ink); }
.dl dd.pending { color: var(--muted); font-style: italic; }
.dl-compact .dl-row { grid-template-columns: minmax(130px, 40%) 1fr; }

/* ---------- note ---------------------------------------------------------- */
.note { background: var(--olive-soft); border-left: 3px solid var(--olive); border-radius: 0 var(--r) var(--r) 0; padding: 20px 24px; margin-top: 28px; }
.note p { font-size: 14.5px; margin: 0; max-width: 74ch; }
.note-inline { margin-top: 24px; }
.note-lead { margin-top: 0; padding: 28px 30px; }
.note-lead h2 { font-size: 20px; margin-bottom: 10px; }

/* ---------- centred closing CTA (About page) ------------------------------ */
.center-cta { text-align: center; }
.center-cta .sec-foot { display: flex; justify-content: center; }

/* ---------- contact ------------------------------------------------------- */
.contact-direct { background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-lg); padding: 32px; }
.contact-direct h2 { font-size: 20px; margin-bottom: 16px; }

/* ---------- forms --------------------------------------------------------- */
.form-block { position: relative; }
.form { background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-lg); padding: 34px; }
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
/* Field groups (2026-09-11 brief, P1) — "Material Requirement" and "Contact
   Information" read as two different questions, so the RFQ form splits
   them visibly instead of one undifferentiated 8-field grid. Reset to a
   block element first: a bare <fieldset> carries a browser default border,
   padding and min-width that would otherwise fight .fgrid's own grid. */
.field-group { border: 0; padding: 0; margin: 0 0 28px; min-width: 0; }
.field-group:last-of-type { margin-bottom: 0; }
.field-group legend {
  font-family: var(--f-head); font-size: 12px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--olive-700);
  padding: 0 0 10px; margin: 0;
}
.fgrid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
.field { display: flex; flex-direction: column; grid-column: span 2; }
.field-half { grid-column: span 1; }
.field-full { grid-column: span 2; }
.field label { font-family: var(--f-head); font-size: 13.5px; font-weight: 700; color: var(--navy); margin-bottom: 6px; }
.req, .opt { font-family: var(--f-body); font-size: 11.5px; font-weight: 500; letter-spacing: .04em; text-transform: uppercase; margin-left: 4px; }
.req { color: var(--olive-700); }
.opt { color: var(--muted); }
.hint { font-size: 12.5px; color: var(--muted); margin: 0 0 7px; max-width: none; }

.field input, .field select, .field textarea {
  font-family: var(--f-body); font-size: 15px; color: var(--ink);
  background: var(--paper-tint); border: 1px solid var(--line); border-radius: var(--r);
  padding: 11px 13px; width: 100%;
  transition: border-color .15s ease, box-shadow .15s ease, background-color .15s ease;
}
.field textarea { resize: vertical; min-height: 100px; }
.field select {
  appearance: none;
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%236E7682' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 13px center; background-size: 11px; padding-right: 36px;
}
.field input[type="file"] { padding: 9px 12px; background: var(--paper); font-size: 14px; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; background: var(--paper); border-color: var(--olive);
  box-shadow: 0 0 0 3px rgba(76, 128, 54, .16);
}
.field.invalid input, .field.invalid select, .field.invalid textarea { border-color: var(--danger); background: var(--danger-soft); }
.err { margin: 7px 0 0; font-size: 13px; color: var(--danger); display: flex; gap: 6px; max-width: none; }
.err::before { content: "!"; font-weight: 700; }

.optional-section {
  grid-column: span 2; border: 1px solid var(--line-soft); border-radius: var(--r);
  padding: 2px 18px; margin-top: 4px;
}
.optional-section summary {
  cursor: pointer; padding: 14px 0; list-style: none;
  font-family: var(--f-head); font-size: 14px; font-weight: 700; color: var(--navy);
}
.optional-section summary::-webkit-details-marker { display: none; }
.optional-section summary::before { content: "+"; display: inline-block; width: 1em; margin-right: 6px; color: var(--olive-700); font-weight: 800; }
.optional-section[open] summary::before { content: "–"; }
.optional-section[open] summary { border-bottom: 1px solid var(--line-soft); }
.optional-section .fgrid { margin: 18px 0 16px; }

.product-context {
  background: var(--olive-soft); border-left: 3px solid var(--olive);
  border-radius: 0 var(--r) var(--r) 0; padding: 12px 18px; margin: 0 0 22px;
  font-family: var(--f-head); font-size: 14px; font-weight: 600; color: var(--ink);
}

.field-consent { grid-column: span 2; margin-top: 4px; }
.check { display: flex; align-items: flex-start; gap: 11px; cursor: pointer; }
.check input { width: 18px; height: 18px; flex: none; margin-top: 2px; accent-color: var(--olive); }
.check span { font-family: var(--f-body); font-size: 14.5px; font-weight: 400; color: var(--ink); line-height: 1.5; }
.field-consent.invalid .check span { color: var(--danger); }

.form-foot { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; margin-top: 26px; padding-top: 24px; border-top: 1px solid var(--line-soft); }
.form-summary { margin: 0; font-size: 14px; color: var(--danger); }

.form-success {
  display: none; background: var(--paper); border: 1px solid var(--line);
  border-left: 3px solid var(--navy); border-radius: var(--r-lg); padding: 40px 36px;
}
.form-success.show { display: block; }
.form-success h3 { font-size: 22px; margin-bottom: 10px; }
.form-success p { color: var(--muted); }
/* Deliberately not a green tick: nothing was sent, so the mark reads as
   information rather than as a completed action. */
.proto-mark { width: 40px; height: 40px; border-radius: 50%; background: var(--paper-tint); position: relative; margin-bottom: 18px; }
.proto-mark::after {
  content: "i"; position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-family: var(--f-head); font-size: 19px; font-weight: 800; font-style: italic; color: var(--navy);
}

/* ---------- CTA band ------------------------------------------------------ */
.cta-band { background: var(--navy); color: var(--on-navy); padding-block: 62px; }
.cta-inner { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, .6fr); gap: 36px; align-items: center; }
.cta-band h2 { color: #fff; margin-bottom: 10px; }
.cta-band p { color: var(--on-navy-dim); margin: 0; font-size: 16px; }
.cta-actions { display: flex; flex-direction: column; align-items: flex-end; gap: 12px; }
.supplier-textlink { font-family: var(--f-head); font-size: 14px; font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }
.supplier-textlink.on-navy { color: var(--on-navy); }
.supplier-textlink.on-navy:hover { color: #fff; }

/* ---------- footer -------------------------------------------------------- */
.site-footer { background: var(--navy); color: var(--on-navy-dim); padding-block: 58px 30px; }
.foot-grid { display: grid; grid-template-columns: minmax(0, 1.6fr) repeat(3, minmax(0, 1fr)); gap: 36px; }
/* The supplied logo is drawn for light grounds; it sits on a plate rather
   than being recoloured. The mark itself is never altered. */
.foot-logo { background: var(--paper); border-radius: var(--r); padding: 13px 16px; display: inline-block; margin-bottom: 20px; }
.foot-logo img { width: 216px; height: auto; }
.foot-legal { font-size: 14px; color: var(--on-navy); margin-bottom: 12px; }
.foot-legal strong { font-family: var(--f-head); color: #fff; font-weight: 700; }
.foot-contact { font-size: 13.5px; margin: 0; line-height: 1.75; }
.foot-contact a { color: var(--olive-300); text-decoration: none; display: inline-block; padding-block: 6px; }
.foot-contact a:hover { color: #fff; text-decoration: underline; }
.foot-col h3 { font-size: 11.5px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--on-navy-dim); margin-bottom: 14px; }
.foot-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
/* Footer links measured 17px tall on a phone — under the 24px WCAG 2.5.8
   floor and far under the 44px both platform guidelines ask for. Padding
   the anchor itself (not the li) is what actually grows the hit area. */
.foot-col a {
  font-size: 14px; color: var(--on-navy); text-decoration: none;
  display: inline-block; padding-block: 7px;
}
.foot-col a:hover { color: #fff; text-decoration: underline; }
.foot-col ul { gap: 2px; }
.foot-note-col p { font-size: 13px; line-height: 1.6; margin: 0; }
.credits { margin-top: 46px; padding-top: 24px; border-top: 1px solid var(--line-dark); }
.credits h3 { font-size: 11px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--on-navy-dim); margin-bottom: 10px; }
.credits ul { list-style: none; margin: 0 0 18px; padding: 0; display: grid; gap: 6px; }
.credits li { font-size: 12px; line-height: 1.5; color: var(--on-navy-dim); }
/* Licence links are legally required attribution and rarely tapped, but at
   15px they were still the last targets under the 24px floor. */
.credits a { color: var(--on-navy); display: inline-block; padding-block: 5px; }
.copyline { font-size: 12px; color: var(--on-navy-dim); margin: 0; }

/* ---------- motion -------------------------------------------------------- */
.reveal { opacity: 0; transform: translateY(12px); }
.reveal.in { opacity: 1; transform: none; transition: opacity .5s ease var(--d, 0ms), transform .5s cubic-bezier(.22,.68,.32,1) var(--d, 0ms); }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; }
  .btn, .cat-card, .offer-card, .site-nav ul a::after { transition: none; }
}

/* ---------- responsive ---------------------------------------------------- */
@media (max-width: 1140px) {
  .site-nav { gap: 16px; }
  .site-nav ul { gap: 15px; }
  .site-nav ul a { font-size: 12px; letter-spacing: .06em; }
  .brand img { width: 150px; }
}
@media (max-width: 1080px) {
  .steps { row-gap: 30px; }
  .steps li { padding-right: 22px; }
}
@media (max-width: 980px) {
  :root { --gutter: 20px; }
  .mobile-cta-group { display: flex; align-items: center; gap: 10px; margin-left: auto; }
  .nav-toggle { display: block; }
  .site-nav {
    display: none; position: absolute; left: 0; right: 0; top: 100%;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--paper); border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
    box-shadow: 0 16px 30px rgba(15, 36, 78, .09);
    padding: 10px var(--gutter) 20px; max-height: calc(100vh - var(--nav-h)); overflow-y: auto;
  }
  body.nav-open .site-nav { display: flex; }
  body.nav-open { overflow: hidden; }
  .header-inner { position: relative; }
  .site-nav ul { flex-direction: column; align-items: stretch; gap: 0; }
  .site-nav li { border-bottom: 1px solid var(--line-soft); }
  .site-nav ul a { display: block; padding: 14px 0; font-size: 14px; letter-spacing: .09em; }
  .site-nav ul a::after { display: none; }
  .nav-cta { flex-direction: column; align-items: stretch; gap: 10px; margin-top: 16px; }
  .nav-cta .btn { justify-content: center; padding: 13px 20px; font-size: 14.5px; }
  .lang-switch { order: -1; text-align: center; padding: 11px 20px; }

  .sec { padding-block: 64px; }
  .sec-tight { padding-block: 52px; }
  .hero { padding-block: 52px 56px; }
  .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cat-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .split, .cta-inner, .cat-head { grid-template-columns: 1fr; gap: 32px; }
  /* Mobile order (2026-09-11 brief, P1): summary + RFQ CTA before the
     photograph, not after — a buyer scrolling on a phone hits the thing
     they came for (specs, price action) before a large decorative image.
     Desktop keeps image-left/summary-right via source order; this only
     changes the two columns' stacking order once .split is single-column. */
  .offer-panel { order: 1; }
  .split-media { order: 2; }
  .cta-actions { align-items: flex-start; }
  .foot-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 28px; }
  .form { padding: 26px; }
}
@media (max-width: 700px) {
  .grid-2, .grid-3, .steps { grid-template-columns: 1fr; }
  .cat-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ct-code { font-size: 24px; }
  .steps li { padding-right: 0; }
  .dl-row { grid-template-columns: 1fr; gap: 3px; }
  .fgrid { grid-template-columns: 1fr; }
  .field-half { grid-column: span 2; }
  .foot-grid { grid-template-columns: 1fr; }
  .page-head { padding-block: 46px 42px; }
  .band-rfq, .band-supplier { padding-left: 20px; }
  .form-success { padding: 28px 24px; }
}


/* ==========================================================================
   VISUAL LAYER (2026-10-08, approved by William: "F 綜合版本上線")
   Presentation only. Markup, copy and URLs are untouched. Sits on top of the
   rules above so it can be removed by deleting this block and the matching
   block 11 in app.js.
   Base: photo-led hero and flat, photo-first cards. Hover: spotlight glow and
   lit edge (pointer position from app.js block 11), plus button sweep, arrow
   reveal, image zoom and link underline. Home material index is a bento of
   five equal-coloured tiles (size follows offer count); colour never ranks
   one material above another.
   ========================================================================== */
/* ===== from A: hand-feel ================================================ */
.btn {
  position: relative; isolation: isolate;
  transition: transform .18s cubic-bezier(.22,.68,.32,1), box-shadow .22s ease,
              background-position .35s ease, border-color .18s ease, color .18s ease, background-color .18s ease;
}
.btn:active { transform: translateY(1px) scale(.985); }
.btn-primary {
  background: linear-gradient(100deg, var(--olive) 0 50%, var(--olive-700) 50% 100%) 0 0 / 230% 100%;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.16), 0 8px 16px -10px rgba(62,106,44,.7);
}
.btn-primary:hover {
  background: linear-gradient(100deg, var(--olive) 0 50%, var(--olive-700) 50% 100%) 100% 0 / 230% 100%;
  transform: translateY(-1px);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.16), 0 12px 22px -10px rgba(62,106,44,.8);
}
.btn-primary:active { transform: translateY(1px) scale(.985); }
.btn-primary::after {
  content: "\2192"; display: inline-block; overflow: hidden;
  width: 0; margin-left: -8px; opacity: 0; transform: translateX(-6px);
  transition: width .22s ease, margin-left .22s ease, opacity .22s ease, transform .22s ease;
}
.btn-primary:hover::after { width: 1em; margin-left: 0; opacity: 1; transform: none; }
.btn-outline:hover { transform: translateY(-1px); }

.link-arrow {
  padding-bottom: 3px;
  background: linear-gradient(currentColor, currentColor) 0 100% / 0 1px no-repeat;
  transition: background-size .28s ease;
}
.offer-card:hover .link-arrow, .link-arrow:hover { background-size: 100% 1px; }
.site-nav ul a::after { transform-origin: right; }
.site-nav ul a:hover::after, .site-nav ul a[aria-current="page"]::after { transform-origin: left; }

.pill { transition: background-color .15s ease, color .15s ease, border-color .15s ease, transform .15s ease; }
.pill:hover { transform: translateY(-1px); }
.field input, .field select, .field textarea { transition: border-color .18s ease, box-shadow .22s ease, background-color .18s ease; }
.field input:hover, .field select:hover, .field textarea:hover { border-color: #C3C6CE; }
.field input:focus, .field select:focus, .field textarea:focus { box-shadow: 0 0 0 4px rgba(76,128,54,.18); }

/* ===== from D: photo-led base =========================================== */
.site-header { background: #fff; border-bottom: 1px solid var(--line-soft); }
.site-header.scrolled { box-shadow: none; border-bottom-color: var(--line); }

.hero {
  position: relative; isolation: isolate; overflow: hidden;
  display: flex; align-items: flex-end;
  min-height: clamp(520px, 82vh, 760px);
  padding: 0; background: #0A1937; border-bottom: 0;
}
.hero-grid { display: block; width: 100%; }
.hero-inner { position: relative; z-index: 2; max-width: 700px; padding-block: 150px 84px; }
.hero-media { position: absolute; inset: 0; z-index: 0; }
.hero-media img { width: 100%; height: 100%; aspect-ratio: auto; object-fit: cover; border: 0; border-radius: 0; box-shadow: none; }
.hero::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(90deg, rgba(8,20,46,.93) 0%, rgba(8,20,46,.76) 42%, rgba(8,20,46,.14) 86%);
}
.hero h1 { color: #fff; font-size: clamp(36px, 5.2vw, 66px); line-height: 1.06; letter-spacing: -.03em; margin-bottom: 22px; }
.hero .lede { color: rgba(255,255,255,.9); font-size: clamp(16px, 1.4vw, 18px); max-width: 54ch; }
.hero .eyebrow { color: var(--olive-300); }
.hero .btn-outline { color: #fff; border-color: rgba(255,255,255,.6); background: transparent; }
.hero .btn-outline:hover { color: #fff; border-color: #fff; background: rgba(255,255,255,.14); }

h2 { font-size: clamp(28px, 3.2vw, 42px); letter-spacing: -.025em; }
.page-head h1 { font-size: clamp(34px, 4.6vw, 56px); letter-spacing: -.03em; }
.sec-head { margin-bottom: 52px; }

.offer-card { border: 0; border-radius: 0; background: transparent; overflow: visible; }
.offer-card:hover { transform: none; box-shadow: none; }
.offer-media { overflow: hidden; }
.offer-media img { transition: transform .8s cubic-bezier(.22,.68,.32,1); }
.offer-card:hover .offer-media img { transform: scale(1.03); }
.offer-body { padding: 18px 0 0; }
.link-arrow { border-top: 0; padding-top: 6px; }
.card, .sec-tint .card { background: transparent; border: 0; border-top: 2px solid var(--navy); border-radius: 0; padding: 20px 0 0; }

/* ===== from B: spotlight (glow + lit edge) on hover ===================== */
.offer-card, .cat-tile, .cat-card, .card, .offer-panel { position: relative; isolation: isolate; }
.offer-card > *, .cat-card > *, .cat-tile > *, .card > *, .offer-panel > * { position: relative; z-index: 1; }
.offer-card::before, .cat-tile::before, .cat-card::before, .card::before, .offer-panel::before {
  content: ""; position: absolute; inset: 0; z-index: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(280px circle at var(--mx, 50%) var(--my, 0%), rgba(76,128,54,.14), transparent 65%);
  opacity: 0; transition: opacity .3s ease;
}
.offer-card::after, .cat-tile::after, .cat-card::after, .card::after, .offer-panel::after {
  content: ""; position: absolute; inset: 0; z-index: 2; border-radius: inherit; pointer-events: none; padding: 1px;
  background: radial-gradient(200px circle at var(--mx, 50%) var(--my, 0%), var(--olive), transparent 70%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
  opacity: 0; transition: opacity .3s ease;
}
.offer-card:hover::before, .cat-tile:hover::before, .cat-card:hover::before, .card:hover::before, .offer-panel:hover::before,
.offer-card:hover::after, .cat-tile:hover::after, .cat-card:hover::after, .card:hover::after, .offer-panel:hover::after { opacity: 1; }

/* ===== from B: bento material index (5 tiles, exactly 5 cells) ==========
   12-column grid: the two largest categories (PP, PE: 4-5 offers each) take
   half a row each, the other three a third of a row each. */
.cat-tiles { grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 14px; }
.cat-tile {
  grid-column: span 4; min-height: 150px; padding: 20px 18px 18px;
  border: 1px solid var(--line); border-radius: var(--r-lg);
  background: radial-gradient(circle at 1px 1px, rgba(15,36,78,.07) 1px, transparent 0) 0 0 / 16px 16px, var(--paper);
  transition: border-color .2s ease;
}
.cat-tile:hover { transform: none; box-shadow: none; border-color: var(--olive); }
.cat-tile .ct-code { font-size: 30px; }
.cat-tile:nth-child(1), .cat-tile:nth-child(2) { grid-column: span 6; min-height: 210px; padding: 26px 26px 22px; }
.cat-tile:nth-child(1) .ct-code, .cat-tile:nth-child(2) .ct-code { font-size: 46px; margin-bottom: 4px; }
.cat-tile:nth-child(1) .ct-name, .cat-tile:nth-child(2) .ct-name { font-size: 15px; }

.dl dd { font-variant-numeric: tabular-nums; }
.dl-row { transition: background-color .15s ease; }
.dl-row:hover { background: rgba(76,128,54,.06); }

@media (min-width: 981px) { .sec { padding-block: 104px; } }
@media (max-width: 900px) {
  .hero { min-height: 560px; }
  .hero-inner { padding-block: 96px 56px; }
  .hero::after { background: linear-gradient(180deg, rgba(8,20,46,.6) 0%, rgba(8,20,46,.93) 100%); }
}
@media (max-width: 700px) {
  .cat-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cat-tile { grid-column: span 1; min-height: 130px; padding: 20px 18px 18px; }
  .cat-tile:nth-child(1), .cat-tile:nth-child(2) { grid-column: span 2; min-height: 150px; padding: 26px 26px 22px; }
  .cat-tile:last-child:nth-child(odd) { grid-column: span 2; }
  .cat-tile:nth-child(1) .ct-code, .cat-tile:nth-child(2) .ct-code { font-size: 36px; }
}
@media (prefers-reduced-motion: reduce) {
  .btn, .btn-primary::after, .offer-media img, .link-arrow, .pill, .cat-tile { transition: none; }
  .btn-primary:hover, .btn-outline:hover, .pill:hover, .offer-card:hover .offer-media img { transform: none; }
  .offer-card::before, .cat-tile::before, .cat-card::before, .card::before, .offer-panel::before,
  .offer-card::after, .cat-tile::after, .cat-card::after, .card::after, .offer-panel::after { transition: none; }
}

/* Small phones (<= 400px): the English header (logo + "Request a Quote" +
   menu button) was 7px too wide at 375px and 22px too wide at 360px, so the
   menu button sat partly off-screen. This predates the visual layer above;
   tightened here so nothing is clipped on an iPhone SE / mini or a 360px
   Android. */
@media (max-width: 400px) {
  .header-inner { gap: 10px; }
  .brand img { width: 120px; }
  .mobile-cta-group { gap: 8px; }
  .mobile-cta-group .btn-sm { padding: 9px 10px; font-size: 13px; }
}
