/* ==========================================================================
   LGX Bullion — Component Layer
   Depends on tokens/tokens.css. Every value below resolves through a
   SEMANTIC token — no raw --lgx-* references, so [data-zone="navy"] works
   on any component without a modifier class.
   ========================================================================== */

/* tokens/tokens.css inlined by tools/dist.py — the source pulls it
   in with a nested stylesheet request, which the browser must fetch
   serially after this file before it can render anything. */
/* ==========================================================================
   LGX Bullion — Design Tokens
   Part of the Zhou Liu Fu Group / 周六福集团旗下品牌

   Layer 1  RAW      — the brand palette, literal values. Never used directly
                       in components.
   Layer 2  SEMANTIC — role-based aliases. Components only ever use these.
   Layer 3  ZONES    — [data-zone="navy"] remaps the semantic layer so a dark
                       band inherits correct text/border/accent colours with
                       no component changes.
   ========================================================================== */

:root {
  /* ---------------------------------------------------------------------
     1. RAW PALETTE
     Hex values sourced from the identity boards in brand/identity-explorations.
     Steps marked (derived) were interpolated to complete the ramp.
     --------------------------------------------------------------------- */

  /* Ivory — the page. Warm, uncoated-paper white. */
  --lgx-ivory-50:      #FAF8F3;  /* (derived) lifted surface, cards on ivory  */
  --lgx-ivory-100:     #F3EFE5;  /* IVORY — canonical page background        */
  --lgx-ivory-200:     #EAE3D6;  /* WARM IVORY — alt band, table stripe      */
  --lgx-ivory-300:     #DDD3C0;  /* (derived) hairline borders on ivory      */
  --lgx-ivory-400:     #C8BCA4;  /* (derived) disabled fill, muted rule      */

  /* Gold — accent only. See the contrast note under SEMANTIC before using
     any of these for text. */
  --lgx-gold-300:      #E0CCA3;  /* (derived) tint, hover glow, rule on navy */
  --lgx-gold-400:      #C9AE7A;  /* (derived) hover state for champagne      */
  --lgx-gold-500:      #B39457;  /* CHAMPAGNE GOLD — the brand gold          */
  --lgx-gold-600:      #9A793E;  /* DEEP GOLD                                */
  --lgx-gold-700:      #8D6D38;  /* DARK GOLD                                */
  --lgx-gold-800:      #775A29;  /* (derived) AA-safe gold text on ivory     */

  /* Navy — zoning colour. Header, footer, CTA bands, hero. */
  --lgx-navy-700:      #24405F;  /* (derived) hover on navy surfaces         */
  --lgx-navy-800:      #1E3552;  /* (derived) raised card inside a navy zone */
  --lgx-navy-900:      #172B43;  /* DEEP NAVY — canonical                    */
  --lgx-navy-950:      #0E1B2D;  /* deepest navy, from board 01              */

  /* Charcoal — text. Warm-shifted, never pure black. */
  --lgx-charcoal-500:  #66625A;  /* (derived) muted / tertiary text          */
  --lgx-charcoal-700:  #4A463E;  /* (derived) secondary text                 */
  --lgx-charcoal-900:  #292722;  /* WARM CHARCOAL — body text                */

  /* Support — inherited from board 02. Used for market direction, not decor. */
  --lgx-forest-800:    #183A32;  /* FOREST GREEN — price up, verified        */
  --lgx-forest-600:    #2A5F51;  /* (derived) on-navy legible variant        */
  --lgx-oxblood-800:   #5A252B;  /* OXBLOOD — price down, alert              */
  --lgx-oxblood-600:   #8A3A42;  /* (derived) on-navy legible variant        */

  --lgx-white:         #FFFFFF;


  /* ---------------------------------------------------------------------
     2. SEMANTIC — light (ivory) context. This is the site default.

     CONTRAST RULE, measured against --surface-page (#F3EFE5):
       charcoal-900  15.6:1  ✓ any size
       charcoal-500   5.3:1  ✓ AA body text — and 4.8:1 on --surface-sunken,
                             which is the tighter of the two and the one that
                             sets the value. Striped spec rows and captions on
                             sunken bands both land there.
       gold-800       5.6:1  ✓ AA body text  ← the only gold allowed for copy
                             and 5.0:1 on --surface-sunken, where the section
                             eyebrows sit
       gold-700       4.1:1  ✗ body · ✓ large display (24px+/19px bold)
       gold-500       2.5:1  ✗ text of any size — decorative rules, fills,
                             icon strokes and borders only
     On --surface-inverse (#172B43), gold-500 reaches 5.0:1 and becomes a
     legitimate text colour. Gold reads as text on navy, not on ivory.

     Every ratio above is checked by tools/check-contrast.py — run it after
     touching any colour in this file.
     --------------------------------------------------------------------- */

  /* Surfaces */
  --surface-page:        var(--lgx-ivory-100);
  --surface-raised:      var(--lgx-ivory-50);
  --surface-sunken:      var(--lgx-ivory-200);
  --surface-inverse:     var(--lgx-navy-900);
  --surface-inverse-deep:var(--lgx-navy-950);
  --surface-disabled:    var(--lgx-ivory-300);

  /* Text */
  --text-primary:        var(--lgx-charcoal-900);
  --text-secondary:      var(--lgx-charcoal-700);
  --text-muted:          var(--lgx-charcoal-500);
  --text-accent:         var(--lgx-gold-800);   /* AA-safe gold copy         */
  --text-on-inverse:     var(--lgx-ivory-100);
  --text-on-inverse-mut: #A9B4C2;                /* (derived) 7.0:1 on navy  */
  --text-accent-inverse: var(--lgx-gold-500);    /* gold copy, navy zones    */
  --text-disabled:       var(--lgx-ivory-400);

  /* The logo is a graphic, not text — it is exempt from the contrast rule
     above and uses a richer gold than --text-accent would give it. */
  --brand-mark:          var(--lgx-gold-700);

  /* Borders — the brand runs on hairlines, not shadows. */
  --border-subtle:       var(--lgx-ivory-300);
  --border-strong:       var(--lgx-charcoal-900);
  --border-gold:         var(--lgx-gold-500);
  --border-gold-faint:   color-mix(in srgb, var(--lgx-gold-500) 38%, transparent);
  --border-on-inverse:   color-mix(in srgb, var(--lgx-gold-500) 42%, transparent);
  --border-width-hair:   1px;
  --border-width-rule:   2px;

  /* Interactive — primary is navy, accent is gold. */
  --action-primary-bg:        var(--lgx-navy-900);
  --action-primary-bg-hover:  var(--lgx-navy-700);
  --action-primary-fg:        var(--lgx-ivory-100);
  --action-accent-bg:         var(--lgx-gold-700);
  --action-accent-bg-hover:   var(--lgx-gold-600);
  --action-accent-fg:         var(--lgx-ivory-50);
  --action-quiet-fg:          var(--lgx-charcoal-900);
  --action-quiet-border:      var(--lgx-charcoal-900);
  --focus-ring:               var(--lgx-gold-600);
  --focus-ring-width:         2px;
  --focus-ring-offset:        2px;

  /* Market / status — brand-native, not generic red-green. */
  --status-up:           var(--lgx-forest-800);
  --status-down:         var(--lgx-oxblood-800);
  /* Both of these were previously #4E9B84 / #C97A80 and annotated 5.4:1 and
     5.6:1. The real figures were 4.34 and 4.50 against navy-900 — the note
     was measured against navy-950, the more forgiving of the two surfaces.
     tools/check-contrast.py now tests every navy surface a badge can land on. */
  --status-up-inverse:   #5CB096;   /* 5.5:1 navy-900 · 4.8:1 navy-800 */
  --status-down-inverse: #D5949A;   /* 5.8:1 navy-900 · 5.1:1 navy-800 */
  --status-neutral:      var(--lgx-charcoal-500);
  --status-up-wash:      color-mix(in srgb, var(--lgx-forest-800) 8%, transparent);
  --status-down-wash:    color-mix(in srgb, var(--lgx-oxblood-800) 8%, transparent);


  /* ---------------------------------------------------------------------
     3. TYPOGRAPHY
     Cinzel   — display. Roman capital forms; the licensable stand-in for
                Trajan Pro, which the print collateral uses. ALWAYS uppercase,
                always letterspaced. Never set body copy in it.
     Lora     — body serif. Long-form copy, product descriptions, letters.
     Montserrat — UI sans. Nav, buttons, labels, tables, all numerals.
     Noto Serif SC / Noto Sans SC — the Chinese counterparts. The brand is
                bilingual by default (see brand/catalogue V7).
     --------------------------------------------------------------------- */

  --font-display:  "Cinzel", "Noto Serif SC", "Times New Roman", serif;
  --font-body:     "Lora", "Noto Serif SC", Georgia, serif;

  /* Noto Sans SC used to sit second here, which meant every page — including
     the English ones, where the Chinese is 17 short labels — downloaded a
     second full CJK family for nav and button text. 1089 KB, measured.
     CJK in UI chrome now falls through to the platform's own interface face:
     no download, and it is what a Chinese reader expects a UI to look like on
     their OS anyway. Noto Serif SC still covers CJK in display and body copy,
     where the brand's own voice matters. */
  --font-ui:       "Montserrat", -apple-system, "Segoe UI",
                   "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
  --font-cn-display: "Noto Serif SC", "Songti SC", serif;
  /* Currently the same face as the display stack, and deliberately named
     separately: Chinese long-form copy is the one place this site is most
     likely to want to diverge (a lighter serif, or Noto Sans SC if the desk
     decides the Chinese pages should read more like a platform than a
     brochure). Lora carries no CJK glyphs, so before this existed every
     Chinese paragraph was resolving through an unnamed fallback. */
  --font-cn-body:    "Noto Serif SC", "Songti SC", serif;
  /* Platform faces only — nothing here is downloaded. Reach for this when a
     CJK sans is genuinely wanted; do NOT reintroduce a webfont sans without
     re-reading the payload note above --font-ui. */
  --font-cn-ui:      -apple-system, "PingFang SC", "Hiragino Sans GB",
                     "Microsoft YaHei", sans-serif;

  --weight-regular:  400;
  --weight-medium:   500;
  --weight-semibold: 600;
  --weight-bold:     700;

  /* Size scale — 1.25 modular, display steps stretched for hero use. */
  --text-display-xl: 4rem;      /* 64 */
  --text-display-l:  3rem;      /* 48 */
  --text-h1:         2.5rem;    /* 40 */
  --text-h2:         2rem;      /* 32 */
  --text-h3:         1.5rem;    /* 24 */
  --text-h4:         1.25rem;   /* 20 */
  --text-body-l:     1.125rem;  /* 18 */
  --text-body:       1rem;      /* 16 */
  --text-body-s:     0.875rem;  /* 14 */
  --text-caption:    0.75rem;   /* 12 */

  --leading-tight:   1.1;
  --leading-snug:    1.25;
  --leading-normal:  1.5;
  --leading-relaxed: 1.7;   /* body copy — Lora needs the air */

  /* Tracking — the identity leans hard on letterspaced capitals. */
  --tracking-display: 0.08em;
  --tracking-eyebrow: 0.22em;
  --tracking-caps:    0.14em;
  --tracking-normal:  0;


  /* ---------------------------------------------------------------------
     4. SPACE — 4px base
     --------------------------------------------------------------------- */
  --space-1:   0.25rem;   /*   4 */
  --space-2:   0.5rem;    /*   8 */
  --space-3:   0.75rem;   /*  12 */
  --space-4:   1rem;      /*  16 */
  --space-5:   1.5rem;    /*  24 */
  --space-6:   2rem;      /*  32 */
  --space-7:   3rem;      /*  48 */
  --space-8:   4rem;      /*  64 */
  --space-9:   6rem;      /*  96 */
  --space-10:  8rem;      /* 128 */

  --section-y:        var(--space-9);
  --section-y-tight:  var(--space-7);
  --container-max:    1200px;
  --container-narrow: 720px;
  --container-pad:    var(--space-5);


  /* ---------------------------------------------------------------------
     5. SHAPE
     The identity is classical and squared — engraved plates, hairline
     frames, wax seals. Radii stay near zero on purpose.
     --------------------------------------------------------------------- */
  --radius-none:  0;
  --radius-sm:    2px;    /* buttons, inputs, cards — the default */
  --radius-md:    4px;    /* images, media wells */
  --radius-pill:  999px;  /* badges only */

  /* Shadows are a last resort; prefer a hairline border. Warm-tinted so they
     never read blue against ivory. */
  --shadow-sm:  0 1px 2px rgba(41, 39, 34, 0.06);
  --shadow-md:  0 2px 12px rgba(41, 39, 34, 0.08);
  --shadow-lg:  0 8px 32px rgba(41, 39, 34, 0.12);
  --shadow-navy:0 8px 32px rgba(14, 27, 45, 0.28);


  /* ---------------------------------------------------------------------
     6. MOTION — restrained. Nothing bounces.
     --------------------------------------------------------------------- */
  --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-out:      cubic-bezier(0.16, 1, 0.3, 1);
  --duration-fast:   120ms;
  --duration-normal: 220ms;
  --duration-slow:   400ms;

  --z-base: 0;
  --z-sticky: 100;
  --z-header: 200;
  --z-overlay: 800;
  --z-modal: 900;
  --z-toast: 1000;
  /* The paper grain sits above ordinary content but below anything that
     demands attention. It used to be hard-coded at 9999, i.e. over the toast
     and modal layers it is supposed to sit under. */
  --z-grain: 50;
}


/* ==========================================================================
   ZONE: NAVY
   Put data-zone="navy" on any band — header, footer, CTA, hero — and every
   semantic token flips to its dark-context value. Components inside need no
   modifier classes.
   ========================================================================== */

[data-zone="navy"] {
  --surface-page:      var(--lgx-navy-900);
  --surface-raised:    var(--lgx-navy-800);
  --surface-sunken:    var(--lgx-navy-950);
  --surface-inverse:   var(--lgx-ivory-100);
  --surface-disabled:  var(--lgx-navy-800);

  --text-primary:      var(--lgx-ivory-100);
  --text-secondary:    var(--text-on-inverse-mut);
  /* 5.0:1 on navy-900, 6.0:1 on navy-950. The previous #7E8A99 was 4.09:1 —
     below AA, and it carried the footer disclaimer and the ABN line, which
     are the two pieces of copy on this site that most need to be readable. */
  --text-muted:        #8F99A6;
  --text-accent:       var(--lgx-gold-500);   /* 5.0:1 here — legal as text */
  --text-on-inverse:   var(--lgx-charcoal-900);
  --brand-mark:        var(--lgx-gold-500);
  --text-disabled:     #5A6675;

  --border-subtle:     color-mix(in srgb, var(--lgx-ivory-100) 16%, transparent);
  --border-strong:     var(--lgx-gold-500);
  --border-gold-faint: color-mix(in srgb, var(--lgx-gold-500) 45%, transparent);

  --action-primary-bg:       var(--lgx-gold-500);
  --action-primary-bg-hover: var(--lgx-gold-400);
  --action-primary-fg:       var(--lgx-navy-950);
  --action-accent-bg:        transparent;
  --action-accent-fg:        var(--lgx-gold-500);
  --action-quiet-fg:         var(--lgx-ivory-100);
  --action-quiet-border:     var(--lgx-gold-500);
  --focus-ring:              var(--lgx-gold-300);

  --status-up:      var(--status-up-inverse);
  --status-down:    var(--status-down-inverse);
  --status-neutral: var(--text-on-inverse-mut);  /* charcoal-500 is 2.7:1 here */

  color: var(--text-primary);
  background: var(--surface-page);
}


@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-fast: 0ms;
    --duration-normal: 0ms;
    --duration-slow: 0ms;
  }
}


/* --------------------------------------------------------------------------
   Reset / base
   -------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--surface-page);
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: var(--text-body);
  line-height: var(--leading-relaxed);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* height:auto is load-bearing: images carry width/height attributes (so the
   browser reserves space and the page does not shift on load), and without
   this the attribute height becomes the used height once CSS scales the
   width down. */
img, svg { max-width: 100%; height: auto; display: block; }

/* <picture> is a source-selection wrapper, not a box. Without this it lays
   out as an inline element and every `.parent img { width: 100% }` rule in
   the sheet starts measuring against the wrong thing. */
picture { display: contents; }

:where(a) {
  color: var(--text-accent);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
  transition: color var(--duration-fast) var(--ease-standard);
}
:where(a):hover { color: var(--text-primary); }

:where(:focus-visible) {
  outline: var(--focus-ring-width) solid var(--focus-ring);
  outline-offset: var(--focus-ring-offset);
  border-radius: var(--radius-sm);
}

::selection { background: var(--border-gold-faint); }

/* Skip link — the header is a lockup, a menu button, five nav links, a
   language switch and a login button before you reach any content. That is a
   lot of tabbing to repeat on every page. Off-screen until focused. */
.lgx-skip {
  position: absolute;
  left: var(--space-4);
  top: var(--space-4);
  z-index: var(--z-toast);
  transform: translateY(-200%);
  padding: var(--space-3) var(--space-5);
  background: var(--surface-page);
  color: var(--text-primary);
  border: var(--border-width-rule) solid var(--border-gold);
  border-radius: var(--radius-sm);
  font-family: var(--font-ui);
  font-size: var(--text-body-s);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  text-decoration: none;
  transition: transform var(--duration-fast) var(--ease-standard);
}
.lgx-skip:focus { transform: translateY(0); }

/* Landing target for the skip link. Without this the browser moves the
   viewport but not the focus ring, and the next Tab resumes in the header. */
:where([tabindex="-1"]:focus) { outline: none; }

/* Visible to assistive tech, not to the eye. Used to disambiguate repeated
   link text — a grid of nine "View" buttons is useless in a screen reader's
   link list. */
.lgx-sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}


/* --------------------------------------------------------------------------
   Typography
   Cinzel is display-only and always uppercase + letterspaced. Setting it
   lowercase or at body size breaks the identity — the print collateral has
   no instance of it below 20px.
   -------------------------------------------------------------------------- */

.lgx-display,
.lgx-h1, .lgx-h2, .lgx-h3, .lgx-h4 {
  font-family: var(--font-display);
  font-weight: var(--weight-regular);
  text-transform: uppercase;
  letter-spacing: var(--tracking-display);
  line-height: var(--leading-tight);
  color: var(--text-primary);
  margin: 0;
  text-wrap: balance;
}

.lgx-display { font-size: var(--text-display-xl); }
.lgx-h1      { font-size: var(--text-h1); }
.lgx-h2      { font-size: var(--text-h2); }
.lgx-h3      { font-size: var(--text-h3); line-height: var(--leading-snug); }
.lgx-h4      { font-size: var(--text-h4); line-height: var(--leading-snug);
               letter-spacing: var(--tracking-caps); }

/* Chinese headings drop the letterspacing — CJK glyphs are already on an
   em grid and tracking them reads as broken kerning. */
.lgx-h1:lang(zh), .lgx-h2:lang(zh), .lgx-h3:lang(zh), .lgx-h4:lang(zh),
.lgx-display:lang(zh) {
  font-family: var(--font-cn-display);
  font-weight: var(--weight-bold);
  letter-spacing: 0.04em;
  text-transform: none;
  line-height: 1.35;   /* CJK glyphs fill their em box; 1.1 collides */
}


/* ==========================================================================
   CJK CONTEXT
   --------------------------------------------------------------------------
   The identity leans hard on letterspaced Latin capitals: --tracking-eyebrow
   is 0.22em. Applied to 中文 that does not read as elegant, it reads as
   broken — CJK glyphs already sit on a fixed em grid, so tracking prises them
   apart into unrelated characters.

   Rather than chase forty component rules, this rebinds the three tracking
   tokens for a Chinese document. Every component resolves its spacing through
   those tokens, so they all correct at once — which is the whole reason the
   token layer exists.

   Latin islands inside a Chinese page (the wordmark, AUD/oz, refiner names)
   opt back in via lang="en", so the brand's letterspacing survives exactly
   where it belongs.
   ========================================================================== */

:root:lang(zh), [lang^="zh"] {
  /* Not zero: short Chinese labels genuinely benefit from a little air, and
     Chinese editorial practice does track headings slightly. Just not by a
     fifth of an em. */
  --tracking-display: 0.02em;
  --tracking-eyebrow: 0.08em;
  --tracking-caps:    0.05em;

  /* CJK needs more leading than Latin at the same size. */
  --leading-tight:  1.35;
  --leading-snug:   1.45;
  --leading-normal: 1.65;
  --leading-relaxed: 1.9;
}

/* A Latin run inside a Chinese page gets the original values back. */
[lang^="zh"] :lang(en) {
  --tracking-display: 0.08em;
  --tracking-eyebrow: 0.22em;
  --tracking-caps:    0.14em;
}

/* Measure. `ch` is the width of "0", which is half-width in Noto Sans/Serif
   SC — so 60ch is about 30 Chinese characters, well under a comfortable line.
   em-based measure puts it back in the 34–40 character range Chinese
   long-form copy wants. */
[lang^="zh"] .lgx-lede { max-width: 34em; }
[lang^="zh"] .lgx-body { max-width: 38em; }
[lang^="zh"] .lgx-quote,
[lang^="zh"] .lgx-trust__note { max-width: 16em; }

/* Chinese sets no wider than its Latin equivalent, so a nav or button label
   that fitted in English always fits here — but the reverse is not true of
   uppercase, which is a no-op on CJK and leaves mixed strings shouting. */
[lang^="zh"] .lgx-btn,
[lang^="zh"] .lgx-badge,
[lang^="zh"] .lgx-label { text-transform: none; }

/* Body copy in Chinese wants the sans, not Lora — Lora has no CJK coverage
   at all, so every character was already falling through to the Noto stack.
   Naming it directly stops the fallback lottery deciding the page's texture. */
[lang^="zh"] body { font-family: var(--font-cn-body); }
/* The textarea sets --font-body explicitly (Lora), which was the only thing
   pulling Lora onto the Chinese pages at all — 76 KB for one form field. */
[lang^="zh"] .lgx-textarea { font-family: var(--font-cn-body); }

/* The second language beside a heading — "Specification 产品规格". Was an
   inline style repeated at every call site in site.js. Sized down and set in
   the other script's face, so the pair reads as one label rather than two
   competing headings. */
.lgx-h4__alt {
  font-family: var(--font-cn-display);
  font-size: 0.85em;
  font-weight: var(--weight-regular);
  letter-spacing: 0;
  color: var(--text-muted);
  text-transform: none;
}
.lgx-h4__alt:lang(en) {
  font-family: var(--font-ui);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  font-size: 0.7em;
}

.lgx-eyebrow {
  font-family: var(--font-ui);
  font-size: var(--text-caption);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-eyebrow);
  color: var(--text-accent);
  margin: 0 0 var(--space-3);
}

.lgx-lede {
  font-size: var(--text-body-l);
  line-height: var(--leading-relaxed);
  color: var(--text-secondary);
  max-width: 60ch;
  margin: 0;
}

.lgx-body    { margin: 0 0 var(--space-4); max-width: 68ch; }
.lgx-small   { font-size: var(--text-body-s); color: var(--text-secondary); }
.lgx-caption {
  font-family: var(--font-ui);
  font-size: var(--text-caption);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Every numeral on this site is tabular. Prices, weights, fineness, phone
   numbers, serials — they all sit in columns somewhere. */
.lgx-num, table, .lgx-price, .lgx-spec {
  font-family: var(--font-ui);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}


/* --------------------------------------------------------------------------
   Layout
   -------------------------------------------------------------------------- */

.lgx-container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-pad);
}
.lgx-container--narrow { max-width: var(--container-narrow); }

.lgx-section {
  padding-block: var(--section-y);
  background: var(--surface-page);
  color: var(--text-primary);
}
.lgx-section--tight { padding-block: var(--section-y-tight); }
.lgx-section--sunken { background: var(--surface-sunken); }

.lgx-stack     { display: flex; flex-direction: column; gap: var(--space-4); }
.lgx-row       { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.lgx-grid      { display: grid; gap: var(--space-5); }
.lgx-grid--3   { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.lgx-grid--4   { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }


/* --------------------------------------------------------------------------
   Brand ornaments
   The diamond rule is the single most repeated device across the collateral
   — it appears on every cover, letterhead, envelope and catalogue page.
   -------------------------------------------------------------------------- */

.lgx-rule {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  color: var(--border-gold);
}
.lgx-rule::before,
.lgx-rule::after {
  content: "";
  flex: 1;
  height: 1px;
  background: currentColor;
  opacity: 0.55;
}
.lgx-rule__diamond {
  width: 7px; height: 7px;
  background: currentColor;
  transform: rotate(45deg);
  flex: none;
}
/* Explicit width, not max-width: an auto cross-axis margin on a flex item
   makes it shrink-to-fit, which would starve the flex:1 lines to zero. */
.lgx-rule--short { width: 180px; max-width: 100%; margin-inline: auto; }

/* Hairline gold frame, inset — the neoclassical border from the posters. */
.lgx-frame {
  position: relative;
  padding: var(--space-7);
  border: var(--border-width-hair) solid var(--border-gold-faint);
}
.lgx-frame::after {
  content: "";
  position: absolute;
  inset: 6px;
  border: var(--border-width-hair) solid var(--border-gold-faint);
  pointer-events: none;
}

.lgx-section-header {
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
  margin-bottom: var(--space-7);
}
.lgx-section-header .lgx-rule { width: 160px; }


/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */

.lgx-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  font-family: var(--font-ui);
  font-size: var(--text-body-s);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  line-height: 1;
  padding: var(--space-4) var(--space-6);
  border: var(--border-width-hair) solid transparent;
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-decoration: none;
  transition: background-color var(--duration-normal) var(--ease-standard),
              color var(--duration-normal) var(--ease-standard),
              border-color var(--duration-normal) var(--ease-standard);
}

.lgx-btn--primary {
  background: var(--action-primary-bg);
  color: var(--action-primary-fg);
}
.lgx-btn--primary:hover { background: var(--action-primary-bg-hover); }

.lgx-btn--accent {
  background: var(--action-accent-bg);
  color: var(--action-accent-fg);
  border-color: var(--action-accent-bg);
}
.lgx-btn--accent:hover {
  background: var(--action-accent-bg-hover);
  border-color: var(--action-accent-bg-hover);
}

.lgx-btn--outline {
  background: transparent;
  color: var(--action-quiet-fg);
  border-color: var(--action-quiet-border);
}
.lgx-btn--outline:hover {
  background: var(--action-quiet-fg);
  color: var(--surface-page);
}

.lgx-btn--ghost {
  background: transparent;
  color: var(--text-accent);
  padding-inline: var(--space-2);
}
.lgx-btn--ghost:hover { color: var(--text-primary); }

/* min-height, not more padding: the label stays visually small and tight —
   which is the point of the modifier — while the hit area clears 44px. */
.lgx-btn--sm { padding: var(--space-3) var(--space-4); font-size: var(--text-caption);
               min-height: 44px; }
/* Uppercase + 0.14em tracking already makes these labels wide; --space-8 of
   side padding pushed two large buttons past a 780px row. */
.lgx-btn--lg { padding: var(--space-5) var(--space-7); font-size: var(--text-body); }

.lgx-btn:disabled,
.lgx-btn[aria-disabled="true"] {
  background: var(--surface-disabled);
  border-color: var(--surface-disabled);
  color: var(--text-disabled);
  cursor: not-allowed;
}


/* --------------------------------------------------------------------------
   Badges
   -------------------------------------------------------------------------- */

.lgx-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-family: var(--font-ui);
  font-size: var(--text-caption);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  padding: var(--space-1) var(--space-3);
  border: var(--border-width-hair) solid var(--border-subtle);
  border-radius: var(--radius-pill);
  color: var(--text-secondary);
  background: transparent;
}
.lgx-badge--gold {
  border-color: var(--border-gold);
  color: var(--text-accent);
}
.lgx-badge--solid {
  background: var(--action-primary-bg);
  border-color: var(--action-primary-bg);
  color: var(--action-primary-fg);
}
.lgx-badge--stock {
  border-color: color-mix(in srgb, var(--status-up) 45%, transparent);
  color: var(--status-up);
  background: var(--status-up-wash);
}
.lgx-badge--out {
  border-color: color-mix(in srgb, var(--status-down) 45%, transparent);
  color: var(--status-down);
  background: var(--status-down-wash);
}


/* --------------------------------------------------------------------------
   Card / product card
   -------------------------------------------------------------------------- */

.lgx-card {
  background: var(--surface-raised);
  border: var(--border-width-hair) solid var(--border-subtle);
  border-radius: var(--radius-sm);
  padding: var(--space-5);
  transition: border-color var(--duration-normal) var(--ease-standard),
              box-shadow var(--duration-normal) var(--ease-standard);
}
.lgx-card--interactive:hover {
  border-color: var(--border-gold);
  box-shadow: var(--shadow-md);
}

.lgx-product {
  display: flex;
  flex-direction: column;
  background: var(--surface-raised);
  border: var(--border-width-hair) solid var(--border-subtle);
  border-radius: var(--radius-sm);
  overflow: hidden;
  transition: border-color var(--duration-normal) var(--ease-standard),
              box-shadow var(--duration-normal) var(--ease-standard);
}
.lgx-product:hover {
  border-color: var(--border-gold);
  box-shadow: var(--shadow-md);
}
.lgx-product__media {
  aspect-ratio: 4 / 3;
  display: grid;
  place-items: center;
  background: var(--surface-sunken);
  border-bottom: var(--border-width-hair) solid var(--border-subtle);
  padding: var(--space-5);
}
.lgx-product__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-5);
  flex: 1;
}
.lgx-product__mint {
  font-family: var(--font-ui);
  font-size: var(--text-caption);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--text-muted);
}
.lgx-product__name {
  font-family: var(--font-display);
  font-size: var(--text-h4);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  line-height: var(--leading-snug);
  margin: 0;
}
.lgx-product__name-cn {
  font-family: var(--font-cn-display);
  font-size: var(--text-body-s);
  color: var(--text-secondary);
  margin: 0;
}
.lgx-product__price {
  font-family: var(--font-ui);
  font-size: var(--text-h3);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
  margin-top: auto;
  padding-top: var(--space-4);
}
.lgx-product__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-top: var(--border-width-hair) solid var(--border-subtle);
}


/* --------------------------------------------------------------------------
   Spec table — the bilingual row pattern from the V7 catalogue
   -------------------------------------------------------------------------- */

.lgx-spec {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-body-s);
  text-align: left;
}
.lgx-spec th,
.lgx-spec td {
  padding: var(--space-3) var(--space-4);
  border-bottom: var(--border-width-hair) solid var(--border-subtle);
  vertical-align: top;
}
.lgx-spec th {
  width: 34%;
  font-weight: var(--weight-medium);
  color: var(--text-secondary);
  white-space: nowrap;
}
.lgx-spec td { color: var(--text-primary); }
.lgx-spec tr:last-child th,
.lgx-spec tr:last-child td { border-bottom: 0; }
.lgx-spec__cn {
  display: block;
  font-family: var(--font-cn-display);
  font-size: var(--text-caption);
  color: var(--text-muted);
  letter-spacing: 0.02em;
}
.lgx-spec--striped tbody tr:nth-child(odd) { background: var(--surface-sunken); }


/* --------------------------------------------------------------------------
   Price tile / live metal rate
   -------------------------------------------------------------------------- */

.lgx-price {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-5);
  border: var(--border-width-hair) solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--surface-raised);
}
.lgx-price__metal {
  font-family: var(--font-ui);
  font-size: var(--text-caption);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--text-muted);
}
.lgx-price__value {
  font-size: var(--text-h2);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
  line-height: var(--leading-tight);
}
.lgx-price__delta {
  font-size: var(--text-body-s);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
}
.lgx-price__delta[data-dir="up"]   { color: var(--status-up); }
.lgx-price__delta[data-dir="down"] { color: var(--status-down); }
.lgx-price__delta[data-dir="flat"] { color: var(--status-neutral); }
.lgx-price__delta[data-dir="up"]::before   { content: "▲ "; }
.lgx-price__delta[data-dir="down"]::before { content: "▼ "; }

/* Marquee-free ticker strip. Sits directly under the header. */
.lgx-ticker {
  display: flex;
  gap: var(--space-7);
  flex-wrap: wrap;
  align-items: baseline;
  padding: var(--space-3) 0;
  font-family: var(--font-ui);
  font-size: var(--text-body-s);
  font-variant-numeric: tabular-nums;
  border-block: var(--border-width-hair) solid var(--border-subtle);
}
.lgx-ticker__item { display: flex; gap: var(--space-2); align-items: baseline; }
.lgx-ticker__label {
  font-size: var(--text-caption);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}
.lgx-ticker__value { font-weight: var(--weight-semibold); }


/* --------------------------------------------------------------------------
   Header / nav / footer
   -------------------------------------------------------------------------- */

.lgx-header {
  position: relative;
  z-index: var(--z-header);
  border-bottom: var(--border-width-hair) solid var(--border-subtle);
}
.lgx-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-6);
  padding-block: var(--space-4);
}

.lgx-logo {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  text-decoration: none;
  color: var(--text-accent);
}
.lgx-logo__mark {
  font-family: var(--font-display);
  font-size: var(--text-h2);
  font-weight: var(--weight-bold);
  letter-spacing: 0.02em;
  line-height: 1;
}
.lgx-logo__sub {
  font-family: var(--font-display);
  font-size: var(--text-caption);
  letter-spacing: var(--tracking-eyebrow);
  line-height: 1;
  padding-top: 4px;
  border-top: var(--border-width-hair) solid currentColor;
  width: 100%;
  text-align: center;
}

.lgx-nav { display: flex; gap: var(--space-6); align-items: center; }
.lgx-nav a {
  font-family: var(--font-ui);
  font-size: var(--text-body-s);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  text-decoration: none;
  color: var(--text-primary);
  padding-block: var(--space-2);
  border-bottom: var(--border-width-rule) solid transparent;
  transition: border-color var(--duration-normal) var(--ease-standard);
}
.lgx-nav a:hover,
.lgx-nav a[aria-current="page"] { border-bottom-color: var(--border-gold); }

.lgx-footer { padding-block: var(--space-8) var(--space-6); }
.lgx-footer__cols {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}
.lgx-footer h5 {
  font-family: var(--font-ui);
  font-size: var(--text-caption);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--text-accent);
  margin: 0 0 var(--space-4);
}
.lgx-footer ul { list-style: none; margin: 0; padding: 0;
                 display: flex; flex-direction: column; gap: var(--space-2); }
.lgx-footer a {
  font-family: var(--font-ui);
  font-size: var(--text-body-s);
  color: var(--text-secondary);
  text-decoration: none;
}
.lgx-footer a:hover { color: var(--text-primary); }
.lgx-footer__legal {
  margin-top: var(--space-7);
  padding-top: var(--space-5);
  border-top: var(--border-width-hair) solid var(--border-subtle);
  font-family: var(--font-ui);
  font-size: var(--text-caption);
  color: var(--text-muted);
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}


/* --------------------------------------------------------------------------
   Forms
   -------------------------------------------------------------------------- */

.lgx-field { display: flex; flex-direction: column; gap: var(--space-2); }
.lgx-label {
  font-family: var(--font-ui);
  font-size: var(--text-caption);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-secondary);
}
.lgx-input,
.lgx-select,
.lgx-textarea {
  font-family: var(--font-ui);
  font-size: var(--text-body-s);
  color: var(--text-primary);
  background: var(--surface-raised);
  border: var(--border-width-hair) solid var(--border-subtle);
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-4);
  transition: border-color var(--duration-fast) var(--ease-standard);
  width: 100%;
}
.lgx-input:hover, .lgx-select:hover, .lgx-textarea:hover { border-color: var(--lgx-ivory-400); }

/* The gold border is a nice touch on pointer focus, but it is 2.5:1 against
   the field — nowhere near the 3:1 WCAG 1.4.11 wants from a focus indicator.
   So it decorates, and the :focus-visible ring from the base layer does the
   actual work. Never put `outline: none` back here. */
.lgx-input:focus, .lgx-select:focus, .lgx-textarea:focus {
  border-color: var(--border-gold);
}
.lgx-input::placeholder, .lgx-textarea::placeholder { color: var(--text-muted); }
.lgx-textarea { min-height: 120px; resize: vertical; font-family: var(--font-body); }
.lgx-help { font-family: var(--font-ui); font-size: var(--text-caption); color: var(--text-muted); }

/* Touch target: 44px minimum on every control a finger has to hit. */
.lgx-input, .lgx-select { min-height: 44px; }

.lgx-field[data-invalid] .lgx-input,
.lgx-field[data-invalid] .lgx-select,
.lgx-field[data-invalid] .lgx-textarea { border-color: var(--status-down); }
.lgx-field[data-invalid] .lgx-help  { color: var(--status-down); }
/* Colour alone never carries the error — the ! prefix survives greyscale,
   colour-blindness and a screen-reader's flat text rendering. */
.lgx-field[data-invalid] .lgx-help::before {
  content: "! ";
  font-weight: var(--weight-bold);
}


/* --------------------------------------------------------------------------
   Trust row, notice, breadcrumb, pull quote
   -------------------------------------------------------------------------- */

.lgx-trust {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--space-5);
  text-align: center;
}
.lgx-trust__item { display: flex; flex-direction: column; align-items: center; gap: var(--space-3); }
.lgx-trust__icon {
  width: 40px; height: 40px;
  color: var(--border-gold);
  stroke: currentColor;
  fill: none;
  stroke-width: 1.25;
}
.lgx-trust__label {
  font-family: var(--font-ui);
  font-size: var(--text-caption);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--text-primary);
}
.lgx-trust__note { font-size: var(--text-body-s); color: var(--text-secondary); max-width: 24ch; }

.lgx-notice {
  display: flex;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  border-left: 3px solid var(--border-gold);
  background: var(--surface-sunken);
  font-size: var(--text-body-s);
  color: var(--text-secondary);
}
.lgx-notice--warn { border-left-color: var(--status-down); }

.lgx-breadcrumb {
  display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap;
  font-family: var(--font-ui);
  font-size: var(--text-caption);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}
/* 24x24 is the WCAG 2.5.8 (AA) minimum for a target that is not inline prose.
   A breadcrumb is a navigation list, so the exception does not apply and the
   bare 15px-tall links did not clear it. */
.lgx-breadcrumb a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  padding-inline: var(--space-1);
  margin-inline: calc(var(--space-1) * -1);
  color: var(--text-muted);
  text-decoration: none;
}
.lgx-breadcrumb a:hover { color: var(--text-accent); }
.lgx-breadcrumb li + li::before { content: "◆"; font-size: 6px; margin-right: var(--space-2);
                                  vertical-align: middle; color: var(--border-gold); }
.lgx-breadcrumb ol { list-style: none; display: flex; gap: var(--space-2); margin: 0; padding: 0; }

.lgx-quote {
  font-family: var(--font-display);
  font-size: var(--text-h3);
  text-transform: uppercase;
  letter-spacing: var(--tracking-display);
  line-height: var(--leading-snug);
  color: var(--text-accent);
  text-align: center;
  margin: 0;
  max-width: 24ch;
  margin-inline: auto;
}


/* --------------------------------------------------------------------------
   Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 900px) {
  :root {
    --text-display-xl: 2.75rem;
    --text-display-l:  2.25rem;
    --text-h1:         2rem;
    --text-h2:         1.625rem;
    --section-y:       var(--space-7);
  }
  .lgx-header__inner { flex-wrap: wrap; }
  .lgx-nav { gap: var(--space-4); }
}
