/* EUROCUTPRECISION — Component Library (implements docs/41-44) */

/* ===== Header / Navigation (docs/43) ===== */
.site-header {
  position: sticky; top: 0; z-index: 100;
  background: var(--color-neutral-0);
  border-bottom: 1px solid var(--color-neutral-300);
}
.site-header__inner { display: flex; align-items: center; justify-content: space-between; height: 72px; gap: var(--space-6); }
.site-header__logo { display: flex; align-items: center; gap: var(--space-3); font-weight: 700; font-size: 17px; letter-spacing: 0.01em; color: var(--color-neutral-900); flex-shrink: 0; }
.site-header__logo-mark { height: 32px; width: auto; display: block; }
.site-nav { display: flex; gap: clamp(0.9rem, 1.7vw, 2rem); list-style: none; margin: 0; padding: 0; }
.site-nav a { color: var(--color-neutral-700); font-size: var(--type-small-size); font-weight: 500; padding: var(--space-1) 0; border-bottom: 2px solid transparent; }
.site-nav a:hover { color: var(--color-neutral-900); text-decoration: none; }
.site-nav a[aria-current="page"] { color: var(--color-neutral-900); font-weight: 600; border-bottom-color: var(--color-accent-500); }
.site-header__actions { display: flex; align-items: center; gap: var(--space-3); flex-shrink: 0; }

/* RFQ basket indicator — deliberately minimal/secondary (icon + count only), so it never
   competes visually with the one primary "Request a Quotation" button beside it. */
.rfq-indicator {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: var(--radius-full);
  color: var(--color-neutral-700); border: 1.5px solid transparent;
}
.rfq-indicator:hover { color: var(--color-neutral-900); background: var(--color-neutral-100); text-decoration: none; }
.rfq-indicator svg { width: 20px; height: 20px; }
.rfq-indicator__count {
  position: absolute; top: 1px; right: 1px;
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 16px; height: 16px; padding: 0 3px;
  background: var(--color-accent-500); color: #fff; border-radius: var(--radius-full);
  font-size: 10px; font-weight: 700; line-height: 1; font-family: var(--font-sans);
}
.nav-toggle { display: none; background: none; border: 1px solid var(--color-neutral-500); border-radius: var(--radius-sm); padding: var(--space-2) var(--space-3); font-size: 16px; min-width: 44px; min-height: 44px; }
.site-nav > .site-nav__rfq-link { display: none; } /* higher specificity than .btn's display:inline-flex, which otherwise wins on source order */
@media (min-width: 1024px) and (max-width: 1199px) {
  /* Narrow-desktop pinch: the full 6-item nav + actions bar (indicator + button) doesn't
     fit in this band. Drop the secondary "Quotation N" indicator only — the primary
     Request a Quotation button stays fully visible, so the RFQ action is never hidden. */
  .rfq-indicator { display: none; }
}
@media (max-width: 1023px) {
  .site-nav { display: none; }
  .nav-toggle { display: inline-flex; }
  .site-nav.is-open {
    display: flex; flex-direction: column; position: absolute; top: 72px; left: 0; right: 0;
    background: var(--color-neutral-0); border-bottom: 1px solid var(--color-neutral-300);
    padding: var(--space-4) var(--space-6); gap: var(--space-3);
  }
  /* Fix: .site-header__actions (RFQ indicator + button) overflowed narrow viewports
     alongside the full logo/wordmark and nav-toggle. Reuses the existing nav-collapse
     breakpoint rather than a new one-off patch: the RFQ action moves into the same
     mobile menu the nav already collapses into, instead of competing for header-bar
     width. Nothing is hidden completely — it's one tap away via the existing hamburger. */
  .site-header__actions { display: none; }
  .site-nav > .site-nav__rfq-link { display: inline-flex; margin-top: var(--space-2); align-self: flex-start; }
}

/* ===== Hero (premium industrial — DC SWISS restraint + DATRON impact) ===== */
.hero { padding: var(--space-16) 0 var(--space-20); border-top: 3px solid var(--color-accent-500); }
.hero__grid { display: grid; grid-template-columns: 1fr 0.92fr; gap: var(--space-16); align-items: center; }
.hero__headline { margin-top: var(--space-3); }
.hero__lead { margin-top: var(--space-5); max-width: 46ch; font-size: 1.0625rem; color: var(--color-neutral-700); }
.hero__actions { margin-top: var(--space-8); }
.hero__visual-frame {
  position: relative; background: var(--color-neutral-900); border-radius: var(--radius-md);
  display: flex; align-items: center; justify-content: center; padding: var(--space-10);
  aspect-ratio: 4 / 3.6; overflow: hidden;
  background-image:
    linear-gradient(rgba(255,255,255,0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.05) 1px, transparent 1px);
  background-size: 28px 28px;
}
.hero__visual-frame svg { width: 100%; height: auto; max-width: 320px; }
.hero__visual-label {
  position: absolute; left: var(--space-5); bottom: var(--space-4);
  font-family: var(--font-mono); font-size: var(--type-caption-size); letter-spacing: var(--tracking-wide);
  text-transform: uppercase; color: var(--color-neutral-300);
}
@media (max-width: 1023px) { .hero__grid { grid-template-columns: 1fr; gap: var(--space-10); } .hero__visual-frame { aspect-ratio: 16/10; } }
@media (max-width: 639px) { .hero { padding: var(--space-10) 0 var(--space-12); } }

/* ===== Footer (docs/43) ===== */
.site-footer { background: var(--color-neutral-900); color: var(--color-neutral-300); padding: var(--space-20) 0 var(--space-8); }
/* h2 AND h3.
   These column headings were h3 sitting under an h1, which skips a level, and Sprint 3
   corrected the markup to h2 — without changing this selector. The headings then
   inherited the global `h2 { color: var(--color-neutral-900) }`, which is #1B1E27 text
   on a #1B1E27 footer. Company, Products, Resources and Partnerships were invisible on
   all forty pages, and every automated check passed: the text was present, the links
   worked, and contrast is not measured between a heading and a background set two rules
   apart. It is visible in a screenshot and nowhere else. */
.site-footer h2,
.site-footer h3 {
  color: var(--color-neutral-0); font-size: var(--type-caption-size); font-family: var(--font-mono);
  letter-spacing: var(--tracking-wide); line-height: var(--type-caption-line);
  text-transform: uppercase; font-weight: 600; margin-bottom: var(--space-4);
}
.site-footer a { color: var(--color-neutral-300); font-size: var(--type-small-size); line-height: 2.1; }
.site-footer a:hover { color: var(--color-neutral-0); }
.footer-top { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--space-10); padding-bottom: var(--space-10); margin-bottom: var(--space-10); border-bottom: 1px solid var(--color-neutral-700); }
.footer-top .footer-brand { flex-shrink: 0; }
.footer-top .footer-brand-mark { height: 30px; }
.footer-top__tagline { color: var(--color-on-dark-muted); font-size: var(--type-small-size); margin-top: var(--space-3); max-width: 42ch; }
.footer-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-8); margin-bottom: var(--space-10); }
.footer-grid ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0; }

/* The footer ends in a rule, a copyright and the policy links, and nothing else. The
   quotation button that used to sit here — and the second one beside the brand above —
   moved into the pre-footer band, where one of them does the work all three were doing. */
.footer-bottom {
  display: flex; justify-content: space-between; align-items: center;
  border-top: 1px solid var(--color-neutral-700); padding-top: var(--space-6);
  flex-wrap: wrap; gap: var(--space-3) var(--space-6);
}
.footer-bottom small { color: var(--color-on-dark-muted); font-size: var(--type-small-size); }
.footer-legal { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-5); }
.footer-legal a { font-size: var(--type-small-size); line-height: 1.8; color: var(--color-on-dark-muted); }
.footer-legal a:hover { color: var(--color-neutral-0); }
.footer-brand { display: inline-flex; align-items: center; gap: var(--space-3); }
.footer-brand-mark { height: 22px; width: auto; display: block; flex-shrink: 0; }
@media (max-width: 1023px) { .footer-grid { grid-template-columns: repeat(2, 1fr); } .footer-top { flex-direction: column; gap: var(--space-6); } }
@media (max-width: 639px) {
  .footer-grid { grid-template-columns: 1fr; gap: var(--space-6); }
  .footer-bottom { flex-direction: column; align-items: flex-start; }
}

/* ===== Pre-footer call to action =====
   The single quotation call to action in the page body: one per page, always last,
   always the same heading, sentence and button. */
.cta-band {
  background: var(--color-neutral-950); color: var(--color-neutral-0);
  padding: var(--space-16) 0;
  /* The band and the footer are two dark surfaces meeting directly. Without a rule
     between them there is no seam, and the two read as one very long dark block. */
  border-bottom: 1px solid var(--color-neutral-700);
}
/* 64px below the band plus 80px above the footer put 144px of empty dark ground between
   them. On a light page the footer's top padding separates it from white content; after
   the band it is separating dark from dark, and it only has to mark a change. */
main:has(.cta-band) + .site-footer { padding-top: var(--space-12); }
.cta-band__inner {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--space-6) var(--space-10);
}
.cta-band__heading { color: var(--color-neutral-0); font-size: var(--type-h2-size); line-height: var(--type-h2-line); margin: 0; }
.cta-band__note { margin: var(--space-3) 0 0; max-width: 54ch; color: var(--color-neutral-300); font-size: var(--type-small-size); line-height: 1.6; }
.cta-band .btn { flex-shrink: 0; }
@media (max-width: 639px) {
  .cta-band { padding: var(--space-12) 0; }
  .cta-band__inner { flex-direction: column; align-items: stretch; }
  .cta-band .btn { width: 100%; }
}

/* ===== Breadcrumbs (docs/41) ===== */
.breadcrumb { padding: var(--space-3) 0; font-size: var(--type-small-size); color: var(--color-neutral-500); }
.breadcrumb ol { list-style: none; display: flex; flex-wrap: wrap; gap: var(--space-1); margin: 0; padding: 0; }
.breadcrumb li:not(:last-child)::after { content: "/"; margin-left: var(--space-1); color: var(--color-neutral-300); }
.breadcrumb a { color: var(--color-neutral-500); }
.breadcrumb [aria-current="page"] { color: var(--color-neutral-900); font-weight: 600; }

/* ===== Unavailable form control (honest, non-interactive — never looks like a working input) ===== */
.form-field__unavailable {
  padding: var(--space-3); border: 1px dashed var(--color-neutral-300); border-radius: var(--radius-sm);
  background: var(--color-neutral-100); color: var(--color-neutral-500); font-size: var(--type-small-size);
}

/* ===== Button (docs/41) ===== */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  font-family: var(--font-sans); font-size: var(--type-small-size); font-weight: 600;
  padding: var(--space-3) var(--space-6); border-radius: var(--radius-sm);
  border: 1.5px solid transparent; cursor: pointer; min-height: 44px;
  transition: transform var(--motion-fast) var(--motion-easing);
}
.btn:active { transform: translateY(1px); }
.btn--primary { background: var(--color-accent-500); color: #fff; }
.btn--primary:hover { background: var(--color-accent-700); text-decoration: none; }
.btn--secondary { background: transparent; color: var(--color-neutral-900); border-color: var(--color-neutral-500); }
.btn--secondary:hover { border-color: var(--color-neutral-900); text-decoration: none; }
.btn--tertiary { background: transparent; color: var(--color-accent-700); border: none; padding: var(--space-2) 0; min-height: auto; }
.btn--tertiary:hover { text-decoration: underline; }
.btn--block { width: 100%; }
.btn--lg { padding: var(--space-4) var(--space-8); font-size: 1rem; min-height: 52px; }

/* ===== Inputs / Forms (docs/41, docs/43) ===== */
.form-field { margin-bottom: var(--space-5); }
.form-field label { display: block; font-size: var(--type-small-size); font-weight: 600; color: var(--color-neutral-900); margin-bottom: var(--space-2); }
.form-field .required { color: var(--color-error-700); }
.form-field .hint { display: block; font-size: var(--type-caption-size); color: var(--color-neutral-500); margin-top: var(--space-1); }
.form-field input, .form-field select, .form-field textarea {
  width: 100%; font-family: var(--font-sans); font-size: var(--type-body-size);
  padding: var(--space-3); border: 1.5px solid var(--color-neutral-500); border-radius: var(--radius-sm);
  background: var(--color-neutral-0); color: var(--color-neutral-900);
}
.form-field input:focus, .form-field select:focus, .form-field textarea:focus { border-color: var(--color-accent-500); }
.form-field textarea { min-height: 110px; resize: vertical; }
.form-field.has-error input, .form-field.has-error textarea, .form-field.has-error select { border-color: var(--color-error-700); }
.form-checkbox.has-error { outline: 1.5px solid var(--color-error-700); outline-offset: 4px; border-radius: var(--radius-sm); }
.form-checkbox .error-message { display: block; color: var(--color-error-700); font-size: var(--type-caption-size); margin-top: var(--space-1); }
.form-field .error-message { display: block; color: var(--color-error-700); font-size: var(--type-caption-size); margin-top: var(--space-1); }
/* The consent checkbox rendered at the browser default of 13x13 CSS pixels, which is
   below every touch-target guideline there is and is the single control a visitor MUST
   hit to send a quotation. 20px with padding around the row, and the label is clickable
   too — but a 13px box that is hard to hit on a phone is a form that does not submit. */
.form-checkbox { display: flex; align-items: flex-start; gap: var(--space-3); font-size: var(--type-small-size); }
.form-checkbox input[type="checkbox"],
.form-checkbox input[type="radio"] {
  width: 24px; height: 24px; flex-shrink: 0;
  /* The row is the target, not just the box: 12px of padding above and below puts the
     hit area over 44px without moving anything on screen. */
  padding: 12px; box-sizing: content-box; margin: -12px -12px -12px 0;
  accent-color: var(--color-accent-500);
}
.form-checkbox label { padding-top: 1px; }
.error-summary {
  background: var(--color-error-100); border: 1px solid var(--color-error-700); border-radius: var(--radius-sm);
  padding: var(--space-4); margin-bottom: var(--space-5); color: var(--color-error-700); font-size: var(--type-small-size);
}
.error-summary[hidden] { display: none; }

/* ===== Badge (docs/41) ===== */
.badge {
  display: inline-flex; align-items: center; font-size: var(--type-caption-size); font-weight: 600;
  padding: var(--space-1) var(--space-3); border-radius: var(--radius-full);
  background: var(--color-neutral-100); color: var(--color-neutral-700);
}
.badge--accent { background: var(--color-accent-100); color: var(--color-accent-700); }

/* ===== Alert / Toast / Status (docs/41, docs/44) ===== */
.alert { padding: var(--space-4); border-radius: var(--radius-sm); font-size: var(--type-small-size); margin-bottom: var(--space-5); }
.alert--info { background: var(--color-neutral-100); color: var(--color-neutral-900); }
.alert--success { background: var(--color-success-100); color: var(--color-success-700); }
.alert--error { background: var(--color-error-100); color: var(--color-error-700); }
.toast {
  position: fixed; bottom: var(--space-6); right: var(--space-6); z-index: 200;
  background: var(--color-neutral-900); color: #fff; padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-sm); font-size: var(--type-small-size);
  opacity: 0; transform: translateY(8px); transition: opacity var(--motion-base) var(--motion-easing), transform var(--motion-base) var(--motion-easing);
  pointer-events: none;
}
.toast.is-visible { opacity: 1; transform: translateY(0); }

/* ===== Card (docs/42) ===== */
.card { background: var(--color-neutral-0); border: 1px solid var(--color-neutral-300); border-radius: var(--radius-md); box-shadow: var(--shadow-none); padding: var(--space-6); transition: border-color var(--motion-fast) var(--motion-easing), transform var(--motion-fast) var(--motion-easing); }
.card--link { display: block; color: inherit; }
.card--link:hover { border-color: var(--color-accent-500); text-decoration: none; transform: translateY(-2px); }
.card h3 { margin-bottom: var(--space-2); }
.card p { margin: 0; color: var(--color-neutral-700); font-size: var(--type-small-size); }

/* ===== Product family card — premium category presentation, not a doc card ===== */
.family-card { padding: 0; overflow: hidden; }
.family-card__frame {
  position: relative; background: var(--color-neutral-900); min-height: 180px;
  display: flex; align-items: center; justify-content: center; padding: var(--space-6);
  background-image:
    linear-gradient(rgba(255,255,255,0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.05) 1px, transparent 1px);
  background-size: 24px 24px;
}
.family-card__frame svg { width: 100%; max-width: 130px; height: auto; }
.family-card__body { padding: var(--space-6); }
.family-card__status { margin-bottom: var(--space-3); }
.family-card h3 { margin-bottom: var(--space-2); }
.family-card p { margin: 0 0 var(--space-4); color: var(--color-neutral-700); font-size: var(--type-small-size); }
.family-card__cta { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
/* Family-card grid — one card per row below desktop, never a 2+1 tablet layout. */
.family-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-6); }
@media (max-width: 1023px) { .family-grid { grid-template-columns: 1fr; max-width: 480px; margin: 0 auto; } }

/* ===== Data Table / Specification Table (docs/42) ===== */
table.data { width: 100%; border-collapse: collapse; font-size: var(--type-small-size); }
table.data caption { text-align: left; font-weight: 600; color: var(--color-neutral-900); padding-bottom: var(--space-3); font-family: var(--font-sans); }
table.data th, table.data td { text-align: left; padding: var(--space-4); border-bottom: 1px solid var(--color-neutral-300); }
table.data thead th {
  color: var(--color-neutral-500); font-size: var(--type-caption-size); text-transform: uppercase; letter-spacing: var(--tracking-wide);
  font-family: var(--font-sans); font-weight: 600; background: var(--color-neutral-0);
  /* `top` resolves against the nearest scrolling ancestor, which is the
     `overflow-x:auto` wrapper each of these tables sits in — not the viewport.
     (A non-`visible` overflow-x forces overflow-y to compute to `auto`, making
     that wrapper a scroll container.) A 72px offset therefore pinned the header
     72px BELOW the table's own top, covering the first data row permanently,
     even unscrolled. It must be 0: the site header is not what this clears. */
  border-bottom: 2px solid var(--color-neutral-900); position: sticky; top: 0; z-index: 10;
}
table.data tbody tr { transition: background var(--motion-fast) var(--motion-easing); }
table.data tbody tr:hover { background: var(--color-accent-100); }
table.data tbody tr:nth-child(even) { background: rgba(238,240,243,0.5); }
table.data tbody tr:hover:nth-child(even) { background: var(--color-accent-100); }
table.data tbody tr:focus-within { background: var(--color-accent-100); }
table.data .btn--tertiary { padding: var(--space-1) var(--space-3); border: 1.5px solid var(--color-neutral-300); border-radius: var(--radius-sm); font-size: var(--type-caption-size); }
table.data .btn--tertiary:hover { border-color: var(--color-accent-500); background: var(--color-accent-100); text-decoration: none; }
@media (max-width: 639px) {
  table.data.stack-mobile thead { display: none; }
  table.data.stack-mobile, table.data.stack-mobile tbody, table.data.stack-mobile tr, table.data.stack-mobile td { display: block; width: 100%; }
  table.data.stack-mobile tr { border-bottom: 2px solid var(--color-neutral-300); padding: var(--space-3) 0; }
  table.data.stack-mobile td { border: none; padding: var(--space-1) 0; }
  table.data.stack-mobile td::before { content: attr(data-label); display: block; font-size: var(--type-caption-size); color: var(--color-neutral-500); text-transform: uppercase; }

  /* Compact 2-column label/value card variant — catalogue-style tables only (multiple
     fields + a trailing action per row), not single label/value spec tables. */
  table.data.stack-mobile-cards tr {
    display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-1) var(--space-4);
    border: 1px solid var(--color-neutral-300); border-radius: var(--radius-md);
    padding: var(--space-4); margin-bottom: var(--space-3);
  }
  table.data.stack-mobile-cards td { padding: var(--space-1) 0; }
  table.data.stack-mobile-cards td::before { font-size: 10px; letter-spacing: var(--tracking-wide); }
  table.data.stack-mobile-cards td:last-child {
    grid-column: 1 / -1; margin-top: var(--space-2); padding-top: var(--space-3);
    border-top: 1px solid var(--color-neutral-100);
  }
  table.data.stack-mobile-cards td:last-child::before { display: none; }
  table.data.stack-mobile-cards td:last-child .btn { width: 100%; }
}

/* ===== Feature List (docs/42) ===== */
.feature-list { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-8); list-style: none; margin: 0; padding: 0; }
.feature-list li { text-align: center; }
.feature-icon {
  width: 44px; height: 44px; border-radius: var(--radius-full); border: 2px solid var(--color-accent-500);
  display: flex; align-items: center; justify-content: center; margin: 0 auto var(--space-4);
  color: var(--color-accent-500); font-weight: 700;
}
@media (max-width: 1023px) { .feature-list { grid-template-columns: 1fr; gap: var(--space-6); max-width: 420px; margin: var(--space-10) auto 0; } }

/* ===== Download Card (docs/42) ===== */
.download-card { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); padding: var(--space-4); border: 1px solid var(--color-neutral-500); border-radius: var(--radius-sm); }
.download-card__meta { font-size: var(--type-caption-size); color: var(--color-neutral-500); }
.download-card__title { font-weight: 600; color: var(--color-neutral-900); }

/* ===== Documentation availability (single honest state — replaces per-asset "coming soon" rows) =====
   There is deliberately no download link here: no datasheet or CAD file exists yet, so the only
   real action is to ask for one through the RFQ that already exists. Never turn this into a
   link that looks like a file until a real asset is in assets/. */
.doc-availability {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-6);
  margin-top: var(--space-4); padding: var(--space-6);
  border: 1px solid var(--color-neutral-300); border-radius: var(--radius-md); background: var(--color-neutral-100);
}
.doc-availability p { margin: 0; max-width: 62ch; color: var(--color-neutral-700); font-size: var(--type-small-size); }
.doc-availability .btn { flex-shrink: 0; }
@media (max-width: 639px) {
  .doc-availability { flex-direction: column; align-items: flex-start; padding: var(--space-5); }
  .doc-availability .btn { width: 100%; }
}

/* ===== Contextual technical references =====
   Links out to the general-engineering guides in the Technical Center from a product context.
   These are standard industry reference (formulas, ISO classifications) — NOT EUROCUT-specific
   cutting data. The accompanying copy must keep saying so. */
.tech-refs { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-5); list-style: none; margin: var(--space-6) 0 0; padding: 0; }
.tech-refs li { border-left: 2px solid var(--color-neutral-300); padding-left: var(--space-4); }
.tech-refs a { font-weight: 600; font-size: var(--type-small-size); }
.tech-refs p { margin: var(--space-1) 0 0; font-size: var(--type-caption-size); color: var(--color-neutral-500); line-height: 1.5; }
@media (max-width: 1023px) { .tech-refs { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 639px) { .tech-refs { grid-template-columns: 1fr; gap: var(--space-4); } }

/* ===== Technical drawing frame (identity device, D-012) ===== */
.tech-drawing-frame { background: var(--color-neutral-100); display: flex; align-items: center; justify-content: center; padding: var(--space-8); }
.tech-drawing-frame svg { width: 100%; height: auto; }
.tech-drawing-label { font-family: var(--font-mono); font-size: var(--type-caption-size); color: var(--color-neutral-500); text-transform: uppercase; letter-spacing: 0.05em; text-align: center; margin-bottom: var(--space-3); }

/* ===== Photo placeholder (honest, per docs/32-33 fallback rule) ===== */
.photo-placeholder {
  background: var(--color-neutral-100); border: 1px dashed var(--color-neutral-300);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  min-height: 320px; padding: var(--space-6); text-align: center; color: var(--color-neutral-500);
}
.photo-placeholder .type-caption { max-width: 260px; }

/* ===== Proof strip stat (docs/42 Technical Data Block) ===== */
.stat-block .type-caption { color: var(--color-neutral-500); text-transform: uppercase; letter-spacing: 0.04em; display: block; margin-bottom: var(--space-1); }
.stat-block .stat-value { font-family: var(--font-mono); font-size: 20px; font-weight: 600; color: var(--color-neutral-900); }

/* ===== Accordion (docs/41) ===== */
.accordion-item { border-bottom: 1px solid var(--color-neutral-300); }
.accordion-trigger {
  width: 100%; text-align: left; background: none; border: none; cursor: pointer;
  padding: var(--space-4) 0; display: flex; justify-content: space-between; align-items: center;
  font-family: var(--font-sans); font-size: var(--type-body-size); font-weight: 600; color: var(--color-neutral-900);
}
.accordion-trigger .chevron { transition: transform var(--motion-base) var(--motion-easing); }
.accordion-trigger[aria-expanded="true"] .chevron { transform: rotate(180deg); }
.accordion-panel { overflow: hidden; max-height: 0; transition: max-height var(--motion-base) var(--motion-easing); }
.accordion-panel:not([hidden]) { max-height: 400px; padding-bottom: var(--space-4); }
.accordion-panel p { margin: 0; font-size: var(--type-small-size); color: var(--color-neutral-700); }

/* ===== RFQ page layout ===== */
.rfq-layout { display: grid; grid-template-columns: 1.5fr 1fr; gap: var(--space-12); align-items: start; }
.rfq-sidebar { position: sticky; top: calc(72px + var(--space-6)); }
.rfq-steps { list-style: none; margin: var(--space-4) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-4); counter-reset: rfq-step; }
.rfq-steps li { padding-left: var(--space-8); position: relative; font-size: var(--type-small-size); color: var(--color-neutral-700); }
.rfq-steps li::before {
  counter-increment: rfq-step; content: counter(rfq-step);
  position: absolute; left: 0; top: 0; width: 22px; height: 22px; border-radius: var(--radius-full);
  background: var(--color-accent-500); color: #fff; font-size: 12px; font-weight: 700;
  display: flex; align-items: center; justify-content: center; font-family: var(--font-mono);
}
.rfq-steps li strong { display: block; color: var(--color-neutral-900); }
@media (max-width: 1023px) { .rfq-layout { grid-template-columns: 1fr; } .rfq-sidebar { position: static; } }

/* ===== Utility layout ===== */
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-10); align-items: center; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-6); }
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-6); }
@media (max-width: 1023px) { .grid-2 { grid-template-columns: 1fr; } .grid-3 { grid-template-columns: repeat(2, 1fr); } .grid-4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 639px) { .grid-3 { grid-template-columns: 1fr; } .grid-4 { grid-template-columns: 1fr; } }
.text-center { text-align: center; }
.mt-0 { margin-top: 0; }
.stack { display: flex; flex-direction: column; gap: var(--space-4); }
.cluster { display: flex; gap: var(--space-4); flex-wrap: wrap; align-items: center; }

/* ===== Real Z5 product photography (2026-08-22) =====
   The photographs are isolated on white or shot on a neutral sweep, so every
   frame uses a light ground and object-fit: contain. Never cover on the
   product itself: these tools are photographed edge-to-edge and any crop would
   cut the cutting geometry. No gradient, glow or metallic treatment is applied
   over the product — the photograph is the visual. */

.product-gallery { display: flex; flex-direction: column; gap: var(--space-4); max-width: 460px; }
.product-gallery__figure { margin: 0; }
.product-gallery__stage {
  aspect-ratio: 3 / 4; background: var(--color-neutral-0);
  border: 1px solid var(--color-neutral-300); border-radius: var(--radius-md);
  display: flex; align-items: center; justify-content: center;
  padding: var(--space-5); overflow: hidden;
}
.product-gallery__stage picture { display: block; width: 100%; height: 100%; }
.product-gallery__img { width: 100%; height: 100%; object-fit: contain; display: block; }
/* All three photographs sit in the stage. Without JavaScript the thumbnail
   anchors drive :target, so switching still works; main.js sets .is-enhanced
   and takes over with .is-shown, which also suppresses the anchor jump. */
.product-gallery__item { display: none; width: 100%; height: 100%; }
.product-gallery__item:target { display: block; }
.product-gallery__stage:not(:has(.product-gallery__item:target)) .product-gallery__item.is-shown { display: block; }
.product-gallery.is-enhanced .product-gallery__item { display: none; }
.product-gallery.is-enhanced .product-gallery__item.is-shown { display: block; }
.product-gallery__caption {
  font-family: var(--font-mono); font-size: var(--type-caption-size);
  color: var(--color-neutral-500); line-height: 1.5;
  margin-top: var(--space-3); max-width: 46ch;
}
.product-gallery__thumbs {
  list-style: none; margin: 0; padding: 0;
  display: flex; gap: var(--space-3); overflow-x: auto; scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
}
.product-gallery__thumb-item { flex: 0 0 auto; scroll-snap-align: start; }
.product-gallery__thumb {
  display: flex; align-items: center; justify-content: center;
  width: 80px; height: 80px; padding: var(--space-2);
  background: var(--color-neutral-0);
  border: 1px solid var(--color-neutral-300); border-radius: var(--radius-sm);
  transition: border-color 120ms ease;
}
/* The thumbnail <img> lives inside a <picture>, so the picture element must
   itself become the sized flex child or max-height has nothing to resolve
   against and tall images escape the 80px box. */
.product-gallery__thumb picture { display: block; width: 100%; height: 100%; }
.product-gallery__thumb img { width: 100%; height: 100%; object-fit: contain; display: block; }
.product-gallery__thumb:hover { border-color: var(--color-neutral-500); }
.product-gallery__thumb.is-active { border-color: var(--color-accent-500); border-width: 2px; padding: calc(var(--space-2) - 1px); }
.product-gallery__thumb:focus-visible { outline: 2px solid var(--color-accent-500); outline-offset: 2px; }

/* Relocated technical drawing — now a full-width section after Specifications. */
.tech-drawing-frame--section { padding: var(--space-8) var(--space-6); border-radius: var(--radius-md); }
.tech-drawing-frame--section svg { max-width: 520px; margin: 0 auto; display: block; }


/* Homepage hero photograph — replaces the previous synthetic SVG visual. */
.hero__visual-frame--photo {
  background: var(--color-neutral-100); background-image: none;
  /* 2.1:1 sits just above the photograph's own 2.07 aspect, so contain
     fills the frame's width almost exactly — the tool renders as large as it
     can without ever cropping its cutting geometry. Tighter padding than the
     old SVG frame for the same reason. The cool grey ground settles the
     slightly warm studio background against the site palette; the photograph
     itself is untouched. */
  aspect-ratio: 2.1 / 1; padding: var(--space-3);
}
.hero__visual-frame--photo picture { display: block; width: 100%; height: 100%; }
.hero__visual-img { width: 100%; height: 100%; object-fit: contain; display: block; }
.hero__visual-frame--photo .hero__visual-label { color: var(--color-neutral-500); }
@media (max-width: 1023px) { .hero__visual-frame--photo { aspect-ratio: 2 / 1; } }

/* Z5 series page banner. DEAD SINCE THE DESIGN-SYSTEM SPRINT — no page carries a
   `.series-banner` any more; the family hero panel in system.css replaced it. The
   photograph it was written for, `z5-series-band`, was withdrawn on 2026-09-17.
   Left in place rather than removed here: sweeping unused component CSS is a job
   of its own, not part of a hero correction. */
.series-banner { margin: 0; }
.series-banner__frame {
  aspect-ratio: 5 / 2; background: var(--color-neutral-100);
  border-radius: var(--radius-md); overflow: hidden;
}
.series-banner__frame picture { display: block; width: 100%; height: 100%; }
.series-banner__img { width: 100%; height: 100%; object-fit: cover; object-position: center; display: block; }
.series-banner__caption {
  font-family: var(--font-mono); font-size: var(--type-caption-size);
  color: var(--color-neutral-500); margin-top: var(--space-3);
}
@media (max-width: 639px) { .series-banner__frame { aspect-ratio: 16 / 9; } }

/* Products landing — Z5 family card carries the photograph in place of its icon. */
.family-card__frame--photo { background: var(--color-neutral-100); padding: 0; }
.family-card__frame--photo picture { display: block; width: 100%; height: 100%; }
.family-card__img { width: 100%; height: 100%; object-fit: cover; object-position: center 46%; display: block; }

@media (prefers-reduced-motion: reduce) { .product-gallery__thumb { transition: none; } }
/* Sprint 2: the primary navigation gained a seventh item (Distribution) and the
   header row stopped fitting between 1024px and 1279px - measured, not guessed:
   scripts/qa-screens.mjs reported 89-91px of horizontal overflow on every page
   at 1024px. In that band the header keeps the navigation and the quotation
   indicator, and drops the duplicate "Request a Quotation" button, which is the
   one element on the row that is repeated in the page body and the footer. */
/* Sprint 2 hid the header quotation button between 1024 and 1279px, because a
   seven-item navigation plus the button overflowed the row by 89-91px — measured by
   scripts/qa-screens.mjs, not guessed. Sprint 3 dropped "Distributors" from the
   primary navigation (see PRIMARY_NAV in scripts/lib/page-shell.mjs), and a re-run of
   the same harness reports 0 overflow at every width with the button restored. The
   rule is removed rather than kept "just in case": a hidden call to action that no
   longer needs hiding is a call to action nobody at that width can use. */

/* ---------------------------------------------------------------------------
   Sprint 3 — product-detail architecture.
   Twenty-one sections in one declared order (scripts/lib/pdp-architecture.mjs).
   These three components are what make that length navigable and what make an
   unanswered field readable as a stated gap rather than as a broken page.
   --------------------------------------------------------------------------- */

/* On-page contents. Sticky below the header on desktop so a reader deep in the
   cutting-parameters section can still jump to documentation; static on mobile,
   where a sticky bar would eat a third of the viewport. */
.pdp-index { border-block: 1px solid var(--color-neutral-300); background: var(--color-neutral-100); }
.pdp-index__list {
  list-style: none; margin: 0; padding: var(--space-3) 0;
  display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4);
  counter-reset: pdp-index;
}
.pdp-index__list li { counter-increment: pdp-index; }
.pdp-index__list a {
  font-size: var(--type-caption-size); font-family: var(--font-mono);
  color: var(--color-neutral-700); text-decoration: none;
  display: inline-block; padding: var(--space-1) 0;
}
.pdp-index__list a::before {
  content: counter(pdp-index, decimal-leading-zero) " ";
  color: var(--color-neutral-300);
}
.pdp-index__list a:hover, .pdp-index__list a:focus-visible { color: var(--color-accent-500); text-decoration: underline; }
@media (min-width: 1024px) { .pdp-index { position: sticky; top: 0; z-index: 20; } }

/* Commercial status. A definition list, not a table: six one-line answers, and
   the label/value pairing is the whole content. */
.pdp-status { margin: var(--space-4) 0 0; display: grid; gap: 0; max-width: 68ch; }
.pdp-status__row {
  display: grid; grid-template-columns: minmax(9rem, 14rem) 1fr; gap: var(--space-4);
  padding: var(--space-3) 0; border-bottom: 1px solid var(--color-neutral-300);
}
.pdp-status dt { color: var(--color-neutral-500); font-size: var(--type-small-size); margin: 0; }
.pdp-status dd { margin: 0; font-size: var(--type-small-size); color: var(--color-neutral-900); }
@media (max-width: 639px) {
  .pdp-status__row { grid-template-columns: 1fr; gap: var(--space-1); }
}

/* Documentation availability. Every document this catalogue will eventually carry,
   each with its current state — a list of five pending items says more than an
   empty downloads table, and turns into a list of links without a redesign. */
.doc-list { list-style: none; margin: var(--space-5) 0 0; padding: 0; max-width: 68ch; }
.doc-list li {
  display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-3);
  align-items: baseline; justify-content: space-between;
  padding: var(--space-3) 0; border-bottom: 1px solid var(--color-neutral-300);
  font-size: var(--type-small-size);
}

/* Active-filter chips. Each chip removes its own filter; the button beside them
   removes all of them. Both are rendered by JS and hidden when nothing is applied. */
.filter-active { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); }
.filter-active__list { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.filter-chip {
  font: inherit; font-size: var(--type-caption-size); font-family: var(--font-mono);
  display: inline-flex; align-items: center; gap: var(--space-1);
  padding: 0.35rem 0.6rem; border: 1px solid var(--color-neutral-300);
  border-radius: var(--radius-sm, 4px); background: var(--color-neutral-0);
  color: var(--color-neutral-700); cursor: pointer; min-height: 32px;
}
.filter-chip::after { content: "×"; font-size: 1rem; line-height: 1; color: var(--color-neutral-500); }
.filter-chip:hover, .filter-chip:focus-visible { border-color: var(--color-accent-500); color: var(--color-accent-500); }

/* RFQ special requirements — three disclosure groups.
   Fifteen optional inputs shown at once reads as fifteen obligations. Grouped and
   collapsed, the form asks one question ("anything special?") and expands only for
   the people who have an answer. <details> needs no JavaScript, and a collapsed
   group's inputs are still submitted — the form works with scripting disabled. */
.rfq-group { border-top: 1px solid var(--color-neutral-300); padding: var(--space-3) 0; }
.rfq-group__summary {
  cursor: pointer; list-style: none;
  font-size: var(--type-small-size); font-weight: 600; color: var(--color-neutral-900);
  padding: var(--space-2) 0; min-height: 44px; display: flex; align-items: center; gap: var(--space-2);
}
.rfq-group__summary::-webkit-details-marker { display: none; }
.rfq-group__summary::before {
  content: "+"; font-family: var(--font-mono); color: var(--color-accent-500);
  width: 1rem; text-align: center;
}
.rfq-group[open] > .rfq-group__summary::before { content: "−"; }
.rfq-group__summary:focus-visible { outline: 2px solid var(--color-accent-500); outline-offset: 2px; }
.rfq-group > .rfq-special__grid { margin-top: var(--space-2); }

/* The absent-price detail line beneath "Quoted on request". */
.fx-tier__unavailable-detail {
  margin: var(--space-2) 0 0; font-size: var(--type-caption-size); color: var(--color-neutral-500);
}

/* Touch targets.
   The filter chips and the comparison's per-column remove button are 32px tall,
   which is comfortable with a mouse and too small for a thumb. Rather than making
   every control 44px everywhere — which would bloat a dense filter row on desktop —
   they grow only where the pointer is coarse. */
@media (pointer: coarse) {
  .filter-chip, .cmp-drop { min-height: 44px; min-width: 44px; }
}

/* ===== Policy pages =====
   Privacy, cookies, terms, accessibility, shipping, returns. One column, a measured
   line length, and a visible block for what has not been decided. The absences are the
   most important thing on these pages, so they are given a panel rather than a
   parenthesis. */
.container--reading { max-width: 78ch; }

.policy h1 { margin-bottom: var(--space-4); }
.policy__intro { font-size: 1.0625rem; line-height: 1.65; color: var(--color-neutral-700); max-width: 68ch; margin: 0 0 var(--space-3); }
.policy__updated { font-family: var(--font-mono); font-size: var(--type-caption-size); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--color-neutral-500); margin: 0 0 var(--space-10); }

.policy-section { margin-bottom: var(--space-12); }
.policy-section > h2 {
  font-size: var(--type-h3-size); line-height: var(--type-h3-line);
  padding-bottom: var(--space-3); margin-bottom: var(--space-4);
  border-bottom: 1px solid var(--color-neutral-100);
}
.policy-section p { margin: 0 0 var(--space-4); max-width: 72ch; line-height: 1.65; }
.policy-section p:last-child { margin-bottom: 0; }
.policy-section code { font-family: var(--font-mono); font-size: 0.875em; background: var(--color-neutral-100); padding: 1px 5px; border-radius: var(--radius-sm); }

.policy-list { margin: 0 0 var(--space-4); padding-left: var(--space-5); max-width: 72ch; }
.policy-list li { margin-bottom: var(--space-3); line-height: 1.6; }

.policy-defs { margin: 0 0 var(--space-4); }
.policy-defs dt { font-weight: 600; color: var(--color-neutral-900); margin-top: var(--space-5); }
.policy-defs dt:first-child { margin-top: 0; }
.policy-defs dd { margin: var(--space-2) 0 0; line-height: 1.6; color: var(--color-neutral-700); }

/* The gap panel. Warning tone, not error: nothing is broken, something is undecided. */
.policy-pending {
  background: var(--color-warning-100);
  border-left: 3px solid var(--color-warning-700);
  padding: var(--space-6);
  margin-bottom: var(--space-12);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
.policy-pending__title { font-size: var(--type-h3-size); line-height: var(--type-h3-line); color: var(--color-warning-700); margin-bottom: var(--space-3); }
.policy-pending p { margin: 0 0 var(--space-4); max-width: 68ch; line-height: 1.6; }
.policy-pending__list { margin: 0 0 var(--space-4); }
.policy-pending__list dt { font-weight: 600; color: var(--color-neutral-900); margin-top: var(--space-4); }
.policy-pending__list dt:first-child { margin-top: 0; }
.policy-pending__list dd { margin: var(--space-1) 0 0; font-size: var(--type-small-size); color: var(--color-neutral-700); }
.policy-pending__foot { font-size: var(--type-small-size); color: var(--color-neutral-700); margin-bottom: 0 !important; }

.policy-table { width: 100%; margin: 0 0 var(--space-4); }
.policy-table th[scope="row"] { font-weight: 600; white-space: nowrap; }
.policy-table code { white-space: nowrap; }

/* Any table wider than the column scrolls inside its own box rather than pushing the
   page sideways. The page body must never scroll horizontally. */
.table-scroll { overflow-x: auto; margin: 0 0 var(--space-4); -webkit-overflow-scrolling: touch; }
.table-scroll > table { min-width: 640px; }

.policy-tag {
  display: inline-block; font-family: var(--font-mono); font-size: var(--type-caption-size);
  letter-spacing: var(--tracking-wide); font-weight: 600;
  padding: 1px var(--space-2); border-radius: var(--radius-sm); white-space: nowrap;
}
.policy-tag--essential { background: var(--color-accent-100); color: var(--color-accent-700); }
.policy-tag--functional { background: var(--color-neutral-100); color: var(--color-neutral-700); }
.policy-tag--analytics, .policy-tag--marketing { background: var(--color-error-100); color: var(--color-error-700); }

/* Storage inventory — one block per item, because five columns of prose in a reading
   column is one word per line, and because the same markup then works at 390px. */
.storage-list { list-style: none; margin: 0 0 var(--space-4); padding: 0; display: grid; gap: var(--space-4); }
.storage-item { border: 1px solid var(--color-neutral-300); border-radius: var(--radius-sm); padding: var(--space-5); }
.storage-item__head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); margin: 0 0 var(--space-2) !important; }
.storage-item__head code { font-size: var(--type-small-size); font-weight: 600; background: var(--color-neutral-100); }
.storage-item__purpose { margin: 0 0 var(--space-4) !important; line-height: 1.6; }
.storage-item__meta { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: var(--space-3) var(--space-5); margin: 0; padding-top: var(--space-4); border-top: 1px solid var(--color-neutral-100); }
.storage-item__meta dt { font-family: var(--font-mono); font-size: var(--type-caption-size); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--color-neutral-500); }
.storage-item__meta dd { margin: var(--space-1) 0 0; font-size: var(--type-small-size); color: var(--color-neutral-700); line-height: 1.5; }
.storage-item__meta code { font-size: 0.8125rem; }

/* ===== 404 =====
   Answered with navigation rather than an apology. The oversized numeral is decorative
   and aria-hidden; the heading carries the meaning. */
.notfound__code {
  font-family: var(--font-mono); font-weight: 600;
  font-size: clamp(3.5rem, 11vw, 7rem); line-height: 1;
  color: var(--color-neutral-100); margin: 0 0 var(--space-2); letter-spacing: -0.02em;
}
.notfound__lead { margin: var(--space-4) 0 0; max-width: 58ch; font-size: 1.0625rem; line-height: 1.65; color: var(--color-neutral-700); }
.notfound__subhead {
  margin: var(--space-12) 0 var(--space-4); font-family: var(--font-mono);
  font-size: var(--type-caption-size); line-height: var(--type-caption-line);
  letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--color-neutral-500);
}
.notfound__routes { list-style: none; margin: 0; padding: 0; max-width: 62ch; border-top: 1px solid var(--color-neutral-300); }
.notfound__routes li { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2) var(--space-5); padding: var(--space-4) 0; border-bottom: 1px solid var(--color-neutral-300); }
.notfound__routes a { font-size: 1.0625rem; font-weight: 600; color: var(--color-neutral-900); flex: 0 0 auto; min-width: 12rem; }
.notfound__routes a:hover { color: var(--color-accent-700); }
.notfound__routes span { flex: 1 1 18rem; font-size: var(--type-small-size); line-height: 1.5; color: var(--color-neutral-500); }
@media (max-width: 639px) { .notfound__routes a { min-width: 0; flex-basis: 100%; } }
