/* ==========================================================================
   Al Watania Precast — public site.

   Everything here is scoped to `.site`, the body class on the public pages
   only, so the dashboard and the printed documents - which share base.html
   and style.css - are untouched by any of it.

   The colour decision: the logo is orange on deep navy, and on a navy header
   the navy half of the mark disappears. So the header is paper, the logo is
   the full-colour one, and the navy is spent where it is worth something -
   the hero, the process band, the footer. Paper, navy, sand, navy: the page
   has a rhythm instead of one slab of colour.

   Contrast, checked not guessed: white on #F9711F is 2.83:1 and is never
   used. Orange carries --ink (5.98:1); navy carries white (16.9:1).
   ========================================================================== */

.site {
  --brand: #F9711F;
  --brand-700: #D95B10;
  /* The same orange, darkened only as far as text contrast demands. On
     paper it is 5.26:1, on sand 4.79:1, on the orange wash 4.53:1 - all
     AA. --brand-700 is 3.85:1 on paper and is for fills and borders only,
     never for words. */
  --brand-ink: #B8490A;
  --ink: #241043;
  --ink-2: #3A1E62;
  --sand: #F7F4EF;
  --line: #E4DFD7;
  --muted: #6B6472;
  --paper: #FFFFFF;

  /* Tints of the above, for drawing lines and tinted chips. No new hues. */
  --line-strong: #CFC7BA;
  --brand-wash: #FDEBDD;
  --ink-wash: #EDE9F2;

  --head-h: 76px;
  --r: 14px;
  --r-sm: 10px;
  --ease: cubic-bezier(.2, .7, .3, 1);

  background: var(--paper);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
}

/* The sticky header covers an anchor target unless the target reserves room
   for it. scroll-margin sits on the target, so it works without touching the
   scroll container (which is <html>, outside this stylesheet's scope). */
.site [id] { scroll-margin-top: calc(var(--head-h) + 18px); }

@media (prefers-reduced-motion: no-preference) {
  :root:has(> body.site) { scroll-behavior: smooth; }
}

.site .wrap { max-width: 1180px; }
.site h1, .site h2, .site h3, .site h4 { color: var(--ink); letter-spacing: -.01em; }
.site p { margin: 0 0 1em; }
.site p:last-child { margin-bottom: 0; }
.site .muted { color: var(--muted); }
.site figure { margin: 0; }
/* Every <img> here carries width/height attributes so the browser reserves
   the right box before the file arrives. Those attributes are presentational
   hints on the CSS `height` property, and a fixed height beats aspect-ratio
   - which is how a hero plate ends up 620px tall inside a 278px column. The
   height goes back to auto and the ratio takes over. */
.site img[width][height] { height: auto; }
.site ::selection { background: var(--brand); color: var(--ink); }

/* A focus ring you can actually see. Orange on paper is 2.83:1 and would
   fail here too, so the ring is ink on light surfaces and white on dark. */
.site :focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 2px;
  border-radius: 3px;
}
.site .on-dark :focus-visible,
.site .hero :focus-visible,
.site .site-footer :focus-visible { outline-color: #fff; }

.site .skip {
  position: absolute; inset-inline-start: 12px; top: -200px; z-index: 100;
  background: var(--ink); color: #fff; padding: 12px 20px;
  border-radius: 0 0 var(--r-sm) var(--r-sm); text-decoration: none; font-weight: 700;
}
.site .skip:focus { top: 0; }

/* Numbers are numbers: Latin digits, tabular, isolated LTR inside RTL text. */
.site .num, .site .fig {
  font-variant-numeric: tabular-nums;
  direction: ltr; unicode-bidi: isolate;
}

/* ==========================================================================
   The millimetre rule — a scale bar, two gradients, no images.
   It runs under the header and under every section heading. A plant that
   sells dimensional accuracy should look like it measures things.
   ========================================================================== */
.site .rule {
  height: 9px; flex: none;
  background:
    repeating-linear-gradient(to right, var(--line-strong) 0 1px, transparent 1px 7px) bottom/100% 5px no-repeat,
    repeating-linear-gradient(to right, var(--line-strong) 0 1px, transparent 1px 35px) bottom/100% 9px no-repeat;
  border-bottom: 1px solid var(--line);
}
.site .rule.on-dark {
  background:
    repeating-linear-gradient(to right, rgba(255,255,255,.30) 0 1px, transparent 1px 7px) bottom/100% 5px no-repeat,
    repeating-linear-gradient(to right, rgba(255,255,255,.55) 0 1px, transparent 1px 35px) bottom/100% 9px no-repeat;
  border-bottom-color: rgba(255,255,255,.18);
}

/* ==========================================================================
   The dimension line — the one thing a visitor remembers.
   A precast buyer reads shop drawings all day. A size set as a drawing
   dimension (extension ticks, arrow terminators, the figure in a gap in the
   line) is the language he already reads. Pure CSS, three empty elements,
   degrades to the plain string when the CSS does not load.
   ========================================================================== */
.site .dim {
  display: flex; align-items: center; gap: 9px;
  direction: ltr; unicode-bidi: isolate;      /* drawings read left to right */
  color: var(--ink);
  font-size: 13px; font-weight: 700;
  font-variant-numeric: tabular-nums;
  min-width: 0;
}
.site .dim b { font-weight: 700; white-space: nowrap; }
.site .dim i {
  position: relative; flex: 1 1 14px; min-width: 14px;
  height: 1px; background: currentColor; opacity: .55;
}
.site .dim i::before {                         /* arrow terminator */
  content: ""; position: absolute; top: -3px;
  border-top: 3.5px solid transparent;
  border-bottom: 3.5px solid transparent;
}
.site .dim i:first-child::before { left: 0; border-right: 7px solid currentColor; }
.site .dim i:last-child::before  { right: 0; border-left: 7px solid currentColor; }
.site .dim i::after {                          /* extension tick */
  content: ""; position: absolute; top: -5px; width: 1px; height: 11px;
  background: currentColor;
}
.site .dim i:first-child::after { left: 0; }
.site .dim i:last-child::after  { right: 0; }
.site .dim.lg { font-size: 15px; gap: 12px; }
.site .dim.on-dark { color: #fff; }

/* ==========================================================================
   Header — paper, sticky, full-colour logo
   ========================================================================== */
.site .site-head {
  position: sticky; top: 0; z-index: 50;
  background: rgba(255,255,255,.94);
  -webkit-backdrop-filter: saturate(1.6) blur(10px);
  backdrop-filter: saturate(1.6) blur(10px);
  box-shadow: 0 1px 0 var(--line);
}
.site .site-head .rule { position: absolute; inset-inline: 0; bottom: -10px; opacity: .85; }
.site .head-inner {
  display: flex; align-items: center; gap: 18px;
  height: var(--head-h);
}
.site .brandmark { display: flex; align-items: center; text-decoration: none; flex: none; }
.site .brandmark img { height: 38px; width: auto; display: block; }
.site .brandmark .txt { font-weight: 900; font-size: 19px; color: var(--ink); }
.site .brandmark .txt span { color: var(--brand-ink); }

.site .site-nav { display: flex; align-items: center; gap: 4px; margin-inline-start: auto; }
.site .site-nav a {
  color: var(--ink); text-decoration: none; font-size: 15px; font-weight: 500;
  padding: 9px 13px; border-radius: var(--r-sm); position: relative;
  transition: background .15s var(--ease), color .15s var(--ease);
}
.site .site-nav a:hover { background: var(--sand); }
.site .site-nav a[aria-current="page"] { font-weight: 700; }
.site .site-nav a[aria-current="page"]::after {
  content: ""; position: absolute; inset-inline: 13px; bottom: 2px;
  height: 2px; background: var(--brand); border-radius: 2px;
}
.site .head-actions { display: flex; align-items: center; gap: 10px; flex: none; }
.site .lang {
  border: 1px solid var(--line-strong); color: var(--ink); background: var(--paper);
  border-radius: 999px; padding: 6px 13px; font-size: 13px; font-weight: 700;
  text-decoration: none; line-height: 1;
  transition: border-color .15s var(--ease), background .15s var(--ease);
}
.site .lang:hover { border-color: var(--ink); background: var(--sand); }

/* Phone menu. <details> so it works with the JavaScript switched off — the
   old header simply had `display:none` here and a phone got no navigation
   at all. The script below only closes it again when a link is followed. */
.site .menu { display: none; margin-inline-start: auto; position: relative; }
.site .menu > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: 8px;
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  padding: 9px 14px; font-weight: 700; font-size: 14px; color: var(--ink);
  background: var(--paper); user-select: none;
}
.site .menu > summary::-webkit-details-marker { display: none; }
.site .menu > summary .bars { display: grid; gap: 3px; }
.site .menu > summary .bars i { display: block; width: 17px; height: 2px; background: var(--ink); border-radius: 2px; }
.site .menu[open] > summary { background: var(--ink); color: #fff; border-color: var(--ink); }
.site .menu[open] > summary .bars i { background: #fff; }
.site .menu-panel {
  position: absolute; inset-inline-end: 0; top: calc(100% + 10px);
  min-width: min(74vw, 290px);
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r); box-shadow: 0 18px 44px rgba(36,16,67,.17);
  padding: 8px; display: grid; gap: 2px;
}
.site .menu-panel a {
  text-decoration: none; color: var(--ink); font-weight: 500;
  padding: 11px 14px; border-radius: var(--r-sm); font-size: 15.5px;
}
.site .menu-panel a:hover { background: var(--sand); }
.site .menu-panel a[aria-current="page"] { background: var(--ink-wash); font-weight: 700; }
.site .menu-panel .sep { height: 1px; background: var(--line); margin: 6px 8px; }
.site .menu-panel .btn { margin: 6px 6px 2px; }

/* ==========================================================================
   Buttons
   ========================================================================== */
.site .btn {
  background: var(--brand); color: var(--ink); font-weight: 700;
  border-radius: var(--r-sm); padding: 12px 22px; font-size: 15px;
  border: 1px solid transparent;
  transition: background .15s var(--ease), transform .15s var(--ease), box-shadow .15s var(--ease);
}
.site .btn:hover { background: var(--brand-ink); color: #fff; filter: none; transform: translateY(-1px); }
.site .btn:active { transform: translateY(0); }
.site .btn.small { padding: 8px 15px; font-size: 13.5px; }
.site .btn.ghost {
  background: transparent; color: var(--ink); border-color: var(--line-strong);
}
.site .btn.ghost:hover { background: var(--sand); color: var(--ink); border-color: var(--ink); }
.site .on-dark .btn.ghost, .site .hero .btn.ghost, .site .cta .btn.ghost {
  color: #fff; border-color: rgba(255,255,255,.45);
}
.site .on-dark .btn.ghost:hover, .site .hero .btn.ghost:hover, .site .cta .btn.ghost:hover {
  background: rgba(255,255,255,.12); color: #fff; border-color: #fff;
}

/* ==========================================================================
   Bands and section headings
   ========================================================================== */
.site .band { padding: 78px 0; }
.site .band.tight { padding: 54px 0; }
.site .band--paper { background: var(--paper); }
.site .band--sand  { background: var(--sand); }
.site .band--ink   { background: var(--ink); color: rgba(255,255,255,.80); }
.site .band--ink h1, .site .band--ink h2, .site .band--ink h3, .site .band--ink h4 { color: #fff; }
.site .band--ink .muted { color: rgba(255,255,255,.62); }

.site .head2 { max-width: 62ch; margin: 0 0 34px; }
.site .band > .wrap > .head2:only-child { margin-bottom: 0; }
.site .head2 .eyebrow {
  display: flex; align-items: center; gap: 10px;
  font-size: 12.5px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--brand-ink); margin-bottom: 10px;
}
.site .band--ink .head2 .eyebrow { color: var(--brand); }
.site .head2 .eyebrow::after {
  content: ""; flex: 1; max-width: 70px; height: 1px; background: currentColor; opacity: .45;
}
.site .head2 h2 { font-size: clamp(25px, 3vw, 33px); font-weight: 900; margin: 0 0 10px; }
.site .head2 p { color: var(--muted); font-size: 16.5px; margin: 0; }
.site .band--ink .head2 p { color: rgba(255,255,255,.72); }

/* ==========================================================================
   Hero
   ========================================================================== */
.site .hero {
  position: relative; background: var(--ink); color: #fff;
  background-size: cover; background-position: center;
  padding: 0; overflow: hidden; isolation: isolate;
}
.site .hero::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  /* Strong enough that white text clears AA over any part of the frame,
     light enough that the plant is still visibly there. */
  background:
    linear-gradient(to bottom, rgba(36,16,67,.62), rgba(36,16,67,.84) 58%, rgba(36,16,67,.96)),
    var(--hero-shot) center/cover no-repeat;
}
.site .hero-inner {
  display: grid; grid-template-columns: 1.05fr .95fr; gap: 52px;
  align-items: center; padding: 76px 20px 72px; max-width: 1180px;
}
.site .hero .eyebrow {
  display: inline-flex; align-items: center; gap: 9px;
  font-size: 12.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--brand); margin-bottom: 16px;
}
.site .hero .eyebrow .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--brand); flex: none; }
.site .hero h1 {
  font-size: clamp(31px, 4.4vw, 52px); font-weight: 900; line-height: 1.17;
  color: #fff; margin: 0 0 18px; text-wrap: balance;
}
.site .hero h1 em { font-style: normal; color: var(--brand); }
.site .hero .lead { font-size: 17.5px; color: rgba(255,255,255,.80); max-width: 54ch; margin: 0 0 30px; }
.site .hero-actions { display: flex; flex-wrap: wrap; gap: 12px; }

/* The photograph, framed as a plate rather than stretched behind the text.
   The source files top out at 1130px, so a full-bleed crop would be soft;
   at plate size they are at or below native resolution and stay sharp. */
.site .plate { position: relative; }
.site .plate img {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover;
  border-radius: var(--r); display: block;
  box-shadow: 0 26px 60px rgba(0,0,0,.42);
}
.site .plate figcaption {
  position: absolute; inset-inline-start: 14px; inset-block-end: 14px;
  inset-inline-end: 14px;
  background: rgba(36,16,67,.86); color: rgba(255,255,255,.92);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  font-size: 12.5px; padding: 8px 12px; border-radius: var(--r-sm);
  border-inline-start: 3px solid var(--brand);
}

/* ==========================================================================
   Figure strip — real numbers only, straight off the catalogue
   ========================================================================== */
.site .figs {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1px; background: var(--line); border-block: 1px solid var(--line);
}
.site .figs > div { background: var(--sand); padding: 22px 24px; }
.site .figs .fig {
  display: block; font-size: 25px; font-weight: 900; color: var(--ink);
  line-height: 1.2; margin-bottom: 3px;
}
.site .figs .fig small { font-size: 15px; font-weight: 700; color: var(--brand-ink); }
.site .figs span.lbl { font-size: 13.5px; color: var(--muted); display: block; }

/* ==========================================================================
   Product cards
   ========================================================================== */
.site .grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(268px, 1fr)); gap: 20px;
}
.site .grid.wide { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }

.site .pcard {
  display: flex; flex-direction: column; background: var(--paper);
  border: 1px solid var(--line); border-radius: var(--r); overflow: hidden;
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease), transform .15s var(--ease);
}
.site .pcard:hover {
  border-color: var(--line-strong); transform: translateY(-2px);
  box-shadow: 0 14px 34px rgba(36,16,67,.10);
}
.site .pcard:focus-within { border-color: var(--ink); }
.site .pshot { position: relative; aspect-ratio: 4 / 3; background: var(--sand); overflow: hidden; }
.site .pshot img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  aspect-ratio: auto;
  transition: transform .4s var(--ease);
}
.site .pcard:hover .pshot img { transform: scale(1.035); }

/* The two families the profile was never photographed for get a cast plate,
   not a borrowed picture: the code stamped on a concrete-grey ground. */
.site .pshot.none {
  display: grid; place-items: center; text-align: center;
  background:
    repeating-linear-gradient(135deg, rgba(36,16,67,.035) 0 11px, transparent 11px 22px),
    var(--sand);
}
.site .pshot.none span {
  font-size: 13px; font-weight: 900; letter-spacing: .13em; color: var(--muted);
  border: 1px dashed var(--line-strong); border-radius: 6px; padding: 9px 14px;
  direction: ltr; unicode-bidi: isolate; background: rgba(255,255,255,.6);
}
.site .pshot .code {
  position: absolute; inset-block-start: 10px; inset-inline-start: 10px;
  background: rgba(255,255,255,.95); color: var(--ink);
  font-size: 11.5px; font-weight: 900; letter-spacing: .05em;
  padding: 5px 10px; border-radius: 999px;
  /* `plaintext` and not `direction:ltr`: setting direction on this element
     would also flip what inset-inline-start means, and the chip would jump
     to the wrong corner of an RTL card. plaintext takes the run direction
     from the text itself and leaves the box where the page put it. */
  unicode-bidi: plaintext;
}
.site .pbody { padding: 18px; display: flex; flex-direction: column; gap: 12px; flex: 1; }
.site .pbody h3 { font-size: 16.5px; font-weight: 700; margin: 0; line-height: 1.35; }
.site .pbody h3 a { text-decoration: none; color: inherit; }
.site .pbody h3 a:hover { color: var(--brand-ink); }
.site .pbody .blurb { font-size: 14px; color: var(--muted); margin: 0; }
.site .pdim { padding-top: 12px; border-top: 1px dashed var(--line); }
.site .pmeta {
  display: flex; flex-wrap: wrap; gap: 6px;
}
.site .chipnum {
  font-size: 11.5px; font-weight: 700; padding: 4px 10px; border-radius: 999px;
  background: var(--brand-wash); color: var(--ink);
  direction: ltr; unicode-bidi: isolate; font-variant-numeric: tabular-nums;
}
.site .chipnum.plain { background: var(--ink-wash); }
/* The buttons sit on the card floor, so a row of cards has one action line
   across it however long the blurbs and sizes above them run. */
.site .pact { display: flex; gap: 8px; flex-wrap: wrap; margin-top: auto; padding-top: 4px; }

/* ==========================================================================
   Filters
   ========================================================================== */
.site .chips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 30px; }
.site .chips a {
  display: inline-flex; align-items: baseline; gap: 7px;
  padding: 8px 15px; border-radius: 999px; text-decoration: none;
  border: 1px solid var(--line-strong); background: var(--paper);
  color: var(--ink); font-size: 14px; font-weight: 500;
  transition: background .15s var(--ease), border-color .15s var(--ease), color .15s var(--ease);
}
.site .chips a:hover { background: var(--sand); border-color: var(--ink); }
.site .chips a[aria-current="true"] {
  background: var(--ink); border-color: var(--ink); color: #fff; font-weight: 700;
}
.site .chips a .n {
  font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums;
  direction: ltr; unicode-bidi: isolate;
}
.site .chips a[aria-current="true"] .n { color: rgba(255,255,255,.7); }

.site .empty {
  border: 1px dashed var(--line-strong); border-radius: var(--r);
  background: var(--sand); padding: 46px 28px; text-align: center;
}
.site .empty h3 { font-size: 18px; margin: 0 0 8px; }
.site .empty p { color: var(--muted); margin: 0 0 18px; }

/* ==========================================================================
   Process — a numbered sequence with the matching plant photograph
   ========================================================================== */
.site .steps { display: grid; gap: 20px; grid-template-columns: repeat(3, 1fr); counter-reset: step; }
.site .step {
  background: rgba(255,255,255,.055); border: 1px solid rgba(255,255,255,.12);
  border-radius: var(--r); overflow: hidden; display: flex; flex-direction: column;
  transition: border-color .15s var(--ease), background .15s var(--ease);
}
.site .step:hover { border-color: rgba(249,113,31,.5); background: rgba(255,255,255,.08); }
.site .step img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; display: block; }
.site .step .inner { padding: 20px 22px 24px; }
.site .step .n {
  display: inline-grid; place-items: center; width: 34px; height: 34px;
  border-radius: 8px; background: var(--brand); color: var(--ink);
  font-weight: 900; font-size: 15px; margin-bottom: 12px;
  direction: ltr; unicode-bidi: isolate; font-variant-numeric: tabular-nums;
}
.site .step h3 { font-size: 17px; margin: 0 0 8px; }
.site .step p { font-size: 14.5px; color: rgba(255,255,255,.72); margin: 0; }

/* ==========================================================================
   Feature / point lists
   ========================================================================== */
.site .feats { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 18px; }
.site .feat {
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r);
  padding: 22px; transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.site .band--sand .feat { background: var(--paper); }
.site .feat:hover { border-color: var(--line-strong); box-shadow: 0 10px 26px rgba(36,16,67,.07); }
.site .feat h3 { font-size: 16.5px; margin: 0 0 8px; }
.site .feat p { font-size: 14.5px; color: var(--muted); margin: 0; }
.site .feat .mk {
  width: 30px; height: 3px; border-radius: 3px; background: var(--brand);
  display: block; margin-bottom: 14px;
}

.site .ticks { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.site .ticks li {
  display: flex; gap: 11px; align-items: flex-start;
  font-size: 15.5px; line-height: 1.6;
}
.site .ticks li::before {
  content: ""; flex: none; width: 9px; height: 9px; margin-top: 8px;
  background: var(--brand); border-radius: 2px; transform: rotate(45deg);
}
.site .band--ink .ticks li { color: rgba(255,255,255,.84); }

.site .two { display: grid; grid-template-columns: 1.25fr 1fr; gap: 48px; align-items: start; }
.site .two.even { grid-template-columns: 1fr 1fr; }
/* The CEO's message takes the wider half. Written here rather than
   inline on the element, so the rule that collapses `.two` on a narrow
   screen can still reach it - an inline style cannot be beaten by a
   media query, and this section used to stay in two columns on a phone
   and carry the whole page 69px wider than the screen. */
.site .two--ceo { grid-template-columns: .9fr 1.1fr; }
.site .prose { font-size: 16.5px; line-height: 1.85; color: var(--ink); }
.site .prose.pre { white-space: pre-line; }
.site .band--ink .prose { color: rgba(255,255,255,.82); }

/* ==========================================================================
   Team, org chart, certificates, tables
   ========================================================================== */
.site .person {
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r);
  padding: 22px; display: flex; flex-direction: column; gap: 10px;
}
.site .person .initials {
  width: 46px; height: 46px; border-radius: 12px; display: grid; place-items: center;
  background: var(--ink); color: var(--brand); font-weight: 900; font-size: 16px;
  direction: ltr; unicode-bidi: isolate;
}
.site .person b { font-size: 16px; display: block; direction: ltr; unicode-bidi: isolate; text-align: start; }
.site .person .role { font-size: 13px; font-weight: 700; color: var(--brand-ink); }
.site .person p { font-size: 14px; color: var(--muted); margin: 0; }

.site .org { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 16px; }
.site .org .dept {
  border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; background: var(--paper);
}
.site .org .dept h3 {
  margin: 0; font-size: 14.5px; padding: 12px 16px;
  background: var(--ink); color: #fff; font-weight: 700;
}
.site .org .dept ul { list-style: none; margin: 0; padding: 8px 16px 14px; display: grid; gap: 2px; }
.site .org .dept li {
  font-size: 14px; color: var(--muted); padding: 5px 0 5px 0;
  border-bottom: 1px dashed var(--line);
}
.site .org .dept li:last-child { border-bottom: 0; }

.site .certs { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.site .certs li {
  display: grid; grid-template-columns: 38px 1fr; gap: 16px; align-items: start;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r);
  padding: 18px 20px;
}
.site .certs .seal {
  width: 38px; height: 38px; border-radius: 50%;
  background: var(--brand-wash); border: 2px solid var(--brand);
  display: grid; place-items: center; color: var(--brand-ink); font-weight: 900; font-size: 15px;
}
.site .certs b { display: block; font-size: 15.5px; margin-bottom: 3px; }
.site .certs .issuer { font-size: 13.5px; font-weight: 700; color: var(--brand-ink); display: block; margin-bottom: 5px; }
.site .certs p { font-size: 14px; color: var(--muted); margin: 0; }

.site .tablewrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--r); background: var(--paper); }
.site table.grid3 { width: 100%; border-collapse: collapse; min-width: 560px; }
.site table.grid3 th, .site table.grid3 td {
  text-align: start; padding: 13px 18px; font-size: 14.5px;
  border-bottom: 1px solid var(--line); vertical-align: top;
}
.site table.grid3 thead th {
  background: var(--ink); color: #fff; font-weight: 700; font-size: 13.5px;
  letter-spacing: .03em; border-bottom: 0;
}
.site table.grid3 tbody tr:last-child td { border-bottom: 0; }
.site table.grid3 tbody tr:nth-child(even) td { background: var(--sand); }
.site table.grid3 td:first-child { font-weight: 700; color: var(--ink); }
/* A two-column spec sheet: the labels take a fixed measure so the values
   line up in a column instead of floating at the halfway mark. */
.site table.grid3.specs td:first-child { width: 230px; }
.site table.grid3 td.ctl { color: var(--brand-ink); font-weight: 700; }

/* The method statement, as a numbered run of steps */
.site .method { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; counter-reset: m; }
.site .method li {
  display: grid; grid-template-columns: 54px 1fr; gap: 18px; align-items: start;
  padding: 20px 4px; border-bottom: 1px solid var(--line);
}
.site .method li:last-child { border-bottom: 0; }
.site .method li::before {
  counter-increment: m; content: counter(m, decimal-leading-zero);
  font-size: 17px; font-weight: 900; color: var(--brand-ink);
  font-variant-numeric: tabular-nums; direction: ltr; unicode-bidi: isolate;
  border-inline-start: 3px solid var(--brand); padding-inline-start: 12px; line-height: 1.3;
}
.site .method h3 { font-size: 16px; margin: 0 0 6px; }
.site .method p { font-size: 14.5px; color: var(--muted); margin: 0; }

/* ==========================================================================
   Gallery and lightbox
   ========================================================================== */
.site .tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(258px, 1fr)); gap: 16px; }
.site .tile { margin: 0; position: relative; }
.site .tile a {
  display: block; border-radius: var(--r); overflow: hidden; position: relative;
  border: 1px solid var(--line); background: var(--sand);
  transition: box-shadow .15s var(--ease), transform .15s var(--ease);
}
.site .tile a:hover { transform: translateY(-2px); box-shadow: 0 14px 32px rgba(36,16,67,.16); }
.site .tile img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block; }
.site .tile figcaption { font-size: 13.5px; color: var(--muted); padding: 10px 2px 0; }
.site .tile .zoom {
  position: absolute; inset-block-end: 10px; inset-inline-end: 10px;
  width: 30px; height: 30px; border-radius: 50%;
  background: rgba(255,255,255,.94); color: var(--ink);
  display: grid; place-items: center; font-size: 15px; font-weight: 900;
  opacity: 0; transition: opacity .15s var(--ease);
}
.site .tile a:hover .zoom, .site .tile a:focus-visible .zoom { opacity: 1; }

/* While the viewer is open the header drops its backdrop-filter. An
   element that filters its backdrop composites after the overlay above it,
   so the sticky header paints through a translucent full-screen layer even
   though the layer is higher in z-order and wins hit-testing. Removing the
   filter for that moment puts it back under where it belongs. */
.site.lb-open .site-head { -webkit-backdrop-filter: none; backdrop-filter: none; }

.site .lbox {
  position: fixed; inset: 0; z-index: 90; display: none;
  background: rgba(20,8,38,.93); padding: 24px;
  place-items: center;
}
.site .lbox[open-now] { display: grid; }
.site .lbox figure { margin: 0; max-width: min(1000px, 94vw); text-align: center; }
.site .lbox img {
  max-width: 100%; max-height: 74vh; width: auto; border-radius: var(--r);
  box-shadow: 0 30px 80px rgba(0,0,0,.6); margin: 0 auto;
}
.site .lbox figcaption { color: rgba(255,255,255,.88); font-size: 15px; margin-top: 16px; }
.site .lbox .counter {
  color: rgba(255,255,255,.5); font-size: 13px; margin-top: 6px;
  direction: ltr; unicode-bidi: isolate; font-variant-numeric: tabular-nums;
}
.site .lbox button {
  position: absolute; background: rgba(255,255,255,.12); color: #fff;
  border: 1px solid rgba(255,255,255,.28); border-radius: 50%;
  width: 46px; height: 46px; font-size: 20px; cursor: pointer; line-height: 1;
  display: grid; place-items: center; font-family: inherit;
  transition: background .15s var(--ease);
}
.site .lbox button:hover { background: rgba(255,255,255,.26); }
.site .lbox .lb-close { top: 18px; inset-inline-end: 18px; }
.site .lbox .lb-prev { top: 50%; inset-inline-start: 18px; transform: translateY(-50%); }
.site .lbox .lb-next { top: 50%; inset-inline-end: 18px; transform: translateY(-50%); }

/* ==========================================================================
   Quote form
   ========================================================================== */
.site .qform {
  display: grid; grid-template-columns: 1fr 1fr; gap: 15px;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r); padding: 26px;
}
.site .qform .full { grid-column: 1 / -1; }
.site .qform label { font-size: 13.5px; color: var(--muted); font-weight: 500; gap: 6px; }
.site .qform label > span { display: block; }
.site .qform label .req { color: var(--brand-ink); font-weight: 900; font-style: normal; }
.site .qform input, .site .qform textarea, .site .qform select {
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  padding: 11px 13px; color: var(--ink); background: var(--paper);
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.site .qform input:hover, .site .qform textarea:hover { border-color: var(--muted); }
.site .qform input:focus, .site .qform textarea:focus, .site .qform select:focus {
  outline: 3px solid var(--ink); outline-offset: 1px; border-color: var(--ink);
}
.site .qform .note { font-size: 13px; color: var(--muted); margin: 0; }

.site .contact-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.site .contact-list li {
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r);
  padding: 15px 18px;
}
.site .band--sand .contact-list li { background: var(--paper); }
.site .contact-list .k {
  display: block; font-size: 12px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--brand-ink); margin-bottom: 4px;
}
.site .contact-list a { color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--line-strong); }
.site .contact-list a:hover { border-bottom-color: var(--brand); color: var(--brand-ink); }
.site .contact-list .pre { white-space: pre-line; color: var(--muted); font-size: 14.5px; }

/* ==========================================================================
   Call to action band
   ========================================================================== */
.site .cta { background: var(--ink-2); color: #fff; }
.site .cta .inner {
  display: flex; flex-wrap: wrap; align-items: center; gap: 26px;
  padding: 44px 0;
}
.site .cta h2 { font-size: clamp(22px, 2.4vw, 28px); margin: 0 0 6px; color: #fff; }
.site .cta p { color: rgba(255,255,255,.72); margin: 0; font-size: 15.5px; }
.site .cta .acts { margin-inline-start: auto; display: flex; gap: 12px; flex-wrap: wrap; }

/* ==========================================================================
   Footer, flashes, floating WhatsApp — base.html owns the markup, this
   only re-tones it so the public pages end on the same navy as the hero.
   ========================================================================== */
.site .site-footer {
  background: var(--ink); color: rgba(255,255,255,.72);
  /* base.html's footer markup uses .muted, which is a grey meant for paper.
     On navy it lands at 3:1. Rebinding the token for this subtree is enough
     - the markup is not ours to change and does not need to be. */
  --muted: rgba(255,255,255,.72);
}
.site .site-footer a:hover { color: var(--brand); }
.site .footer-brand img { height: 40px; }
.site .site-footer .credit { border-top-color: rgba(255,255,255,.14); color: rgba(255,255,255,.5); }
.site .site-footer .credit .dev a { color: var(--brand); }
/* The old `.wa` telephone glyph is gone from every public template - see
   THE WHATSAPP BUTTON below - so there is nothing left here to re-tone. */
.site .flash { background: var(--ink); }
.site .flash.ok { background: #176B3A; }

/* ==========================================================================
   Motion. Felt, not watched: one reveal on first sight, nothing on a loop.
   The reveal only hides anything once the script has marked the page `js`,
   so with JavaScript off the content is simply there.
   ========================================================================== */
.site.js [data-rv] {
  opacity: 0; transform: translateY(16px);
  transition: opacity .6s var(--ease), transform .6s var(--ease);
}
.site.js [data-rv].rv-in { opacity: 1; transform: none; }

/* ONE place decides how long a thing waits before it arrives, and that is
   the --rv-i below. The numbers a template writes into `data-rv` set it, and
   the script sets it inline on the children of a stagger group - an inline
   custom property beats any rule here, so a grid's true index always wins
   over the template's hand-written one with no specificity games. */
.site.js [data-rv="2"] { --rv-i: 1; }
.site.js [data-rv="3"] { --rv-i: 2; }
.site.js [data-rv="4"] { --rv-i: 3; }

@media (prefers-reduced-motion: reduce) {
  .site.js [data-rv] { opacity: 1 !important; transform: none !important; transition: none !important; }
  .site * { animation-duration: .001ms !important; transition-duration: .001ms !important; }
  .site .pcard:hover { transform: none; }
  .site .pcard:hover .pshot img { transform: none; }
}

/* ==========================================================================
   Responsive. Nothing overflows sideways at any width, in either direction.
   ========================================================================== */
@media (max-width: 1040px) {
  .site .hero-inner { gap: 36px; }
  .site .steps { grid-template-columns: 1fr; }
  .site .two, .site .two.even, .site .two--ceo { grid-template-columns: 1fr; gap: 34px; }
}

@media (max-width: 900px) {
  .site { --head-h: 68px; }
  /* Direct child only: the same .btn also appears inside the phone panel,
     and a descendant selector would hide it there too. */
  .site .site-nav, .site .head-actions > .btn { display: none; }
  .site .menu { display: block; }
  .site .hero-inner { grid-template-columns: 1fr; padding: 54px 20px 56px; }
  .site .hero .plate, .site .hero .hero-plate { order: -1; }
  .site .plate img { aspect-ratio: 3 / 2; }
  .site .band { padding: 56px 0; }
  .site .cta .acts { margin-inline-start: 0; }
}

@media (max-width: 620px) {
  .site .wrap { padding: 0 16px; }
  .site .hero-inner { padding: 44px 16px 48px; }
  .site .qform { grid-template-columns: 1fr; padding: 20px; }
  .site .grid { grid-template-columns: 1fr; }
  .site .tiles { grid-template-columns: 1fr; }
  .site .figs > div { padding: 18px 16px; }
  .site .brandmark img { height: 31px; }
  .site .method li { grid-template-columns: 42px 1fr; gap: 12px; }
  .site .certs li { grid-template-columns: 1fr; gap: 10px; }
  .site .lbox { padding: 14px; }
  .site .lbox .lb-prev, .site .lbox .lb-next { top: auto; bottom: 16px; transform: none; width: 42px; height: 42px; }
  .site .lbox .lb-prev { inset-inline-start: 24%; }
  .site .lbox .lb-next { inset-inline-end: 24%; }
}

/* ==========================================================================
   Page furniture added by the individual pages
   ========================================================================== */
.site .crumbs { display: flex; flex-wrap: wrap; gap: 9px; font-size: 13.5px; color: var(--muted); }
.site .crumbs a { color: var(--muted); text-decoration: none; }
.site .crumbs a:hover { color: var(--ink); text-decoration: underline; }
.site .crumbs span { opacity: .5; }

/* The same step card on a light band. */
.site .steps.light .step { background: var(--paper); border-color: var(--line); }
.site .steps.light .step:hover { background: var(--paper); border-color: var(--line-strong); box-shadow: 0 12px 30px rgba(36,16,67,.09); }
.site .steps.light .step h3 { color: var(--ink); }
.site .steps.light .step p { color: var(--muted); }

.site .hsecard {
  background: rgba(255,255,255,.05); border: 1px solid rgba(255,255,255,.12);
  border-radius: var(--r); padding: 20px 22px;
  transition: border-color .15s var(--ease), background .15s var(--ease);
}
.site .hsecard:hover { border-color: rgba(249,113,31,.5); background: rgba(255,255,255,.08); }
.site .hsecard .n {
  display: block; font-size: 12.5px; font-weight: 900; color: var(--brand);
  letter-spacing: .08em; margin-bottom: 9px;
  direction: ltr; unicode-bidi: isolate; font-variant-numeric: tabular-nums;
}
.site .hsecard h3 { font-size: 16px; margin: 0 0 7px; color: #fff; }
.site .hsecard p { font-size: 14.5px; color: rgba(255,255,255,.70); margin: 0; }

.site .ceo-msg {
  margin: 0; padding: 28px 30px;
  background: rgba(255,255,255,.05);
  border: 1px solid rgba(255,255,255,.12);
  border-inline-start: 4px solid var(--brand);
  border-radius: var(--r); font-size: 16px; line-height: 1.95;
}

/* The figure strip is used inside a band on the quality page, where it
   needs its own edges rather than the full-bleed ones. */
.site .band .figs { border: 1px solid var(--line); }

/* ---------------------------------------------------------- utility bar
   Navy strip above the white header: it separates the page from the
   browser chrome, carries the three facts a contractor looks for first,
   and gives the paper header an edge to sit on. Hidden on a phone, where
   the same details are one tap away in the menu and the screen is needed
   for the page. */
.site .utility { background: var(--ink); color: rgba(255,255,255,.82); font-size: 13px; }
.site .utility-inner { display: flex; align-items: center; gap: 18px;
  min-height: 36px; flex-wrap: wrap; }
.site .utility .u-reach { margin-inline-start: auto; display: flex; gap: 16px; }
.site .utility a { color: #fff; text-decoration: none; border-bottom: 1px solid rgba(255,255,255,.28); }
.site .utility a:hover { border-bottom-color: var(--brand); color: var(--brand); }
.site .utility .u-where::before { content: "\25C6"; color: var(--brand);
  margin-inline-end: 7px; font-size: 9px; vertical-align: 2px; }
@media (max-width: 760px) { .site .utility { display: none; } }

/* ------------------------------------------------------------- portraits
   The plant's own people, on the plant's own profile. The picture is
   cropped square at the source, so the box is square too and object-fit
   only ever has to correct for a browser rounding a fractional column. */
.site .person .portrait {
  width: 76px; height: 76px; border-radius: 16px; object-fit: cover;
  object-position: 50% 22%; display: block; flex: none; background: var(--sand);
  border: 1px solid var(--line);
}
/* Portrait and name read as one unit; the note sits under both. */
.site .person header { display: flex; align-items: center; gap: 14px; }
.site .person header > div { min-width: 0; }
/* Four people, four columns, and no card stranded on a row of its own. */
.site .grid.team { grid-template-columns: repeat(auto-fit, minmax(248px, 1fr)); }

/* The CEO's message: his photograph sits with his name, the way the
   company profile prints it. On a phone the two stack. */
.site .ceo-card { display: flex; gap: 22px; align-items: center; flex-wrap: wrap; }
.site .ceo-card .portrait-lg { margin: 0; flex: none; }
.site .ceo-card .portrait-lg img {
  width: 148px; height: 148px; border-radius: 20px; object-fit: cover;
  display: block; background: var(--sand);
  border: 1px solid rgba(255,255,255,.16);
  box-shadow: 0 16px 40px rgba(0,0,0,.28);
}
.site .ceo-card .ceo-id { min-width: 220px; flex: 1 1 220px; }
@media (max-width: 520px) {
  .site .ceo-card .portrait-lg img { width: 112px; height: 112px; }
}

/* ------------------------------------------------- approvals / partners
   Who the plant is approved by. The mark is cropped from the organisation's
   own document, so it arrives on its own white ground and keeps it: a mark
   tinted to match the page is a mark altered. */
.site .markstrip, .site .partners { list-style: none; margin: 0; padding: 0; }

.site .markstrip {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 16px;
}
.site .markstrip li {
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r); padding: 16px 16px 14px;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  text-align: center;
}
.site .markstrip img {
  width: 100%; max-width: 168px; height: auto; display: block;
  mix-blend-mode: multiply;
}
.site .markstrip .rel {
  font-size: 12.5px; font-weight: 700; color: var(--brand-ink);
  line-height: 1.45;
}

.site .partners { display: grid; gap: 14px; }
.site .partners li {
  display: grid; grid-template-columns: 184px 1fr; gap: 22px; align-items: center;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r); padding: 20px 22px;
}
.site .partners .mark {
  margin: 0; background: #fff; border: 1px solid var(--line);
  border-radius: 12px; padding: 12px; display: grid; place-items: center;
}
.site .partners .mark img {
  width: 100%; height: auto; display: block; mix-blend-mode: multiply;
}
.site .partners b { display: block; font-size: 16.5px; margin-bottom: 7px; }
/* Orange ground carries --ink, never white: white on this orange is 2.83:1. */
.site .partners .rel {
  display: inline-block; background: var(--brand); color: var(--ink);
  font-size: 12.5px; font-weight: 800; border-radius: 999px;
  padding: 3px 11px; margin-bottom: 9px;
}
.site .partners p { font-size: 14.5px; color: var(--muted); margin: 0; line-height: 1.8; }

.site .fineprint {
  margin: 20px 0 0; font-size: 13px; color: var(--muted); line-height: 1.8;
  border-inline-start: 3px solid var(--line-strong); padding-inline-start: 14px;
  max-width: 78ch;
}

@media (max-width: 620px) {
  .site .partners li { grid-template-columns: 1fr; gap: 14px; }
  .site .partners .mark { max-width: 200px; }
}

/* The sample count beside the catalogue link on the front page. */
.site .more { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.site .more .shown { font-size: 13.5px; color: var(--muted); font-weight: 600; }


/* ==========================================================================
   ==========================================================================
   THE CRAFT PASS
   ==========================================================================

   Everything below is scoped to `.site` like everything above it.

   THE CURVE. Two, chosen on purpose and used everywhere:

     --ease        cubic-bezier(.2,.7,.3,1)   already here. It leaves at once
                   and settles long. It is for states a finger is waiting on
                   - hover, focus, press - where any delay reads as lag.

     --ease-weight cubic-bezier(.33,0,.2,1)   new. It holds for a beat before
                   it moves, then glides to a stop with no overshoot. That
                   hesitation is the whole point: this is a plant that casts
                   five-tonne blocks, and a panel that springs into place
                   like a toy is the wrong material. It is for anything that
                   arrives on its own - reveals, the hero strip, images
                   decoding - never for anything a person is pressing.

   THE NEW COLOURS, each measured against the ground it actually sits on,
   with the ratio written beside it. Nothing here was chosen by eye.

     --wa     #17803F  WhatsApp resting  white glyph 5.00:1
                                         disc on paper 5.00:1, on sand 4.56:1,
                                         on the navy hero 3.41:1
     --wa-hi  #1E8A4C  WhatsApp hover    white glyph 4.38:1
     --wa-lo  #136A33  WhatsApp pressed  white glyph 6.69:1
     --flow   #D95B10  progress fills    3.85:1 on paper. NOT --brand, which
                                         is 2.83:1 on paper and would fail
                                         the 3:1 a meaningful graphic needs.
     --scrim  #1B0C33  photo captions    white on it 18.31:1,
                                         --brand on it 6.46:1
   ========================================================================== */

.site {
  --ease-weight: cubic-bezier(.33, 0, .2, 1);
  --wa: #17803F;
  --wa-hi: #1E8A4C;
  --wa-lo: #136A33;
  --flow: #D95B10;
  --scrim: #1B0C33;
  --rail-h: 40px;
}

/* ---------------------------------------------------------- the basics ---
   Fixes small enough to be invisible and loud enough when they are missing.
   -------------------------------------------------------------------------- */

/* Visually hidden, the only safe recipe on an RTL page: clipped in place,
   never pushed off-canvas. A negative inline offset adds ten thousand pixels
   of horizontal scroll to this layout - it has happened here before, and the
   honeypot in the quote form still carries the same recipe for the same
   reason. */
.site .vh {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
  padding: 0; margin: -1px; border: 0;
}

/* THE ANCHOR OFFSET.

   One offset, not two. scroll-padding on <html> and scroll-margin on the
   target both push an anchor down and they ADD: with both set, every
   heading landed 134px further down the page than it needed to. The target
   keeps the margin, because that works without owning the scroll container
   - which is <html>, outside this stylesheet's scope - and because it also
   covers an in-page scrollIntoView.

   --sticky-h is how much of the top of the screen is permanently spoken
   for. The quality page carries a second rail of its own and says so with
   a body class, rather than this file guessing. */
.site { --sticky-h: calc(var(--head-h) + var(--rail-h)); }
.site.has-rail { --sticky-h: calc(var(--head-h) + var(--rail-h) + 50px); }
.site [id] { scroll-margin-top: calc(var(--sticky-h) + 18px); }

/* List markers in the brand, not browser black. */
.site li::marker { color: var(--brand-ink); }
.site .band--ink li::marker, .site .on-dark li::marker { color: var(--brand); }

/* The skip link lands on paper, so it is drawn as ink and announces itself
   with the same rule the header sits on. */
.site .skip {
  transition: top .18s var(--ease);
  box-shadow: 0 10px 30px rgba(36, 16, 67, .3);
  border-block-end: 3px solid var(--brand);
}

/* ------------------------------------------------- the scroll indicator ---
   How far down the page you are, drawn as one 3px line across the very top.
   It is a graphic that carries meaning, so it is measured: --flow is 3.85:1
   on paper where --brand would be 2.83:1.

   Where the browser can drive it from the scroll position itself, it does,
   and no JavaScript runs at all. Where it cannot, the script writes --sp and
   this same rule reads it - one custom property, one compositor transform,
   no layout read on any frame.
   -------------------------------------------------------------------------- */
.site .sprogress {
  position: fixed; inset-block-start: 0; inset-inline: 0; height: 3px;
  z-index: 60; pointer-events: none;
}
.site .sprogress i {
  display: block; height: 100%; background: var(--flow);
  transform: scaleX(var(--sp, 0)); transform-origin: 0 50%;
  will-change: transform;
}
/* transform-origin has no logical form, so the reading direction is read off
   the document and the origin named explicitly. This is the one physical
   value in the file, and it is here because there is no logical one. */
[dir="rtl"] .site .sprogress i { transform-origin: 100% 50%; }

@supports (animation-timeline: scroll()) {
  .site .sprogress i {
    transform: scaleX(0);
    animation: sprogress linear both;
    animation-timeline: scroll(root block);
  }
  @keyframes sprogress { to { transform: scaleX(1); } }
}

/* --------------------------------------------- the header, once scrolled ---
   At rest the header is a sheet of paper lying on the page. Once the page
   has moved under it, it lifts: a shadow it did not have, a ground that
   stops being translucent, and the millimetre rule beneath it fading back so
   the shadow is the only edge. Nothing here is driven by a scroll handler -
   a one-pixel sentinel above the header tells an observer when it has gone.
   -------------------------------------------------------------------------- */
.site .site-head {
  transition: box-shadow .22s var(--ease), background-color .22s var(--ease);
}
.site .site-head.is-stuck {
  background: rgba(255, 255, 255, .985);
  box-shadow: 0 1px 0 var(--line), 0 14px 34px -14px rgba(36, 16, 67, .34);
}
.site .site-head .rule { transition: opacity .22s var(--ease); }
.site .site-head.is-stuck .rule { opacity: .35; }
.site .head-sentinel { position: absolute; inset-block-start: 0; height: 1px; width: 1px; }
.site .brandmark img { transition: transform .22s var(--ease); transform-origin: center; }
.site .site-head.is-stuck .brandmark img { transform: scale(.94); }

/* ------------------------------------------------------- the answer rail ---
   The four things a main contractor pricing a job wants to know, one tap
   from every page: do you make my element, to what grade, how long, and will
   my consultant accept you. It rides inside the sticky header, so the answer
   to each is one move away wherever the visitor has got to.
   -------------------------------------------------------------------------- */
.site .askbar {
  background: var(--sand); border-block-start: 1px solid var(--line);
  /* the border is drawn outside the target, so the links inside still get
     the full --rail-h and a phone still gets its 44 pixels */
  block-size: calc(var(--rail-h) + 1px);
}
.site .askbar-inner {
  display: flex; align-items: stretch; gap: 2px; block-size: 100%;
  overflow-x: auto; overflow-y: hidden;
  scrollbar-width: none; -ms-overflow-style: none;
  scroll-snap-type: inline proximity;
  overscroll-behavior-inline: contain;
}
.site .askbar-inner::-webkit-scrollbar { display: none; }
/* The rail runs past the edge of a phone. A fade on the end it runs towards
   says there is more, without a scrollbar and without a control. The mask is
   written in logical terms, so it fades the left in Arabic and the right in
   English on its own. */
@media (max-width: 760px) {
  .site .askbar {
    -webkit-mask-image: linear-gradient(to left, transparent 0, #000 26px);
            mask-image: linear-gradient(to left, transparent 0, #000 26px);
  }
  [dir="rtl"] .site .askbar {
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 26px);
            mask-image: linear-gradient(to right, transparent 0, #000 26px);
  }
}
.site .askbar-k {
  display: flex; align-items: center; flex: none; padding-inline-end: 12px;
  font-size: 11.5px; font-weight: 800; letter-spacing: .1em;
  text-transform: uppercase; color: var(--muted); white-space: nowrap;
}
.site .askbar a {
  display: inline-flex; align-items: center; gap: 7px; flex: none;
  padding-inline: 13px; text-decoration: none; white-space: nowrap;
  font-size: 13.5px; font-weight: 600; color: var(--ink);
  scroll-snap-align: start; position: relative;
  transition: color .15s var(--ease), background-color .15s var(--ease);
}
.site .askbar a::before {
  content: ""; inline-size: 5px; block-size: 5px; border-radius: 1px;
  background: var(--brand); transform: rotate(45deg); flex: none;
  transition: transform .18s var(--ease);
}
.site .askbar a:hover { background: var(--paper); color: var(--brand-ink); }
.site .askbar a:hover::before { transform: rotate(135deg); }
.site .askbar a[aria-current="page"] { font-weight: 800; }
.site .askbar a[aria-current="page"]::after {
  content: ""; position: absolute; inset-inline: 10px; inset-block-end: 0;
  block-size: 2px; background: var(--brand-ink);
}
@media (max-width: 620px) {
  .site { --rail-h: 44px; }
  .site .askbar-k { display: none; }
  .site .askbar a { font-size: 13px; padding-inline: 11px; }
}

/* =========================================================================
   THE WHATSAPP BUTTON

   Before: the character U+2706 - a telephone - set in a green circle, at
   whatever size the font felt like, with no hover, no focus ring and the
   accessible name "WhatsApp".

   After: the actual mark, drawn as a path. A disc that reads as a physical
   cap - a highlight along its top edge, a shadow beneath it tinted with its
   own green rather than grey - that lifts on hover and presses on click. The
   label rides beside it on a pointer device and is never built on a phone,
   where it would be a tooltip nobody can summon sitting on top of the page.
   ========================================================================= */
.site .wafab {
  position: fixed; z-index: 45;
  inset-inline-end: 20px;
  inset-block-end: calc(20px + env(safe-area-inset-bottom, 0px));
  display: flex; align-items: center; gap: 10px;
  text-decoration: none; line-height: 0;
  /* The anchor is the 56px disc plus the label; only the disc is drawn, so
     the hit area is never smaller than the thing you can see. */
}
.site .wafab-disc {
  inline-size: 56px; block-size: 56px; border-radius: 50%;
  display: grid; place-items: center; flex: none;
  background: var(--wa); color: #fff;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .26),
    inset 0 -1px 0 rgba(0, 0, 0, .18),
    0 6px 16px -4px rgba(10, 48, 24, .55),
    0 14px 34px -10px rgba(10, 48, 24, .42);
  transition:
    background-color .17s var(--ease),
    transform .17s var(--ease),
    box-shadow .17s var(--ease);
}
.site .wafab .wa-mark { display: block; }
.site .wafab:hover .wafab-disc {
  background: var(--wa-hi); transform: translateY(-2px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .3),
    inset 0 -1px 0 rgba(0, 0, 0, .18),
    0 10px 20px -4px rgba(10, 48, 24, .5),
    0 22px 44px -12px rgba(10, 48, 24, .46);
}
.site .wafab:active .wafab-disc {
  background: var(--wa-lo); transform: translateY(0) scale(.965);
  box-shadow:
    inset 0 2px 4px rgba(0, 0, 0, .26),
    0 3px 10px -2px rgba(10, 48, 24, .5);
}
/* A ring that is legible whichever ground the button happens to be floating
   over: a white halo first, then ink. Ink alone disappears on the navy
   footer, and white alone disappears on paper. */
.site .wafab:focus { outline: none; }
.site .wafab:focus-visible .wafab-disc {
  outline: none;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .26),
    0 0 0 3px #fff,
    0 0 0 6px var(--ink),
    0 14px 34px -10px rgba(10, 48, 24, .42);
}
.site .wafab-tip {
  order: -1; /* the label sits on the content side of the disc in both
                directions, because `order` follows the writing mode */
  background: var(--ink); color: #fff;           /* 17.07:1 */
  font-size: 13px; font-weight: 700; line-height: 1.2;
  padding: 9px 13px; border-radius: var(--r-sm); white-space: nowrap;
  box-shadow: 0 10px 26px -8px rgba(36, 16, 67, .55);
  opacity: 0; transform: translateX(6px);
  transition: opacity .17s var(--ease), transform .17s var(--ease);
  pointer-events: none;
}
[dir="rtl"] .site .wafab-tip { transform: translateX(-6px); }
.site .wafab:hover .wafab-tip,
.site .wafab:focus-visible .wafab-tip { opacity: 1; transform: translateX(0); }
/* A phone has no hover, so the label is not drawn at all rather than drawn
   and hidden: a tooltip that can only be summoned by a state the device does
   not have is dead weight in the box. */
@media (hover: none), (pointer: coarse) {
  .site .wafab-tip { display: none; }
}
/* On the product page the sticky action bar already carries WhatsApp with
   the element's name in it, so the floating button stands down on a phone
   rather than stacking a second one on top of it. */
@media (max-width: 760px) {
  .site.product-page .wafab { display: none; }
}

/* =========================================================================
   THE HERO STRIP

   A rotating plate: the plant's own photograph, and one true line out of its
   own profile beside it.

   The stage is a fixed-ratio box and every slide is absolutely placed inside
   it, so the strip cannot change the height of anything as it cycles. The
   caption is anchored to the foot of the stage and grows up into the
   photograph; it never pushes.

   The progress bar is the clock. The slide advances when that animation
   ends, which means :hover and :focus-within pausing the animation in CSS
   pauses the strip itself - there is no timer to keep in step with it, and
   under `prefers-reduced-motion` there is no animation, so there is no
   advance either.
   ========================================================================= */
.site .hero-plate { min-inline-size: 0; }
.site .hstrip { position: relative; display: grid; gap: 14px; min-inline-size: 0; }

.site .hstrip-stage {
  position: relative; aspect-ratio: 4 / 3; overflow: hidden;
  border-radius: var(--r); background: var(--scrim);
  box-shadow: 0 26px 60px rgba(0, 0, 0, .42);
  isolation: isolate; touch-action: pan-y;
}

.site .hslide {
  position: absolute; inset: 0; margin: 0;
  opacity: 0; visibility: hidden;
  transition: opacity .62s var(--ease-weight), visibility 0s linear .62s;
}
.site .hslide.is-on {
  opacity: 1; visibility: visible; z-index: 1;
  transition: opacity .62s var(--ease-weight), visibility 0s;
}
.site .hslide img {
  position: absolute; inset: 0; inline-size: 100%; block-size: 100%;
  object-fit: cover; display: block; aspect-ratio: auto;
  /* A very slow settle while the slide sits - 1.04 down to 1.00 over the
     whole dwell. It is barely a movement; it is the picture coming to
     rest, which is the only kind of motion a concrete yard should have. */
  transform: scale(1.045);
  transition: transform 7.6s linear;
}
.site .hslide.is-on img { transform: scale(1); }

/*
  The caption is one flat scrim where the words are, and a separate band
  above it that fades the scrim into the photograph. It used to be a single
  gradient, which looked the same and could not be measured: a gradient is a
  background IMAGE, so neither a browser nor an audit can read a colour off
  it, and "white on a gradient" is not a contrast ratio.

  Now the ground is rgba(27,12,51,.95), composited over the photograph. The
  floor - the scrim over the brightest photograph the plant owns - measures
  16.1:1 for the title, 11.2:1 for the body and 5.7:1 for the orange kicker.
*/
.site .hslide figcaption {
  position: absolute; inset-inline: 0; inset-block-end: 0;
  padding: 16px 20px 18px;
  display: grid; gap: 7px; align-content: end; color: #fff;
  background-color: rgba(27, 12, 51, .95);
}
.site .hslide figcaption::before {
  content: ""; position: absolute; inset-inline: 0; inset-block-end: 100%;
  block-size: 62px; pointer-events: none;
  background: linear-gradient(to top, rgba(27, 12, 51, .95), rgba(27, 12, 51, 0));
}
.site .hslide figcaption .k {
  font-size: 11.5px; font-weight: 800; letter-spacing: .13em;
  text-transform: uppercase; color: var(--brand);          /* 6.46:1 */
}
.site .hslide figcaption .t {
  font-size: 20px; font-weight: 900; line-height: 1.3; color: #fff;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.site .hslide figcaption .b {
  font-size: 13.5px; line-height: 1.65; color: rgba(255, 255, 255, .82);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.site .hslide figcaption .c {
  display: flex; flex-wrap: wrap; gap: 6px; max-block-size: 24px;
  overflow: hidden;
}
.site .hslide figcaption .c span {
  font-size: 11px; font-weight: 800; color: #fff;
  background: rgba(255, 255, 255, .15); border: 1px solid rgba(255, 255, 255, .34);
  border-radius: 999px; padding: 3px 9px; white-space: nowrap;
  unicode-bidi: plaintext; font-variant-numeric: tabular-nums;
}
.site .hslide figcaption .go {
  justify-self: start; margin-block-start: 3px;
  font-size: 13px; font-weight: 800; color: #fff; text-decoration: none;
  padding-block-end: 3px; border-block-end: 2px solid var(--brand);
  transition: color .15s var(--ease), border-color .15s var(--ease);
}
.site .hslide figcaption .go:hover { color: var(--brand); }

/* The arrows live in the top corner of the stage, clear of the caption, as
   one pair so the two are found together. 44px of target around a 40px disc. */
.site .hstrip-arrows {
  position: absolute; z-index: 2;
  inset-block-start: 10px; inset-inline-end: 10px;
  display: flex; gap: 6px;
}
/* `hidden` is how the controls stay out of a page with no script to drive
   them, and a class selector outranks the browser's own [hidden] rule. Say
   it here or a page without JavaScript is handed four buttons that do
   nothing - exactly the trap the catalogue search fell into. */
.site .hstrip-arrows[hidden], .site .hstrip-dots[hidden] { display: none; }
.site .hstrip-arrow {
  inline-size: 44px; block-size: 44px; padding: 0;
  display: grid; place-items: center; cursor: pointer;
  border-radius: 50%; border: 1px solid rgba(255, 255, 255, .34);
  background: rgba(27, 12, 51, .62); color: #fff;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  transition: background-color .15s var(--ease), border-color .15s var(--ease),
              transform .15s var(--ease);
}
.site .hstrip-arrow svg { inline-size: 19px; block-size: 19px; display: block; }
/* The glyph points along the reading direction, so in RTL the pair mirrors
   with the layout and "previous" still points back the way you came. */
[dir="rtl"] .site .hstrip-arrow svg { transform: scaleX(-1); }
.site .hstrip-arrow:hover {
  background: rgba(27, 12, 51, .9); border-color: #fff; transform: scale(1.06);
}
.site .hstrip-arrow:active { transform: scale(.94); }
.site .hstrip-arrow:focus-visible { outline: 3px solid #fff; outline-offset: 2px; }

.site .hstrip-bar {
  position: absolute; z-index: 3;
  inset-block-start: 0; inset-inline: 0; block-size: 3px;
  background: var(--brand); transform: scaleX(0); transform-origin: 0 50%;
}
[dir="rtl"] .site .hstrip-bar { transform-origin: 100% 50%; }
.site .hstrip.is-live .hstrip-bar { animation: hstrip-run 6800ms linear both; }
/* Pause on hover, pause on focus, pause when the strip is not on screen. */
.site .hstrip:hover .hstrip-bar,
.site .hstrip:focus-within .hstrip-bar,
.site .hstrip.is-away .hstrip-bar { animation-play-state: paused; }
@keyframes hstrip-run { from { transform: scaleX(0); } to { transform: scaleX(1); } }

.site .hstrip-dots { display: flex; gap: 2px; justify-content: center; flex-wrap: wrap; }
.site .hstrip-dot {
  inline-size: 34px; block-size: 44px; padding: 0; cursor: pointer;
  background: none; border: 0; display: grid; place-items: center;
}
.site .hstrip-dot > span {
  display: block; block-size: 4px; inline-size: 14px; border-radius: 3px;
  background: var(--line-strong);
  transition: inline-size .3s var(--ease-weight), background-color .2s var(--ease);
}
.site .hstrip-dot:hover > span { background: var(--muted); }
.site .hstrip-dot[aria-current="true"] > span { inline-size: 26px; background: var(--brand-ink); }
.site .hstrip-dot:focus-visible { outline: 3px solid var(--ink); outline-offset: -3px; border-radius: 6px; }
/* On the navy hero the dots sit on navy, so they take the light tones. */
.site .hero .hstrip-dot > span { background: rgba(255, 255, 255, .34); }
.site .hero .hstrip-dot:hover > span { background: rgba(255, 255, 255, .6); }
.site .hero .hstrip-dot[aria-current="true"] > span { background: var(--brand); }
.site .hero .hstrip-dot:focus-visible { outline-color: #fff; }

@media (max-width: 900px) {
  .site .hstrip-stage { aspect-ratio: 3 / 2; }
}
@media (max-width: 620px) {
  /* A 3:2 box on a 358px column is 239px tall, and the caption wanted 130
     of them. Back to 4:3 and the picture is the larger half again. */
  .site .hstrip-stage { aspect-ratio: 4 / 3; }
  .site .hslide figcaption { padding: 13px 15px 14px; gap: 5px; }
  .site .hslide figcaption::before { block-size: 46px; }
  .site .hslide figcaption .t { font-size: 17px; }
  .site .hslide figcaption .b { font-size: 13px; line-height: 1.55; }
  /* The arrow keeps its 44px target on a phone; only the glyph inside it
     gets smaller, so the button looks lighter without being harder to hit. */
  .site .hstrip-arrow svg { inline-size: 17px; block-size: 17px; }
}

/* ------------------------------------------------ reveals, now staggered ---
   A grid used to arrive as one block. Each child now carries its index, and
   the delay is read off that index, so a row of cards lands one after the
   other - fast enough that it reads as a single arrival with weight in it,
   not as eight separate events. Capped, so a long grid never keeps a visitor
   waiting for its tail.
   -------------------------------------------------------------------------- */
.site.js [data-rv] {
  transition: opacity .62s var(--ease-weight), transform .62s var(--ease-weight);
  /* Capped at seven: a long grid must not keep a visitor waiting for its
     tail, and past about half a second the stagger stops reading as one
     arrival and starts reading as a queue. */
  transition-delay: calc(min(var(--rv-i, 0), 7) * 58ms);
}
.site.js [data-rv-stagger] > [data-rv] { transform: translateY(18px); }

/* ---------------------------------------------- images, decoded not popped ---
   An image that is already in cache is never touched, so nothing flashes on
   a second visit. One that has to be fetched fades up as it decodes. The
   class is only ever added by the script that also holds the handler that
   removes it, and a sweep clears any straggler, so a photograph cannot be
   left invisible by a load event that never came.
   -------------------------------------------------------------------------- */
.site.js img.fx { opacity: 0; transition: opacity .55s var(--ease-weight); }
.site.js img.fx.is-ready { opacity: 1; }

/* ------------------------------------------------ cards as physical things ---
   A card lifts, gains an edge where the light would catch it, and drops a
   shadow that tightens as it rises. No colour wash: the object moves, the
   surface does not change colour.
   -------------------------------------------------------------------------- */
.site .pcard, .site .feat, .site .tile a, .site .onward, .site .certs li {
  transition:
    transform .18s var(--ease),
    box-shadow .18s var(--ease),
    border-color .18s var(--ease);
}
.site .pcard:hover {
  transform: translateY(-3px);
  border-color: var(--line-strong);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, .9) inset,
    0 2px 6px -2px rgba(36, 16, 67, .14),
    0 18px 38px -14px rgba(36, 16, 67, .3);
}
.site .pcard:active { transform: translateY(-1px); }
.site .feat:hover, .site .certs li:hover {
  transform: translateY(-2px);
  border-color: var(--line-strong);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, .9) inset,
    0 14px 30px -14px rgba(36, 16, 67, .26);
}
.site .tile a:hover {
  transform: translateY(-3px);
  box-shadow:
    0 2px 6px -2px rgba(36, 16, 67, .18),
    0 20px 40px -14px rgba(36, 16, 67, .34);
}
.site .markstrip li {
  transition: transform .18s var(--ease), box-shadow .18s var(--ease),
              border-color .18s var(--ease);
}
.site .markstrip li:hover {
  transform: translateY(-2px); border-color: var(--line-strong);
  box-shadow: 0 14px 30px -14px rgba(36, 16, 67, .24);
}
/* The number counts up once. Tabular figures so the box does not twitch
   between 7 and 18 while it runs. */
.site .fig[data-count] { font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------ breadcrumbs ---
   An ordered list, because the order is the meaning. The separator is drawn,
   not typed, so a screen reader is not read a slash between every step.
   -------------------------------------------------------------------------- */
.site .crumbs ol { list-style: none; margin: 0; padding: 0; display: flex;
                   flex-wrap: wrap; align-items: center; gap: 0; }
.site .crumbs li { display: inline-flex; align-items: center; }
.site .crumbs li + li::before {
  content: ""; inline-size: 5px; block-size: 5px; margin-inline: 9px;
  border-block-start: 1.5px solid var(--line-strong);
  border-inline-end: 1.5px solid var(--line-strong);
  transform: rotate(45deg); flex: none;
}
/* The chevron points along the reading direction.

   `border-inline-end` has already flipped to the left in RTL, so the corner
   now sits at the TOP-LEFT and its bisector points up and to the left. From
   there it needs -45deg to lie flat pointing left, not -135deg, which stood
   it up pointing down. */
[dir="rtl"] .site .crumbs li + li::before { transform: rotate(-45deg); }
.site .crumbs [aria-current="page"] { color: var(--ink); font-weight: 700; }
.site .on-dark .crumbs, .site .band--ink .crumbs { color: rgba(255, 255, 255, .66); }
.site .on-dark .crumbs a, .site .band--ink .crumbs a { color: rgba(255, 255, 255, .78); }
.site .on-dark .crumbs a:hover, .site .band--ink .crumbs a:hover { color: #fff; }
.site .on-dark .crumbs [aria-current="page"],
.site .band--ink .crumbs [aria-current="page"] { color: #fff; }
.site .on-dark .crumbs li + li::before, .site .band--ink .crumbs li + li::before {
  border-color: rgba(255, 255, 255, .4);
}

/* ------------------------------------------------------ where to go next ---
   No page ends in nothing. Three cards, each saying what the next page
   answers rather than only naming it.
   -------------------------------------------------------------------------- */
.site .onwards { border-block-start: 1px solid var(--line); }
.site .onwards-h {
  font-size: 12.5px; font-weight: 800; letter-spacing: .13em;
  text-transform: uppercase; color: var(--muted); margin: 0 0 18px;
}
.site .onwards-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 14px;
}
.site .onward {
  display: grid; gap: 5px; text-decoration: none; position: relative;
  padding: 20px 22px; border: 1px solid var(--line); border-radius: var(--r);
  background: var(--paper); color: var(--ink);
}
.site .onward .k {
  font-size: 11.5px; font-weight: 800; letter-spacing: .1em;
  text-transform: uppercase; color: var(--brand-ink);
}
.site .onward .t { font-size: 16px; font-weight: 700; line-height: 1.45; padding-inline-end: 22px; }
.site .onward .go {
  position: absolute; inset-inline-end: 20px; inset-block-end: 20px;
  inline-size: 9px; block-size: 9px;
  border-block-start: 2px solid var(--brand); border-inline-end: 2px solid var(--brand);
  transform: rotate(45deg);
  transition: transform .18s var(--ease), translate .18s var(--ease);
}
[dir="rtl"] .site .onward .go { transform: rotate(-45deg); }
.site .onward:hover {
  transform: translateY(-2px); border-color: var(--line-strong);
  box-shadow: 0 14px 30px -14px rgba(36, 16, 67, .26);
}
.site .onward:hover .go { translate: 3px 0; }
[dir="rtl"] .site .onward:hover .go { translate: -3px 0; }

/* ------------------------------------------------------ where it is used ---
   The link from a product to the sector the profile's own words place it in.
   -------------------------------------------------------------------------- */
.site .uses { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; margin: 0; }
.site .uses-k {
  font-size: 11.5px; font-weight: 800; letter-spacing: .09em;
  text-transform: uppercase; color: var(--muted);
}
.site .uses a {
  font-size: 12.5px; font-weight: 700; text-decoration: none;
  color: var(--ink); background: var(--brand-wash);       /* ink on it 14.72:1 */
  border: 1px solid transparent; border-radius: 999px; padding: 4px 11px;
  transition: border-color .15s var(--ease), background-color .15s var(--ease);
}
.site .uses a:hover { border-color: var(--brand); background: var(--paper); }
.site .uses.on-dark .uses-k { color: rgba(255, 255, 255, .66); }
.site .uses.on-dark a {
  color: #fff; background: rgba(255, 255, 255, .11);
  border-color: rgba(255, 255, 255, .3);
}
.site .uses.on-dark a:hover { background: rgba(255, 255, 255, .2); border-color: #fff; }

/* -------------------------------------------------- the sector index page ---
   The other direction: pick the job, get the elements that serve it.
   -------------------------------------------------------------------------- */
.site .sectors { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 16px; }
.site .sector {
  border: 1px solid var(--line); border-radius: var(--r); background: var(--paper);
  padding: 20px 22px; display: grid; gap: 10px; align-content: start;
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease),
              transform .18s var(--ease);
}
.site .sector:hover {
  transform: translateY(-2px); border-color: var(--line-strong);
  box-shadow: 0 14px 30px -14px rgba(36, 16, 67, .26);
}
.site .sector h3 { font-size: 16.5px; margin: 0; line-height: 1.4; }
.site .sector h3 a { color: inherit; text-decoration: none; }
.site .sector h3 a:hover { color: var(--brand-ink); }
.site .sector ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.site .sector ul a {
  font-size: 12.5px; font-weight: 600; text-decoration: none; color: var(--ink);
  border: 1px solid var(--line-strong); border-radius: 999px; padding: 4px 11px;
  transition: border-color .15s var(--ease), background-color .15s var(--ease);
}
.site .sector ul a:hover { background: var(--sand); border-color: var(--ink); }
.site .band--sand .sector { background: var(--paper); }

/* ---------------------------------------- the method statement, with photos ---
   Eight steps; the plant photographed seven of them. A step without a
   photograph keeps the full measure rather than being given someone else's.
   -------------------------------------------------------------------------- */
.site .method li { grid-template-columns: 54px 1fr; }
.site .method li.has-shot { grid-template-columns: 54px 1fr 212px; }
.site .method .shot { margin: 0; grid-column: 3; }
.site .method .shot img {
  inline-size: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block;
  border-radius: var(--r-sm); border: 1px solid var(--line); background: var(--sand);
  transition: transform .3s var(--ease-weight);
}
.site .method li:hover .shot img { transform: scale(1.025); }
@media (max-width: 860px) {
  .site .method li.has-shot { grid-template-columns: 54px 1fr; }
  .site .method .shot { grid-column: 2; margin-block-start: 12px; max-inline-size: 300px; }
}
@media (max-width: 620px) {
  .site .method li.has-shot { grid-template-columns: 42px 1fr; }
}

/* ------------------------------------------------------- the quality rail ---
   The quality page is long on purpose - it is the page a consultant reads -
   so it carries its own index, and the index says where you are.
   -------------------------------------------------------------------------- */
.site .qrail {
  position: sticky; inset-block-start: calc(var(--head-h) + var(--rail-h));
  /* 50px, which is what .has-rail adds to --sticky-h above. */
  z-index: 30; background: rgba(255, 255, 255, .95);
  -webkit-backdrop-filter: saturate(1.6) blur(10px);
  backdrop-filter: saturate(1.6) blur(10px);
  border-block-end: 1px solid var(--line);
}
.site .qrail-inner {
  display: flex; gap: 2px; overflow-x: auto; scrollbar-width: none;
  scroll-snap-type: inline proximity; min-block-size: 50px; align-items: stretch;
}
.site .qrail-inner::-webkit-scrollbar { display: none; }
.site .qrail a {
  display: inline-flex; align-items: center; flex: none; white-space: nowrap;
  padding-inline: 14px; text-decoration: none; scroll-snap-align: start;
  font-size: 14px; font-weight: 600; color: var(--muted); position: relative;
  transition: color .15s var(--ease);
}
.site .qrail a:hover { color: var(--ink); }
.site .qrail a.is-here { color: var(--ink); font-weight: 800; }
.site .qrail a.is-here::after {
  content: ""; position: absolute; inset-inline: 12px; inset-block-end: 0;
  block-size: 3px; background: var(--brand); border-radius: 3px 3px 0 0;
}

/* --------------------------------------------------------- the lead times ---
   Every figure on this strip is one the plant already publishes.
   -------------------------------------------------------------------------- */
.site .leadgrid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 1px; background: var(--line); border: 1px solid var(--line);
  border-radius: var(--r); overflow: hidden;
}
.site .leadgrid > div { background: var(--paper); padding: 22px 24px; }
.site .leadgrid .fig {
  display: block; font-size: 27px; font-weight: 900; color: var(--ink);
  line-height: 1.15; margin-block-end: 4px;
}
.site .leadgrid .fig small { font-size: 14px; font-weight: 700; color: var(--brand-ink); margin-inline-start: 4px; }
.site .leadgrid .lbl { font-size: 13.5px; color: var(--muted); display: block; line-height: 1.6; }

/* ------------------------------------------------- the documents, grouped ---
   Nine pieces of paper read as three: who we are, what we are certified to,
   and what a consultant has already approved.
   -------------------------------------------------------------------------- */
.site .certgroup + .certgroup { margin-block-start: 34px; }
.site .certgroup > h3 {
  font-size: 12.5px; font-weight: 800; letter-spacing: .12em;
  text-transform: uppercase; color: var(--brand-ink); margin: 0 0 14px;
  display: flex; align-items: center; gap: 12px;
}
.site .certgroup > h3::after {
  content: ""; flex: 1; block-size: 1px; background: var(--line); opacity: .9;
}
.site .certs .covers {
  display: inline-flex; align-items: center; gap: 6px; margin-block-start: 10px;
  font-size: 12.5px; font-weight: 700; color: var(--brand-ink);
  text-decoration: none; border-block-end: 1px solid transparent;
  transition: border-color .15s var(--ease);
}
.site .certs .covers::after {
  content: ""; inline-size: 7px; block-size: 7px;
  border-block-start: 2px solid currentColor; border-inline-end: 2px solid currentColor;
  transform: rotate(45deg);
}
[dir="rtl"] .site .certs .covers::after { transform: rotate(-45deg); }
.site .certs .covers:hover { border-block-end-color: currentColor; }

/* ------------------------------------------------- finding it in the list ---
   Nineteen elements across nine families. The chips are how a buyer who
   knows the family finds it; this is how a buyer who knows the code, the
   size or the word finds it. It is built by script and so is not drawn at
   all without one, where the chips and the full list are already enough.
   -------------------------------------------------------------------------- */
/* The `hidden` attribute is what keeps it out of the page until a script
   can drive it, so the display rule has to yield to it - a class selector
   outranks the browser's own [hidden] rule and would show a search box that
   searches nothing. */
.site .finder { display: grid; gap: 10px; margin-block-end: 26px; }
.site .finder[hidden] { display: none; }
.site .finder-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.site .finder label { flex: 1 1 260px; position: relative; display: block; min-inline-size: 0; }
.site .finder input {
  inline-size: 100%; font: inherit; font-size: 15px;
  padding: 12px 42px 12px 16px; padding-inline: 42px 16px;
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  background: var(--paper); color: var(--ink);
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.site .finder input:hover { border-color: var(--muted); }
.site .finder input:focus { outline: 3px solid var(--ink); outline-offset: 1px; border-color: var(--ink); }
.site .finder .mag {
  position: absolute; inset-inline-start: 14px; inset-block-start: 50%;
  translate: 0 -50%; inline-size: 17px; block-size: 17px; color: var(--muted);
  pointer-events: none;
}
.site .finder .count { font-size: 13.5px; color: var(--muted); font-weight: 600; }
.site .finder .clear {
  font: inherit; font-size: 13px; font-weight: 700; cursor: pointer;
  background: none; border: 0; color: var(--brand-ink); padding: 11px 6px;
  text-decoration: underline; text-underline-offset: 3px;
}
.site .pcard[data-hidden], .site .pgroup[data-hidden] { display: none; }

/* ---------------------------------------------- the full specification table ---
   One screen a buyer can read straight down, print, or hand to an estimator.
   -------------------------------------------------------------------------- */
.site table.grid3.allspecs { min-inline-size: 760px; }
.site table.grid3.allspecs td .fam { display: block; font-size: 12.5px; color: var(--muted); font-weight: 400; }
.site table.grid3.allspecs a { color: var(--ink); text-decoration: none; border-block-end: 1px solid var(--line-strong); }
.site table.grid3.allspecs a:hover { color: var(--brand-ink); border-block-end-color: var(--brand); }
.site table.grid3 thead th { position: sticky; inset-block-start: 0; z-index: 1; }

/* ------------------------------------------- the price-this bar, on a phone ---
   The product page keeps its own call to action within thumb reach the whole
   way down, carrying the element's name into both the form and WhatsApp.
   -------------------------------------------------------------------------- */
.site .pricebar { display: none; }
@media (max-width: 760px) {
  .site .pricebar {
    position: fixed; inset-inline: 0; inset-block-end: 0; z-index: 46;
    display: flex; gap: 8px; align-items: center;
    padding: 10px 14px calc(10px + env(safe-area-inset-bottom, 0px));
    background: rgba(255, 255, 255, .97);
    -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
    border-block-start: 1px solid var(--line);
    box-shadow: 0 -10px 30px -16px rgba(36, 16, 67, .4);
    transform: translateY(0); transition: transform .24s var(--ease-weight);
  }
  .site .pricebar .btn { flex: 1 1 auto; min-block-size: 46px; display: inline-flex;
                         align-items: center; justify-content: center; }
  .site .pricebar .wa-btn {
    flex: none; inline-size: 46px; block-size: 46px; border-radius: var(--r-sm);
    display: grid; place-items: center; background: var(--wa); color: #fff;
    transition: background-color .15s var(--ease);
  }
  .site .pricebar .wa-btn:hover { background: var(--wa-hi); }
  .site.product-page main { padding-block-end: 74px; }
}

/* ========================================================== tap targets ===
   Forty-four pixels, wherever a finger is the input.

   This block lives at the END of the stylesheet on purpose. Every rule in it
   is the same weight as the component rule it is adjusting, so it only wins
   on source order - put it higher up and a later `padding: 4px 11px`
   shorthand quietly undoes a `padding-block` set here, which is exactly what
   happened to the sector chips.

   The target is grown with padding, never by setting `display` on something
   that is already visible. The small button in the header is hidden below
   900px by `.site .head-actions > .btn` - three classes, exactly the weight
   of `.site .btn.small` - so a rule down here that set `display: inline-flex`
   on it would win on source order and put the hidden button back. It did,
   the header then needed 504px on a 390px phone, and the whole page scaled
   down to fit. Padding cannot have that argument with anything.
   ========================================================================== */
@media (pointer: coarse) {
  .site .chips a { padding-block: 12px; }
  .site .site-nav a { padding-block: 11px; }
  .site .menu-panel a { padding-block: 12px; }
  .site .btn.small { padding-block: 13px; }
  .site .lang { padding-block: 15px; }

  /* An inline link takes no block padding into its line box, so each of
     these is made inline-block first. None of them is hidden by any rule,
     so there is nothing here for `display` to override - unlike .btn.small
     above, which is why that one is grown with padding alone. */
  .site .contact-list a,
  .site .utility a,
  .site .ticks-link a,
  .site .sector ul a,
  .site .uses a,
  .site table.grid3 td a,
  .site .certs .covers { display: inline-block; }
  .site .ticks-link a, .site .sector ul a { padding-block: 17px; }
  .site .sector h3 a { display: block; padding-block: 12px; margin-block: -12px; }
  .site .uses a { padding-block: 12px; }
  .site .contact-list a, .site .utility a, .site table.grid3 td a { padding-block: 12px; }
  .site .certs .covers { padding-block: 12px; }
  /* A list of links gets a taller row and a tighter gap, so each line is a
     full target and the list as a whole takes about the space it did. */
  .site .ticks-link { gap: 0; }
  .site .sector ul { gap: 2px 6px; }

  /* Breadcrumbs are short words. The padding grows the target in both axes
     and the matching negative margin leaves the row looking untouched. */
  .site .crumbs a, .site .crumbs [aria-current="page"] {
    display: inline-block; padding: 11px 6px; margin: -11px -6px;
  }

  /* The card title is the biggest thing on a card and had the smallest
     target on it. It becomes a block so the whole width of the card's
     heading is tappable, and the negative margin keeps the card looking
     exactly as it did. */
  .site .pbody h3 a { display: block; padding-block: 12px; margin-block: -12px; }

  /* base.html owns the footer markup; this is the only place its links can
     be grown, and padding is enough. */
  .site .site-footer a { display: inline-block; padding-block: 9px; }
  .site .site-footer .footer-grid p { margin-bottom: 0; }
  .site .brandmark { padding-block: 7px; }

  .site .hstrip-dot { inline-size: 44px; }
}

/* ================================================================= print ===
   The public pages, on paper. Everything that is a control, a decoration or
   a way back to the screen goes; the words, the sizes and the photographs
   stay, and a card is not allowed to break across two sheets.
   ========================================================================== */
@media print {
  .site .utility, .site .askbar, .site .site-nav, .site .menu,
  .site .head-actions, .site .wafab, .site .sprogress, .site .skip,
  .site .hstrip-arrows, .site .hstrip-dots, .site .hstrip-bar,
  .site .qrail, .site .finder, .site .pricebar, .site .cta,
  .site .onwards, .site .lbox { display: none !important; }

  .site { background: #fff; color: #000; }
  .site .site-head { position: static; box-shadow: none; background: #fff; }
  .site .band { padding: 18px 0; page-break-inside: auto; }
  .site .band--ink, .site .hero, .site .band--sand, .site .cta {
    background: #fff !important; color: #000 !important;
  }
  .site .band--ink h1, .site .band--ink h2, .site .band--ink h3,
  .site .hero h1, .site .on-dark h2, .site .on-dark h3 { color: #000 !important; }
  .site .band--ink p, .site .on-dark p, .site .hero .lead,
  .site .band--ink .prose { color: #222 !important; }
  .site .hero::before { display: none; }
  .site .pcard, .site .feat, .site .certs li, .site .person, .site .sector,
  .site .step, .site .method li, .site .partners li {
    break-inside: avoid; page-break-inside: avoid;
    box-shadow: none !important; border-color: #bbb !important;
    background: #fff !important; transform: none !important;
  }
  /* On a dark band these were drawn in white, and white does not print.
     Everything that used to sit on navy comes back as ink. */
  .site .on-dark .crumbs, .site .band--ink .crumbs,
  .site .on-dark .crumbs a, .site .band--ink .crumbs a,
  .site .on-dark .crumbs [aria-current="page"],
  .site .band--ink .crumbs [aria-current="page"] { color: #222 !important; }
  .site .on-dark .crumbs li + li::before,
  .site .band--ink .crumbs li + li::before { border-color: #888 !important; }
  .site .head2 .eyebrow, .site .band--ink .head2 .eyebrow { color: #444 !important; }

  /* A photograph is evidence on paper, not the page. Capped so a sheet
     carries the picture and the words that go with it. */
  .site .plate img, .site .hslide img, .site .step img, .site .method .shot img {
    max-block-size: 86mm; inline-size: auto; max-inline-size: 100%;
    break-inside: avoid;
  }
  .site .plate figcaption, .site .hslide figcaption {
    position: static; background: none !important; color: #333 !important;
    border: 0; padding: 6px 0; font-size: 10pt;
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
  /* The approval marks are cropped onto their own white ground; multiply
     against a white sheet is a no-op on screen and a muddy grey on some
     printers. */
  .site .markstrip img, .site .partners .mark img { mix-blend-mode: normal; }

  .site .hstrip-stage { aspect-ratio: auto; box-shadow: none; }
  .site .hslide { position: static; opacity: 1 !important; visibility: visible !important; }
  .site .hslide + .hslide { display: none; }   /* one plate on paper, not six */
  .site .hslide img { position: static; block-size: auto; }
  .site .hslide figcaption { position: static; background: #fff; color: #000; padding: 10px 0; }
  .site .hslide figcaption .k, .site .hslide figcaption .t,
  .site .hslide figcaption .b, .site .hslide figcaption .go { color: #000 !important; }
  .site a[href^="http"]::after, .site a[href^="mailto"]::after, .site a[href^="tel"]::after {
    content: " (" attr(href) ")"; font-size: 10px; color: #555; word-break: break-all;
  }
  .site .site-footer { background: #fff !important; color: #000 !important; border-block-start: 1px solid #bbb; }
  .site .site-footer a { color: #000 !important; }
  @page { margin: 14mm; }
}

/* ======================================================= reduced motion ====
   Every single thing added above, switched off by the one query. The strip
   keeps its controls and loses its clock; the reveals, the image fades, the
   counting numbers, the lifts and the slow settle all stop. The rule above
   already flattens durations across `.site *`; these are the ones that need
   more than a shorter duration - they need not to happen at all.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .site .hstrip-bar { animation: none !important; opacity: 0; }
  .site .hslide { transition: none !important; }
  .site .hslide img, .site .hslide.is-on img { transform: none !important; transition: none !important; }
  .site.js img.fx { opacity: 1 !important; transition: none !important; }
  .site.js [data-rv] { transition-delay: 0s !important; }
  .site .pcard:hover, .site .feat:hover, .site .tile a:hover, .site .onward:hover,
  .site .sector:hover, .site .markstrip li:hover, .site .certs li:hover,
  .site .wafab:hover .wafab-disc, .site .hstrip-arrow:hover,
  .site .site-head.is-stuck .brandmark img { transform: none !important; }
  .site .method li:hover .shot img { transform: none !important; }
  .site .sprogress i { animation: none !important; }
  .site .onward:hover .go { translate: 0 !important; }
}

/* A tick list whose items are links. The tick stays the tick; only the words
   become a target, so the list still reads as a list. */
.site .ticks-link a {
  color: inherit; text-decoration: none;
  border-block-end: 1px solid transparent; padding-block-end: 1px;
  transition: border-color .15s var(--ease), color .15s var(--ease);
}
.site .ticks-link a:hover { color: var(--brand-ink); border-block-end-color: var(--brand); }

/* The WhatsApp button where it sits in the flow of a page: the same mark,
   the same green, sized to the line it is on. White on --wa is 5.00:1. */
.site .btn.wa-inline {
  background: var(--wa); color: #fff; border-color: transparent;
  display: inline-flex; align-items: center; gap: 9px;
}
.site .btn.wa-inline:hover { background: var(--wa-hi); color: #fff; }
.site .btn.wa-inline .wa-mark { flex: none; }

/* A plate that refuses to draw its photograph larger than it was shot. The
   native width rides in on a custom property; where none is known - a
   picture the plant uploaded through the dashboard, whose size nobody
   recorded - the plate behaves as it always did. In RTL the plate keeps to
   the inline start of its column rather than drifting to the middle. */
.site .plate.native { inline-size: min(100%, var(--native, 100%)); margin-inline-end: auto; }

/* The floating WhatsApp button sits in the inline-end corner of the screen,
   which on a phone is exactly where a sideways-scrolling rail runs out of
   room. A little padding on that end means the last item of the rail can
   always be scrolled clear of the button instead of under it. */
@media (max-width: 760px) {
  .site .qrail-inner { padding-inline-end: 58px; }
}
