/* ==========================================================================
   mingda · components (design-spec §4: C1–C8)
   ========================================================================== */

/* ------------------------------------------------------------------ C1 header */
.md-header{position:sticky;top:0;z-index:999;background:var(--md-color-white);}
.md-header.is-scrolled{box-shadow:var(--md-shadow-sticky);}
.md-header.is-hidden{transform:translateY(-100%);}
.md-header{transition:transform 150ms linear,box-shadow 180ms ease-out;}

.md-utility-bar{background:var(--md-color-bg-dark);color:var(--md-color-text-inverse-secondary);
  font-size:0.875rem;min-height:42px;}
.md-utility-bar__inner{display:flex;align-items:center;justify-content:space-between;
  gap:var(--md-space-5);min-height:42px;}
.md-utility-bar__right{display:flex;align-items:center;gap:var(--md-space-4);}
.md-utility-bar__social{display:flex;align-items:center;gap:var(--md-space-3);}
.md-utility-bar__social a{display:inline-flex;align-items:center;justify-content:center;
  width:28px;height:28px;border-radius:4px;
  transition:transform .15s ease,opacity .15s ease;}
.md-utility-bar__social a:hover{transform:scale(1.15);opacity:0.92;text-decoration:none;}
.md-utility-bar a{color:var(--md-color-text-inverse);text-decoration:none;font-weight:500;}
.md-utility-bar a:hover{color:var(--md-color-white);text-decoration:underline;}
.md-utility-bar__list{display:flex;align-items:center;gap:var(--md-space-5);flex-wrap:wrap;
  list-style:none;margin:0;padding:0;}
.md-utility-bar__list li{margin:0;}
.md-utility-bar__sep{color:var(--md-color-grey-600);font-size:0.75rem;}

.md-nav{position:relative;border-bottom:1px solid var(--md-color-border);
  background:var(--md-color-white);}
.md-nav__inner{display:flex;align-items:center;gap:var(--md-space-6);
  min-height:var(--md-size-header);}
.md-nav__brand{display:flex;align-items:center;gap:var(--md-space-3);
  text-decoration:none;flex:0 0 auto;}
.md-nav__brand img{height:44px;width:auto;}
.md-nav__brand-text{display:flex;flex-direction:column;line-height:1.1;}
.md-nav__brand-name{font-family:var(--md-font-heading);font-weight:700;
  font-size:var(--md-text-h5);color:var(--md-color-text-primary);letter-spacing:.01em;}
.md-nav__brand-tag{font-size:var(--md-text-caption);color:var(--md-color-text-secondary);}
/* The Chinese wordmark is fixed copy — 汕头市明达纺织 — and the tracking tuned for
   the Latin lockup works against it: the .05em set at the 1024px+ breakpoint is
   the width the condensed Latin face needed, but on seven Chinese characters it
   only reads as letters floating apart. Chinese also has no lowercase to balance
   an optical gap, so the tracking is pulled back to near zero here.
   Placed after the brand block and specific enough (element + attribute + class)
   to beat the media-query rule further down without relying on source order. */
html[lang="zh-CN"] .md-nav__brand-name{letter-spacing:.01em;}

.md-nav__menu{display:flex;align-items:center;gap:var(--md-space-6);list-style:none;
  margin:0 0 0 auto;padding:0;}
.md-nav__menu > li{margin:0;}
.md-nav__link{position:relative;display:inline-flex;align-items:center;gap:var(--md-space-1);
  padding:var(--md-space-2) 0;font-family:var(--md-font-heading);
  font-size:var(--md-text-body);font-weight:600;letter-spacing:var(--md-tracking-button);
  color:var(--md-color-text-primary);text-decoration:none;white-space:nowrap;}
.md-nav__link::after{content:"";position:absolute;left:0;bottom:0;height:2px;width:0;
  background:var(--md-color-primary);transition:width 180ms ease-out;}
.md-nav__link:hover,.md-nav__link:focus-visible{color:var(--md-color-text-link);}
.md-nav__link:hover::after,.md-nav__link:focus-visible::after,
.md-nav__item.is-open > .md-nav__link::after{width:100%;}
.md-nav__item.is-open > .md-nav__link{color:var(--md-color-text-link);}
.md-nav__caret{width:8px;height:8px;border-right:1px solid currentColor;
  border-bottom:1px solid currentColor;transform:rotate(45deg) translate(-2px,-2px);}
.md-nav__actions{display:flex;align-items:center;gap:var(--md-space-4);flex:0 0 auto;}

/* mega panel */
.md-mega{position:absolute;left:0;right:0;top:100%;z-index:998;
  background:var(--md-color-white);box-shadow:var(--md-shadow-2);
  border-top:1px solid var(--md-color-border-subtle);
  opacity:0;visibility:hidden;transform:translateY(-6px);
  transition:opacity 180ms cubic-bezier(.2,.7,.2,1),transform 180ms cubic-bezier(.2,.7,.2,1),visibility 180ms;}
.md-nav__item.is-open .md-mega{opacity:1;visibility:visible;transform:translateY(0);}
.md-mega__inner{display:grid;grid-template-columns:1fr 1fr 1fr 320px;
  gap:var(--md-space-6);padding:var(--md-space-6) var(--md-container-gutter);}
.md-mega__inner--role{grid-template-columns:1fr 320px;}
.md-mega__inner--industries{grid-template-columns:1fr 1fr 320px;}
.md-mega__inner--about{grid-template-columns:1fr 1fr 320px;}
.md-mega__group-title{font-family:var(--md-font-heading);font-size:var(--md-text-small);
  font-weight:600;text-transform:uppercase;letter-spacing:var(--md-tracking-caption);
  color:var(--md-color-text-secondary);margin:0 0 var(--md-space-3);}
.md-mega__group-title--hailidun{color:var(--md-color-red-500);display:flex;align-items:center;
  gap:var(--md-space-2);}
.md-mega__group-title--hailidun::before{content:"";width:6px;height:6px;
  border-radius:var(--md-radius-pill);background:var(--md-color-hailidun);}
.md-mega__list{list-style:none;margin:0;padding:0;}
.md-mega__list li{margin:0;}
.md-mega__link{display:block;position:relative;padding:var(--md-space-2) 0
  var(--md-space-2) var(--md-space-3);font-size:var(--md-text-body);font-weight:500;
  color:var(--md-color-text-primary);text-decoration:none;line-height:1.5;}
.md-mega__link::before{content:"";position:absolute;left:0;top:50%;
  transform:translateY(-50%);width:0;height:1em;background:var(--md-color-primary);
  transition:width 150ms ease-out;}
.md-mega__link:hover{color:var(--md-color-text-link);}
.md-mega__link:hover::before{width:2px;}
.md-mega__link small{display:block;font-size:var(--md-text-caption);
  color:var(--md-color-text-secondary);font-weight:400;}
.md-mega__cta{background:var(--md-color-bg-brand-soft);border-radius:var(--md-radius-sm);
  padding:var(--md-space-5);align-self:start;}
.md-mega__cta h4{margin:0 0 var(--md-space-2);font-size:var(--md-text-h5);}
.md-mega__cta p{font-size:var(--md-text-small);color:var(--md-color-text-secondary);
  margin:0 0 var(--md-space-3);}

/* language switcher */
.md-lang{display:flex;align-items:center;gap:var(--md-space-2);font-size:var(--md-text-caption);
  list-style:none;margin:0;padding:0;}
.md-lang li{margin:0;}
.md-lang a{padding-bottom:2px;text-decoration:none;}
.md-lang .is-current a,.md-lang .current-lang a{
  color:var(--md-color-text-inverse);border-bottom:2px solid var(--md-color-primary);}
.md-lang--footer .is-current a,.md-lang--footer .current-lang a{
  color:var(--md-color-text-inverse);border-bottom:2px solid var(--md-color-primary);}

.md-lang__pending span{color:var(--md-color-grey-500);cursor:not-allowed;}
.md-utility-bar .md-lang{font-size:0.875rem;}
.md-utility-bar .md-lang a{color:var(--md-color-text-inverse-secondary);font-weight:500;}
.md-utility-bar .md-lang .is-current a,.md-utility-bar .md-lang .current-lang a{color:var(--md-color-text-inverse);}

.md-burger{display:none;width:44px;height:44px;align-items:center;justify-content:center;
  background:transparent;border:1px solid var(--md-color-border);
  border-radius:var(--md-radius-sm);cursor:pointer;padding:0;}
.md-burger span{display:block;width:20px;height:2px;background:var(--md-color-text-primary);
  position:relative;}
.md-burger span::before,.md-burger span::after{content:"";position:absolute;left:0;
  width:20px;height:2px;background:var(--md-color-text-primary);}
.md-burger span::before{top:-6px;} .md-burger span::after{top:6px;}

/* mobile drawer */
.md-drawer{position:fixed;top:0;right:0;bottom:0;width:min(400px,100%);height:100dvh;
  background:var(--md-color-white);border-radius:var(--md-radius-md) 0 0 var(--md-radius-md);
  box-shadow:var(--md-shadow-3);z-index:1200;display:flex;flex-direction:column;
  transform:translateX(100%);transition:transform 280ms cubic-bezier(.2,.7,.2,1);}
.md-drawer.is-open{transform:translateX(0);}
.md-drawer__head{display:flex;align-items:center;justify-content:space-between;
  gap:var(--md-space-4);padding:var(--md-space-4);border-bottom:1px solid var(--md-color-border);}
.md-drawer__close{width:40px;height:40px;display:flex;align-items:center;justify-content:center;
  background:transparent;border:1px solid var(--md-color-border);
  border-radius:var(--md-radius-sm);cursor:pointer;font-size:var(--md-text-h5);
  color:var(--md-color-text-primary);}
.md-drawer__body{flex:1 1 auto;overflow-y:auto;padding:0 var(--md-space-4) var(--md-space-9);}
.md-drawer__acc{list-style:none;margin:0;padding:0;}
.md-drawer__acc > li{margin:0;border-bottom:1px solid var(--md-color-border-subtle);}
.md-drawer__row{display:flex;align-items:center;justify-content:space-between;min-height:52px;}
.md-drawer__link{flex:1 1 auto;display:flex;align-items:center;min-height:52px;
  padding:var(--md-space-3) var(--md-space-2);font-family:var(--md-font-heading);
  font-size:1.1875rem;font-weight:600;letter-spacing:0.02em;
  color:var(--md-color-text-primary);text-decoration:none;}
.md-drawer__link:hover,.md-drawer__link:focus-visible{color:var(--md-color-text-link);}
.md-drawer__arrow{display:flex;align-items:center;justify-content:center;
  width:52px;min-height:52px;background:transparent;border:0;cursor:pointer;padding:0;}
.md-drawer__arrow-icon{display:inline-flex;align-items:center;justify-content:center;
  width:32px;height:32px;border-radius:var(--md-radius-sm);
  background:var(--md-color-bg-subtle);font-size:1.25rem;font-weight:400;line-height:1;
  color:var(--md-color-text-primary);transition:background-color 180ms ease,color 180ms ease;}
.md-drawer__arrow:hover .md-drawer__arrow-icon,
.md-drawer__acc li.is-open .md-drawer__arrow-icon{
  background:var(--md-color-primary);color:var(--md-color-white);}
.md-drawer__sub{list-style:none;margin:0 0 var(--md-space-3) var(--md-space-2);
  padding:var(--md-space-1) 0 var(--md-space-2) var(--md-space-3);
  display:none;border-left:2px solid var(--md-color-green-100);}
.md-drawer__acc li.is-open > .md-drawer__sub{display:block;}
.md-drawer__sub li{margin:0;}
.md-drawer__sub-overview{display:flex;align-items:center;min-height:40px;
  padding:var(--md-space-2) var(--md-space-3);font-family:var(--md-font-heading);
  font-weight:600;font-size:var(--md-text-small);color:var(--md-color-primary);
  text-decoration:none;border-radius:var(--md-radius-sm);background:var(--md-color-green-50);
  margin-bottom:var(--md-space-2);}
.md-drawer__group-header{padding:var(--md-space-2) var(--md-space-3) 2px;
  font-size:var(--md-text-caption);font-weight:700;text-transform:uppercase;
  letter-spacing:0.06em;color:var(--md-color-text-muted);}
.md-drawer__sub a:not(.md-drawer__sub-overview){display:flex;align-items:center;
  min-height:42px;padding:var(--md-space-2) var(--md-space-3);
  color:var(--md-color-text-secondary);text-decoration:none;
  font-size:var(--md-text-small);line-height:1.35;border-radius:var(--md-radius-sm);}
.md-drawer__sub a:not(.md-drawer__sub-overview):hover{
  color:var(--md-color-primary);background:var(--md-color-bg-subtle);}
.md-drawer__foot{position:sticky;bottom:0;background:var(--md-color-white);
  border-top:1px solid var(--md-color-border);padding:var(--md-space-4);}
.md-drawer__foot .md-contact-lines{margin-top:var(--md-space-3);font-size:var(--md-text-small);}
.md-contact-lines{list-style:none;margin:0;padding:0;}
.md-contact-lines li{margin:0 0 var(--md-space-2);}
.md-drawer__social{display:flex;align-items:center;gap:var(--md-space-2);margin-top:var(--md-space-4);}
.md-drawer__social-btn{display:inline-flex;align-items:center;gap:var(--md-space-2);flex:1 1 0;
  justify-content:center;min-height:44px;padding:var(--md-space-2) var(--md-space-3);border-radius:var(--md-radius-sm);
  background:var(--md-color-bg-subtle);border:1px solid var(--md-color-border);
  color:var(--md-color-text-primary);font-size:0.9375rem;font-weight:600;
  text-decoration:none;transition:background-color .15s ease,color .15s ease,border-color .15s ease;}
.md-drawer__social-btn--linkedin:hover{border-color:#0A66C2;color:#0A66C2;background:#eef6fc;text-decoration:none;}
.md-drawer__social-btn--facebook:hover{border-color:#1877F2;color:#1877F2;background:#eef4fe;text-decoration:none;}
.md-drawer__social-btn svg{flex-shrink:0;}
.md-drawer-mask{position:fixed;inset:0;background:var(--md-color-overlay);z-index:1100;
  opacity:0;visibility:hidden;transition:opacity 200ms ease-out,visibility 200ms;}
.md-drawer-mask.is-open{opacity:1;visibility:visible;}
body.md-drawer-open{overflow:hidden;}

@media (max-width:1023px){
  .md-utility-bar,.md-nav__menu,.md-nav__lang{display:none;}
  .md-burger{display:flex;}
  .md-nav__inner{justify-content:space-between;}
  .md-nav__actions{flex-shrink:0;}
  /*
   * OPEN — the header row is 60px too wide on the Chinese pages at 390px.
   *
   * Measured 2026-09-23 on /zh/product/meta-aramid-fabric-zh/: .md-nav__inner is
   * 343px wide with a scrollWidth of 403, .md-nav__brand is 327px, and the burger
   * sits at right=419 — 29px past a 390px viewport. English pages are clean, so it
   * is the length of the Chinese brand tagline that tips it over.
   *
   * A first attempt added `.md-nav__brand{flex-shrink:1;min-width:0}` here and
   * changed nothing, which the re-measurement showed as byte-identical numbers.
   * The reason is visible further down this file: the @media (max-width:1023px)
   * block near the end already sets `.md-nav__brand{flex:1 1 auto;min-width:0}` and
   * `.md-nav__brand-text{min-width:0;flex:1 1 auto}`, so the brand is ALREADY
   * allowed to shrink and something else is holding the row open. That rule was
   * therefore removed rather than left in place looking like a fix.
   *
   * Next measurement needed: .md-nav__inner's computed flex-wrap, and the rect of
   * each direct child including .md-nav__brand-text and .md-nav__brand-tag, to find
   * which box refuses to give up width.
   */
}
@media (min-width:1024px){
  .md-drawer,.md-drawer-mask{display:none;}
  .md-nav__lang{display:flex;}
}

/* --------------------------------------------------------------- C2 buttons */
.md-btn{display:inline-flex;align-items:center;justify-content:center;
  gap:var(--md-space-2);min-height:var(--md-size-btn-h);
  padding:0 var(--md-space-5);font-family:var(--md-font-heading);
  font-size:var(--md-text-button);font-weight:600;letter-spacing:var(--md-tracking-button);
  line-height:1;border-radius:var(--md-radius-sm);border:1px solid transparent;
  cursor:pointer;text-decoration:none;text-align:center;
  transition:background-color 150ms ease-out,border-color 150ms ease-out,color 150ms ease-out;}
.md-btn:focus-visible{outline:none;box-shadow:0 0 0 3px var(--md-color-focus);}
.md-btn--sm{min-height:var(--md-size-btn-h-sm);padding:0 var(--md-space-4);}
.md-btn--lg{min-height:var(--md-size-btn-h-lg);padding:0 var(--md-space-6);font-size:1.0625rem;}
.md-btn--block{width:100%;}

.md-btn--primary{background:var(--md-color-primary);color:var(--md-color-text-on-primary);}
.md-btn--primary:hover{background:var(--md-color-primary-hover);
  color:var(--md-color-text-on-primary);text-decoration:none;}
.md-btn--primary:active{background:var(--md-color-primary-active);transform:translateY(1px);}

.md-btn--secondary{background:var(--md-color-grey-800);color:var(--md-color-text-inverse);}
.md-btn--secondary:hover{background:var(--md-color-grey-900);
  color:var(--md-color-text-inverse);text-decoration:none;}

.md-btn--outline{background:transparent;border-color:var(--md-color-border-strong);
  color:var(--md-color-text-primary);}
.md-btn--outline:hover{background:var(--md-color-primary-soft);
  border-color:var(--md-color-primary);color:var(--md-color-text-link);text-decoration:none;}
.md-btn--outline:active{background:var(--md-color-green-100);
  border-color:var(--md-color-text-link);}

.md-btn--hailidun{background:var(--md-color-hailidun);color:var(--md-color-text-inverse);}
.md-btn--hailidun:hover{background:var(--md-color-red-600);
  color:var(--md-color-text-inverse);text-decoration:none;}
.md-btn--hailidun:active{background:var(--md-color-red-700);}

.md-btn--link{background:none;border:0;padding:0;min-height:0;
  color:var(--md-color-text-link);text-decoration:underline;text-underline-offset:3px;
  text-decoration-thickness:1px;font-weight:600;}
.md-btn--link:hover{color:var(--md-color-text-link-hover);text-decoration-thickness:2px;}

.md-btn--ghost-dark{background:transparent;border-color:var(--md-color-grey-600);
  color:var(--md-color-text-inverse);}
.md-btn--ghost-dark:hover{border-color:var(--md-color-text-inverse);
  color:var(--md-color-text-inverse);text-decoration:none;}

.md-btn[disabled],.md-btn.is-disabled{background:var(--md-color-bg-muted);
  color:var(--md-color-text-muted);border-color:var(--md-color-border-subtle);
  cursor:not-allowed;opacity:1;pointer-events:none;}

@media (max-width:767px){
  .md-actions--stack .md-btn{width:100%;}
}

/* ---------------------------------------------------------- C3 product card */
.md-card{position:relative;display:flex;flex-direction:column;background:var(--md-color-white);
  border:1px solid var(--md-color-border);border-radius:var(--md-radius-sm);
  overflow:hidden;transition:border-color 240ms ease-out,box-shadow 240ms ease-out;}
.md-card:hover{border-color:var(--md-color-primary);box-shadow:var(--md-shadow-1);}
.md-card__media{position:relative;display:block;overflow:hidden;background:var(--md-color-bg-subtle);}
.md-card__media img{width:100%;object-fit:cover;transition:transform 240ms ease-out;}
.md-card:hover .md-card__media img{transform:scale(1.03);}
.md-card__body{display:flex;flex-direction:column;gap:var(--md-space-2);
  padding:var(--md-space-5);}
.md-card__sku{font-size:var(--md-text-small);color:var(--md-color-text-secondary);
  font-variant-numeric:tabular-nums;}
.md-card__title{font-size:var(--md-text-h4);line-height:1.3;margin:0;font-weight:600;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;}
.md-card__title a{color:inherit;text-decoration:none;}
.md-card__params{font-size:var(--md-text-small);color:var(--md-color-text-secondary);margin:0;}
.md-card__moq{font-size:var(--md-text-small);color:var(--md-color-text-primary);margin:0;}
.md-card__chips{display:flex;flex-wrap:wrap;gap:var(--md-space-2);list-style:none;
  margin:0;padding:0;}
.md-card__chips li{margin:0;}
.md-chip{display:inline-block;font-size:var(--md-text-caption);color:var(--md-color-grey-700);
  background:var(--md-color-bg-subtle);border-radius:var(--md-radius-pill);
  padding:2px var(--md-space-2);white-space:nowrap;}
.md-card__cta{margin-top:auto;}
.md-card__link-cover{position:absolute;inset:0;z-index:1;}

.md-badge{position:absolute;top:var(--md-space-3);left:var(--md-space-3);z-index:2;
  padding:2px var(--md-space-2);border-radius:var(--md-radius-xs);
  font-family:var(--md-font-heading);font-size:var(--md-text-caption);font-weight:600;
  letter-spacing:var(--md-tracking-caption);text-transform:uppercase;
  color:var(--md-color-text-inverse);background:var(--md-color-primary);}
.md-badge--hailidun{background:var(--md-color-hailidun);}

/* C3-b home card */
.md-card-home{display:flex;flex-direction:column;background:var(--md-color-white);
  border-top:2px solid var(--md-color-primary);text-decoration:none;}
.md-card-home--hailidun{border-top-color:var(--md-color-hailidun);}
.md-card-home__media{aspect-ratio:3/2;overflow:hidden;background:var(--md-color-bg-subtle);}
.md-card-home__media img{width:100%;height:100%;object-fit:cover;
  transition:transform 240ms ease-out;}
.md-card-home:hover .md-card-home__media img{transform:scale(1.03);}
.md-card-home__body{padding-top:var(--md-space-5);}
.md-card-home__title{font-size:var(--md-text-h3);margin:0 0 var(--md-space-2);
  color:var(--md-color-text-primary);}
.md-card-home__line{font-size:var(--md-text-body-lg);color:var(--md-color-text-secondary);
  margin:0 0 var(--md-space-4);}
@media (max-width:767px){.md-card-home__media{aspect-ratio:16/9;}}

/* C3-c related card */
.md-card-related{display:block;text-decoration:none;color:inherit;
  border:1px solid var(--md-color-border);border-radius:var(--md-radius-sm);
  overflow:hidden;background:var(--md-color-white);}
.md-card-related__media{aspect-ratio:1/1;overflow:hidden;background:var(--md-color-bg-subtle);}
.md-card-related__media img{width:100%;height:100%;object-fit:cover;}
.md-card-related__body{padding:var(--md-space-4);}
.md-card-related__sku{font-size:var(--md-text-caption);color:var(--md-color-text-secondary);
  display:block;font-variant-numeric:tabular-nums;}
.md-card-related__title{font-size:var(--md-text-h6);font-weight:600;line-height:1.35;
  margin:var(--md-space-1) 0 0;color:var(--md-color-text-primary);}
.md-card-related:hover{border-color:var(--md-color-primary);}
.md-card-related:hover .md-card-related__title{color:var(--md-color-text-link);}

/* ------------------------------------------------------------ C4 spec table */
.md-spec-table{background:var(--md-color-white);border:1px solid var(--md-color-border);
  border-radius:var(--md-radius-sm);overflow-x:auto;overflow-y:hidden;box-shadow:var(--md-shadow-0);}
.md-spec-table table{width:100%;border-collapse:collapse;min-width:920px;}
.md-spec-table caption{text-align:left;}
.md-spec-table thead th{background:var(--md-color-bg-subtle);
  font-family:var(--md-font-heading);font-size:var(--md-text-small);font-weight:600;
  color:var(--md-color-grey-700);text-transform:uppercase;
  letter-spacing:var(--md-tracking-caption);text-align:left;
  padding:var(--md-space-3) var(--md-space-4);
  border-bottom:2px solid var(--md-color-primary);white-space:nowrap;}
.md-spec-table tbody th,.md-spec-table tbody td{
  padding:var(--md-space-3) var(--md-space-4);font-size:var(--md-text-small);
  border-bottom:1px solid var(--md-color-border-subtle);vertical-align:top;
  color:var(--md-color-text-primary);font-weight:400;text-align:left;}
.md-spec-table tbody th{font-weight:600;font-variant-numeric:tabular-nums;}
.md-spec-table tbody tr:nth-child(even) td,
.md-spec-table tbody tr:nth-child(even) th{background:var(--md-color-bg-subtle);}
.md-spec-table tbody tr:hover td,.md-spec-table tbody tr:hover th{
  background:var(--md-color-primary-soft);}
.md-spec-table tbody tr:hover th a{color:var(--md-color-text-link);}
.md-spec-table tbody tr:last-child th,.md-spec-table tbody tr:last-child td{border-bottom:0;}
.md-spec-table .is-num{text-align:right;font-variant-numeric:tabular-nums;}
.md-spec-table__empty{color:var(--md-color-text-muted);text-transform:uppercase;
  font-size:var(--md-text-caption);letter-spacing:var(--md-tracking-caption);}
.md-spec-table--family table{min-width:880px;}

@media (max-width:767px){
  .md-spec-table{overflow:visible;border:0;background:transparent;border-radius:0;}
  .md-spec-table table{min-width:0;display:block;}
  .md-spec-table thead{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);}
  .md-spec-table tbody,.md-spec-table tr,.md-spec-table th,.md-spec-table td{display:block;width:100%;}
  .md-spec-table tbody tr{border:1px solid var(--md-color-border);
    border-radius:var(--md-radius-sm);background:var(--md-color-white);
    margin-bottom:var(--md-space-4);padding:var(--md-space-2) 0;overflow:hidden;}
  .md-spec-table tbody th{background:var(--md-color-bg-subtle);border-bottom:0;
    font-size:var(--md-text-h6);padding:var(--md-space-3) var(--md-space-4);}
  .md-spec-table tbody td{border-bottom:1px solid var(--md-color-border-subtle);
    display:flex;justify-content:space-between;gap:var(--md-space-4);
    padding:var(--md-space-2) var(--md-space-4);}
  .md-spec-table tbody td::before{content:attr(data-label);font-weight:600;
    color:var(--md-color-text-secondary);text-transform:uppercase;
    font-size:var(--md-text-caption);letter-spacing:var(--md-tracking-caption);
    flex:0 0 42%;}
  .md-spec-table tbody td:last-child{border-bottom:0;}
  .md-spec-table tbody tr:nth-child(even) td,
  .md-spec-table tbody tr:nth-child(even) th{background:transparent;}
  .md-spec-table tbody tr:nth-child(even) th{background:var(--md-color-bg-subtle);}
  .md-spec-table .is-num{text-align:right;}
}

@media print{
  .md-spec-table tbody tr:nth-child(even) td{background:var(--md-color-white);}
  .md-spec-table tbody tr:hover td{background:var(--md-color-white);}
}

/* key-value spec table (§4.4 detail page) */
.md-spec-keyvalue{width:100%;border-collapse:collapse;background:var(--md-color-white);
  border:1px solid var(--md-color-border);border-radius:var(--md-radius-sm);
  overflow:hidden;}
.md-spec-keyvalue th,.md-spec-keyvalue td{padding:var(--md-space-3) var(--md-space-4);
  border-bottom:1px solid var(--md-color-border-subtle);font-size:var(--md-text-body);
  text-align:left;vertical-align:top;}
.md-spec-keyvalue th{width:40%;font-weight:600;color:var(--md-color-text-primary);
  background:var(--md-color-bg-subtle);}
.md-spec-keyvalue td{color:var(--md-color-text-primary);}
.md-spec-keyvalue tr:last-child th,.md-spec-keyvalue tr:last-child td{border-bottom:0;}
.md-spec-keyvalue .is-num{font-variant-numeric:tabular-nums;}
.md-onrequest{color:var(--md-color-text-secondary);}
/* options table sits full width under the swatch row on the detail page */
.md-pdp-options{margin-top:var(--md-space-6);}
/* related-class links: compact row, kept just above the closing CTA */
.md-related-links{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--md-space-4) var(--md-space-6);}
.md-related-links ul{display:flex;flex-wrap:wrap;gap:var(--md-space-4) var(--md-space-6);
  list-style:none;margin:0;padding:0;}
.md-related-links li{margin:0;}

/* ----------------------------------------------------------- C5 cert list */
.md-cert-list{list-style:none;margin:0;padding:0;display:grid;
  grid-template-columns:repeat(3,1fr);gap:var(--md-space-6);}
.md-cert-list li.md-cert{margin:0;padding:var(--md-space-4) 0;
  border-top:1px solid var(--md-color-border-subtle);}
.md-cert__claim{font-family:var(--md-font-heading);font-size:var(--md-text-h6);
  font-weight:600;line-height:1.4;margin:0 0 var(--md-space-2);
  color:var(--md-color-text-primary);text-transform:none;letter-spacing:0;}
.md-cert__standard{font-family:var(--md-font-heading);font-size:1.125rem;font-weight:600;
  color:var(--md-color-text-link);font-variant-numeric:tabular-nums;margin:0;}
.md-cert__status{font-size:var(--md-text-caption);color:var(--md-color-text-secondary);
  margin:var(--md-space-1) 0 0;font-variant-numeric:tabular-nums;}
.md-cert-list__note{margin:var(--md-space-6) 0 0;padding-top:var(--md-space-4);
  border-top:1px solid var(--md-color-border-subtle);font-size:var(--md-text-small);
  color:var(--md-color-text-secondary);}
.md-cert-list--hailidun li.md-cert{border-top:2px solid var(--md-color-hailidun);}
.md-cert-list--numbered{counter-reset:md-cert;}
.md-cert-list--numbered li.md-cert{display:grid;grid-template-columns:40px 1fr;
  gap:0 var(--md-space-3);}
.md-cert-list--numbered li.md-cert::before{counter-increment:md-cert;
  content:counter(md-cert,decimal-leading-zero);font-size:var(--md-text-small);
  color:var(--md-color-text-muted);grid-row:span 3;font-variant-numeric:tabular-nums;}
@media (max-width:1023px){.md-cert-list{grid-template-columns:repeat(2,1fr);}}
@media (max-width:767px){.md-cert-list{grid-template-columns:1fr;}}

/* cert wall (footer) */
/* Page banner — a full-bleed image band across the top of a page (About).
   No .md-container: being edge to edge is what separates it from a content
   block. The photograph is 1920x800, so 2.4:1 is its natural shape; the 520px
   ceiling stops it dominating a wide display, and 16:9 replaces 2.4:1 on small
   screens where the natural ratio would collapse to a letterbox slit.

   width:100% is load-bearing, not decoration. With aspect-ratio and max-height
   but no width, the ceiling is satisfied by shrinking the WIDTH instead of
   clamping the height: the band measured 1248px on a 1417px page — exactly
   520 x 2.4 — leaving a white strip down the right edge. A definite width
   leaves the ratio nowhere to transfer to, so the height clamps and the
   photograph crops through object-fit, which is the intent.

   object-position 20%: the ceiling crops more of the photograph the wider the
   window, and the red signage on the building starts 24% down. Keeping only 20%
   of the lost height above the fold leaves the sign intact at every width —
   measured with scripts/locate_banner_sign.py. Anything above about 38% starts
   clipping it on an ultra-wide display. */
.md-page-banner{width:100%;overflow:hidden;background:var(--md-color-bg-subtle);
  aspect-ratio:16/9;}
.md-page-banner img{display:block;width:100%;height:100%;object-fit:cover;
  object-position:50% 20%;}
@media (min-width:768px){
  .md-page-banner{aspect-ratio:2.4/1;max-height:520px;}
}

.md-cert-wall__title{font-size:var(--md-text-caption);letter-spacing:.04em;
  text-transform:uppercase;color:var(--md-color-text-muted);
  margin:0 0 var(--md-space-4);}
.md-cert-wall{display:flex;flex-wrap:wrap;align-items:flex-start;
  gap:var(--md-space-6);list-style:none;margin:0;padding:0;}
.md-cert-wall li{margin:0;min-width:120px;}
.md-cert-wall__mark{height:32px;display:flex;align-items:center;
  font-family:var(--md-font-heading);font-size:var(--md-text-h6);font-weight:600;
  letter-spacing:.04em;color:var(--md-color-text-inverse);}
.md-cert-wall__std{font-size:var(--md-text-caption);color:var(--md-color-text-muted);
  margin-top:var(--md-space-2);}

/* forms (inquiry page) */
.md-field{margin-bottom:var(--md-space-5);}
.md-field label{display:block;font-size:var(--md-text-small);font-weight:600;
  color:var(--md-color-text-primary);margin-bottom:var(--md-space-2);}
.md-field .md-req{color:var(--md-color-text-secondary);font-weight:400;}
.md-input,.md-select,.md-textarea{width:100%;min-height:var(--md-size-input-h);
  padding:0 var(--md-space-4);font-family:var(--md-font-body);
  font-size:var(--md-text-body);color:var(--md-color-text-primary);
  background:var(--md-color-white);border:1px solid var(--md-color-border-strong);
  border-radius:var(--md-radius-sm);}
.md-textarea{min-height:120px;padding:var(--md-space-3) var(--md-space-4);}
.md-input:focus,.md-select:focus,.md-textarea:focus{
  border-color:var(--md-color-border-brand);box-shadow:0 0 0 3px var(--md-color-focus);
  outline:none;}
.md-field--check{display:flex;align-items:flex-start;gap:var(--md-space-2);}
.md-field--check label{font-weight:400;font-size:var(--md-text-small);margin:0;}
.md-help{font-size:var(--md-text-caption);color:var(--md-color-text-muted);
  margin-top:var(--md-space-1);}
.md-msg{font-size:var(--md-text-caption);color:var(--md-color-error);
  margin-top:var(--md-space-1);display:none;}
.md-field.has-error .md-input,.md-field.has-error .md-select,
.md-field.has-error .md-textarea{border-color:var(--md-color-error);}
.md-field.has-error .md-msg{display:block;}
.md-form-alert{border-radius:var(--md-radius-sm);padding:var(--md-space-3) var(--md-space-4);
  font-size:var(--md-text-small);margin-bottom:var(--md-space-4);display:none;}
.md-form-alert--error{background:var(--md-color-error-bg);
  border:1px solid var(--md-color-error);color:var(--md-color-error);}
.md-form-alert--warn{background:var(--md-color-warning-bg);
  border:1px solid var(--md-color-warning-border);color:var(--md-color-warning-text);}
.md-form-success{display:none;align-items:flex-start;gap:var(--md-space-3);
  background:var(--md-color-success-bg);border:1px solid var(--md-color-success-border);
  border-radius:var(--md-radius-sm);padding:var(--md-space-4);}
.md-form-success__icon{color:var(--md-color-success);font-size:var(--md-text-h5);line-height:1;}
.md-form-success.is-visible{display:flex;}

/* ------------------------------------------------------------- C7 CTA band */
.md-cta-band{background:var(--md-color-bg-dark);color:var(--md-color-text-inverse);
  padding-block:var(--md-space-11);position:relative;}
.md-cta-band__inner{display:grid;grid-template-columns:7fr 5fr;gap:var(--md-space-8);
  align-items:center;}
.md-cta-band__bar{position:absolute;top:var(--md-space-11);left:var(--md-container-gutter);
  width:4px;height:64px;background:var(--md-color-primary);}
.md-cta-band h2{color:var(--md-color-text-inverse);margin:0 0 var(--md-space-4);}
.md-cta-band p{color:var(--md-color-text-inverse-secondary);font-size:var(--md-text-body-lg);
  margin:0;}
.md-cta-band__actions{display:flex;flex-direction:column;gap:var(--md-space-3);
  align-items:flex-start;}
.md-cta-band--light{background:var(--md-color-white);color:var(--md-color-text-primary);
  border-top:1px solid var(--md-color-border);}
.md-cta-band--light h2{color:var(--md-color-text-primary);}
.md-cta-band--light p{color:var(--md-color-text-secondary);}
.md-cta-band--hailidun .md-cta-band__bar{background:var(--md-color-hailidun);}
@media (max-width:1023px){
  .md-cta-band__inner{grid-template-columns:1fr;}
  .md-cta-band__bar{display:none;}
}
@media (max-width:767px){
  .md-cta-band__actions{align-items:stretch;}
  .md-cta-band{padding-block:var(--md-space-9);}
}

/* --------------------------------------------------------------- C8 footer */
.md-footer{background:var(--md-color-bg-dark);color:var(--md-color-text-inverse-secondary);
  padding-top:var(--md-space-11);font-size:var(--md-text-small);}
/* padding-bottom matches the contact band's own padding-top, so the rule
   between them sits equidistant instead of pooling 48px above the divider. */
.md-footer__cols{display:grid;grid-template-columns:2fr 1.2fr 1.2fr 1.2fr;
  gap:var(--md-space-6);padding-bottom:var(--md-space-6);}
.md-footer__col-title{font-family:var(--md-font-heading);font-size:var(--md-text-h5);
  font-weight:600;color:var(--md-color-text-inverse);text-transform:uppercase;
  letter-spacing:.04em;margin:0 0 var(--md-space-4);}
.md-footer__toggle{display:none;}
.md-footer ul{list-style:none;margin:0;padding:0;}
.md-footer li{margin:0 0 var(--md-space-1);line-height:2.2;}
.md-footer a{color:var(--md-color-text-inverse-secondary);text-decoration:none;}
.md-footer a:hover{color:var(--md-color-text-inverse);text-decoration:underline;}
/* Client feedback 2026-09-18: the marks are the original coloured logos, drawn
   for a light surface — the HAILIDUN wordmark is near-black. On the dark footer
   they need a plate behind them or the wordmark vanishes, which is why the
   previous white knockout artwork read as a black smudge instead. */
.md-footer__logo-plate{display:inline-flex;align-items:center;justify-content:center;
  background:var(--md-color-white);border-radius:var(--md-radius-sm);
  padding:var(--md-space-2) var(--md-space-3);margin-bottom:var(--md-space-4);}
.md-footer__logo-plate img{height:56px;width:auto;margin:0;display:block;}
.md-footer__logo-plate--sm{padding:var(--md-space-1) var(--md-space-2);margin-bottom:0;}
.md-footer__logo-plate--sm img{height:40px;}
.md-footer__brand-line{color:var(--md-color-text-inverse-secondary);margin:0 0 var(--md-space-6);}
.md-footer__sub{display:flex;align-items:center;gap:var(--md-space-3);
  margin-bottom:var(--md-space-3);}
.md-footer__sub-line{font-size:var(--md-text-caption);
  color:var(--md-color-text-muted);margin:0;}
.md-footer__social{display:flex;align-items:center;gap:var(--md-space-3);margin-top:var(--md-space-5);flex-wrap:wrap;}
.md-footer__social-btn{display:inline-flex;align-items:center;gap:var(--md-space-3);
  min-height:42px;padding:8px 18px;border-radius:var(--md-radius-sm);
  background:var(--md-color-grey-900);border:1px solid var(--md-color-grey-800);
  color:var(--md-color-text-inverse);font-size:0.9375rem;font-weight:600;
  text-decoration:none;transition:background-color .18s ease,color .18s ease,border-color .18s ease,transform .18s ease;}
.md-footer__social-btn:hover{transform:translateY(-1px);color:var(--md-color-white);text-decoration:none;}
.md-footer__social-btn--linkedin:hover{border-color:#0A66C2;background:rgba(10,102,194,0.22);}
.md-footer__social-btn--facebook:hover{border-color:#1877F2;background:rgba(24,119,242,0.22);}
.md-footer__social-btn svg{flex-shrink:0;}
/* Contact information left the narrow fifth column for a full-width band, so
   the three sites read side by side. line-height 2.2 is the nav-link rhythm and
   is reset here: applied to four-line addresses it was the main reason the
   footer grew taller than the page content above it. */
.md-footer__contact{border-top:1px solid var(--md-color-grey-800);
  padding-top:var(--md-space-6);padding-bottom:var(--md-space-2);}
.md-footer__contact-entity{margin:0 0 var(--md-space-5);
  color:var(--md-color-text-inverse);}
.md-footer__offices{display:grid;grid-template-columns:repeat(3,1fr);
  gap:var(--md-space-4) var(--md-space-6);}
.md-footer__offices li{margin:0;line-height:1.7;}
.md-footer__offices strong{display:block;color:var(--md-color-text-inverse);}
.md-footer__contact-lines{display:flex;flex-wrap:wrap;
  gap:var(--md-space-2) var(--md-space-6);margin-top:var(--md-space-6);}
.md-footer__contact-lines li{margin:0;line-height:1.6;}
.md-footer__section{border-top:1px solid var(--md-color-grey-800);
  padding-block:var(--md-space-6);}
.md-footer__bottom{display:flex;align-items:center;justify-content:space-between;
  gap:var(--md-space-5);flex-wrap:wrap;}
.md-footer__regions{max-width:60ch;margin:0;}
.md-footer__legal{border-top:1px solid var(--md-color-grey-800);
  padding-block:var(--md-space-5);display:flex;align-items:center;
  justify-content:space-between;gap:var(--md-space-5);flex-wrap:wrap;
  font-size:var(--md-text-caption);color:var(--md-color-text-muted);}
.md-footer__legal ul{display:flex;gap:var(--md-space-4);}
.md-footer__legal li{line-height:1.4;margin:0;}

@media (max-width:1023px){
  /* Three nav columns and a full-width brand row: with four grid items, two
     columns would strand the Company column on a row of its own. */
  .md-footer__cols{grid-template-columns:repeat(3,1fr);}
  .md-footer__brand{grid-column:span 3;}
  .md-footer__offices{grid-template-columns:1fr 1fr;}
}
@media (max-width:767px){
  .md-footer{padding-top:var(--md-space-9);}
  .md-footer__cols{grid-template-columns:1fr;}
  .md-footer__brand{grid-column:span 1;}
  .md-footer__col{border-top:1px solid var(--md-color-grey-800);}
  .md-footer__col-title{margin:0;}
  .md-footer__toggle{display:flex;width:100%;align-items:center;justify-content:space-between;
    background:transparent;border:0;color:var(--md-color-text-inverse);
    font-family:var(--md-font-heading);font-size:var(--md-text-h5);font-weight:600;
    text-align:left;padding:var(--md-space-4) 0;text-transform:uppercase;letter-spacing:.04em;
    cursor:pointer;}
  .md-footer__col .md-footer__col-title{display:none;}
  .md-footer__col-body{display:none;padding-bottom:var(--md-space-4);}
  .md-footer__col.is-open .md-footer__col-body{display:block;}
  .md-footer__offices{grid-template-columns:1fr;}
}

/* ------------------------------------------------- global lightbox / notice */
.md-note-bar{background:var(--md-color-bg-subtle);border-top:1px solid var(--md-color-border);
  font-size:var(--md-text-small);color:var(--md-color-text-secondary);
  padding-block:var(--md-space-3);}

/* =============================================================== review fixes
   Found by rendering the sample at 1440px and 375px (docs/sample-review.md).
   1. The persistent nav CTA duplicated the drawer's button and pushed the 375px
      layout 63px wide, so it is desktop-only.
   2. The off-canvas drawer was still taking part in layout on mobile.
   3. Heading levels: the sample must not repeat the old site's H2 -> H5/H6 jumps. */
@media (max-width:1023px){
  .md-nav__cta{display:none;}
}
.md-drawer[hidden],.md-drawer-mask[hidden]{display:none;}

/* the mega-panel CTA title is not a document heading (§7.4 item 1) */
.md-mega__cta .md-mega__cta-title{margin:0 0 var(--md-space-2);
  font-family:var(--md-font-heading);font-size:var(--md-text-h5);
  color:var(--md-color-text-primary);line-height:1.25;}

/* application cards sit directly under a section H2 */
.md-app-card h3{margin:0 0 var(--md-space-2);font-size:var(--md-text-h5);}

/* The two blocks below changed element (h6/h5 -> h3) for heading order, so the
   browser's larger default margins have to be neutralised explicitly. */
.md-cert__claim{margin:0;}
.md-footer__col-title{margin:0;}

/* ======================================================= client review 2026-09-16

   1. RIGHT-HAND GAP ON WIDE SCREENS
      Astra wraps everything below the header in `.ast-container`, and its
      max-width is what stopped the dark bands (hero, stat bar, CTA band) at
      1440px — so on a 1536px window they sat ~96px short of the right edge while
      the header and footer, which live outside that wrapper, ran full width.
      The product template already opted out of the container; the home template
      needs the same so every band is genuinely edge to edge. */
/* All templates opt out of Astra's default container constraint so banners and background bands run full width across wide screens */
.site-content > .ast-container{max-width:none !important;padding-inline:0 !important;width:100% !important;}

/*   2. BRAND BLOCK — the client wants the Mingda mark clearly legible.
      Was a 78x98 thumbnail next to a small wordmark; the emblem now comes from
      the 898x293 master file and renders at 56px. */
.md-nav__brand{gap:var(--md-space-4);align-items:center;}
  /* 64px is the largest the mark can go while the bar stays 72px: it leaves 4px
     above and below. logo-mark-tm.png carries the (R) at 14% of its height, so
     64px renders it at 9px — the size at which it first reads. */
.md-nav__brand img{height:64px;width:auto;max-height:none;}
.md-nav__brand-text{display:flex;flex-direction:column;gap:2px;}
.md-nav__brand-name{font-size:1.625rem;line-height:1.1;letter-spacing:.05em;}
.md-nav__brand-tag{font-size:.8125rem;line-height:1.35;max-width:30ch;}

/*   3. YARN IS THE PRIMARY PRODUCT (client note) but there are no yarn photos in
      the old site's media yet, so the first product-line card is a type-led tile
      instead of a photo. Swap it for a photo card once yarn shots exist. */
.md-card-home--text{display:flex;flex-direction:column;justify-content:space-between;
  min-height:15rem;padding:var(--md-space-6);background:var(--md-color-brand-green);
  color:#fff;}
.md-card-home--text h3{color:#fff;margin:0 0 var(--md-space-3);}
.md-card-home--text p{color:rgba(255,255,255,.88);margin:0 0 var(--md-space-4);}
.md-card-home--text ul{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:var(--md-space-2);}
.md-card-home--text li{border:1px solid rgba(255,255,255,.45);border-radius:var(--md-radius-xs);
  padding:.15rem .5rem;font-size:var(--md-text-xs);}
.md-card-home--text .md-text-link{color:#fff;margin-top:var(--md-space-4);}

/* The root cause of the right-hand gap, confirmed by walking the DOM at 1512px:
   Astra renders `.ast-container` as `display:flex; flex-direction:row`, so <main>
   is a flex item. Flex items do not stretch along the main axis, so <main> shrink-
   wrapped to its widest child — the 1440px inner container — instead of filling the
   window. Removing the container's max-width alone was not enough; <main> has to be
   told to fill. */
.site-content > .ast-container > main,
.site-content > .ast-container > #primary,
#md-main,
body.md-tpl-home .site-content > .ast-container > main,
body.md-tpl-product .site-content > .ast-container > main{width:100% !important;flex:1 1 100% !important;min-width:0 !important;}

/* Growing the brand block (56px mark + wordmark + strap line) pushed the mobile
   header 14px wider than a 375px screen. The flex children need permission to
   shrink below their content width so the strap line wraps instead of overflowing. */
@media (max-width:1023px){
  .md-nav__inner{min-width:0;}
  .md-nav__brand{gap:var(--md-space-3);min-width:0;flex:1 1 auto;}
  .md-nav__brand img{height:44px;}
  .md-nav__brand-text{min-width:0;flex:1 1 auto;}
  .md-nav__brand-name{font-size:1.0625rem;letter-spacing:.04em;}
  .md-nav__brand-tag{font-size:.6875rem;max-width:none;}
}

/* ================================================= header width 2026-09-18
   The desktop header overflowed between the 1024px layout breakpoint and
   1200px, giving the whole site a horizontal scrollbar on tablets and small
   laptops.

   The width is not a guess: scripts/measure_header.py decodes the self-hosted
   woff2 faces and sums the real advance widths of every string in the bar,
   against the box values in this file. The bar needs 1072px of intrinsic width
   — brand 294 (mark 61 + gap 12 + a 30ch strap line at 220) + gap 32 + menu 509
   (labels 301 + four 12px carets + five 32px gaps) + gap 32 + actions 205.
   The narrowest container in the broken range is 961px (1024px window less a
   scrollbar and two 24px gutters), hence roughly 85-111px of overflow.

   Nothing is dropped, only tightened, and every value still comes from a token.
   The strap line is capped rather than removed: it hands 59px back on its own
   and costs nothing visible. The cap is 22ch, not the 20ch that would give back
   a little more, because of where the line breaks — at 20ch (146.9px) "…aramid &
   HPPE" no longer fits on the first row and the strap line falls to THREE rows,
   taking the header from 72px to 79px. scripts/tag_wrap.py simulates the greedy
   break against the real font metrics: 21ch (154.2px) is the first cap that
   holds two rows, and 22ch leaves a little room for rendering differences.

   The block stops at 1200px, where the full-size header already fits with 65px
   to spare. Measured in Chrome at 1024-1440, the page now has no horizontal
   overflow at any width in or either side of this range. */
@media (min-width:1024px) and (max-width:1199px){
  .md-nav__inner{gap:var(--md-space-5);}
  .md-nav__menu{gap:var(--md-space-4);}
  .md-nav__brand{gap:var(--md-space-2);}
  .md-nav__brand img{height:56px;}
  /* The name steps down here as well as the mark: at 1.625rem it measures 178px,
     which is what sets the brand column once the strap line is capped, and the
     1024px container only has 961px to give. */
  .md-nav__brand-name{font-size:1.5rem;}
  .md-nav__brand-tag{max-width:22ch;}
  .md-nav__cta{padding:0 var(--md-space-3);}
}

/* ============================================ client review 2026-09-17 (B1–B5)

   Five changes were asked for on both module templates. They are additive: no
   existing component is re-described, no new style system is introduced, and
   every value still comes from tokens.css. The rules live here rather than in
   templates.css because they arrived after the page templates were built, and
   components.css loads before templates.css — so each selector below is written
   with two classes to out-rank the single-class rule it adjusts, making the
   result independent of sheet order.

   1  B4 · standards block is now ONE column (was Application standards beside
      Our compliance). templates.css sets `.md-std{grid-template-columns:1fr 1fr}`. */
.md-std.md-std--single{grid-template-columns:1fr;}
.md-std__lead{margin:0 0 var(--md-space-5);font-size:var(--md-text-body);
  line-height:var(--md-lh-body);color:var(--md-color-text-primary);max-width:90ch;}

/* 2  B3 · one extra swatch tile, `Custom colours welcome`. It must not look like
      a shade we can ship, so it is a hatched square with a dashed outline and a
      plus sign — never a flat colour. The hatch uses a 6px/12px repeating
      gradient: that is a graphic device, not a spacing value, so it stays off the
      spacing scale on purpose. Seven tiles need seven columns on desktop. */
.md-swatch__chip.md-swatch__chip--custom{
  background-image:repeating-linear-gradient(45deg,
    var(--md-color-grey-100) 0 6px,var(--md-color-white) 6px 12px);
  border:1px dashed var(--md-color-border-strong);
  display:flex;align-items:center;justify-content:center;}
.md-swatch__chip.md-swatch__chip--custom::before{
  content:"+";font-family:var(--md-font-heading);font-weight:600;
  font-size:1.75rem;line-height:1;color:var(--md-color-text-secondary);}
.md-swatches.md-swatches--custom{grid-template-columns:repeat(7,1fr);}
@media (max-width:1023px){
  .md-swatches.md-swatches--custom{grid-template-columns:repeat(4,1fr);}
}
@media (max-width:767px){
  .md-swatches.md-swatches--custom{grid-template-columns:repeat(3,1fr);}
}

/* 3  B5 · applications become a media-card grid: image on top, title and body
      below, everything left-aligned. Two columns is deliberate — both templates
      carry an even number of cards (2 on the yarn page, 4 on the fabric page), so
      two columns always closes the last row and nothing is left half-aligned.
      The body copy steps up from --md-text-small (14px) to --md-text-body (16px),
      the site's regular body size, and the card title from 18px to 22px. */
.md-app-cards.md-app-cards--media{grid-template-columns:repeat(2,1fr);
  gap:var(--md-space-8) var(--md-space-6);align-items:start;}
.md-app-cards--media .md-app-card{border-top:0;padding-top:0;}
.md-app-cards--media .md-app-card__media{margin:0 0 var(--md-space-4);
  border:1px solid var(--md-color-border);border-radius:var(--md-radius-sm);
  overflow:hidden;background:var(--md-color-bg-subtle);}
.md-app-cards--media .md-app-card__media img{display:block;width:100%;height:auto;
  aspect-ratio:3/2;object-fit:cover;}
.md-app-cards--media .md-app-card__title{margin:0 0 var(--md-space-2);
  font-size:var(--md-text-h4);line-height:var(--md-lh-h4);}
.md-app-cards--media .md-app-card__body{margin:0;max-width:62ch;
  font-size:var(--md-text-body);line-height:var(--md-lh-body);
  color:var(--md-color-text-secondary);}
@media (max-width:767px){
  .md-app-cards.md-app-cards--media{grid-template-columns:1fr;
    gap:var(--md-space-6);}
}

/* 4  B2 · module 4 series table. Six columns need a little more room than the
      five-column family table, and the `Source` column is provenance, not sales
      copy, so it is muted and set in caption size. */
.md-spec-table--series table{min-width:1040px;}
.md-spec-table .md-spec-table__source{color:var(--md-color-text-muted);
  font-size:var(--md-text-caption);white-space:nowrap;}

/* ======================================================= regression fix 2026-09-17
   The series table (module 4) blew the mobile layout out by 681px.

   Cause: `.md-spec-table--series table{min-width:1040px}` sits outside any media
   query, so its higher specificity beat the mobile rule
   `.md-spec-table table{min-width:0}` in the 767px block — while that same block
   also sets `overflow:visible`, so the over-wide table spilled into the document
   instead of scrolling. Re-assert the reset below the 767px block so it wins on
   both specificity and order. */
@media (max-width:767px){
  .md-spec-table--series table{min-width:0;}
}

/* ============================================ Template C module 3b / 3c 2026-09-17

   Two blocks were added to module 3 of the hose page (客户资料授权 2026-09-17):
   the market-share statement and the wall of customer marks. They are new
   because nothing in templates.css does this job — `.md-pdp-metrics` is a
   2-column number grid, and the market share is a sentence that has to carry
   its own statistical basis (v3 §6.4 rule 2), not a metric card. Both blocks
   are written with tokens only, and both sit below the existing three
   paragraphs and four metric cards, which are untouched.

   3b · market share. The figure is set in the heading face at h3 so it reads
   as the lead of the sentence, and the scope and the basis are set in caption
   size so the qualifier can never be separated from the number visually. */
.md-share{margin-top:var(--md-space-6);padding:var(--md-space-5);
  background:var(--md-color-bg-brand-soft);
  border-left:3px solid var(--md-color-border-brand);
  border-radius:var(--md-radius-sm);}
.md-share__figure{margin:0;font-family:var(--md-font-heading);font-weight:700;
  font-size:var(--md-text-h3);line-height:var(--md-lh-h3);
  color:var(--md-color-text-primary);}
.md-share__scope{margin:var(--md-space-2) 0 0;font-size:var(--md-text-body);
  line-height:var(--md-lh-body);color:var(--md-color-text-primary);}
.md-share__note{margin:var(--md-space-3) 0 0;font-size:var(--md-text-caption);
  line-height:var(--md-lh-small);color:var(--md-color-text-muted);max-width:90ch;}

/* 3c · customer marks. Five tiles, equal columns on desktop so the row closes
   exactly; the marks are all exported at one 2x height and one ink tone, so the
   only thing that varies between tiles is the mark's own width. `object-fit`
   keeps every mark inside its box without distortion. A tile whose logo file is
   missing renders as the company name alone (the template skips the <img>). */
.md-clients{margin-top:var(--md-space-8);}
.md-clients__heading{margin:0 0 var(--md-space-5);font-size:var(--md-text-h4);
  line-height:var(--md-lh-h4);color:var(--md-color-text-primary);}
.md-clients__grid{list-style:none;margin:0;padding:0;display:grid;
  grid-template-columns:repeat(5,1fr);gap:var(--md-space-4);}
.md-client{display:flex;flex-direction:column;align-items:center;
  justify-content:flex-start;gap:var(--md-space-3);height:100%;
  background:var(--md-color-white);border:1px solid var(--md-color-border);
  border-radius:var(--md-radius-sm);padding:var(--md-space-5) var(--md-space-4);
  text-align:center;}
.md-client__logo{display:flex;align-items:center;justify-content:center;
  height:44px;width:100%;}
.md-client__logo img{height:44px;width:auto;max-width:100%;object-fit:contain;}
.md-client__name{font-size:var(--md-text-caption);line-height:var(--md-lh-small);
  color:var(--md-color-text-secondary);}
.md-clients__note{margin:var(--md-space-5) 0 0;font-size:var(--md-text-caption);
  line-height:var(--md-lh-small);color:var(--md-color-text-muted);max-width:90ch;}
@media (max-width:1023px){
  .md-clients__grid{grid-template-columns:repeat(3,1fr);}
}
@media (max-width:767px){
  .md-clients__grid{grid-template-columns:repeat(2,1fr);}
  .md-share{padding:var(--md-space-4);}
}

/* ======================================================= nav rebuild 2026-09-17
   The Products panel now mirrors the nine real categories instead of the old
   "by material / by form" groupings, so it needs a fourth column. Below 1280px the
   CTA card is dropped rather than squeezing four columns of long category labels
   into the panel. */
.md-mega__inner--products{grid-template-columns:1fr 1fr 1fr 1fr 340px;}
@media (min-width:1024px) and (max-width:1279px){
  .md-mega__inner--products{grid-template-columns:1fr 1fr 1fr 1fr;}
  .md-mega__inner--products .md-mega__cta{display:none;}
}

/* ================================================= journey timeline 2026-09-18
   Client review (修改意见2): the company history was a one-line list and read as
   "too thin". The client supplied their own graphic, which puts the years on a
   green arrow sweeping left to right, and asked for that shape. Ten nodes do not
   fit on one arrow, so they are chunked into rows of five and each row is one
   segment — see template-parts/components/journey.php.

   The arrow is the row's ::before (band) and ::after (head) rather than an SVG,
   so it cannot drift out of line with the dots: its centre is measured from the
   row's top edge, and the year block above each dot has a fixed line height so
   that measurement holds for every node. */
.md-journey-wrap{margin-top:var(--md-space-8);
  border-top:1px solid var(--md-color-border-subtle);padding-top:var(--md-space-6);}
.md-journey-wrap__heading{font-size:1.0625rem;margin:0 0 var(--md-space-6);
  color:var(--md-color-text-primary);}
.md-journey__row{position:relative;margin-bottom:var(--md-space-8);}
.md-journey__row:last-child{margin-bottom:0;}
/* 2.1rem = the fixed year line height; + 9px = half of the 18px dot.
   The band's right edge is set to the arrowhead's BASE — the head is 20px wide
   and pinned at right:2.5%, so `calc(2.5% + 20px)` makes the two meet exactly.
   An earlier right:5.5% left a visible 17px seam between band and head (found in
   visual review 2026-09-18). */
.md-journey__row::before{content:"";position:absolute;left:10%;right:calc(2.5% + 20px);
  top:calc(2.1rem + 9px);transform:translateY(-50%);height:6px;border-radius:3px;
  background:linear-gradient(90deg,var(--md-color-green-200),var(--md-color-green-500));}
.md-journey__row::after{content:"";position:absolute;right:2.5%;
  top:calc(2.1rem + 9px);transform:translateY(-50%);width:0;height:0;
  border-left:20px solid var(--md-color-green-500);
  border-top:13px solid transparent;border-bottom:13px solid transparent;}
.md-journey__list{list-style:none;margin:0;padding:0;display:grid;
  grid-template-columns:repeat(5,1fr);gap:var(--md-space-5);}
.md-journey__item{display:flex;flex-direction:column;align-items:center;text-align:center;}
.md-journey__year{font-size:1.25rem;font-weight:700;line-height:2.1rem;
  color:var(--md-color-text-link);}
.md-journey__dot{box-sizing:border-box;width:18px;height:18px;border-radius:50%;
  background:var(--md-color-white);border:5px solid var(--md-color-green-500);
  margin:0 0 var(--md-space-3);position:relative;z-index:1;}
.md-journey__title{font-size:0.9375rem;font-weight:600;line-height:1.4;}
.md-journey__note{font-size:var(--md-text-caption);line-height:1.45;
  color:var(--md-color-text-muted);margin-top:6px;max-width:24ch;}
@media (max-width:1023px){
  .md-journey__list{grid-template-columns:repeat(2,1fr);gap:var(--md-space-6);}
  .md-journey__row{margin-bottom:var(--md-space-6);}
  .md-journey__row::before,.md-journey__row::after{display:none;}
}
@media (max-width:767px){
  .md-journey__list{grid-template-columns:1fr;}
  .md-journey__item{padding-left:2.4rem;align-items:flex-start;text-align:left;
    position:relative;}
  /* The arrow is hidden below 768px, so the nodes get a vertical connector
     instead: without it the dots read as ten unrelated rings and the "journey"
     the client asked for is lost.

     The connector is drawn per NODE, from its dot centre down to the next dot
     centre, rather than as one line per list. A first attempt used a single
     `.md-journey__list::before` and visual review on 2026-09-18 found it broke
     into two segments with a visible 56px gap between the 2012 and 2015 nodes,
     because the timeline is two separate `.md-journey__row` blocks — each list
     painted its own line and neither crossed the row gap.

     Geometry: 6px wide at left:6px centres the line on the dots (dots are 18px
     wide at left:0, so their centre is at 9px). top:9px starts it at the dot
     centre, where the opaque dot masks it. The bottom reaches the next node's
     dot centre: the row gap (--md-space-6) plus the next dot's 11px offset.
     Only the FINAL node of the FINAL row suppresses it, so the line still
     crosses from 2012 into 2015 but leaves no dangling tail after "Next". */
  .md-journey__item::after{content:"";position:absolute;left:6px;top:9px;
    bottom:calc(-1 * var(--md-space-6) - 11px);width:6px;
    background:var(--md-color-green-200);}
  .md-journey__row:last-child .md-journey__item:last-child::after{display:none;}
  .md-journey__year{line-height:1.6;}
  .md-journey__dot{position:absolute;left:0;top:2px;margin:0;}
  .md-journey__note{max-width:none;}
}

/* ============================================ about · the protection arc 2026-09-20
   Client instruction (deferred from 2026-09-18): the About history block was ten
   plain cards. Their brochure graphic is a big half-curved arrow with the years
   sitting on it, and they asked for that shape — "可以融入阻燃防护风格的设计更好".

   Geometry contract, mirrored from arc-timeline.php: the row is exactly as tall as
   the viewBox (280), so one viewBox unit is one CSS pixel vertically and a dot at
   `top: var(--y)` lands on the tape. The band is stretched with
   preserveAspectRatio="none" — x scales with the container, y does not — so the
   same markup stays on the path from 1024px to the 1280px container cap.

   The columns deliberately carry NO grid gap: the spacing is padding inside each
   column, which keeps a column's centre at exactly (i + .5) / 5 of the width. With
   a gap the centres drift up to 10px off the tape at the fifth column.

   Below 1024px the tape is dropped rather than shrunk, and the markers go back to
   being a plain stacked list: an arrow that has to wrap is worse than honest
   columns. That split is the same one .md-journey already uses. */
.md-arc{margin-top:var(--md-space-8);}
.md-arc__row{position:relative;}
.md-arc__row + .md-arc__row{margin-top:var(--md-space-9);}
/* Faint twill weave, the one decorative nod to the protective textiles the plant
   actually makes. Kept at 6% so it textures the band without hatching it; sits
   behind both the tape and the copy. */
.md-arc__row::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  opacity:.06;
  background-image:repeating-linear-gradient(-45deg,var(--md-color-green-500) 0 1px,transparent 1px 8px);}
/* overflow:visible so the tape's rounded left end is not sliced off by the SVG
   viewport — it is the one thing that leaves the viewBox (by the 8px cap radius),
   and a square-cut start reads as a crop rather than as where the tape begins. */
.md-arc__band{position:absolute;top:0;left:0;width:100%;height:280px;z-index:1;
  display:block;pointer-events:none;overflow:visible;}
.md-arc__shine{stroke:var(--md-color-white);opacity:.28;}
.md-arc__list{list-style:none;margin:0;padding:0;position:relative;z-index:1;
  display:grid;grid-template-columns:repeat(5,1fr);}
/* + 36px = the dot's half height (9) plus the clearance the copy needs from the
   tape. The tape runs THROUGH the dot and leans at up to ~11°, so at the far edge
   of a label's column its lower edge sits ~13px below the centreline. Measured
   against the live page on 2026-09-20, the first glyph of a title came within 4px
   of that edge at 29px — ink on the text. 36px leaves the worst case 7px clear and
   still reads as "this copy belongs to that dot". The year and the dot hang above
   the copy, out of flow, so the copy block is what sets the row's height. */
.md-arc__item{position:relative;padding:calc(var(--y) + 36px) var(--md-space-4) 0;}
.md-arc__dot{position:absolute;top:var(--y);left:50%;transform:translate(-50%,-9px);
  box-sizing:border-box;width:18px;height:18px;border-radius:50%;
  background:var(--md-color-white);border:5px solid var(--md-color-green-500);}
.md-arc__year{position:absolute;top:calc(var(--y) - 14px);left:50%;
  transform:translate(-50%,-100%);white-space:nowrap;
  font-family:var(--md-font-heading);font-size:1.375rem;font-weight:700;line-height:1;
  color:var(--md-color-text-link);font-variant-numeric:tabular-nums;}
.md-arc__title{display:block;font-size:0.9375rem;font-weight:600;line-height:1.4;
  color:var(--md-color-text-primary);text-align:center;}
.md-arc__note{display:block;margin-top:6px;font-size:var(--md-text-caption);
  line-height:1.45;color:var(--md-color-text-muted);text-align:center;}
@media (max-width:1023px){
  .md-arc__band,.md-arc__row::before{display:none;}
  .md-arc__list{grid-template-columns:1fr 1fr;gap:var(--md-space-6);}
  .md-arc__item{padding:0;}
  .md-arc__dot,.md-arc__year{position:static;transform:none;}
  .md-arc__year{display:block;text-align:center;margin-bottom:var(--md-space-2);
    font-size:1.125rem;}
  .md-arc__dot{margin:0 auto var(--md-space-3);}
  .md-arc__row + .md-arc__row{margin-top:var(--md-space-7);}
}
@media (max-width:767px){
  .md-arc__list{grid-template-columns:1fr;gap:0;}
  .md-arc__item{padding:0 0 0 2.4rem;margin-bottom:var(--md-space-6);}
  .md-arc__item:last-child{margin-bottom:0;}
  .md-arc__dot{position:absolute;left:0;top:2px;margin:0;}
  .md-arc__year{text-align:left;line-height:1.6;}
  .md-arc__title,.md-arc__note{text-align:left;}
  /* The tape is gone below 768px, so the nodes get a vertical connector — without
     it the eyelets read as ten unrelated rings. Drawn per NODE, from this dot's
     centre to the next one, for the reason recorded on .md-journey__item::after:
     one line per list breaks into two segments across the row boundary, because
     the timeline is two .md-arc__row blocks. Geometry: 6px wide at left:6px centres
     on an 18px dot at left:0; top:11px is that dot's centre (2 + 9). Only the final
     node of the final row suppresses it, so the line still crosses the row gap but
     leaves no tail after "Next". */
  .md-arc__item::after{content:"";position:absolute;left:6px;top:11px;
    bottom:calc(-1 * var(--md-space-6) - 11px);width:6px;
    background:var(--md-color-green-200);}
  .md-arc__row:last-child .md-arc__item:last-child::after{display:none;}
}

/* ================================================== standards page 2026-09-18
   Client review (修改意见2): the nav's standard names had no destination and
   "How to read a standard" linked back to itself. Both now land on /standards/,
   so this page needs two new components: the hazard cards (scenario image +
   the standards that answer it) and the register (one entry per standard, each
   an anchor the nav can deep-link to). */
/* Capacity: the four "what decides what we can deliver" blocks, iconed.
   Client review 2026-09-18 (修改意见2): four blocks of solid text read as a wall. */
.md-feature-grid--iconed .md-feature{padding-top:var(--md-space-4);}
.md-feature__icon{display:inline-flex;align-items:center;justify-content:center;
  width:56px;height:56px;border-radius:var(--md-radius-md);
  background:var(--md-color-bg-brand-soft);color:var(--md-color-green-600);
  margin-bottom:var(--md-space-3);}
.md-feature__icon svg{display:block;}

.md-hazard-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--md-space-6);}
.md-hazard{display:flex;flex-direction:column;background:var(--md-color-bg-page);
  border:1px solid var(--md-color-border);border-radius:var(--md-radius-md);
  overflow:hidden;}
.md-hazard__media{margin:0;aspect-ratio:3/2;background:var(--md-color-bg-subtle);}
.md-hazard__media img{display:block;width:100%;height:100%;object-fit:cover;}
.md-hazard__body{padding:var(--md-space-5);display:flex;flex-direction:column;
  gap:var(--md-space-3);}
.md-hazard__body h3{margin:0;font-size:1.0625rem;}
.md-hazard__body p{margin:0;font-size:0.9375rem;line-height:1.55;color:var(--md-color-text-secondary);}
.md-hazard__std{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;
  gap:6px;margin-top:auto;}
.md-chip-link{display:inline-block;padding:4px 10px;border-radius:999px;
  font-size:var(--md-text-caption);font-weight:600;text-decoration:none;
  color:var(--md-color-text-link);background:var(--md-color-bg-brand-soft);
  border:1px solid var(--md-color-green-200);}
.md-chip-link:hover{border-color:var(--md-color-green-500);}

.md-register__group{margin-bottom:var(--md-space-8);}
.md-register__group-title{font-size:0.8125rem;text-transform:uppercase;
  letter-spacing:0.08em;color:var(--md-color-text-muted);
  margin:0 0 var(--md-space-4);}
.md-register{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--md-space-4);}
.md-register__entry{border:1px solid var(--md-color-border);border-radius:var(--md-radius-md);
  padding:var(--md-space-5);background:var(--md-color-bg-page);
  scroll-margin-top:7rem;}
.md-register__standard{margin:0 0 4px;font-size:1rem;}
.md-register__standard span{color:var(--md-color-text-muted);font-weight:400;}
.md-register__claim{margin:0 0 var(--md-space-2);font-weight:600;font-size:0.9375rem;
  color:var(--md-color-text-primary);}
.md-register__status{margin:0 0 var(--md-space-3);display:inline-block;
  font-size:var(--md-text-caption);font-weight:600;padding:2px 8px;border-radius:999px;
  color:var(--md-color-text-link);background:var(--md-color-bg-brand-soft);}
.md-register__how{margin:0;font-size:var(--md-text-caption);line-height:1.6;
  color:var(--md-color-text-muted);}
/* A deep link from the nav should be obvious when it lands, otherwise the
   reader cannot tell which of thirty entries they were sent to. */
.md-register__entry:target{border-color:var(--md-color-green-500);
  box-shadow:0 0 0 3px var(--md-color-bg-brand-soft);}
@media (max-width:899px){
  .md-hazard-grid,.md-register{grid-template-columns:1fr;}
}


/* ------------------------------------------- C5-b certificate thumbnails */
/* Client instruction 2026-09-22 (修改意见3, item 5). Small on purpose: the
   pictures are there to show that the documents exist, not to be read, which is
   why they are laid out as modest thumbnails under a caption rather than as
   full-width figures. The label and scope under each one carry the meaning, so
   nothing depends on the image being legible. */
.md-cert-media{margin-top:var(--md-space-8);padding-top:var(--md-space-6);
  border-top:1px solid var(--md-color-border-subtle);}
.md-cert-media__grid{list-style:none;margin:0;padding:0;display:grid;
  grid-template-columns:repeat(6,1fr);gap:var(--md-space-4);}
.md-cert-media__item{margin:0;}
.md-cert-media__figure{margin:0;}
.md-cert-media__image{display:block;width:100%;height:auto;
  border:1px solid var(--md-color-border);border-radius:var(--md-radius-sm);
  background:var(--md-color-white);}
.md-cert-media__caption{display:block;margin-top:var(--md-space-3);}
.md-cert-media__label{display:block;font-family:var(--md-font-heading);
  font-size:var(--md-text-caption);font-weight:600;line-height:1.35;
  color:var(--md-color-text-primary);}
.md-cert-media__scope{display:block;margin-top:2px;
  font-size:var(--md-text-caption);line-height:1.4;
  color:var(--md-color-text-secondary);}
.md-cert-media__note{margin:var(--md-space-6) 0 0;font-size:var(--md-text-small);
  color:var(--md-color-text-secondary);}
.md-cert-media__cta{margin-left:var(--md-space-2);white-space:nowrap;}
@media (max-width:1099px){
  .md-cert-media__grid{grid-template-columns:repeat(3,1fr);}
}
@media (max-width:599px){
  .md-cert-media__grid{grid-template-columns:repeat(2,1fr);gap:var(--md-space-3);}
  .md-cert-media__cta{margin-left:0;display:block;margin-top:var(--md-space-2);}
}
