/* ============================================================================
   PACKAGING 100 · COMPONENT LIBRARY  (V2-J, 2026-08-17)
   Requires tokens.css. Zero offshore dependencies.
   Includes promoted Scheme B capability matrix & comparison components.

   Design contract, in one line: this is a working tool for a buyer, not a
   brochure about us. Data constructs (tables, badges, facets, chips, matrix)
   carry the visual language; decoration stays out of the way.
   ========================================================================= */

@layer reset, base, components, utilities;

/* ═══ RESET ═══════════════════════════════════════════════════════════ */
@layer reset {
  *, *::before, *::after { box-sizing: border-box; }
  body, h1, h2, h3, h4, h5, p, figure, blockquote, dl, dd { margin: 0; }
  ul[class], ol[class] { list-style: none; margin: 0; padding: 0; }
  img, svg, video { max-inline-size: 100%; display: block; }
  button, input, select, textarea { font: inherit; color: inherit; }
  button { cursor: pointer; background: none; border: 0; padding: 0; }
  table { border-collapse: collapse; inline-size: 100%; }
  a { color: inherit; }
}

/* ═══ BASE ════════════════════════════════════════════════════════════ */
@layer base {
  html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
  @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

  body {
    margin: 0;
    background: var(--color-canvas);
    color: var(--color-text);
    font-family: var(--font-sans);
    font-size: var(--text-md);
    line-height: var(--leading-body);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
  }

  h1, h2, h3, h4, h5 {
    font-family: var(--font-sans);
    line-height: var(--leading-tight);
    font-weight: 650;
    letter-spacing: -0.012em;
    text-wrap: balance;
  }
  h1 { font-size: var(--text-3xl); }
  h2 { font-size: var(--text-xl); }
  h3 { font-size: var(--text-lg); }
  h4 { font-size: var(--text-md); }
  p  { text-wrap: pretty; }

  :focus-visible {
    outline: 2px solid var(--color-focus);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
  }
  ::selection { background: var(--color-primary-soft); }

  /* Every figure on this site is either a real, sourced number or demo data.
     Demo data is labelled — never dressed up as a client metric. */
  .demo-note {
    font-size: var(--text-2xs);
    color: var(--color-text-muted);
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
  }
  :lang(zh) .demo-note { text-transform: none; }
}

@layer components {

  /* ═══ LAYOUT ════════════════════════════════════════════════════════ */
  .wrap { max-inline-size: var(--wrap-max); margin-inline: auto; padding-inline: var(--gutter); }
  .wrap-narrow { max-inline-size: var(--wrap-narrow); margin-inline: auto; padding-inline: var(--gutter); }

  .section { padding-block: var(--sp-12); }
  .section--tight { padding-block: var(--sp-8); }
  .section--surface { background: var(--color-surface); border-block: 1px solid var(--color-border); }
  .section--sunken  { background: var(--color-surface-sunken); }
  .section--brand   { background: var(--color-surface-brand); color: var(--color-text-invert); }
  .section--brand :is(h2, h3) { color: var(--color-text-invert); }
  .section--brand p { color: var(--color-text-invert-muted); }

  .section-head {
    display: flex; flex-wrap: wrap; align-items: flex-end;
    justify-content: space-between; gap: var(--sp-4);
    margin-block-end: var(--sp-6);
  }
  .section-head > div { max-inline-size: 60ch; }
  .section-head p { color: var(--color-text-secondary); font-size: var(--text-sm); margin-block-start: var(--sp-2); }

  .eyebrow {
    display: block;
    font-size: var(--text-2xs); font-weight: 600;
    letter-spacing: var(--tracking-caps); text-transform: uppercase;
    color: var(--color-text-muted);
    margin-block-end: var(--sp-2);
  }
  :lang(zh) .eyebrow { text-transform: none; }

  .link-more {
    font-size: var(--text-sm); font-weight: 600;
    color: var(--color-text-link); text-decoration: none;
    display: inline-flex; align-items: center; gap: var(--sp-2);
    white-space: nowrap;
  }
  .link-more:hover { text-decoration: underline; }

  /* ═══ BUTTONS ═══════════════════════════════════════════════════════ */
  .btn {
    display: inline-flex; align-items: center; justify-content: center;
    gap: var(--sp-2);
    block-size: var(--control-height);
    padding-inline: var(--sp-4);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius);
    background: var(--color-surface);
    color: var(--color-text);
    font-size: var(--text-sm); font-weight: 600;
    text-decoration: none; white-space: nowrap;
    transition: background var(--dur-fast) var(--ease-standard),
                border-color var(--dur-fast) var(--ease-standard),
                color var(--dur-fast) var(--ease-standard);
  }
  .btn:hover { background: var(--grey-50); border-color: var(--grey-400); }
  .btn:active { background: var(--grey-100); }

  .btn--primary {
    background: var(--color-primary); border-color: var(--color-primary);
    color: var(--color-on-primary);
  }
  .btn--primary:hover { background: var(--color-primary-hover); border-color: var(--color-primary-hover); }
  .btn--primary:active { background: var(--color-primary-active); border-color: var(--color-primary-active); }

  .btn--ghost { background: transparent; border-color: transparent; color: var(--color-text-link); }
  .btn--ghost:hover { background: var(--color-surface-tint); border-color: transparent; }

  .btn--on-brand {
    background: transparent; border-color: color-mix(in srgb, var(--white) 40%, transparent);
    color: var(--color-text-invert);
  }
  .btn--on-brand:hover { background: color-mix(in srgb, var(--white) 12%, transparent); border-color: var(--white); }

  .btn--lg { block-size: var(--control-height-lg); padding-inline: var(--sp-6); font-size: var(--text-md); }
  .btn--sm { block-size: var(--control-height-sm); padding-inline: var(--sp-3); font-size: var(--text-xs); }
  .btn--block { inline-size: 100%; }
  .btn[disabled], .btn[aria-disabled="true"] { opacity: 0.5; pointer-events: none; }

  /* ═══ FORM CONTROLS ═════════════════════════════════════════════════ */
  .field { display: grid; gap: var(--sp-2); }
  .field > label, .label {
    font-size: var(--text-xs); font-weight: 600; color: var(--color-text-secondary);
  }
  .hint { font-size: var(--text-2xs); color: var(--color-text-muted); }

  .input, .select, .textarea {
    inline-size: 100%;
    block-size: var(--control-height);
    padding-inline: var(--sp-3);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius);
    background: var(--color-surface);
    font-size: var(--text-sm);
    transition: border-color var(--dur-fast) var(--ease-standard),
                box-shadow var(--dur-fast) var(--ease-standard);
  }
  .textarea { block-size: auto; padding-block: var(--sp-2); line-height: var(--leading-body); resize: vertical; }
  .input::placeholder, .textarea::placeholder { color: var(--color-text-muted); }
  .input:focus, .select:focus, .textarea:focus {
    outline: none; border-color: var(--color-primary); box-shadow: var(--focus-ring);
  }
  .select {
    appearance: none;
    padding-inline-end: var(--sp-8);
    /* Caret drawn with a gradient pair, not an image — no asset to fetch. */
    background-image:
      linear-gradient(45deg, transparent 50%, var(--grey-600) 50%),
      linear-gradient(135deg, var(--grey-600) 50%, transparent 50%);
    background-position: right 1.05rem center, right 0.7rem center;
    background-size: 0.35rem 0.35rem, 0.35rem 0.35rem;
    background-repeat: no-repeat;
  }
  :dir(rtl) .select { background-position: left 1.05rem center, left 0.7rem center; }

  .checkbox { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--text-sm); cursor: pointer; }
  .checkbox input { inline-size: 1rem; block-size: 1rem; margin: 0; accent-color: var(--color-primary); }
  .checkbox .count { margin-inline-start: auto; font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--color-text-muted); font-variant-numeric: tabular-nums; }

  /* ═══ SEARCH CONSOLE ════════════════════════════════════════════════
     The homepage's主角. ThomasNet opens on a search box, not a manifesto.
     Segmented: keyword + category + export region + submit, one control. */
  .search-console { display: grid; gap: var(--sp-3); }

  .search-bar {
    display: grid;
    grid-template-columns: minmax(0, 2.2fr) minmax(0, 1fr) minmax(0, 1fr) auto;
    background: var(--color-surface);
    border-radius: var(--radius-lg);
    padding: var(--sp-2);
    gap: var(--sp-2);
    box-shadow: var(--shadow-3);
  }
  .search-bar .seg { display: flex; align-items: center; gap: var(--sp-2); min-inline-size: 0; }
  .search-bar .seg + .seg { border-inline-start: 1px solid var(--color-divider); padding-inline-start: var(--sp-2); }
  .search-bar .p100-icon { color: var(--color-text-muted); margin-inline-start: var(--sp-2); }
  /* The console sits on the dark brand band, so these controls must re-assert
     the light-surface text colour rather than inherit the band's white. */
  .search-bar .input, .search-bar .select {
    border: 0; box-shadow: none; block-size: var(--control-height-lg);
    font-size: var(--text-md); padding-inline: var(--sp-1);
    color: var(--color-text); background-color: transparent;
  }
  .search-bar .select option { color: var(--color-text); background: var(--color-surface); }
  .search-bar .input:focus, .search-bar .select:focus { box-shadow: none; }
  .search-bar .seg:focus-within { border-radius: var(--radius); background: var(--color-surface-tint); }
  .search-bar .btn { block-size: var(--control-height-lg); padding-inline: var(--sp-8); }
  @media (max-width: 60rem) {
    .search-bar { grid-template-columns: 1fr 1fr; }
    .search-bar .seg:first-child { grid-column: 1 / -1; }
    .search-bar .seg + .seg { border-inline-start: 0; padding-inline-start: 0; }
    .search-bar .btn { grid-column: 1 / -1; }
  }

  .search-suggest {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-2) var(--sp-3);
    font-size: var(--text-sm);
  }
  .search-suggest > span { color: var(--color-text-invert-muted); }
  .search-suggest a {
    color: var(--color-text-invert); text-decoration: none;
    border-block-end: 1px solid color-mix(in srgb, var(--white) 35%, transparent);
  }
  .search-suggest a:hover { border-color: var(--white); }

  /* ═══ CHIPS (quick filters / applied filters) ═══════════════════════ */
  .chip-row { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
  .chip {
    display: inline-flex; align-items: center; gap: var(--sp-2);
    block-size: var(--control-height-sm); padding-inline: var(--sp-3);
    border: 1px solid var(--color-border-strong); border-radius: var(--radius-pill);
    background: var(--color-surface);
    font-size: var(--text-xs); font-weight: 500; color: var(--color-text-secondary);
    text-decoration: none; white-space: nowrap;
    transition: all var(--dur-fast) var(--ease-standard);
  }
  .chip:hover { border-color: var(--color-primary); color: var(--color-primary); }
  .chip[aria-pressed="true"], .chip--on {
    background: var(--color-primary-soft); border-color: var(--color-primary);
    color: var(--brand-text); font-weight: 600;
  }
  .chip--on-brand {
    background: color-mix(in srgb, var(--white) 10%, transparent);
    border-color: color-mix(in srgb, var(--white) 30%, transparent);
    color: var(--color-text-invert);
  }
  .chip--on-brand:hover { background: color-mix(in srgb, var(--white) 20%, transparent); border-color: var(--white); color: var(--white); }
  .chip .x { font-size: var(--text-sm); line-height: 1; opacity: 0.6; }

  /* ═══ BADGES (certifications, status, expo) ═════════════════════════
     The badge is the single most repeated construct on this platform —
     every company card and every table row carries three or four. */
  .badge {
    display: inline-flex; align-items: center; gap: var(--sp-1);
    padding: 0.15rem var(--sp-2);
    border-radius: var(--radius-sm);
    background: var(--color-surface-sunken);
    border: 1px solid var(--color-border);
    font-size: var(--text-2xs); font-weight: 600;
    letter-spacing: 0.02em; color: var(--color-text-secondary);
    white-space: nowrap;
  }
  .badge--cert    { background: var(--grey-100);           border-color: var(--grey-300); color: var(--grey-800); }
  .badge--verified{ background: var(--color-success-soft); border-color: #b7e0c8;        color: var(--green-600); }
  .badge--expo    { background: var(--color-warning-soft); border-color: #edd79b;        color: var(--amber-600); }
  .badge--vip     { background: var(--color-vip-soft);     border-color: #cfc2ee;        color: var(--violet-600); }
  .badge--alert   { background: var(--color-danger-soft);  border-color: #f0bdb9;        color: var(--color-danger); }
  .badge--plain   { background: transparent; }
  .badge-row { display: flex; flex-wrap: wrap; gap: var(--sp-2); }

  /* ═══ CARDS ═════════════════════════════════════════════════════════ */
  .card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: var(--sp-5);
    transition: border-color var(--dur-base) var(--ease-standard),
                box-shadow var(--dur-base) var(--ease-standard);
  }
  .card--flat { box-shadow: none; }
  .card--link:hover { border-color: var(--color-border-strong); box-shadow: var(--shadow-2); }
  .card-grid { display: grid; gap: var(--sp-4); grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr)); }

  /* Category tile — the browse-by-capability grid. Icon + label + count.
     This is the second half of the ThomasNet opening: search OR browse. */
  .cat-grid { display: grid; gap: var(--sp-3); grid-template-columns: repeat(auto-fill, minmax(min(100%, 11.5rem), 1fr)); }
  .cat-tile {
    display: grid; gap: var(--sp-2);
    padding: var(--sp-4);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    text-decoration: none;
    transition: border-color var(--dur-base) var(--ease-standard),
                box-shadow var(--dur-base) var(--ease-standard),
                transform var(--dur-base) var(--ease-standard);
  }
  .cat-tile:hover { border-color: var(--color-primary); box-shadow: var(--shadow-2); }
  .cat-tile .p100-icon { --p100-icon-size: 1.75rem; color: var(--color-primary); }
  .cat-tile .name { font-size: var(--text-sm); font-weight: 600; line-height: var(--leading-snug); }
  .cat-tile .count {
    font-family: var(--font-mono); font-size: var(--text-2xs);
    color: var(--color-text-muted); font-variant-numeric: tabular-nums;
  }

  /* Company result card — the directory's atom. Mirrors the Company shape
     published by W1-A (name_en/name_zh, country/city, certifications[],
     export_regions[], accepts_small_batch, exhibitions[]). */
  .company-card {
    display: grid; gap: var(--sp-3);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: var(--sp-4) var(--sp-5);
  }
  .company-card:hover { border-color: var(--color-border-strong); box-shadow: var(--shadow-2); }
  .company-card .head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-3); }
  .company-card .name { font-size: var(--text-md); font-weight: 650; line-height: var(--leading-snug); }
  /* 名录卡片里 .name 就是 <a> 本身，不是包着 <a> 的容器 —— 早先写成
     `.name a` 的两条规则从来没匹配上，于是链接一直挂着浏览器默认下划线。
     中日韩字形没有西文那样的下降部留白，默认位置的下划线会**从字底切过去**
     （「设备有限公司」这类字尤其明显）。这里恢复原本的设计意图：静止不加线、
     悬停才加，并且把线压低、留出避让，中英文都不会被切到。 */
  .company-card a.name,
  .company-card .name a { text-decoration: none; }
  .company-card a.name:hover,
  .company-card .name a:hover {
    color: var(--color-text-link);
    text-decoration: underline;
    text-underline-offset: 0.22em;
    text-decoration-thickness: 1px;
    text-decoration-skip-ink: auto;
  }
  .company-card .where { font-size: var(--text-xs); color: var(--color-text-muted); margin-block-start: 0.1rem; }
  .company-card .specs { display: grid; gap: var(--sp-1); font-size: var(--text-xs); }
  .company-card .specs .row { display: grid; grid-template-columns: 6.5rem 1fr; gap: var(--sp-3); }
  .company-card .specs dt { color: var(--color-text-muted); }
  .company-card .specs dd { margin: 0; color: var(--color-text-secondary); }
  .company-card .actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); padding-block-start: var(--sp-3); border-block-start: 1px solid var(--color-divider); }
  /* 甲方要求把 logo 放大，与公司名／产品／所在地组成清晰的卡片头部。
     两点刻意的处理：
     1. object-fit 用 contain 不用 cover —— 企业标准字标大多是宽形（实测 400×199），
        cover 会把两侧裁掉只剩中间一截，放得越大裁得越难看。
     2. 38 家里只有 18 家有真正的 logo 文件，其余 20 家的图是厂房实拍。
        厂房照裁成方块摆在公司名旁边，看起来就像那是人家的商标 —— 那是在替企业
        造一个它没有的东西。没有 logo 的一律走 .logo--initials 首字母块，
        干净、整齐、且不声称任何它不是的东西。 */

  /* ── 区块滚动淡入 ────────────────────────────────────────────────────────
     配合 public/scroll-reveal.js。注意 .reveal-pending 是由脚本加上去的，
     **不是** HTML 里的初始状态 —— 元素默认可见，脚本先把它变透明再淡入。
     反过来做（默认 opacity:0 等 JS 点亮）会在脚本加载失败时整页空白。
     位移 14px、320ms，甲方要的是「不要过度，保持专业感」。 */
  [data-reveal].reveal-pending {
    opacity: 0;
    transform: translateY(14px);
  }
  [data-reveal].reveal-in {
    opacity: 1;
    transform: none;
    transition: opacity var(--dur-slow) var(--ease-out),
                transform var(--dur-slow) var(--ease-out);
  }

  .company-card .logo {
    inline-size: 5.5rem; block-size: 5.5rem; flex: none;
    display: grid; place-items: center;
    border: 1px solid var(--color-border); border-radius: var(--radius-sm);
    background: var(--color-surface);
    padding: var(--sp-1);
    object-fit: contain;
  }
  .company-card .logo--initials {
    background: var(--color-surface-sunken);
    font-family: var(--font-mono);
    font-size: var(--text-2xl);
    font-weight: 600;
    color: var(--color-text-muted);
    letter-spacing: .02em;
    padding: 0;
  }

  /* ═══ FACET RAIL (search filters) ═══════════════════════════════════ */
  .facets { display: grid; gap: var(--sp-1); align-content: start; }
  .facet {
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface);
    padding: var(--sp-3) var(--sp-4);
  }
  .facet + .facet { margin-block-start: var(--sp-3); }
  .facet > summary, .facet > .facet-title {
    display: flex; align-items: center; justify-content: space-between;
    font-size: var(--text-xs); font-weight: 700;
    letter-spacing: var(--tracking-caps); text-transform: uppercase;
    color: var(--color-text-secondary);
    cursor: pointer; list-style: none;
  }
  :lang(zh) .facet > summary, :lang(zh) .facet > .facet-title { text-transform: none; letter-spacing: 0.02em; }
  .facet > summary::-webkit-details-marker { display: none; }
  .facet > summary::after { content: "–"; font-family: var(--font-mono); color: var(--color-text-muted); }
  .facet:not([open]) > summary::after { content: "+"; }
  .facet ul { display: grid; gap: var(--sp-2); margin-block-start: var(--sp-3); }

  /* ═══ TABLES ════════════════════════════════════════════════════════
     Expo calendar, spec tables, supply/demand rows. Ruled, tight, tabular
     figures — the sort of table a buyer scans, not a marketing grid. */
  .table-wrap { overflow-x: auto; border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-surface); }
  .table { font-size: var(--text-sm); }
  .table thead th {
    text-align: start;
    font-size: var(--text-2xs); font-weight: 700;
    letter-spacing: var(--tracking-caps); text-transform: uppercase;
    color: var(--color-text-secondary);
    background: var(--color-surface-sunken);
    padding: var(--sp-3) var(--sp-4);
    border-block-end: 1px solid var(--color-border-strong);
    white-space: nowrap;
  }
  :lang(zh) .table thead th { text-transform: none; letter-spacing: 0.02em; font-size: var(--text-xs); }
  .table tbody td { padding: var(--sp-3) var(--sp-4); border-block-start: 1px solid var(--color-divider); vertical-align: top; }
  .table tbody tr:first-child td { border-block-start: 0; }
  .table tbody tr:hover { background: var(--color-surface-tint); }
  .table .num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
  .table .primary-cell { font-weight: 600; }
  .table .sub { display: block; font-size: var(--text-2xs); color: var(--color-text-muted); font-weight: 400; }
  .table--zebra tbody tr:nth-child(even) { background: var(--grey-50); }
  .table--zebra tbody tr:nth-child(even):hover { background: var(--color-surface-tint); }

  /* ═══ PAGINATION ════════════════════════════════════════════════════ */
  .pagination { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
  .pagination .page {
    min-inline-size: var(--control-height-sm); block-size: var(--control-height-sm);
    padding-inline: var(--sp-2);
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--color-border); border-radius: var(--radius-sm);
    background: var(--color-surface);
    font-family: var(--font-mono); font-size: var(--text-xs); font-variant-numeric: tabular-nums;
    text-decoration: none; color: var(--color-text-secondary);
  }
  .pagination .page:hover { border-color: var(--color-primary); color: var(--color-primary); }
  .pagination .page[aria-current="page"] {
    background: var(--color-primary); border-color: var(--color-primary); color: var(--color-on-primary);
  }
  .pagination .gap { color: var(--color-text-muted); padding-inline: var(--sp-1); }
  .pagination .summary { margin-inline-start: auto; font-size: var(--text-xs); color: var(--color-text-muted); }

  /* ═══ RESULT TOOLBAR (count + sort) ═════════════════════════════════ */
  .result-bar {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3);
    padding-block-end: var(--sp-3); margin-block-end: var(--sp-4);
    border-block-end: 1px solid var(--color-border);
  }
  .result-bar .count { font-size: var(--text-sm); }
  .result-bar .count b { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
  .result-bar .spacer { margin-inline-start: auto; }
  .result-bar .select { inline-size: auto; block-size: var(--control-height-sm); font-size: var(--text-xs); }

  /* ═══ SITE CHROME ═══════════════════════════════════════════════════ */
  .utility-bar {
    background: var(--grey-950); color: var(--color-text-invert-muted);
    font-size: var(--text-2xs);
  }
  .utility-bar .wrap { display: flex; align-items: center; gap: var(--sp-4); min-block-size: 2.1rem; }
  .utility-bar a { color: inherit; text-decoration: none; }
  .utility-bar a:hover { color: var(--white); }
  .utility-bar .spacer { margin-inline-start: auto; }

  .lang-switch { display: inline-flex; border: 1px solid color-mix(in srgb, var(--white) 30%, transparent); border-radius: var(--radius-sm); overflow: hidden; }
  .lang-switch button {
    padding: 0.1rem var(--sp-2); font-size: var(--text-3xs); font-weight: 600;
    color: inherit; letter-spacing: 0.04em;
  }
  .lang-switch button[aria-pressed="true"] { background: var(--white); color: var(--grey-950); }

  .masthead { background: var(--color-surface); border-block-end: 1px solid var(--color-border); position: sticky; inset-block-start: 0; z-index: var(--z-sticky); }
  .masthead .wrap { display: flex; align-items: center; gap: var(--sp-5); min-block-size: 4rem; }

  .wordmark { display: inline-flex; align-items: baseline; gap: var(--sp-2); text-decoration: none; white-space: nowrap; }
  .wordmark .mark {
    font-weight: 800; font-size: var(--text-lg); letter-spacing: -0.02em;
    color: var(--grey-950);
  }
  .wordmark .mark .hundred { color: var(--color-primary); }
  .wordmark .zh { font-size: var(--text-xs); color: var(--color-text-muted); letter-spacing: 0.16em; }

  .site-nav { display: flex; align-items: center; gap: var(--sp-1); margin-inline-start: var(--sp-4); }
  .site-nav a {
    padding: var(--sp-2) var(--sp-3); border-radius: var(--radius-sm);
    font-size: var(--text-sm); font-weight: 550; text-decoration: none;
    color: var(--color-text-secondary); white-space: nowrap;
  }
  .site-nav a:hover { background: var(--color-surface-sunken); color: var(--color-text); }
  .site-nav a[aria-current="page"] { color: var(--grey-950); box-shadow: inset 0 -2px 0 var(--color-primary); border-radius: 0; }
  /* The purchasing spine comes first; editorial links are a second tier and
     are marked as such — the identity stays, the priority changes. */
  .site-nav .nav-divider { inline-size: 1px; block-size: 1.25rem; background: var(--color-border); margin-inline: var(--sp-2); }
  .masthead .actions { margin-inline-start: auto; display: flex; align-items: center; gap: var(--sp-2); min-inline-size: 0; }

  /* Header search — 甲方 2026-08-27 反馈 一.1: buyers had to land on a page
     before they could search anything. The form GETs to directory.html?q=,
     which directory.js already reads on load (see its readState()), so no new
     JS is involved. */
  /* Lives in the utility bar, not the masthead. The masthead row is already
     wordmark + a nine-item nav + the CTA; a text field there was measured
     overflowing .wrap by 68px at 1440 and overflowing the page at 1160. The
     utility bar has a flexible spacer and only two small items, so it has the
     room this needs at every width. */
  .masthead-search { position: relative; display: flex; align-items: center; flex: 0 1 20rem; min-inline-size: 8rem; }
  .masthead-search-icon {
    position: absolute;
    inset-inline-start: var(--sp-2);
    color: var(--color-text-invert-muted);
    pointer-events: none;
    --p100-icon-size: 0.85rem;
  }
  .masthead-search-input {
    inline-size: 100%;
    padding-block: 0.15rem;
    padding-inline: calc(var(--sp-2) * 2 + 0.85rem) var(--sp-2);
    font: inherit;
    font-size: var(--text-2xs);
    color: var(--white);
    background: color-mix(in srgb, var(--white) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--white) 22%, transparent);
    border-radius: var(--radius-sm);
  }
  .masthead-search-input::placeholder { color: var(--color-text-invert-muted); }
  .masthead-search-input:focus-visible {
    outline: 2px solid var(--white);
    outline-offset: 1px;
    background: color-mix(in srgb, var(--white) 16%, transparent);
  }
  /* WebKit paints its own decoration/clear widgets inside type=search, which
     collide with the leading icon. */
  .masthead-search-input::-webkit-search-decoration,
  .masthead-search-input::-webkit-search-cancel-button { -webkit-appearance: none; }
  /* Below this the utility bar wraps to three rows (measured 96px tall at 375px)
     and the drawer already carries a full-width search of its own. */
  @media (max-width: 48rem) {
    .masthead-search { display: none; }
  }

  .mobile-nav-search { position: relative; display: flex; align-items: center; }
  .mobile-nav-search-icon {
    position: absolute;
    inset-inline-start: var(--sp-2);
    color: var(--color-text-muted);
    pointer-events: none;
    --p100-icon-size: 1rem;
  }
  .mobile-nav-search-input {
    inline-size: 100%;
    padding-block: var(--sp-2);
    padding-inline: calc(var(--sp-2) * 2 + 1rem) var(--sp-2);
    font: inherit;
    font-size: var(--text-sm);
    color: var(--color-text);
    background: var(--color-surface-sunken);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
  }
  .mobile-nav-search-input::placeholder { color: var(--color-text-muted); }
  .mobile-nav-search-input:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 1px; }
  .mobile-nav-search-input::-webkit-search-decoration,
  .mobile-nav-search-input::-webkit-search-cancel-button { -webkit-appearance: none; }

  /* ═══ MOBILE NAVIGATION & DRAWER (V2-S) ═════════════════════════════ */
  .nav-toggle {
    display: none;
    align-items: center;
    justify-content: center;
    inline-size: 2.5rem;
    block-size: 2.5rem;
    padding: 0;
    background: transparent;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    color: var(--color-text);
    cursor: pointer;
    transition: background var(--dur-fast), border-color var(--dur-fast), color var(--dur-fast);
  }
  .nav-toggle:hover {
    background: var(--color-surface-sunken);
    color: var(--color-text);
  }
  .nav-toggle:focus-visible,
  .mobile-nav-close:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
  }
  .nav-toggle-icon {
    display: block;
  }

  .mobile-nav-backdrop {
    display: none;
  }
  .mobile-nav-drawer {
    display: none;
  }

  @media (max-width: 68rem) {
    .site-nav { display: none; }
    .nav-toggle { display: inline-flex; }

    .mobile-nav-backdrop {
      display: block;
      position: fixed;
      inset: 0;
      background: rgba(11, 12, 14, 0.45);
      z-index: var(--z-overlay);
      backdrop-filter: blur(2px);
      opacity: 0;
      pointer-events: none;
      transition: opacity var(--dur-base) var(--ease-standard);
    }
    .mobile-nav-backdrop.is-open {
      opacity: 1;
      pointer-events: auto;
    }

    .mobile-nav-drawer {
      display: flex;
      flex-direction: column;
      position: fixed;
      inset-block: 0;
      inset-inline-end: 0;
      inline-size: min(85vw, 20rem);
      background: var(--color-surface);
      z-index: calc(var(--z-overlay) + 1);
      box-shadow: var(--shadow-3);
      transform: translateX(100%);
      transition: transform var(--dur-slow) var(--ease-out);
      overflow: hidden;
    }
    .mobile-nav-drawer.is-open {
      transform: translateX(0);
    }

    .mobile-nav-header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: var(--sp-3) var(--sp-4);
      border-block-end: 1px solid var(--color-divider);
      background: var(--color-surface-sunken);
      min-block-size: 3.5rem;
      flex-shrink: 0;
    }
    .mobile-nav-title {
      font-size: var(--text-sm);
      font-weight: 600;
      color: var(--color-text);
    }
    .mobile-nav-close {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      inline-size: 2.25rem;
      block-size: 2.25rem;
      border: 1px solid var(--color-border);
      border-radius: var(--radius);
      background: var(--color-surface);
      color: var(--color-text);
      cursor: pointer;
      transition: background var(--dur-fast), color var(--dur-fast);
    }
    .mobile-nav-close:hover {
      background: var(--color-surface-sunken);
      color: var(--color-text);
    }

    .mobile-nav-body {
      padding: var(--sp-4);
      display: flex;
      flex-direction: column;
      gap: var(--sp-3);
      flex: 1;
      overflow-y: auto;
      overscroll-behavior: contain;
    }
    .mobile-nav-links {
      display: flex;
      flex-direction: column;
      gap: var(--sp-1);
    }
    .mobile-nav-link {
      display: flex;
      align-items: center;
      padding: var(--sp-2) var(--sp-3);
      border-radius: var(--radius);
      font-size: var(--text-sm);
      font-weight: 550;
      color: var(--color-text-secondary);
      text-decoration: none;
      transition: background var(--dur-fast), color var(--dur-fast);
    }
    .mobile-nav-link:hover,
    .mobile-nav-link:focus-visible {
      background: var(--color-surface-sunken);
      color: var(--color-text);
      outline: none;
    }
    .mobile-nav-link[aria-current="page"] {
      background: var(--color-surface-tint);
      color: var(--color-primary);
      font-weight: 600;
      box-shadow: inset 3px 0 0 var(--color-primary);
    }
    .mobile-nav-divider {
      display: block;
      block-size: 1px;
      background: var(--color-divider);
      margin-block: var(--sp-2);
    }
    .mobile-nav-cta {
      margin-block-start: var(--sp-2);
    }
    .mobile-nav-lang {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding-block-start: var(--sp-3);
      border-block-start: 1px solid var(--color-divider);
      margin-block-start: var(--sp-2);
    }
    .mobile-nav-lang-label {
      font-size: var(--text-xs);
      color: var(--color-text-muted);
    }
    .mobile-nav-lang .lang-switch {
      border-color: var(--color-border);
    }
    .mobile-nav-lang .lang-switch button {
      color: var(--color-text-secondary);
      padding: 0.2rem var(--sp-3);
    }
    .mobile-nav-lang .lang-switch button[aria-pressed="true"] {
      background: var(--grey-950);
      color: var(--white);
    }
    .mobile-nav-backoffice {
      margin-block-start: auto;
      padding-block-start: var(--sp-3);
      text-align: center;
    }
    .mobile-nav-backoffice a {
      color: var(--color-text-muted);
      text-decoration: none;
      font-size: var(--text-2xs);
    }
    .mobile-nav-backoffice a:hover {
      color: var(--color-text);
      text-decoration: underline;
    }
  }

  @media (max-width: 36rem) {
    .masthead .actions .masthead-cta {
      display: none;
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .mobile-nav-drawer,
    .mobile-nav-backdrop {
      transition: none !important;
    }
  }

  .site-footer { background: var(--grey-950); color: var(--grey-300); padding-block: var(--sp-12) var(--sp-6); font-size: var(--text-sm); }
  .site-footer h4 { font-size: var(--text-2xs); letter-spacing: var(--tracking-caps); text-transform: uppercase; color: var(--white); margin-block-end: var(--sp-3); }
  :lang(zh) .site-footer h4 { text-transform: none; }
  .site-footer a { color: var(--grey-300); text-decoration: none; display: block; padding-block: 0.2rem; }
  .site-footer a:hover { color: var(--white); }
  .footer-grid { display: grid; gap: var(--sp-8); grid-template-columns: minmax(0, 1.6fr) repeat(3, minmax(0, 1fr)); }
  .footer-grid > div { min-inline-size: 0; }
  .footer-grid > div:first-child p { max-inline-size: 38ch; }
  @media (max-width: 700px) {
    .footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .footer-grid > div:first-child { grid-column: 1 / -1; }
    .utility-bar .member-sign-in { display: none; }
    .utility-bar .lang-switch { flex-shrink: 0; }
  }
  .footer-legal {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    margin-block-start: var(--sp-6);
    font-size: var(--text-2xs);
  }
  .footer-legal a {
    color: var(--grey-400);
    text-decoration: none;
  }
  .footer-legal a:hover {
    color: var(--white);
    text-decoration: underline;
  }
  .footer-legal-sep {
    color: var(--grey-600);
  }
  .site-footer .legal { margin-block-start: var(--sp-2); padding-block-start: var(--sp-3); border-block-start: 1px solid var(--grey-800); font-size: var(--text-2xs); color: var(--grey-400); }

  /* ═══ CREDENTIALS STRIP ═════════════════════════════════════════════
     Real numbers only: 2,000+ enterprises · 7 editions of C300 China ·
     18 years. Placed low on the page on purpose — it is proof offered
     after the tool has been shown, not a greeting. */
  .cred-strip { display: grid; gap: var(--sp-6); grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr)); }
  .cred { border-inline-start: 2px solid var(--color-primary); padding-inline-start: var(--sp-4); }
  .cred b { display: block; font-family: var(--font-mono); font-size: var(--text-2xl); font-weight: 600; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
  .cred span { font-size: var(--text-xs); color: var(--color-text-secondary); }

  /* ═══ SPLIT PANELS (supply / demand) ════════════════════════════════ */
  .split { display: grid; gap: var(--sp-4); grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr)); }
  .panel { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius); overflow: hidden; }
  .panel > header {
    display: flex; align-items: center; gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    border-block-end: 1px solid var(--color-border);
    background: var(--color-surface-sunken);
  }
  .panel > header h3 { font-size: var(--text-sm); }
  .panel > header .tick { margin-inline-start: auto; font-size: var(--text-2xs); font-family: var(--font-mono); color: var(--color-success); }
  .panel .rows > li { display: grid; gap: var(--sp-2); padding: var(--sp-3) var(--sp-4); border-block-start: 1px solid var(--color-divider); }
  .panel .rows > li:first-child { border-block-start: 0; }
  .panel .rows > li:hover { background: var(--color-surface-tint); }
  .panel .rows .title { font-size: var(--text-sm); font-weight: 600; }
  .panel .rows .meta { font-size: var(--text-2xs); color: var(--color-text-muted); }
  .panel > footer { padding: var(--sp-3) var(--sp-4); border-block-start: 1px solid var(--color-border); }

  /* ═══ INTENT CARDS (展会三入口: 咨询 / 观展 / 参展) ════════════════
     Requested explicitly by 李总. Keep all three, keep them findable. */
  .intent-row { display: grid; gap: var(--sp-3); grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); }
  .intent {
    display: grid; gap: var(--sp-2);
    padding: var(--sp-4);
    border: 1px solid color-mix(in srgb, var(--white) 22%, transparent);
    border-radius: var(--radius);
    background: color-mix(in srgb, var(--white) 6%, transparent);
    text-decoration: none;
    transition: background var(--dur-base) var(--ease-standard), border-color var(--dur-base) var(--ease-standard);
  }
  .intent:hover { background: color-mix(in srgb, var(--white) 13%, transparent); border-color: var(--white); }
  .intent .p100-icon { --p100-icon-size: 1.4rem; color: var(--color-primary); }
  .intent .t { font-size: var(--text-sm); font-weight: 650; color: var(--white); }
  .intent .d { font-size: var(--text-2xs); color: var(--color-text-invert-muted); }

  /* ═══ EDITORIAL LIST (news / academy — the supporting layer) ════════
     Deliberately quieter than the sourcing spine above it: list, not
     hero cards. The industry-media identity keeps its floor, not the roof. */
  .ed-columns { display: grid; gap: var(--sp-8); grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr)); }
  .ed-list > li { padding-block: var(--sp-3); border-block-start: 1px solid var(--color-divider); }
  .ed-list > li:first-child { border-block-start: 0; padding-block-start: 0; }
  .ed-list a { text-decoration: none; font-size: var(--text-sm); font-weight: 600; line-height: var(--leading-snug); display: block; }
  .ed-list a:hover { color: var(--color-text-link); }
  .ed-list .meta { display: flex; gap: var(--sp-2); align-items: center; margin-block-start: var(--sp-1); font-size: var(--text-2xs); color: var(--color-text-muted); }
  .ed-list .kind { font-weight: 600; color: var(--color-text-secondary); }

  /* Inline video slot — the Academy plays on-site, never a social redirect.
     Rendered as a framed placeholder here; no remote embed, by design. */
  .video-slot {
    position: relative; aspect-ratio: 16 / 9;
    border: 1px solid var(--color-border); border-radius: var(--radius);
    background:
      repeating-linear-gradient(135deg, var(--grey-100) 0 10px, var(--grey-50) 10px 20px);
    display: grid; place-items: center;
  }
  .video-slot .play {
    inline-size: 3.25rem; block-size: 3.25rem; border-radius: 50%;
    background: var(--color-primary); color: var(--white);
    display: grid; place-items: center; box-shadow: var(--shadow-2);
  }
  .video-slot .cap { position: absolute; inset-block-end: 0; inset-inline: 0; padding: var(--sp-3); background: color-mix(in srgb, var(--grey-950) 72%, transparent); color: var(--white); font-size: var(--text-xs); }

  /* ═══ NOTICES ═══════════════════════════════════════════════════════ */
  .notice {
    display: flex; gap: var(--sp-3); align-items: flex-start;
    padding: var(--sp-3) var(--sp-4);
    border: 1px solid var(--color-border); border-inline-start: 3px solid var(--color-info);
    border-radius: var(--radius);
    background: var(--color-surface);
    font-size: var(--text-xs); color: var(--color-text-secondary);
  }
  .notice--demo { border-inline-start-color: var(--color-warning); }

  /* ═══ SCHEME B · CAPABILITY MATRIX & DIRECTORY COMPONENTS ═══════════
     Promoted from Scheme B page styles (14 classes: board, cmp, dim,
     directory-layout, dot, dot--no, lbl, matrix, more, n, opt, readout,
     thumb, wrapcell). All rewritten with token variables. */

  /* 1. Board hero container */
  .board { background: var(--color-surface); border-block-end: 1px solid var(--color-border); padding-block: var(--sp-10) var(--sp-12); }
  .board h1 { font-size: var(--text-2xl); max-inline-size: 24ch; }
  .board .sub { color: var(--color-text-secondary); font-size: var(--text-sm); margin-block-start: var(--sp-2); max-inline-size: 62ch; }
  .board .search-console { margin-block-start: var(--sp-6); }
  .board .search-bar { background: var(--color-surface); border: 1px solid var(--color-border-strong); box-shadow: var(--shadow-1); }
  .board .search-bar .input, .board .search-bar .select { color: var(--color-text); }
  .board .search-bar .input::placeholder { color: var(--color-text-muted); }
  .board .search-bar .p100-icon { color: var(--color-text-muted); }

  /* 2. Capability Matrix (matrix, dim, opt, n, more) */
  .matrix {
    margin-block-start: var(--sp-8);
    display: grid; gap: 1px;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
    background: var(--color-border);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    overflow: hidden;
  }
  .dim { background: var(--color-surface); padding: var(--sp-4); display: grid; gap: var(--sp-3); align-content: start; }
  .dim > h3 {
    font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--tracking-caps);
    color: var(--color-text-muted); font-weight: 700; display: flex; align-items: center; gap: var(--sp-2);
  }
  :lang(zh) .dim > h3 { text-transform: none; letter-spacing: 0.02em; }
  .dim > h3 .p100-icon { --p100-icon-size: 1rem; color: var(--color-primary); }
  .dim ul { display: grid; gap: 1px; }
  .dim li { display: block; }
  .dim .opt, .opt {
    inline-size: 100%; text-align: start; display: flex; align-items: center; gap: var(--sp-2);
    font-size: var(--text-xs); padding: var(--sp-2) var(--sp-2);
    border-radius: var(--radius-sm); color: var(--color-text-secondary);
    transition: background var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard);
  }
  .dim .opt:hover, .opt:hover { background: var(--color-surface-tint); color: var(--brand-text); }
  .dim .opt .n, .opt .n { margin-inline-start: auto; font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--text-3xs); color: var(--color-text-muted); }
  .dim .opt[aria-pressed="true"], .opt[aria-pressed="true"] { background: var(--color-primary-soft); color: var(--brand-text); font-weight: 600; }
  .dim .opt[aria-pressed="true"] .n, .opt[aria-pressed="true"] .n { color: var(--brand-600); }
  .dim .more, .more { font-size: var(--text-3xs); color: var(--color-text-link); text-decoration: none; padding-inline: var(--sp-2); }
  .dim .more:hover, .more:hover { text-decoration: underline; }

  /* 3. Live Matrix Readout (readout, lbl) */
  .readout {
    margin-block-start: var(--sp-4); display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4); border: 1px solid var(--color-border-brand);
    background: var(--color-surface-tint); border-radius: var(--radius);
  }
  .readout .n { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--text-lg); font-weight: 650; color: var(--brand-text); }
  .readout .lbl, .lbl { font-size: var(--text-xs); color: var(--color-text-secondary); }
  .readout .spacer { margin-inline-start: auto; }

  /* 4. Comparison Table (cmp, wrapcell, thumb, dot, dot--no) */
  .cmp th, .cmp td { white-space: nowrap; }
  .cmp td.wrapcell, .wrapcell { white-space: normal; min-inline-size: 13rem; }
  .cmp .thumb, .thumb { inline-size: 3.5rem; block-size: 2.5rem; object-fit: cover; border-radius: var(--radius-sm); border: 1px solid var(--color-border); }
  .cmp tbody td { vertical-align: middle; }
  .cmp .dot, .dot { display: inline-block; inline-size: .5rem; block-size: .5rem; border-radius: 50%; background: var(--color-success); }
  .cmp .dot--no, .dot--no { background: var(--grey-300); }

  /* 5. Directory 2-column layout (directory-layout) */
  .directory-layout { display: grid; gap: var(--sp-6); grid-template-columns: 15rem minmax(0, 1fr); align-items: start; }
  @media (max-width: 60rem) { .directory-layout { grid-template-columns: 1fr; } }
}

/* ═══ UTILITIES ═══════════════════════════════════════════════════════ */
@layer utilities {
  .u-mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
  .u-muted { color: var(--color-text-muted); }
  .u-secondary { color: var(--color-text-secondary); }
  .u-xs { font-size: var(--text-xs); }
  .u-2xs { font-size: var(--text-2xs); }
  .u-nowrap { white-space: nowrap; }
  .u-stack-2 { display: grid; gap: var(--sp-2); }
  .u-stack-3 { display: grid; gap: var(--sp-3); }
  .u-stack-4 { display: grid; gap: var(--sp-4); }
  .u-stack-6 { display: grid; gap: var(--sp-6); }
  .u-row { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
  .u-mt-4 { margin-block-start: var(--sp-4); }
  .u-mt-6 { margin-block-start: var(--sp-6); }
  .u-mt-8 { margin-block-start: var(--sp-8); }
  .visually-hidden {
    position: absolute; inline-size: 1px; block-size: 1px;
    padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
}

@layer components {

  /* ═══ GATE DIALOG (email unlock) ══════════════════════════════════════
     These rules used to live in v2.css. Every page has since migrated to the
     design system and nothing loads v2.css any more, so the dialog was
     rendering with pure browser defaults — a bare box with the three fields
     strung across one line. Ported here and re-expressed in tokens.        */

  .gate-link {
    background: none; border: 0; padding: 0;
    color: var(--color-text-link); font-weight: 600;
    display: inline-flex; align-items: center; gap: var(--sp-1);
    min-block-size: 24px; cursor: pointer;
  }
  .gate-link:hover { text-decoration: underline; }

  dialog.gate {
    border: 0; padding: 0; position: relative;
    border-radius: var(--radius-lg);
    max-inline-size: min(28rem, 92vw);
    background: var(--color-surface);
    color: var(--color-text);
    box-shadow: var(--shadow-3);
    /* Entry animation. @starting-style gives the open state something to
       animate *from*, so the dialog rises instead of snapping in. */
    opacity: 0; translate: 0 16px; scale: 0.96;
    transition: opacity var(--dur-fast) var(--ease-standard),
                translate var(--dur-fast) var(--ease-standard),
                scale var(--dur-fast) var(--ease-standard),
                display var(--dur-fast) allow-discrete,
                overlay var(--dur-fast) allow-discrete;
  }
  dialog.gate[open] {
    opacity: 1; translate: 0 0; scale: 1;
    transition-duration: var(--dur-base);
    transition-timing-function: var(--ease-out);
    @starting-style { opacity: 0; translate: 0 16px; scale: 0.96; }
  }
  dialog.gate::backdrop {
    background: rgb(11 12 14 / 0);
    transition: background var(--dur-base) var(--ease-standard),
                display var(--dur-base) allow-discrete,
                overlay var(--dur-base) allow-discrete;
  }
  dialog.gate[open]::backdrop {
    background: rgb(11 12 14 / 0.55);
    @starting-style { background: rgb(11 12 14 / 0); }
  }

  dialog.gate .gate-inner { padding: var(--sp-8); display: grid; gap: var(--sp-4); }
  dialog.gate h3 { font-size: var(--text-xl); margin: 0; }
  dialog.gate > form > p { color: var(--color-text-secondary); font-size: var(--text-sm); margin: 0; }

  dialog.gate label {
    display: grid; gap: var(--sp-1);
    font-size: var(--text-xs); font-weight: 600; color: var(--color-text-secondary);
  }
  dialog.gate input {
    font: inherit; font-size: var(--text-md);
    padding: 0 var(--sp-3);
    min-block-size: var(--control-height);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface);
    color: var(--color-text);
  }
  dialog.gate input:focus-visible { outline: none; box-shadow: var(--focus-ring); border-color: var(--color-focus); }

  dialog.gate .btn { inline-size: 100%; margin-block-start: var(--sp-2); }

  dialog.gate .close {
    position: absolute; inset-block-start: var(--sp-3); inset-inline-end: var(--sp-3);
    border: 0; background: transparent; cursor: pointer;
    font-size: var(--text-xl); line-height: 1;
    min-inline-size: 32px; min-block-size: 32px;
    border-radius: var(--radius-sm);
    color: var(--color-text-muted);
  }
  dialog.gate .close:hover { background: var(--color-surface-sunken); color: var(--color-text); }
  dialog.gate .fine { font-size: var(--text-2xs); color: var(--color-text-muted); margin: 0; }

  @media (prefers-reduced-motion: reduce) {
    dialog.gate, dialog.gate[open] { translate: 0 0; scale: 1; transition-duration: 1ms; }
  }
}

@layer components {

  /* ═══ HERO BOARD DENSITY ══════════════════════════════════════════════
     首屏原本 946px，视口 900px —— 正好 1.05 屏，于是加载后**看不到下面还有内容**，
     用户不知道该往下滚。这里把首屏压到 0.8 屏左右，让「Matching suppliers」
     露出一条边：露边本身就是最有效的「下面还有」提示。
     只收紧密度，不删任何一个维度。                                        */
  .board { padding-block: var(--sp-5) var(--sp-4); }
  /* 原本 clamp 的上限比默认值还大，反而把标题撑高了。这里明确压住。 */
  .board h1 { font-size: clamp(1.5rem, 1.1rem + 1vw, 1.9rem); line-height: 1.15; }
  /* 导语和标题说的是同一件事，桌面端收成两行以内即可，别占三行。 */
  .board .sub { max-inline-size: 78ch; font-size: var(--text-sm); }
  .board .search-console { padding: var(--sp-3); }
  .board .eyebrow { margin-block-end: 0; }
  .board > .wrap > * + * { margin-block-start: var(--sp-3); }

  .board .matrix { gap: var(--sp-4); }
  .board .matrix .dim h3 { margin-block-end: var(--sp-1); }
  .board .matrix .opt { padding-block: 0.22rem; font-size: var(--text-xs); }
  .board .matrix ul { gap: 0; }
  /* 每维最多露 4 行，其余走「全部 →」链接。行数不齐时首屏会忽高忽低。 */
  .board .matrix ul > li:nth-child(n+5) { display: none; }
  /* 品类维例外：会上定的是「4+1」五大类，少一类就不成体系，五行全露。 */
  .board .matrix .dim:first-child ul > li:nth-child(5) { display: revert; }
  .board .matrix .more { font-size: var(--text-2xs); }
  .board .readout { margin-block-start: var(--sp-3); }
  .board .demo-note { font-size: var(--text-3xs); }

  /* ═══ SECTION RAIL (左侧阅读进度) ═════════════════════════════════════
     告诉用户「现在在第几节、后面还有多少」。纯 CSS ＋ IntersectionObserver，
     无依赖。窄屏隐藏（那里空间要留给内容）。                              */
  .rail {
    position: fixed; inset-block-start: 50%; inset-inline-start: var(--sp-4);
    translate: 0 -50%; z-index: var(--z-sticky);
    display: flex; flex-direction: column; gap: var(--sp-2);
    padding: var(--sp-3) var(--sp-2);
    background: color-mix(in srgb, var(--color-surface) 88%, transparent);
    border: 1px solid var(--color-border); border-radius: var(--radius-pill);
    box-shadow: var(--shadow-1);
    backdrop-filter: blur(6px);
  }
  .rail a {
    display: block; inline-size: 8px; block-size: 8px; border-radius: 50%;
    background: var(--color-border-strong); text-decoration: none;
    transition: background var(--dur-fast) var(--ease-standard),
                scale var(--dur-fast) var(--ease-standard);
    position: relative;
  }
  .rail a:hover { background: var(--color-text-muted); scale: 1.25; }
  .rail a[aria-current="true"] { background: var(--color-primary); scale: 1.4; }
  /* 悬停时把小节名推出来，平时不占地方 */
  .rail a::after {
    content: attr(data-label);
    position: absolute; inset-inline-start: calc(100% + 0.6rem); inset-block-start: 50%;
    translate: 0 -50%;
    white-space: nowrap; font-size: var(--text-2xs); font-weight: 600;
    color: var(--color-text); background: var(--color-surface);
    border: 1px solid var(--color-border); border-radius: var(--radius-sm);
    padding: 0.15rem 0.45rem; box-shadow: var(--shadow-1);
    opacity: 0; pointer-events: none;
    transition: opacity var(--dur-fast) var(--ease-standard);
  }
  .rail a:hover::after, .rail a:focus-visible::after { opacity: 1; }

  /* 读完比例。用 scaleY 变换，避免每帧改 height 触发重排。 */
  .rail-progress {
    position: absolute; inset-inline-start: 50%; inset-block-start: 0;
    translate: -50% 0; inline-size: 2px; block-size: 100%;
    background: var(--color-divider); border-radius: 1px; z-index: -1;
  }
  .rail-progress span {
    display: block; inline-size: 100%; block-size: 100%;
    background: var(--color-primary); transform-origin: top;
    scale: 1 0; transition: scale var(--dur-fast) linear;
  }
  @media (max-width: 68rem) { .rail { display: none; } }
  @media (prefers-reduced-motion: reduce) {
    .rail a, .rail-progress span { transition-duration: 1ms; }
  }
}

@layer components {

  /* ═══ 换肤回归修复：依赖「祖先是深色」的白字 ═══════════════════════════
     R2 原版首屏 .board 是深海军蓝底，所以热门检索写白字是对的。
     品牌换肤把 .board 改成白底之后，这些白字直接变成白压白（实测对比度 1.00，
     整行「Popular:」热门检索完全不可见）。
     教训：改深色区块的底色时，必须连带检查所有「靠继承拿到白字」的后代。   */
  .board .search-suggest > span { color: var(--color-text-muted); }
  .board .search-suggest a {
    color: var(--color-text-link);
    border-block-end-color: color-mix(in srgb, var(--color-text-link) 35%, transparent);
  }
  .board .search-suggest a:hover { border-block-end-color: var(--color-text-link); }

  /* 深色区块里的表格是一张**白色卡片**，但文字从 .section--brand 继承了白色，
     于是白压白。展会日历的日期、地点、参展企业名整列都读不出来。
     卡片保持白底（深色带里的白卡是刻意的层次），把文字恢复成正常深色。 */
  .section--brand .table-wrap { color: var(--color-text); }
  .section--brand .table-wrap :is(th, td, p, span, a, strong) { color: inherit; }
  .section--brand .table-wrap .u-muted { color: var(--color-text-muted); }
  .section--brand .table-wrap a { color: var(--color-text-link); }

  /* 深色带里若还有别的**白底卡片**，同样要把文字换回深色。
     用 :has() 只命中真正设了浅底的卡，不要一刀切 —— 上一版写成
     .section--brand .panel 就误伤了深色带上本来正常的说明文字（实测掉到 2.41）。*/
  /* .section-head p 与 .section--brand p 特异度相同（都是 0,1,1），
     靠源码顺序分胜负，而 .section-head p 在后面 —— 于是深色带里的小节说明
     被刷成了 --color-text-secondary（#4A505A 压 #0B0C0E，实测 2.41）。
     用 0,2,1 明确压回去。 */
  .section--brand .section-head p { color: var(--color-text-invert-muted); }

  .section--brand :is(.card, .company-card) { color: var(--color-text); }
  .section--brand :is(.card, .company-card) p { color: var(--color-text-secondary); }
}

@layer components {
  /* ═══ RFQ CONTEXT（Contact 页顶部的商机摘要）═══════════════════════════ */
  .rfq-context {
    background: var(--color-surface-tint);
    border: 1px solid var(--color-border-brand);
    border-inline-start: 3px solid var(--color-primary);
    border-radius: var(--radius);
    padding: var(--sp-4);
    margin-block-end: var(--sp-4);
    display: grid; gap: var(--sp-2);
  }
  .rfq-context-label { margin: 0; font-size: var(--text-2xs); font-weight: 600;
    letter-spacing: var(--tracking-caps); text-transform: uppercase; color: var(--color-text-secondary); }
  :lang(zh) .rfq-context-label { text-transform: none; letter-spacing: 0; }
  .rfq-context-title { margin: 0; font-size: var(--text-lg); font-weight: 650; color: var(--color-text); }
  .rfq-context-meta { display: grid; gap: var(--sp-1); margin: 0;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr)); }
  .rfq-context-meta > div { display: flex; gap: var(--sp-2); font-size: var(--text-xs); }
  .rfq-context-meta dt { color: var(--color-text-muted); }
  .rfq-context-meta dd { margin: 0; font-weight: 600; color: var(--color-text); }
  .rfq-context-back { margin: 0; font-size: var(--text-xs); }
  .rfq-context-back a { color: var(--color-text-link); }
}

/* ═══ CROSS-DOCUMENT VIEW TRANSITIONS ══════════════════════════════════
   Page-to-page transitions with zero JavaScript and no library. The browser
   does the work on the compositor, so the cost is a short GPU cross-fade
   rather than any main-thread render.

   Deliberately NOT inside @layer: @view-transition is a top-level at-rule.

   Progressive enhancement only. Chrome/Edge 126+ and Safari 18.2+ animate;
   Firefox does not support cross-document transitions yet and simply performs
   an ordinary instant navigation. Nothing to fall back to, nothing to ship.

   The chrome (utility bar, masthead, footer) is identical on every page, so
   each gets its own transition name. Named elements are matched across the two
   documents and held in place instead of being cross-faded with the body —
   the header appears to stay put while only the content changes, which is what
   makes it read as one app rather than a page reload.

   Named elements must be unique per document; there is exactly one of each.  */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }


  /* 名录筛选切换：结果区与计数各自命名，交叉淡入时不互相牵连。
     左侧筛选栏**不命名** —— 它自己也在重绘，跟着一起淡会闪。 */
  @media (prefers-reduced-motion: no-preference) {
    #dir-results { view-transition-name: p100-dir-results; }
    #dir-count   { view-transition-name: p100-dir-count; }
    ::view-transition-old(p100-dir-results),
    ::view-transition-new(p100-dir-results) { animation-duration: 160ms; }
  }

  .utility-bar { view-transition-name: p100-utility-bar; }
  .masthead    { view-transition-name: p100-masthead; }
  .site-footer { view-transition-name: p100-site-footer; }

  /* Keep it brief. A long page transition reads as latency, not polish. */
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation-duration: 180ms;
    animation-timing-function: var(--ease-standard, cubic-bezier(0.2, 0, 0, 1));
  }
}

  @media (prefers-reduced-motion: reduce) {
    [data-reveal].reveal-pending,
    [data-reveal].reveal-in {
      opacity: 1 !important;
      transform: none !important;
      transition: none !important;
    }
  }

/* 配合各页 <head> 里的语言预置闸门。用 visibility 不用 display，
   布局照常计算，放出来时不会有回流跳动；只藏 body，背景照常绘制。
   这条必须放在**未分层**的位置，才不会被 @layer 里的规则盖掉。 */
html[data-lang-pending] body { visibility: hidden; }
