/* Gamita Pak-IT — page layout.
   industry.css is the design system and stays verbatim; this file holds the
   site's own layout, built only from its tokens. Every value here is taken
   from design/Gamita Pak-IT Website.dc.html. */

/* ── base ─────────────────────────────────────────────────────────────── */

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
}

a { color: var(--color-accent-700); text-decoration: none; }
a:hover { color: var(--color-accent-800); }
a:active { color: var(--color-accent-900); }

h1, h2, h3, h4 {
  font-family: var(--font-heading);
  font-weight: 600;
  margin: 0;
  line-height: 1.04;
  letter-spacing: -0.005em;
}

p { text-wrap: pretty; }

.page { min-height: 100vh; background: var(--color-bg); }

/* The shared page gutter: 32px, tightening to 20px on small screens. */
.pad {
  width: 100%;
  max-width: 1280px;
  margin: 0 auto;
  padding-left: 32px;
  padding-right: 32px;
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%);
  white-space: nowrap;
}

/* ── top bar ──────────────────────────────────────────────────────────── */

.topbar {
  background: var(--color-accent-900);
  color: var(--color-neutral-100);
  font-size: 12.5px;
  letter-spacing: 0.04em;
}

.topbar-inner {
  padding-top: 8px;
  padding-bottom: 8px;
  display: flex;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

.topbar-address { opacity: 0.75; }

.topbar-contacts { display: flex; gap: 24px; }

.topbar a { color: var(--color-accent-200); }
.topbar a:hover { color: var(--color-neutral-100); }
.topbar a:active { color: var(--color-accent-300); }

/* ── header ───────────────────────────────────────────────────────────── */

.site-header {
  display: block;
  position: sticky;
  top: 0;
  z-index: 60;
  background: var(--color-bg);
  border-bottom: 1px solid var(--color-divider);
  padding: 0;
  gap: 0;
}

.site-header-inner {
  padding-top: 14px;
  padding-bottom: 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 32px;
}

.brand {
  display: flex;
  align-items: baseline;
  gap: 9px;
  color: var(--color-text);
  margin-right: 0;
  font-size: inherit;
}

.brand:hover, .brand:active { color: var(--color-text); }
.brand-logo { max-width: 230px; max-height: 38px; object-fit: contain; }

.brand-name {
  font-family: var(--font-heading);
  font-size: 25px;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.brand-legal {
  font-size: 10.5px;
  letter-spacing: 0.18em;
  color: var(--color-neutral-600);
  text-transform: uppercase;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: 28px;
  font-size: 14px;
  letter-spacing: 0.02em;
}

.site-nav a.nav-link {
  color: var(--color-neutral-800);
  padding: 4px 0;
  border-bottom: 2px solid transparent;
  font-size: 14px;
}

.site-nav a.nav-link:hover,
.site-nav a.nav-link[aria-current="page"] {
  color: var(--color-accent-700);
  border-bottom-color: var(--color-accent);
}

.site-nav a.nav-link:active { color: var(--color-accent-800); }

.search { position: relative; }
.search .input { width: 160px; font-size: 13.5px; padding: 8px 12px; }

.btn-quote {
  position: relative;
  font-size: 13px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  background: none;
  border: 1px solid var(--color-divider);
  cursor: pointer;
  color: var(--color-neutral-800);
  padding: 0;
}

.nav-toggle:hover { border-color: var(--color-accent); color: var(--color-accent-700); }
.nav-toggle:active { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.nav-toggle .icon-close { display: none; }
.nav-toggle[aria-expanded="true"] .icon-close { display: block; }
.nav-toggle[aria-expanded="true"] .icon-open { display: none; }

/* ── mobile menu ──────────────────────────────────────────────────────── */

.mobile-menu {
  border-top: 1px solid var(--color-divider);
  background: var(--color-bg);
}

.mobile-menu[hidden] { display: none; }

.mobile-menu-inner {
  padding-top: 16px;
  padding-bottom: 20px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.mobile-menu .search { margin-bottom: 10px; }
.mobile-menu .search .input { width: 100%; font-size: 15px; padding: 11px 14px; }

.mobile-menu a.nav-link {
  color: var(--color-neutral-800);
  font-family: var(--font-heading);
  font-size: 22px;
  padding: 10px 0;
  border-bottom: 1px solid var(--color-divider);
}

.mobile-menu a.nav-link:hover,
.mobile-menu a.nav-link[aria-current="page"] { color: var(--color-accent-700); }
.mobile-menu a.nav-link:active { color: var(--color-accent-800); }

.mobile-menu .btn-quote { margin-top: 16px; justify-content: center; }

/* ── footer ───────────────────────────────────────────────────────────── */

.site-footer {
  background: var(--color-accent-900);
  color: color-mix(in srgb, var(--color-neutral-100) 78%, transparent);
}

.footer-grid {
  padding-top: 64px;
  padding-bottom: 28px;
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: 48px;
}

.footer-brand {
  font-family: var(--font-heading);
  font-size: 24px;
  font-weight: 700;
  color: var(--color-neutral-100);
  margin-bottom: 14px;
}

.footer-blurb {
  font-size: 14.5px;
  line-height: 1.6;
  margin: 0 0 18px;
  max-width: 34ch;
}

.footer-address { font-size: 14px; line-height: 1.6; }
.footer-address a { color: var(--color-accent-300); }
.footer-address a:hover { color: var(--color-neutral-100); }

.footer-heading {
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-accent-300);
  margin-bottom: 14px;
}

.footer-list {
  display: flex;
  flex-direction: column;
  gap: 9px;
  font-size: 14.5px;
}

.footer-list a { color: inherit; }
.footer-list a:hover { color: var(--color-neutral-100); }
.footer-list a:active { color: var(--color-accent-300); }

.footer-fine { padding-bottom: 32px; }

.footer-fine-inner {
  border-top: 1px solid color-mix(in srgb, var(--color-neutral-100) 16%, transparent);
  padding-top: 20px;
  display: flex;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  font-size: 13px;
  opacity: 0.8;
}

.footer-fine-right { display: flex; gap: 18px; }
.footer-fine a { color: var(--color-accent-300); }
.footer-fine a:hover { color: var(--color-neutral-100); }

/* ── WhatsApp button ──────────────────────────────────────────────────── */

/* #25D366 / #1DA851 are the two deliberate non-token literals in the system;
   the pressed state dims the same green rather than introducing a third. */
.whatsapp {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 80;
  width: 56px;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #25D366;
  color: #fff;
  border-radius: 50%;
  box-shadow: var(--shadow-lg);
  transition: bottom 0.2s;
}

.whatsapp:hover { background: #1DA851; color: #fff; }
.whatsapp:active { background: #1DA851; filter: brightness(0.92); }

/* Lifted clear of the compare bar while it is showing. */
.has-compare-bar .whatsapp { bottom: 96px; }

/* ── compare bar ──────────────────────────────────────────────────────── */

.compare-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 70;
  background: var(--color-accent-900);
  color: var(--color-neutral-100);
  box-shadow: var(--shadow-lg);
}

.compare-bar-inner {
  padding-top: 14px;
  padding-bottom: 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
}

.compare-bar-count {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}

.compare-bar-count strong {
  font-family: var(--font-heading);
  font-size: 19px;
  font-weight: 600;
}

.compare-bar-note { font-size: 13px; color: var(--color-accent-300); }

.compare-bar-actions { display: flex; align-items: center; gap: 18px; }

.compare-bar-clear {
  font-size: 12.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-accent-300);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  font-family: var(--font-body);
}

.compare-bar-clear:hover { color: var(--color-neutral-100); }
.compare-bar-clear:active { color: var(--color-accent-400); }

/* ── image slots ──────────────────────────────────────────────────────── */

/* Every figure is a positioned box; the slot fills it, either with the
   photograph or with the dashed empty-state frame. */
.slot-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.slot-img-cover { object-fit: cover; object-position: center; }
.slot-img-contain { object-fit: contain; object-position: center; }

/* Photographs are shown in their own colours — the client's decision, against
   both the prototype and README. `industry.css` tints everything inside
   `.duotone` with an accent overlay in `::after`; that file is copied verbatim
   and must never be edited, so the overlay is switched off here instead.

   The wrappers stay in the markup. `.duotone` is also `position: relative;
   overflow: hidden`, which is what clips every photograph to its frame —
   stripping the class from the templates would drop the tint and the cropping
   together. This is the whole of the change, and putting the line back is the
   whole of the way to undo it.

   This replaces an earlier rule that suppressed the overlay only while a slot
   was empty. That case is covered by the blanket rule now. */
.duotone::after { content: none; }

.slot-empty {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 12px;
  background: var(--color-neutral-200);
  border: 1px dashed var(--color-neutral-400);
}

.slot-empty-label {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-neutral-600);
  text-align: center;
  line-height: 1.35;
}

/* ── page scaffolding ─────────────────────────────────────────────────── */

.page-body { padding-top: 44px; padding-bottom: 88px; }

.page-title {
  font-size: clamp(34px, 4.4vw, 52px);
  line-height: 1;
  margin-bottom: 14px;
}

.page-lede {
  font-size: 17px;
  line-height: 1.6;
  color: var(--color-neutral-700);
  max-width: 62ch;
  margin: 0 0 40px;
}

.section { padding-top: 84px; }
.section:last-of-type { padding-bottom: 84px; }

.section-head {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 56px;
  align-items: end;
  margin-bottom: 44px;
}

.section-kicker {
  font-size: 11.5px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--color-accent-700);
  margin-bottom: 14px;
}

.section-kicker-dark { color: var(--color-accent-300); }

.section-title { font-size: clamp(32px, 4vw, 46px); line-height: 1; }

.section-intro {
  font-size: 16px;
  line-height: 1.6;
  color: var(--color-neutral-700);
  margin: 0;
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(268px, 1fr));
  gap: 20px;
}

.card-grid-narrow { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }

.breadcrumbs {
  font-size: 13px;
  color: var(--color-neutral-600);
  margin-bottom: 26px;
}

.breadcrumb-sep { opacity: 0.5; margin: 0 4px; }

/* ── hero ─────────────────────────────────────────────────────────────── */

.hero {
  position: relative;
  height: clamp(540px, 74vh, 680px);
  overflow: hidden;
  background: var(--color-accent-900);
}

.hero-layer-bg { position: absolute; inset: -8% -2% -14% -2%; }
.hero-bg-frame { position: relative; width: 100%; height: 100%; }

.hero-scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--color-accent-900) 80%, transparent) 0%,
    color-mix(in srgb, var(--color-accent-900) 52%, transparent) 46%,
    color-mix(in srgb, var(--color-accent-900) 14%, transparent) 100%);
}

.hero-grid {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(color-mix(in srgb, #ffffff 7%, transparent) 1px, transparent 1px),
    linear-gradient(90deg, color-mix(in srgb, #ffffff 7%, transparent) 1px, transparent 1px);
  background-size: 64px 64px;
}

.hero-layer-cutout {
  position: absolute;
  right: 2%;
  bottom: 0;
  width: 46%;
  height: 96%;
  pointer-events: none;
}

/* `contain` letterboxes whatever does not match the frame's proportions, and
   centred it splits that space top and bottom — so a person wider than the
   frame stands in mid-air before a single pixel has scrolled. Anchored to the
   bottom the figure always stands on the hero's edge, and the spare space goes
   above their head where nothing shows it. */
.hero-layer-cutout .slot-img-contain { object-position: bottom; }

.hero-body {
  position: relative;
  padding-top: 96px;
  height: 100%;
}

.hero-copy { max-width: 620px; color: var(--color-neutral-100); }

.hero-kicker {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 11.5px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--color-accent-300);
  margin-bottom: 22px;
}

.hero-kicker-rule { width: 28px; height: 1px; background: var(--color-accent-400); }

.hero-title {
  font-size: clamp(38px, 5.4vw, 70px);
  line-height: 0.96;
  letter-spacing: -0.015em;
  margin-bottom: 22px;
}

.hero-lede {
  font-size: 18px;
  line-height: 1.55;
  color: color-mix(in srgb, var(--color-neutral-100) 82%, transparent);
  margin: 0 0 34px;
}

.hero-actions { display: flex; gap: 14px; flex-wrap: wrap; }

.btn-hero {
  position: relative;
  font-size: 14px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 13px 24px;
}

.hero .btn-hero { padding: 14px 26px; }

/* Secondary action on an accent-900 ground, where .btn-secondary's divider
   border would disappear. */
.btn-on-dark {
  color: var(--color-neutral-100);
  border: 1px solid color-mix(in srgb, var(--color-neutral-100) 45%, transparent);
  background: transparent;
}

.btn-on-dark:hover {
  color: var(--color-neutral-100);
  background: color-mix(in srgb, var(--color-neutral-100) 10%, transparent);
}

.btn-on-dark:active { background: color-mix(in srgb, var(--color-neutral-100) 18%, transparent); }

.btn-small { font-size: 13px; letter-spacing: 0.06em; text-transform: uppercase; }

/* ── brand strip ──────────────────────────────────────────────────────── */

.brand-strip {
  border-bottom: 1px solid var(--color-divider);
  background: var(--color-neutral-100);
}

.brand-strip-inner {
  padding-top: 22px;
  padding-bottom: 22px;
  display: flex;
  align-items: center;
  gap: 32px;
}

.brand-strip-label {
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-neutral-600);
  flex: none;
}

.brand-marquee {
  overflow-x: auto;
  scrollbar-width: none;
  flex: 1;
  min-width: 0;
}

.brand-marquee::-webkit-scrollbar { display: none; }

.brand-marquee-track {
  display: flex;
  gap: 64px;
  align-items: center;
  width: max-content;
  padding-right: 64px;
}

/* Named apart from the header's .brand-name / .brand-logo on purpose: those
   carry the wordmark's own sizing, and an unscoped max-height: 38px would
   squash the marquee's 42px logo slots. */
.marquee-brand {
  font-family: var(--font-heading);
  font-size: 20px;
  letter-spacing: 0.02em;
  color: var(--color-neutral-700);
  white-space: nowrap;
  text-decoration: none;
  transition: color 0.15s ease;
}

.marquee-brand:hover { color: var(--color-accent-700); }
.marquee-brand:active { color: var(--color-accent-900); }

.marquee-logo { position: relative; width: 130px; height: 42px; flex: none; }

/* The logo slot is the link, so the feedback has to be the image itself —
   there is no text to recolour. */
.marquee-logo img { transition: opacity 0.15s ease; }
.marquee-logo:hover img { opacity: 0.7; }
.marquee-logo:active img { opacity: 0.55; }

.marquee-brand:focus-visible,
.marquee-logo:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* ── category card ────────────────────────────────────────────────────── */

/* No overflow:hidden here: the four registration marks sit 6px outside the
   border and a clipping card would swallow them. The image is already clipped
   by its own .duotone wrapper. */
.category-card,
.product-card {
  position: relative;
  padding: 0;
  color: var(--color-text);
  gap: 0;
}

.category-card:hover, .product-card:hover { border-color: var(--color-accent); }
.category-card:active, .product-card:active { border-color: var(--color-accent-700); }
.category-card:hover { color: var(--color-text); }

/* The category card is an <article>, not a link — it holds a link per
   sub-category and anchors cannot nest. This is what keeps the whole card
   clickable anyway: the title's link stretches an invisible ::after across it.
   The card's own :hover above still fires, because that is hover on the
   container and has nothing to do with which element is the anchor. */
.category-card-link {
  color: inherit;
  text-decoration: none;
}

.category-card-link::after {
  content: "";
  position: absolute;
  inset: 0;
  /* Below the tags, above everything else in the card. */
  z-index: 1;
}

/* Keyboard focus has to show on the card, not on the few words of the title:
   the ::after is what a click lands on, so it is what the ring belongs to. */
.category-card-link:focus-visible { outline: none; }

.category-card-link:focus-visible::after {
  outline: 2px solid var(--color-accent);
  outline-offset: -2px;
}

/* Above the stretched overlay, or these would be unclickable — the whole point
   of raising them. Each is a real link to that sub-category's listing. */
.category-card-tags { position: relative; z-index: 2; }

.category-card-tag {
  text-decoration: none;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.category-card-tag:hover {
  background: var(--color-accent);
  color: #fff;
}

.category-card-tag:active {
  background: var(--color-accent-700);
  border-color: var(--color-accent-700);
}

.category-card-tag:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.category-card-figure,
.product-card-figure {
  display: block;
  position: relative;
  height: 186px;
  border-bottom: 1px solid var(--color-divider);
}

.category-card-body { display: block; padding: 22px 24px 26px; }

.category-card-kicker {
  display: block;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-neutral-600);
  margin-bottom: 9px;
}

.category-card-title { font-size: 26px; margin: 0 0 10px; }

.category-card-desc {
  display: block;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--color-neutral-700);
  margin-bottom: 16px;
}

/* Homepage only. That band is a teaser above the real index, so each
   description is cut to two lines with an ellipsis; /products keeps the whole
   sentence, because there the description IS the content of the page.

   It also evens the cards up. The five descriptions run three and four lines,
   which left every card's tag row at a different height across the grid.

   A visual crop, not a shortened string: the full text stays in the markup, so
   search engines and screen readers still get all of it. Doing this in PHP
   would take the words out of the page, and this is a site built around being
   read by crawlers.

   -webkit-box is the only display mode line-clamp works in — the prefixed
   spelling is the interoperable one and is what every current browser
   implements; the unprefixed property is there for when that finishes
   standardising. overflow: hidden is required for the clamp, and this is a
   <span> inside the card rather than the card itself, so it cannot clip the
   corner registration marks. */
.home-category-grid .category-card-desc {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}

/* /industries: five lines, against two on the homepage band. A card here IS the
   index — it is the only place an industry is described before you choose one —
   so it gets room to be read, where the homepage band is a glance on the way
   past. Both stop short of the whole thing, and the industry's own page is
   where it runs in full.

   Same crop-don't-shorten rule as the others: the text stays whole in the
   markup, and the cards in a row end up the same height whatever was written. */
.industries-grid .category-card-desc {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 5;
  line-clamp: 5;
  overflow: hidden;
}

.category-card-tags { display: flex; flex-wrap: wrap; gap: 6px; }
.category-card-tags .tag { font-size: 11.5px; }

/* ── product card ─────────────────────────────────────────────────────── */

.product-card-figure { height: 180px; }
.product-card-link { display: block; color: var(--color-text); }
.product-card-link:hover, .product-card-link:active { color: var(--color-text); }
.product-card-body { display: block; padding: 20px 22px 24px; }

.product-card-code {
  display: block;
  font-size: 11px;
  letter-spacing: 0.14em;
  color: var(--color-neutral-600);
  margin-bottom: 8px;
}

.product-card-title { font-size: 22px; margin: 0 0 9px; }

.product-card-blurb {
  display: block;
  font-size: 14px;
  line-height: 1.5;
  color: var(--color-neutral-700);
  margin-bottom: 14px;
}

.product-card-tag { font-size: 11px; }

.compare-toggle { position: absolute; top: 10px; right: 10px; z-index: 5; }

.compare-toggle-btn {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 5px 10px;
  cursor: pointer;
  border: 1px solid var(--color-divider);
  background: var(--color-bg);
  color: var(--color-neutral-700);
}

.compare-toggle-btn:hover { border-color: var(--color-accent); color: var(--color-accent-700); }
.compare-toggle-btn:active { background: var(--color-accent-100); }

.compare-toggle-btn.is-selected {
  border-color: var(--color-accent);
  background: var(--color-accent);
  color: var(--color-neutral-100);
}

.compare-toggle-btn.is-selected:hover { background: var(--color-accent-600); color: var(--color-neutral-100); }
.compare-toggle-btn.is-selected:active { background: var(--color-accent-700); }

/* ── industry selector ────────────────────────────────────────────────── */

.industry-selector {
  /* One source of truth for the column width: the grid track below and the
     positioned tab list both read it. */
  --industry-tabs-width: 300px;

  display: grid;
  grid-template-columns: var(--industry-tabs-width) 1fr;
  border: 1px solid var(--color-divider);
  /* The containing block for the tab list below. */
  position: relative;
}

/* The tab list is positioned into its grid area rather than laid out in it,
   which takes it out of the row-height calculation entirely. The section is
   then always exactly as tall as the open panel, and the list scrolls inside
   that height when there are more industries than fit.

   Six industries need 372pt of tabs against a 422pt panel, so today the list
   has room to spare and no scrollbar appears. The seventh would have stretched
   the whole section taller — and every one after it more so — which is the
   thing worth preventing: the panel beside it is the designed size, not a
   consequence of how many industries the client happens to sell.

   Offsets and an explicit width, not `inset: 0` against the grid area. An
   absolutely positioned grid child only gets its grid area as containing block
   when its placement is definite in that axis, and `grid-row: 1 / -1` is not:
   `-1` counts back through the EXPLICIT rows, of which this grid has none. The
   placement falls back to auto, the containing block becomes the whole grid
   container, and the list stretches across the panel. */
.industry-tabs {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: var(--industry-tabs-width);
  overflow-y: auto;
  /* No `scrollbar-gutter: stable` here. It was tried, to stop tab text shifting
     when a scrollbar eventually appears, and it reserves that width whether or
     not one is showing — 15px of permanent empty strip between every tab and
     the divider, in the six-industry state the section is actually in. A
     one-off shift on the day a seventh industry is added is the cheaper of the
     two, and on macOS overlay scrollbars mean there is no shift at all. */
  border-right: 1px solid var(--color-divider);
}

/* A hairline scrollbar rather than the browser's default slab, which at 15px
   is wider than the rules it sits beside and reads as a piece of furniture the
   design does not have. Square, neutral, no track — the same restraint as the
   rest of the chrome.

   The two engines are mutually exclusive, and the order matters. Chrome 121+
   supports the standard `scrollbar-width`, and setting it to anything but
   `auto` makes Chrome IGNORE `::-webkit-scrollbar` completely — so declaring
   both gave `thin`, which is 11px, and silently discarded the 6px rule.

   The webkit pseudo-elements are therefore the default, and the standard
   properties apply only where those pseudo-elements do not exist, which is
   Firefox. `scrollbar-width` takes no length, so `thin` is as fine as Firefox
   goes; Chrome, Safari and Edge get the 4px.

   4px is the floor worth using. Thinner still is draggable only by accident —
   though the wheel, the trackpad and a keyboard all scroll this list without
   touching the bar, so the bar is mostly an indicator that there is more.

   Neither makes a scrollbar appear that was not going to — `overflow-y: auto`
   still decides that. They only change how it looks when it does. */
.industry-tabs::-webkit-scrollbar { width: 4px; }
.industry-tabs::-webkit-scrollbar-track { background: transparent; }
.industry-tabs::-webkit-scrollbar-thumb { background: var(--color-neutral-400); border-radius: 0; }
.industry-tabs::-webkit-scrollbar-thumb:hover { background: var(--color-neutral-500); }

@supports not selector(::-webkit-scrollbar) {
  .industry-tabs {
    scrollbar-width: thin;
    scrollbar-color: var(--color-neutral-400) transparent;
  }
}

.industry-tab {
  display: block;
  width: 100%;
  text-align: left;
  padding: 16px 20px;
  border-bottom: 1px solid var(--color-divider);
  font-family: var(--font-heading);
  font-size: 19px;
  letter-spacing: 0.01em;
  background: transparent;
  color: var(--color-neutral-800);
}

.industry-tab:hover { background: var(--color-accent-100); color: var(--color-accent-800); }
.industry-tab:active { background: var(--color-accent-200); }
.industry-tab.is-active { background: var(--color-accent); color: var(--color-neutral-100); }
.industry-tab.is-active:hover { background: var(--color-accent-600); color: var(--color-neutral-100); }

.industry-panel {
  grid-column: 2;
  grid-row: 1;
  padding: 36px 40px;
  display: grid;
  grid-template-columns: 1fr 300px;
  gap: 40px;
}

.industry-panel[hidden] { display: none; }

.industry-panel-title { font-size: 32px; margin-bottom: 12px; }

/* Three lines on the homepage, the whole thing on /industries/{id}. Both print
   the same `blurb`, so the panel is a preview and the industry's own page is
   where it is read — which is what the button under it is for.

   A visual crop, not a shortened string: the full sentence stays in the markup
   for search engines and screen readers, and nothing has to decide where to cut
   a sentence. It also evens the panels up — they share one container whose
   height belongs to the tallest, so one long introduction used to set the
   height for all seven.

   -webkit-box is the only display mode line-clamp works in; the prefixed
   spelling is what every current browser implements, and the unprefixed one is
   there for when that finishes standardising. */
.industry-panel-blurb {
  font-size: 15.5px;
  line-height: 1.6;
  color: var(--color-neutral-700);
  margin: 0 0 24px;
  max-width: 52ch;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
}

.industry-panel-label {
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-neutral-600);
  margin-bottom: 12px;
}

.industry-needs {
  list-style: none;
  margin: 0 0 26px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 9px;
}

.industry-needs li {
  position: relative;
  padding-left: 16px;
  font-size: 15px;
  color: var(--color-neutral-800);
}

.industry-needs li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 5px;
  height: 5px;
  background: var(--color-accent);
}

.industry-panel-figure { position: relative; min-height: 260px; }

/* ── consumables band ─────────────────────────────────────────────────── */

.consumables-band {
  margin-top: 84px;
  background: var(--color-accent-900);
  color: var(--color-neutral-100);
}

.consumables-band-inner {
  padding-top: 76px;
  padding-bottom: 76px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 64px;
  align-items: center;
}

.consumables-band-title { margin-bottom: 18px; }

.consumables-band-body {
  font-size: 16.5px;
  line-height: 1.6;
  color: color-mix(in srgb, var(--color-neutral-100) 80%, transparent);
  margin: 0 0 30px;
  max-width: 50ch;
}

.stat-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: color-mix(in srgb, var(--color-neutral-100) 18%, transparent);
}

.stat { background: var(--color-accent-900); padding: 28px 26px; }

.stat-value {
  font-family: var(--font-heading);
  font-size: 44px;
  line-height: 1;
  color: var(--color-accent-300);
}

.stat-label {
  font-size: 13.5px;
  line-height: 1.45;
  color: color-mix(in srgb, var(--color-neutral-100) 70%, transparent);
  margin-top: 8px;
}

/* ── support cards ────────────────────────────────────────────────────── */

.service-card { padding: 26px 24px 28px; position: relative; gap: 0; }

.service-num {
  font-family: var(--font-heading);
  font-size: 15px;
  color: var(--color-accent-700);
  letter-spacing: 0.08em;
  margin-bottom: 16px;
}

.service-title { font-size: 22px; margin-bottom: 10px; }
.service-body { font-size: 14.5px; line-height: 1.55; color: var(--color-neutral-700); margin: 0; }

/* ── closing CTA ──────────────────────────────────────────────────────── */

.closing-cta { border-top: 1px solid var(--color-divider); }

.closing-cta-inner {
  padding-top: 76px;
  padding-bottom: 76px;
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: 72px;
  align-items: center;
}

.closing-cta-title { font-size: clamp(32px, 3.8vw, 44px); line-height: 1; margin-bottom: 16px; }

.closing-cta-body {
  font-size: 16.5px;
  line-height: 1.6;
  color: var(--color-neutral-700);
  margin: 0 0 28px;
  max-width: 48ch;
}

.closing-cta-figure { position: relative; height: 300px; }

/* ── category listing ─────────────────────────────────────────────────── */

.listing {
  display: grid;
  grid-template-columns: 250px 1fr;
  gap: 44px;
  align-items: start;
}

.listing-sidebar { position: sticky; top: 96px; }

.listing-sidebar-heading {
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-neutral-600);
  margin-bottom: 14px;
}

.listing-nav-group { border-top: 1px solid var(--color-divider); padding: 12px 0; }

.listing-nav-category {
  display: block;
  font-family: var(--font-heading);
  font-size: 19px;
  color: var(--color-neutral-800);
}

.listing-nav-category:hover { color: var(--color-accent-700); }
.listing-nav-category.is-active { color: var(--color-accent-700); }

.listing-nav-subs {
  display: flex;
  flex-direction: column;
  gap: 7px;
  margin-top: 10px;
  padding-left: 12px;
  border-left: 1px solid var(--color-accent-300);
}

.listing-nav-sub { font-size: 14px; color: var(--color-neutral-600); }
.listing-nav-sub:hover { color: var(--color-accent-700); }
.listing-nav-sub.is-active { color: var(--color-accent-700); }

.listing-meta {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  border-bottom: 1px solid var(--color-divider);
  padding-bottom: 12px;
  margin-bottom: 24px;
  font-size: 14px;
  color: var(--color-neutral-700);
  gap: 16px;
  flex-wrap: wrap;
}

.listing-meta-sub { font-size: 12.5px; color: var(--color-neutral-600); }

/* ── product detail ───────────────────────────────────────────────────── */

.product-top {
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  gap: 56px;
  align-items: start;
  margin-bottom: 72px;
}

.product-hero-figure { position: relative; height: 420px; margin-bottom: 14px; }

.product-thumbs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 14px;
}

.product-thumb { position: relative; height: 112px; }

.product-kicker {
  font-size: 11.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-accent-700);
  margin-bottom: 12px;
}

.product-title { font-size: clamp(32px, 4.4vw, 48px); line-height: 0.98; margin-bottom: 8px; }

.product-model {
  font-size: 14px;
  letter-spacing: 0.1em;
  color: var(--color-neutral-600);
  margin-bottom: 22px;
}

.product-detail { font-size: 17px; line-height: 1.6; color: var(--color-neutral-800); margin: 0 0 28px; }

/* What RichText emits. The block is a <div> on the product page and still a
   bare <p> on the consumable page, so the spacing lives on the children and
   both keep working.

   :last-child rather than a margin on the container alone: the container's own
   28px is the gap to whatever follows, and a trailing paragraph margin would
   add to it. */
.product-detail > p { margin: 0 0 14px; }
.product-detail > p:last-child { margin-bottom: 0; }

/* A sub-heading inside the description, one level only. h2 because the
   description sits directly under the product's h1 and skipping to h3 would
   leave a hole in the outline; the size is what keeps it from competing with
   the section headings further down the page. */
.rt-heading {
  font-family: var(--font-heading);
  font-size: 15px;
  font-weight: var(--font-heading-weight);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-neutral-700);
  margin: 22px 0 10px;
}

.product-detail > .rt-heading:first-child { margin-top: 0; }

.rt-list { margin: 0 0 14px; padding-left: 20px; list-style: none; }
.rt-list:last-child { margin-bottom: 0; }

.rt-list li { position: relative; margin-bottom: 6px; }

/* Drawn rather than a list-style marker: the accent hyphen matches the tags
   and spec rows elsewhere, and a real bullet is heavier than anything else on
   this page. */
.rt-list li::before {
  content: "";
  position: absolute;
  left: -20px;
  top: 0.68em;
  width: 9px;
  height: 1px;
  background: var(--color-accent);
}

.product-detail strong { font-weight: 700; color: var(--color-text); }
.product-detail em { font-style: italic; }

.product-actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: 34px;
}

.product-actions .btn-hero { font-size: 13.5px; }
.product-compare-form { display: contents; }

.product-spec-title {
  font-size: 15px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-neutral-700);
  margin-bottom: 12px;
}

.product-specs { font-size: 14.5px; }
.product-spec-key { color: var(--color-neutral-600); width: 44%; }
.product-spec-value { font-weight: 500; }

/* A machine sold as a family carries a value column per model, and six of them
   will not fit a phone. The table scrolls inside its own box rather than
   pushing the page sideways — a table cannot shrink below its own content, so
   the wrapper is the only thing that can give. `overflow-x`, never `overflow`:
   the surrounding card's corner marks sit outside its edges and `hidden` would
   clip them. */
.product-specs-scroll {
  overflow-x: auto;
  max-width: 100%;
}

/* Once there are named columns the name column stops being 44% of the table —
   with four models that leaves the figures nothing. */
.product-specs thead ~ tbody .product-spec-key { width: auto; white-space: nowrap; }

.product-specs thead th {
  font-family: var(--font-heading);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-neutral-600);
  text-align: left;
  white-space: nowrap;
}

/* Above the specification names. Deliberately empty: the names need no heading
   and inventing one would put a word on screen that no content key owns. */
.product-spec-corner { border-bottom: 1px solid var(--color-divider); }

.product-section { border-top: 1px solid var(--color-divider); padding-top: 44px; margin-top: 56px; }
.product-section:first-of-type { margin-top: 0; }

.product-section-title { font-size: 36px; margin-bottom: 26px; }

.product-section-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 20px;
  flex-wrap: wrap;
}

.product-section-head .product-section-title { margin-bottom: 0; }

.product-section-more {
  font-size: 13px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-accent-700);
}

.product-section-head + .card-grid { margin-top: 26px; }

.consumable-card { padding: 22px 22px 24px; position: relative; gap: 0; }
.consumable-figure { position: relative; height: 88px; margin-bottom: 14px; }

.consumable-code {
  font-size: 11px;
  letter-spacing: 0.14em;
  color: var(--color-neutral-600);
  margin-bottom: 8px;
}

.consumable-name { font-size: 20px; margin-bottom: 8px; }
.consumable-note { font-size: 13.5px; line-height: 1.5; color: var(--color-neutral-700); margin: 0; }

/* ── consumables as pages of their own ────────────────────────────────── */

/* The same card as on a product page, made a link for the listing. Each part
   is its own <span> inside the anchor, so the block stays valid HTML. */
.consumable-card-link { display: block; color: var(--color-text); text-decoration: none; }
/* These are <span>s inside the anchor, so they need making block explicitly —
   `.duotone` sets position and overflow but leaves display alone, and an
   inline figure collapses its 88px height under the code and the name. */
.consumable-card-link .consumable-figure,
.consumable-card-link .consumable-code,
.consumable-card-link .consumable-note { display: block; }
.consumable-card-link:hover { border-color: var(--color-accent); }
.consumable-card-link:active { border-color: var(--color-accent-700); }
.consumable-card-link:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* The detail page's figure sits beside the copy, like a product's. */
.consumable-detail {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 56px;
  align-items: start;
  margin-bottom: 56px;
}

.consumable-detail-figure { position: relative; aspect-ratio: 4 / 3; }

/* The pointer to the materials from the product index. Full width under the
   category grid — it is a different kind of thing, not a sixth category. */
.consumables-promo {
  display: flex;
  /* `.card` sets flex-direction: column, so this has to say row explicitly or
     align-items: center centres the copy instead of aligning the arrow. */
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: 32px;
  margin-top: 28px;
  padding: 28px 30px;
  color: var(--color-text);
  text-decoration: none;
}

.consumables-promo:hover { border-color: var(--color-accent); }
.consumables-promo:active { border-color: var(--color-accent-700); }
.consumables-promo:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }


.consumables-promo-title { font-size: clamp(24px, 3vw, 32px); margin-bottom: 10px; }
.consumables-promo-body { display: block; max-width: 62ch; color: var(--color-neutral-700); }
.consumables-promo-go { font-size: 26px; color: var(--color-accent-700); flex: none; }

@media (max-width: 760px) {
  .consumable-detail { grid-template-columns: 1fr; gap: 28px; }
  .consumables-promo { flex-direction: column; align-items: flex-start; gap: 16px; }
}

.media-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 40px;
  align-items: start;
}

.media-grid-single { grid-template-columns: 1fr; max-width: 720px; }

.media-label {
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-neutral-600);
  margin-bottom: 12px;
}

.media-video { position: relative; height: 280px; }

.media-play {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 64px;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, var(--color-accent-900) 78%, transparent);
  color: var(--color-neutral-100);
  pointer-events: none;
}

.download-list { display: flex; flex-direction: column; }

.download-row {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 16px 4px;
  border-top: 1px solid var(--color-divider);
  color: var(--color-text);
}

.download-icon {
  width: 40px;
  height: 40px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--color-divider);
  color: var(--color-accent-700);
}

.download-name { display: block; font-family: var(--font-heading); font-size: 19px; }
.download-meta { display: block; font-size: 13px; color: var(--color-neutral-600); }
.download-note { font-size: 12.5px; color: var(--color-neutral-600); margin: 14px 0 0; }

/* ── industries ───────────────────────────────────────────────────────── */

.industry-card-figure {
  display: block;
  position: relative;
  height: 170px;
  border-bottom: 1px solid var(--color-divider);
}

.industry-card-cta {
  display: block;
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-accent-700);
}

.industry-hero { background: var(--color-accent-900); color: var(--color-neutral-100); }
.industry-hero-inner { padding-top: 56px; padding-bottom: 64px; }
.industry-hero .breadcrumbs { color: var(--color-accent-300); }
.industry-hero .breadcrumbs a { color: var(--color-accent-300); }
.industry-hero .breadcrumbs a:hover { color: var(--color-neutral-100); }

.industry-hero-title {
  font-size: clamp(36px, 5.2vw, 60px);
  line-height: 0.98;
  max-width: 16ch;
  margin-bottom: 20px;
}

.industry-hero-blurb {
  font-size: 18px;
  line-height: 1.55;
  color: color-mix(in srgb, var(--color-neutral-100) 80%, transparent);
  max-width: 60ch;
  margin: 0;
}

.industry-body { padding-top: 64px; }

.industry-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 56px;
  margin-bottom: 56px;
}

.industry-section-title { font-size: 34px; margin-bottom: 24px; }

/* ── brand page ───────────────────────────────────────────────────────── */

/* The logo sits beside the name rather than above it, so a brand with no logo
   loses the column and the text simply fills the row — no gap to explain. */
.brand-hero-inner {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 48px;
  align-items: center;
}

.brand-hero-text { min-width: 0; }

/* Clears the "other brands" row of the cards' bottom registration marks, which
   sit 6px outside the border — the same 56px the industry page uses. */
.brand-machines { margin-bottom: 56px; }

.brand-hero-logo {
  width: 220px;
  height: 120px;
  padding: 20px;
  flex: none;
  background: var(--color-neutral-100);
}

.brand-hero-logo .slot-img { width: 100%; height: 100%; }

@media (max-width: 760px) {
  .brand-hero-inner { grid-template-columns: 1fr; gap: 28px; }
  .brand-hero-logo { width: 180px; height: 100px; }
}
.industry-needs-large li { font-size: 16px; line-height: 1.5; padding-left: 18px; }
.industry-needs-large li::before { width: 6px; height: 6px; }
.industry-hero-figure { position: relative; min-height: 280px; }
.industry-products { margin-bottom: 56px; }


.industry-others { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }

.industry-others-label {
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-neutral-600);
  margin-right: 8px;
}

.industry-others-tag { font-size: 12.5px; background: transparent; }
.industry-others-tag:hover { background: var(--color-accent-100); color: var(--color-accent-800); }
.industry-others-tag:active { background: var(--color-accent-200); }

/* ── text pages ───────────────────────────────────────────────────────── */

.page-body-tight { padding-top: 56px; }

.text-page-title {
  font-size: clamp(36px, 5vw, 58px);
  line-height: 0.98;
  max-width: 18ch;
  margin-bottom: 18px;
}

.page-lede-narrow { max-width: 60ch; margin-bottom: 48px; }

/* Full width, as asked. There is no max-width here on purpose — the copy fills
   the container rather than sitting in what still read as one column of two.
   The trade is line length: at 1216px a paragraph runs about 150 characters a
   line, against the 60–75 that is comfortable to read. Adding `max-width: 72ch`
   is the whole of the fix if that is ever wanted back.

   Flex column with a gap rather than margins, so the paragraphs, lists and
   sub-headings RichText emits are all spaced the same without each needing a
   rule. */
.about-copy {
  font-size: 17px;
  line-height: 1.65;
  color: var(--color-neutral-800);
  display: flex;
  flex-direction: column;
  gap: 18px;
  margin-bottom: 64px;
}

/* The gap does the spacing, so anything RichText emits arrives with its own
   margins zeroed — otherwise a list would sit further from the paragraph above
   it than a paragraph does. */
.about-copy > * { margin: 0; }

/* A sub-heading needs to breathe more above than a paragraph does, and the flex
   gap alone cannot say that. :first-child so a body that opens with one does
   not start with a gap the page has already provided. */
.about-copy > .rt-heading { margin-top: 16px; }
.about-copy > .rt-heading:first-child { margin-top: 0; }

/* Shared by the two new bands, so they read as peers rather than as two
   different ideas of what a section heading is. */
.about-section-title {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: 13px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-neutral-600);
  margin: 0 0 20px;
}

.about-principles { margin-bottom: 64px; }

/* auto-fit here, unlike the category examples: these ARE the content of their
   section and there are two to four of them, so filling the row is right. */
.about-principles-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 20px;
}

.about-principle { padding: 26px 24px; }

.about-principle-title {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: 20px;
  line-height: 1.15;
  margin: 0 0 10px;
  color: var(--color-text);
}

.about-principle-body {
  margin: 0;
  font-size: 15px;
  line-height: 1.6;
  color: var(--color-neutral-700);
}

.about-reach { margin-bottom: 64px; }

/* No height: the map sets its own, so it is never cropped and never sits in a
   band of dead ground. A light ground behind it because a map exported for
   print is usually white to begin with, and the padding keeps it off the
   hairline border.

   .duotone brings position: relative, which the corner marks are placed
   against. */
.about-map {
  position: relative;
  background: var(--color-neutral-100);
  padding: 18px;
  line-height: 0;
}

.about-map-img {
  display: block;
  width: 100%;
  height: auto;
  /* The one guard on natural height: a portrait map would otherwise run past a
     screenful. Above this the picture is fitted instead, which for a map that
     shape is the lesser evil. */
  max-height: 70vh;
  object-fit: contain;
}

.about-map-caption {
  margin: 14px 0 0;
  font-size: 14px;
  line-height: 1.6;
  color: var(--color-neutral-600);
  max-width: 68ch;
}

.about-stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--color-divider);
  border: 1px solid var(--color-divider);
}

.about-stat { background: var(--color-bg); padding: 32px 28px; }

.about-stat-value {
  font-family: var(--font-heading);
  font-size: 48px;
  line-height: 1;
  color: var(--color-accent-700);
}

.about-stat-label { font-size: 14px; color: var(--color-neutral-700); margin-top: 8px; }

.support-grid { margin-bottom: 56px; }

.urgent-band {
  border: 1px solid var(--color-divider);
  padding: 36px 40px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 32px;
  flex-wrap: wrap;
}

.urgent-title { font-size: 30px; margin-bottom: 8px; }
.urgent-body { font-size: 15.5px; color: var(--color-neutral-700); margin: 0; }

/* ── news ─────────────────────────────────────────────────────────────── */

.news-list { display: flex; flex-direction: column; }

.news-row {
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr) 140px;
  gap: 32px;
  align-items: center;
  padding: 26px 4px;
  border-top: 1px solid var(--color-divider);
}

.news-figure { position: relative; height: 120px; }
.news-title { font-size: 26px; margin-bottom: 8px; }

.news-excerpt {
  font-size: 15px;
  line-height: 1.55;
  color: var(--color-neutral-700);
  margin: 0;
  max-width: 64ch;
}

.news-date {
  font-size: 13px;
  letter-spacing: 0.1em;
  color: var(--color-neutral-600);
  text-align: right;
}

/* ── contact ──────────────────────────────────────────────────────────── */

.contact-split {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: 64px;
  align-items: start;
}

.contact-form { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.field-full { grid-column: 1 / -1; }

.field-error {
  display: block;
  margin-top: 5px;
  font-size: 12.5px;
  color: #8a2f2f;
}

.input[aria-invalid="true"] { border-color: #d9b3b3; }

.form-flash {
  padding: 14px 18px;
  margin: 0 0 28px;
  font-size: 14.5px;
  border: 1px solid var(--color-divider);
}

.form-flash-ok { background: var(--color-accent-100); border-color: var(--color-accent-300); color: var(--color-accent-800); }
.form-flash-bad { background: #f7ecec; border-color: #d9b3b3; color: #8a2f2f; }

/* Off-screen rather than display:none, which some bots skip. */
.honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.contact-selected { font-size: 13.5px; color: var(--color-neutral-600); margin: 0; }
.contact-submit { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; }
.contact-note { font-size: 13.5px; color: var(--color-neutral-600); }

.contact-panel { border: 1px solid var(--color-divider); padding: 32px 30px; }
.contact-panel-title { font-size: 24px; margin-bottom: 18px; }

.contact-panel-body {
  display: flex;
  flex-direction: column;
  gap: 16px;
  font-size: 15px;
  line-height: 1.55;
  color: var(--color-neutral-800);
}

.contact-panel-label {
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-neutral-600);
  margin-bottom: 4px;
}

/* ── compare ──────────────────────────────────────────────────────────── */

.compare-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 20px;
  flex-wrap: wrap;
}

.compare-clear-link {
  font-family: var(--font-body);
  font-size: 13px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-neutral-600);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

.compare-clear-link:hover { color: var(--color-accent-700); }
.compare-clear-link:active { color: var(--color-accent-800); }

.compare-empty {
  font-size: 16px;
  color: var(--color-neutral-700);
  margin: 0 0 24px;
  max-width: 56ch;
}

.compare-scroll { overflow-x: auto; }

/* grid-template-columns is set inline: it depends on how many machines are
   selected, which only the server knows. */
.compare-grid {
  display: grid;
  min-width: 720px;
  border: 1px solid var(--color-divider);
}

.compare-cell { border-bottom: 1px solid var(--color-divider); padding: 13px 20px; }
.compare-cell:not(.compare-key):not(.compare-corner) { border-left: 1px solid var(--color-divider); }

.compare-corner {
  padding: 18px 20px;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-neutral-600);
}

.compare-head-cell { padding: 18px 20px; }
.compare-figure { position: relative; height: 130px; margin-bottom: 14px; }
.compare-name { font-size: 22px; margin-bottom: 8px; }
.compare-actions { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; }

.compare-link,
.compare-remove {
  font-family: var(--font-body);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

.compare-link { color: var(--color-accent-700); }
.compare-link:hover { color: var(--color-accent-800); }
.compare-remove { color: var(--color-neutral-600); }
.compare-remove:hover { color: var(--color-accent-700); }
.compare-remove:active { color: var(--color-accent-800); }

.compare-key { font-size: 14px; color: var(--color-neutral-600); }
.compare-value { font-size: 14.5px; font-weight: 500; }

.compare-footer-actions { margin-top: 32px; display: flex; gap: 14px; flex-wrap: wrap; }

/* ── search ───────────────────────────────────────────────────────────── */

.search-results { display: flex; flex-direction: column; border-top: 1px solid var(--color-divider); }

.search-result {
  display: block;
  padding: 11px 16px;
  border-bottom: 1px solid var(--color-divider);
  color: var(--color-text);
}

.search-result:hover { background: var(--color-accent-100); color: var(--color-text); }
.search-result:active { background: var(--color-accent-200); }

.search-result-meta {
  display: block;
  font-size: 10.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-neutral-600);
  margin-bottom: 2px;
}

.search-result-label { display: block; font-family: var(--font-heading); font-size: 18px; }

.search-page-form { margin-top: 40px; max-width: 340px; }
.search-page-form .input { width: 100%; }

.search-dropdown {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  width: 340px;
  max-height: 420px;
  overflow: auto;
  background: var(--color-bg);
  border: 1px solid var(--color-divider);
  box-shadow: var(--shadow-lg);
  z-index: 90;
}

.search-dropdown[hidden] { display: none; }

.search-dropdown-none {
  padding: 14px 16px;
  font-size: 14px;
  color: var(--color-neutral-600);
}

/* In the mobile menu the field is full width, so the panel matches it. */
.mobile-menu .search-dropdown { left: 0; right: 0; width: auto; max-height: 340px; top: calc(100% + 6px); }

/* ── not found ────────────────────────────────────────────────────────── */

.error-page {
  padding-top: 84px;
  padding-bottom: 84px;
  max-width: 720px;
  margin-inline: auto;
}

.error-page h1 { font-size: clamp(32px, 4vw, 46px); margin-bottom: 16px; }
.error-page p { font-size: 17px; line-height: 1.6; margin: 0 0 28px; color: var(--color-neutral-700); }

/* ── responsive ───────────────────────────────────────────────────────── */

@media (max-width: 1080px) {
  .site-nav { display: none; }
  .nav-toggle { display: inline-flex; }
  .footer-grid { grid-template-columns: 1fr 1fr; }

  /* Every two-column split collapses; the sticky sidebar unsticks; the hero
     cut-out layer is dropped. */
  .section-head,
  .consumables-band-inner,
  .closing-cta-inner,
  .listing,
  .product-top,
  .media-grid,
  .industry-selector,
  .industry-panel,
  .industry-split,
  .contact-split { grid-template-columns: 1fr; }

  .about-stats { grid-template-columns: 1fr 1fr; }

  /* Back into normal flow for the stacked layout: absolutely positioned, the
     list would sit on top of the panel instead of above it. The list is the
     whole width here and scrolls with the page, which is the right behaviour
     on a phone — a nested scrolling box inside a scrolling page is not. */
  .industry-tabs {
    grid-column: 1;
    grid-row: 1;
    position: static;
    width: auto;
    overflow-y: visible;
    border-right: 0;
    border-bottom: 1px solid var(--color-divider);
  }
  .industry-panel { grid-column: 1; grid-row: 2; }
  .listing-sidebar { position: static; }
  .hero-layer-cutout { display: none; }
  .stat-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 760px) {
  .pad { padding-left: 20px; padding-right: 20px; }
  .footer-grid { grid-template-columns: 1fr; }
  .stat-grid { grid-template-columns: 1fr; }
  .about-stats { grid-template-columns: 1fr; }
  .news-row { grid-template-columns: 1fr; }
  .news-date { text-align: left; }
  .contact-form { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .whatsapp { transition: none; }
}

/* ── product gallery ──────────────────────────────────────────────────── */

/* A grid item's automatic minimum size is its content's min-content width, so
   without this the thumbnail strip widens the whole column instead of
   scrolling inside it. */
.product-gallery { min-width: 0; }

.product-thumbs-rail { display: flex; align-items: center; gap: 8px; margin-top: 14px; min-width: 0; }

.product-thumbs {
  display: flex;
  gap: 14px;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
  flex: 1;
  min-width: 0;
  /* Room for the registration marks, which sit 6px outside each thumb. The
     matching scroll-padding keeps the snap position at scrollLeft 0 — without
     it the strip rests at 6 and reads as "already scrolled". */
  padding: 6px;
  margin: -6px;
  scroll-padding-left: 6px;
}

.product-thumbs::-webkit-scrollbar { display: none; }

.product-thumb {
  position: relative;
  flex: 0 0 112px;
  height: 112px;
  padding: 0;
  background: none;
  cursor: pointer;
  scroll-snap-align: start;
}

.product-thumb:hover { border-color: var(--color-accent); }
.product-thumb.is-current { border-color: var(--color-accent); box-shadow: inset 0 0 0 1px var(--color-accent); }

.thumb-arrow {
  flex: none;
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-bg);
  border: 1px solid var(--color-divider);
  color: var(--color-neutral-800);
  cursor: pointer;
}

.thumb-arrow:hover { border-color: var(--color-accent); color: var(--color-accent-700); }
.thumb-arrow:active { background: var(--color-accent-100); }
.thumb-arrow[hidden] { display: none; }

@media (prefers-reduced-motion: reduce) {
  .product-thumbs { scroll-behavior: auto; }
}

/* ── product videos ───────────────────────────────────────────────────── */

.media-videos { display: flex; flex-direction: column; gap: 8px; }
.media-videos .media-video { display: block; margin-bottom: 6px; }
.media-videos .media-video + .media-video-title { margin-top: -2px; margin-bottom: 14px; }

.media-video-title {
  font-size: 14px;
  color: var(--color-neutral-700);
}

.media-video.is-playing { height: 280px; overflow: hidden; }
.media-video.is-playing::after { content: none; }

.media-player {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  background: var(--color-accent-900);
}

/* ── video gallery ────────────────────────────────────────────────────── */

.media-video-panel[hidden] { display: none; }
.media-videos .media-video { display: block; }
.media-video-title { font-size: 14px; color: var(--color-neutral-700); margin-top: 10px; }

/* The player sits over the poster rather than replacing it, so switching
   videos can take it back out again. */
.media-video.is-playing .slot-img,
.media-video.is-playing .slot-empty,
.media-video.is-playing .media-play { display: none; }

.media-player {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  background: var(--color-accent-900);
}

.media-videos .product-thumbs-rail { margin-top: 14px; }

.thumb-play {
  position: absolute;
  right: 6px;
  bottom: 6px;
  width: 22px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, var(--color-accent-900) 78%, transparent);
  color: var(--color-neutral-100);
  pointer-events: none;
}

/* A real download is a link; a placeholder row is not, and says so by not
   reacting to the pointer. */
a.download-row:hover { background: var(--color-accent-100); color: var(--color-text); }
a.download-row:active { background: var(--color-accent-200); }
.download-row.is-placeholder { color: var(--color-neutral-700); }

/* The brand sits beside the model code, in the same muted line. */
/* A hairline rule rather than a "|" glyph: it is the same divider the cards and
   tables draw, so it stays crisp at any size and cannot pick up the letter
   spacing the model line carries. Wraps to its own line on a narrow column,
   where the rule would sit stranded at the start, so it is dropped there. */
.product-brand::before {
  content: "";
  display: inline-block;
  width: 1px;
  height: 12px;
  margin: 0 14px -1px;
  background: var(--color-neutral-400);
}
.product-brand strong { font-weight: 500; color: var(--color-neutral-800); }

@media (max-width: 760px) {
  .product-brand { display: block; }
  .product-brand::before { content: none; }
}

/* The link out of a consumable card on a machine's page, now that each part
   has a page of its own. The card is not itself a link here — it sits inside
   the product page's own grid — so the link is a line at the foot of it. */
.consumable-card-more {
  display: inline-block;
  margin-top: 12px;
  font-size: 12.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-accent-700);
}

.consumable-card-more:hover { color: var(--color-accent-800); }
.consumable-card-more:active { color: var(--color-accent-900); }
.consumable-card-more:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* ── public pagination ────────────────────────────────────────────────── */

/* Under a listing grid, not inside it: the grid is `auto-fit`, and a nav in
   there would be handed a column. */
.pagination {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-top: 48px;
  padding-top: 24px;
  border-top: 1px solid var(--color-divider);
}

.page-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 38px;
  height: 38px;
  padding: 0 10px;
  font-size: 14px;
  color: var(--color-neutral-800);
  border: 1px solid var(--color-divider);
}

.page-link:hover { border-color: var(--color-accent); color: var(--color-accent-700); }
.page-link:active { border-color: var(--color-accent-700); color: var(--color-accent-900); }
.page-link:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* The current page is a <span>, not a link — there is nowhere for it to go. */
.page-link.is-current {
  background: var(--color-accent-900);
  border-color: var(--color-accent-900);
  color: var(--color-neutral-100);
}

.page-step { gap: 6px; letter-spacing: 0.04em; }
.page-gap { padding: 0 4px; color: var(--color-neutral-600); }

@media (max-width: 760px) {
  /* The numbers are what fit; the words on the arrows are the first thing to
     go when the row would otherwise wrap. */
  .page-step span:not([aria-hidden]) { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
}

/* The submit button while its form is on its way. Not `disabled` — that would
   stop the browser submitting it at all — so the look has to come from the
   attribute the script sets instead. */
.btn[aria-disabled="true"] { opacity: 0.75; cursor: progress; }

/* ── cookie banner ────────────────────────────────────────────────────── */

/* Fixed to the bottom rather than pushing the page down: it must not move
   what someone came to read. Above the compare bar, because it has to be
   answered before anything else matters. */
.consent {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 95;
  background: var(--color-accent-900);
  color: var(--color-neutral-100);
  border-top: 1px solid var(--color-accent-700);
  box-shadow: var(--shadow-lg);
}

.consent-inner {
  padding-top: 18px;
  padding-bottom: 18px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 28px;
  flex-wrap: wrap;
}

.consent-copy { min-width: 0; flex: 1 1 380px; }

.consent-title {
  font-size: 17px;
  letter-spacing: 0.02em;
  margin-bottom: 6px;
  color: var(--color-neutral-100);
}

.consent-body {
  margin: 0;
  font-size: 14px;
  line-height: 1.55;
  max-width: 78ch;
  color: color-mix(in srgb, var(--color-neutral-100) 82%, transparent);
}

.consent-body a { color: var(--color-accent-300); text-decoration: underline; }
.consent-body a:hover { color: var(--color-neutral-100); }

/* Both buttons the same size. A "reject" that is harder to reach than
   "accept" is not a choice, and this site is built to the EU rule. */
.consent-actions { display: flex; gap: 12px; flex-wrap: wrap; }

.consent-btn {
  position: relative;
  min-width: 168px;
  justify-content: center;
  font-size: 13px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 12px 20px;
}

/* The secondary button sits on the dark band, so it needs its own edge. */
.consent-actions .btn-secondary {
  background: transparent;
  color: var(--color-neutral-100);
  border-color: color-mix(in srgb, var(--color-neutral-100) 45%, transparent);
}

.consent-actions .btn-secondary:hover { border-color: var(--color-neutral-100); background: color-mix(in srgb, var(--color-neutral-100) 10%, transparent); }

@media (max-width: 760px) {
  .consent-actions { width: 100%; }
  .consent-btn { flex: 1 1 auto; min-width: 0; }
}

/* The footer's "change your mind" control is a form, but reads as a link. */
.footer-consent { display: inline; margin: 0; }

.footer-consent button {
  padding: 0;
  background: none;
  border: 0;
  font: inherit;
  color: var(--color-accent-300);
  cursor: pointer;
}

.footer-consent button:hover { color: var(--color-neutral-100); }
.footer-consent button:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

.privacy-reset { margin: 36px 0 0; }
.privacy-updated { margin-top: 28px; font-size: 13px; color: var(--color-neutral-600); }

.privacy-sections { margin-top: 36px; }

/* ── frequently asked questions ───────────────────────────────────────── */

.faq { margin-top: 56px; }
.faq-title { font-size: clamp(26px, 3.2vw, 34px); margin-bottom: 24px; }

/* A description list, because that is what a question and its answer are.
   The wrapper div per pair keeps <dt>/<dd> valid while allowing a border. */
.faq-list { margin: 0; }

.faq-item {
  padding: 22px 0;
  border-top: 1px solid var(--color-divider);
}

.faq-item:last-child { border-bottom: 1px solid var(--color-divider); }

.faq-question {
  font-family: var(--font-heading);
  font-size: 19px;
  font-weight: 600;
  color: var(--color-text);
  margin-bottom: 8px;
}

.faq-answer {
  margin: 0;
  font-size: 15.5px;
  line-height: 1.6;
  color: var(--color-neutral-700);
  max-width: 78ch;
}

/* ── industry page sections ───────────────────────────────────────────── */

.industry-sections { margin-bottom: 56px; }

/* Photograph and copy side by side, alternating, so a run of them reads as a
   sequence. A section with only one of the two simply fills the row. */
.industry-section {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 48px;
  align-items: center;
  padding: 40px 0;
  border-top: 1px solid var(--color-divider);
}

.industry-section:first-child { border-top: 0; padding-top: 0; }

/* The odd ones out: the figure moves to the right without changing the source
   order, so a screen reader still hears heading then photograph. */
.industry-section.is-reversed .industry-section-figure { order: 2; }

.industry-section-figure { position: relative; aspect-ratio: 4 / 3; min-width: 0; }
.industry-section-copy { min-width: 0; }
.industry-section-heading { font-size: clamp(24px, 3vw, 32px); margin-bottom: 14px; }

.industry-section-body {
  font-size: 16px;
  line-height: 1.65;
  color: var(--color-neutral-700);
  margin: 0 0 12px;
  max-width: 62ch;
}

.industry-section-body:last-child { margin-bottom: 0; }

/* ── category example strip ───────────────────────────────────────────── */

/* The category's heading block: text on the left, its photograph on the right.

   The grid only exists when there is a photograph — .has-photo — so a category
   without one keeps a single full-width column rather than a 1fr text block
   with a hole beside it.

   minmax(0, …) on both tracks because a grid item's automatic minimum size is
   its content's min-content width, which would let a long unbroken word in the
   description push the photograph out of the row.

   The photograph takes the narrower track: it is supporting material next to
   the words that say what the category is, and a smaller frame also asks less
   of the source file — the first of these to arrive was 310px wide, which a
   full-width banner had to blow up almost 4x. */
.category-head { margin-bottom: 44px; }

.category-head.has-photo {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
  gap: var(--space-8);
  /* Centred, not start-aligned: most of these descriptions are two lines
     against a photograph three times as tall, and aligning both to the top
     left the text hanging above a void the height of the picture. */
  align-items: center;
}

/* The lede's own 62ch cap is wider than this column, so it would never wrap
   where the column ends; inside the grid the track does the measuring. The
   bottom margin goes with it — the gap and the block's own margin already
   separate the head from the listing. */
.category-head.has-photo .page-lede { max-width: none; margin-bottom: 0; }

/* 4/3 rather than a wide crop: a category photograph is a picture of a machine
   or a pack, not a letterbox, and this is close enough to what a phone or a
   supplier's photo already is that cover has little to throw away.

   .duotone brings position: relative and the overflow: hidden that crops the
   photograph to the frame, which is what .slot-img is positioned against. */
.category-head-photo {
  display: block;
  position: relative;
  margin: 0;
  aspect-ratio: 4 / 3;
}

@media (max-width: 760px) {
  /* One column: side by side, the photograph would be too small to read and
     the description too narrow to scan. */
  .category-head.has-photo { grid-template-columns: minmax(0, 1fr); }
  .category-head.has-photo .page-lede { margin-bottom: var(--space-4); }
}

.category-examples { margin-bottom: 44px; }

.category-examples-title {
  font-family: var(--font-heading);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-neutral-600);
  margin-bottom: 16px;
}

/* auto-FILL, not auto-fit. The two differ only when the row is not full, which
   is exactly this case: auto-fit collapses the empty tracks and lets the items
   share the whole row, so a category with one example rendered it 1216px wide —
   a supporting photograph four times the size of the machines it illustrates.
   auto-fill keeps the empty tracks, so one example is one track wide and a
   second lands beside it.

   This is the one grid on the site that must not stretch. The card grids do,
   and should: a card is the content. An example is a picture beside it. */
.category-examples-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 22px 24px;
}

.category-example { margin: 0; min-width: 0; }

.category-example-figure {
  display: block;
  position: relative;
  aspect-ratio: 3 / 2;
}

.category-example-caption {
  margin-top: 10px;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--color-neutral-700);
}

/* Two lines of text under an example, either of which may be absent: a short
   title, and the sentence explaining what the photograph is of. They were one
   field printed and one field silently used as alt text, which is why a
   description written to be read was nowhere on the page. */
.category-example-title,
.category-example-note { display: block; }

.category-example-title {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: 14.5px;
  letter-spacing: 0.01em;
  color: var(--color-text);
}

/* Smaller than the title and quieter than the machines below: this is a note
   about a picture, and it must not read as a product name. */
.category-example-note {
  margin-top: 3px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--color-neutral-600);
}

@media (max-width: 760px) {
  .industry-section { grid-template-columns: 1fr; gap: 24px; padding: 28px 0; }
  /* Order only matters while they sit side by side. */
  .industry-section.is-reversed .industry-section-figure { order: 0; }
}


/* ---------------------------------------------------------------------------
   The holding page, and the reminder an admin sees while the site is hidden.
   Both built from industry.css tokens — for a while this is the only page of
   the site anyone can see, so it has to read as the same company.
   --------------------------------------------------------------------------- */

.maintenance-page {
  background: var(--color-bg);
  min-height: 100vh;
}

/* The homepage hero's 64px grid, in ink rather than white because this sits on
   a light background. Fixed, so it does not shift if the card is tall enough
   to scroll on a short window. Decorative only — aria-hidden in the markup. */
.maintenance-grid {
  position: fixed;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(color-mix(in srgb, var(--color-text) 5%, transparent) 1px, transparent 1px),
    linear-gradient(90deg, color-mix(in srgb, var(--color-text) 5%, transparent) 1px, transparent 1px);
  background-size: 64px 64px;
  /* Fades out towards the foot so the grid frames the card rather than
     competing with it. */
  mask-image: linear-gradient(180deg, #000 0%, #000 45%, transparent 100%);
}

.maintenance {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6) var(--space-4);
}

/* No `overflow: hidden` — the corner marks sit outside the card's edges and it
   would clip them. The card is opaque so the grid stops at its border. */
.maintenance-card {
  background: var(--color-bg);
  max-width: 620px;
  width: 100%;
  padding: var(--space-6);
  text-align: center;
}

/* With a photograph it becomes two columns and widens to hold both. Text goes
   left-aligned here: centred paragraphs beside a hard-edged photograph look
   accidental. */
.maintenance-card.has-photo {
  max-width: 940px;
  display: grid;
  grid-template-columns: 5fr 6fr;
  gap: var(--space-6);
  align-items: center;
  text-align: left;
}

/* A grid item's automatic minimum size is its content, so without this the
   photograph's intrinsic width can push the card wider than its max-width. */
.maintenance-figure,
.maintenance-body-col { min-width: 0; }

/* Portrait, but only slightly: at 4/5 the photograph towered over a three-line
   message and left the text column floating in space. */
.maintenance-figure {
  display: block;
  position: relative;
  aspect-ratio: 3 / 4;
}

.maintenance-brand { margin-bottom: var(--space-4); }

.maintenance-logo { display: block; max-width: 230px; height: auto; }
.maintenance-card:not(.has-photo) .maintenance-logo { margin: 0 auto; }

.maintenance-wordmark {
  display: block;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 27px;
  letter-spacing: 0.02em;
  line-height: 1;
}

.maintenance-legal {
  display: block;
  margin-top: 4px;
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-neutral-600);
}

.maintenance-kicker {
  font-family: var(--font-heading);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-neutral-600);
  margin-bottom: var(--space-2);
}

/* clamp() rather than per-breakpoint sizes, as everywhere else. */
.maintenance-title {
  font-size: clamp(30px, 5vw, 46px);
  line-height: 1.08;
  margin-bottom: var(--space-3);
}

.maintenance-body {
  font-size: 16px;
  line-height: 1.65;
  color: var(--color-neutral-700);
  max-width: 46ch;
}

.maintenance-card:not(.has-photo) .maintenance-body { margin: 0 auto; }

.maintenance-contact {
  margin-top: var(--space-6);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-divider);
}

.maintenance-contact-label {
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-neutral-600);
  margin-bottom: var(--space-2);
}

.maintenance-contact-lines {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  font-family: var(--font-heading);
  font-size: 19px;
}

.maintenance-card:not(.has-photo) .maintenance-contact-lines { justify-content: center; }

.maintenance-contact-lines a { color: var(--color-text); text-decoration: none; }
.maintenance-contact-lines a:hover { color: var(--color-accent); }
.maintenance-contact-lines a:active { color: var(--color-accent-700); }

.maintenance-contact-lines a:focus-visible,
.preview-banner:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* Sticky rather than fixed: it belongs to the top of the document and must not
   sit over the header once the page scrolls. */
.preview-banner {
  position: sticky;
  top: 0;
  z-index: 60;
  display: block;
  padding: 10px var(--space-4);
  background: var(--color-accent-900);
  color: var(--color-neutral-100);
  text-align: center;
  text-decoration: none;
  font-size: 12.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.preview-banner:hover { background: var(--color-accent-800); color: #fff; }
.preview-banner:active { background: var(--color-accent-700); }

@media (max-width: 760px) {
  /* Photograph above the words once there is no room beside them. */
  .maintenance-card.has-photo {
    grid-template-columns: 1fr;
    gap: var(--space-4);
    padding: var(--space-4);
  }
  .maintenance-figure { aspect-ratio: 3 / 2; }
}

/* ── video watermark ──────────────────────────────────────────────────────
   The site logo over a self-hosted player, bottom right, for as long as the
   video is on screen. Rendered only for uploaded files and only when a logo
   has been uploaded — see the note in templates/product.php.

   This is an overlay, not a burn-in: it identifies the video while it plays
   here, and it is not part of the file. Anyone who downloads the video gets it
   unmarked. Burning the logo into the frames needs ffmpeg on the server and a
   background encoder, which is a different piece of work. */

.media-watermark {
  position: absolute;
  /* Inset from the right rather than hard against it: at 3% the mark sat on
     the edge and crowded the overflow menu below it. One value to tune. */
  right: 9%;
  /* Clear of the native control bar, which is roughly 40px and sits at the
     bottom edge. YouTube places its own branding the same way and for the same
     reason. */
  bottom: 56px;
  width: 16%;
  min-width: 72px;
  max-width: 150px;
  height: auto;

  /* A white plate behind the mark, because a logo supplied with a transparent
     background is usually drawn in the company's dark ink and disappears into
     dark footage. Painting the plate here rather than asking for a light
     variant of the logo means one upload works everywhere: on the header, on
     the holding page and over video. A logo that already carries its own white
     background simply merges into the plate and looks unchanged.

     No token is pure white — the ramp starts at --color-neutral-100 (#f5f5f8),
     which reads as faintly blue over video. This is a deliberate literal, like
     the #fff on the accent and WhatsApp fills. */
  background: #fff;

  /* Border-box is global, so this padding comes out of the widths above: the
     plate stays the size the mark was, and the glyph sits inside it with room
     to breathe instead of running into the white edge. */
  padding: var(--space-2);

  /* site.js APPENDS the player into this container, so the <video> comes
     after the watermark in the DOM. Both are positioned and neither had a
     z-index, so the video painted straight over it and nothing showed. */
  z-index: 2;

  /* Never between the visitor and the controls: the watermark is decoration
     over an interactive element, so every pointer event passes through it. */
  pointer-events: none;

  /* Hidden over the poster — that frame already carries a play button and,
     until the client supplies stills, a dashed empty slot that a logo would
     sit oddly on top of. It appears with the player. */
  opacity: 0;
  transition: opacity 0.18s ease;

  /* Now that the plate is opaque this outlines the plate rather than the glyph,
     which is what keeps a white rectangle from vanishing into pale footage —
     the case the plate itself cannot answer. */
  filter: drop-shadow(0 1px 3px color-mix(in srgb, var(--color-accent-900) 55%, transparent));
}

/* Was 0.88, which let the footage tint the plate: over anything strongly
   coloured the "white" background came through as a wash of that colour. High
   enough to read as white, short of 1 so the mark still sits in the picture
   rather than on top of it like a sticker. */
.media-video.is-playing .media-watermark { opacity: 0.94; }

@media (max-width: 760px) {
  /* Smaller player, smaller control bar, and a 150px mark would dominate it.
     The padding shrinks with it — space-2 out of a 60px plate leaves too
     little glyph to recognise. */
  .media-watermark {
    bottom: 44px;
    width: 22%;
    min-width: 60px;
    max-width: 104px;
    padding: var(--space-1);
  }
}

/* ── a customer's own service page ─────────────────────────────────────────
   Reached by a private link, read on a phone in a factory as often as at a
   desk. Plain, roomy, and built from the same tokens as the rest of the site —
   it is the company's page, not a separate application. */


.service-head { max-width: 72ch; margin-bottom: var(--space-8); }
.service-company {
  margin: var(--space-2) 0 0;
  font-family: var(--font-heading);
  font-size: 20px;
  color: var(--color-accent-800);
}
.service-intro { margin: var(--space-3) 0 0; font-size: 16px; line-height: 1.6; }

/* Each part of the page begins with a rule across the full width, so the eye
   finds the boundary before it reads the words. The customer is not reading
   this page carefully — they are looking for one machine. */
.service-section {
  margin-top: var(--space-8);
  padding-top: var(--space-6);
  border-top: 2px solid var(--color-neutral-300);
}

.service-heading {
  margin: 0 0 var(--space-6);
  font-size: clamp(24px, 3.4vw, 32px);
}

/* The two sections that were loose text now sit in a panel, like the machines
   and the contact block already did. */
/* WHITE, and a literal because the ramp has no white in it: it runs #f5f5f8,
   #f2f2f3, #e9e9ea, every step within a few points of the page itself. The
   design system's card is a wireframe with no fill, which is right everywhere
   a reader is browsing — and wrong on the one page a customer opens cold,
   where the cards have to be found at a glance. --color-neutral-100 was tried
   first and was three points off the page: invisible.

   Scoped to .service-page. The wireframe card stays the house style
   everywhere else and is not restyled site-wide. */
.service-page .card {
  background: #fff;
  border: 1px solid var(--color-neutral-300);
}

.service-panel { padding: var(--space-6); }

.service-empty { color: var(--color-neutral-600); }

/* Their machines. Cards, because each is a separate thing they own. */
.service-machines,
.service-visits,
.service-jobs { list-style: none; margin: 0; padding: 0; }

.service-machines {
  display: grid;
  /* auto-FILL, not auto-fit: with one machine, auto-fit collapses the empty
     tracks and stretches that single card across the whole window, which reads
     as a layout error. Documented in CLAUDE.md for the category grid. */
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: var(--space-4);
}

.service-machine { padding: var(--space-6); }
.service-machine h3 { margin: 0 0 var(--space-3); font-size: 18px; }
.service-machine dl { display: grid; gap: 6px; margin: 0 0 var(--space-3); font-size: 14px; }
.service-machine dl > div { display: flex; gap: 8px; }
.service-machine dt { color: var(--color-neutral-600); }
.service-machine dd { margin: 0; }

.service-warranty { margin: 0; font-weight: 600; }
.service-site { margin: var(--space-2) 0 0; font-size: 14px; color: var(--color-neutral-600); }

/* What is still to come: a short dated list, not a table. */
/* A dated list: the date leads, because "when" is the question. */
.service-visits { display: grid; gap: 0; }

.service-visits li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px var(--space-4);
  font-size: 16px;
  padding: var(--space-3) 0;
  border-top: 1px solid var(--color-divider);
}

.service-visits li:first-child { border-top: 0; padding-top: 0; }
.service-visits li:last-child { padding-bottom: 0; }
.service-visits strong { font-size: 17px; min-width: 9em; }
.service-visits span { color: var(--color-neutral-600); }

/* What has been done. One block per visit, newest first. */
.service-jobs { display: grid; gap: var(--space-4); }
.service-job { padding: var(--space-6); }

.service-job-head {
  display: flex;
  flex-wrap: wrap;
  gap: 4px var(--space-4);
  margin: 0 0 var(--space-3);
  font-size: 14px;
  color: var(--color-neutral-600);
}

.service-job-date { font-family: var(--font-heading); font-size: 17px; color: var(--color-text); }
.service-job-number { margin-left: auto; }

.service-job-line { margin: 0 0 var(--space-2); font-size: 15px; line-height: 1.6; max-width: 78ch; }
.service-job-label { display: block; font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-neutral-600); }
.service-job-parts,
.service-job-advice,
.service-job-pending { color: var(--color-neutral-700); font-size: 14px; }

.service-job-photos {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: var(--space-3);
  margin: var(--space-3) 0 0;
  padding: 0;
}

.service-job-photos img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border: 1px solid var(--color-divider);
}

.service-contact { margin-top: var(--space-8); padding: var(--space-6); }
.service-contact h2 { margin: 0 0 var(--space-2); font-size: 20px; }
.service-contact p { margin: 0; font-size: 16px; }

.service-private {
  margin: var(--space-4) 0 0;
  font-size: 13px;
  color: var(--color-neutral-600);
}

/* One visit within a job, on the customer's own page. */
.service-visit { padding: var(--space-3) 0; border-top: 1px solid var(--color-divider); }
.service-visit:first-of-type { border-top: 0; }

.service-visit-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px var(--space-4);
  margin: 0 0 var(--space-2);
}

.service-visit-number { font-family: var(--font-heading); font-size: 15px; }
.service-visit-date { font-size: 13px; color: var(--color-neutral-600); }
.service-visit-state { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px var(--space-2); }
.service-visit-state .service-job-label { flex-basis: 100%; }

/* ── the customer's summary: a card per machine ────────────────────────── */

/* Shown only when something is open, so it is allowed to be loud. */
.service-open { padding: var(--space-6); margin-bottom: var(--space-6); }
.service-open h2 { margin: 0 0 var(--space-4); font-size: 18px; }
.service-open ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
.service-open li { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-1) var(--space-3); font-size: 15px; }
.service-open-what { font-weight: 600; }
.service-open-serial { color: var(--color-neutral-600); font-size: 14px; }

/* One link, stretched over the whole card — a card may not be an anchor. */
.service-machine { position: relative; }
.service-machine-link { text-decoration: none; color: inherit; }
.service-machine-link::after { content: ''; position: absolute; inset: 0; z-index: 1; }
.service-machine:hover .service-machine-link { color: var(--color-accent-700); }
.service-machine:focus-within { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.service-machine-link:focus-visible { outline: none; }

/* A badge and the date beside it, wrapping to two lines when narrow. */
.service-machine-state {
  margin: var(--space-2) 0 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px var(--space-3);
}

.service-machine-since { font-size: 13px; color: var(--color-neutral-600); }

/* Status badges, built on the design system's own `.tag` rather than a
   parallel component — the same shape as .tag-accent and .tag-neutral.
   THE ONLY GREEN ON THIS SITE besides the WhatsApp button, added at the
   client's request: customers read a machine's state at a glance and green
   is what "running" means to them. Never colour alone — the badge always
   carries the word, so it survives being printed, read aloud, or seen by
   someone who cannot separate the two hues. Both pairs clear 4.5:1 against
   their own fill and against the page (5.80 and 7.18); the mid-green
   #1DA851 of the WhatsApp button does not, at 2.77, which is why this is a
   darker green than that one. */
.tag-running { background: #e9f5ec; color: #146c38; }
.tag-stopped { background: #f7ecec; color: #8a2f2f; }

.service-machine-more {
  margin: var(--space-4) 0 0;
  font-size: 14px;
  color: var(--color-accent-700);
}

.service-recent { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }

.service-recent li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px var(--space-4);
  font-size: 16px;
  padding: var(--space-3) 0;
  border-top: 1px solid var(--color-divider);
}

.service-recent li:first-child { border-top: 0; padding-top: 0; }
.service-recent li:last-child { padding-bottom: 0; }
.service-recent-date { font-family: var(--font-heading); font-size: 16px; }
.service-recent-kind,
.service-recent-number { color: var(--color-neutral-600); font-size: 14px; }
.service-recent-number { margin-left: auto; }

/* ── one machine's own page ─────────────────────────────────────────────── */

.service-back { margin: 0 0 var(--space-4); font-size: 14px; }
.service-machine-facts { padding: var(--space-6); margin-bottom: var(--space-8); }
.service-machine-facts dl { display: grid; gap: 6px; margin: 0 0 var(--space-3); font-size: 14px; }
.service-machine-facts dl > div { display: flex; gap: 8px; }
.service-machine-facts dt { color: var(--color-neutral-600); }
.service-machine-facts dd { margin: 0; }
.service-older { margin: var(--space-6) 0 0; font-size: 15px; }

/* The serial, under the model name — the only thing separating two of the
   same machine. */
.service-machine-serial {
  margin: calc(var(--space-2) * -1) 0 var(--space-4);
  font-size: 14px;
  color: var(--color-neutral-600);
}

.service-machine-serial strong {
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}

/* ── what a maintenance visit covered, on the customer's page ──────────── */

.service-covers { list-style: none; margin: var(--space-2) 0 0; padding: 0; display: grid; gap: var(--space-2); }

.service-covers li {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  font-size: 15px;
  line-height: 1.5;
}

/* The tick is a glyph, not a colour: it still reads when printed in grey, and
   the state is named in text for anything that cannot see either. */
.service-cover-mark { flex: none; width: 1.1em; font-weight: 700; text-align: center; }
.service-cover-done .service-cover-mark { color: #146c38; }
.service-cover-pending .service-cover-mark { color: var(--color-neutral-500); }
.service-cover-pending { color: var(--color-neutral-600); }
