/* ==========================================================================
   Shree Shyam Metals — stylesheet
   Palette: brand navy + catalyst green + warm paper.
   Both brand ramps are sampled from assets/logo.png: --navy-800 is the
   panel the logo is set on, --green-300 the green in the mark. Every other
   step is that colour walked lighter or darker, so nothing on the page is a
   hue the logo does not already contain.

   Contents
     01  Fonts                    12  FAQ (native details)
     02  Tokens                   13  CTA band
     03  Reset & base            13b  Heritage box
     04  Layout utilities         14  Forms
     05  Typography blocks        15  Footer
     06  Buttons & links          16  404
     07  Header / navigation      17  Motion
     08  Page headers             18  Header at awkward widths
     09  Breadcrumbs              19  Quick contact bar
     10  Grids & features         20  Enquiry fallback panel
     11  Lists, tables, steps     21  Photographic plates

   Two smaller blocks sit out of sequence after 17 and keep their original
   numbers: a utilities group and the blog. The numbering has drifted because
   sections have been retired, not renumbered — renumbering would churn every
   comment in the file for nothing. What matters is that each heading below
   still describes what follows it.

   Retired with the pages that used them: the PGM calculator, the product
   cards and featured panel, the recycling jump list, and the photographic
   hero the 3D scene replaced. 111 rules in all. See "Performance" in
   README.md.
   ========================================================================== */

/* -------------------------------------------------------------- 01  fonts */
@font-face {
  font-family: 'Sora';
  src: url('../fonts/sora-var.woff2') format('woff2-variations'),
       url('../fonts/sora-var.woff2') format('woff2');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'InterVar';
  src: url('../fonts/inter-var.woff2') format('woff2-variations'),
       url('../fonts/inter-var.woff2') format('woff2');
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}

/* ------------------------------------------------------------- 02  tokens */
:root {
  /* neutrals */
  --navy-900: #061a30;   /* now type, not background — see the light bands below */
  --navy-800: #092847;   /* sampled from the logo panel */
  --navy-700: #13385c;
  --navy-600: #1d4a75;
  --slate-500: #5a6a80;
  --slate-400: #7e8ea4;
  --slate-300: #a9b6c8;

  --paper: #fbfaf8;
  --paper-2: #f3f1ec;
  --paper-3: #e9e5dd;
  --line: #e2ddd3;
  --line-strong: #cfc8ba;

  /* The site used to put four bands on near-black: the utility strip, the
     figures under the hero, the page headers and the closing call to action,
     plus the footer. They are all paper now. --mist is the cool panel that
     replaced the ink one — a green so far down the ramp it reads as a tint
     rather than a colour — and --mist-line is its edge. Keeping them as tokens
     means the bands stay in step with each other instead of drifting apart. */
  --mist: #eef4f0;
  --mist-2: #e4ede7;
  --mist-line: #d3e0d8;

  /* brand */
  /* The ramp is pitched so the steps that carry TEXT clear 4.5:1 where they
     are used: -700 and -600 only ever appear on paper, -400 and -300 only on
     navy. -500 is the middle step, used for rules and marks rather than type. */
  --green-700: #0f5f2e;
  --green-600: #15773a;
  --green-500: #1d8f47;
  --green-400: #2ba757;
  --green-300: #5cc86f;   /* sampled from the logo mark */

  /* semantic */
  --bg: var(--paper);
  --fg: var(--navy-900);
  --muted: var(--slate-500);

  /* Fluid type scale, lifted one notch across the board. Body text now starts
     at about 17.5px on a phone and settles near 19px on a desktop; it used to
     start at 15.7px and stop at 17. Everything else on the page is measured
     off these six steps, so the whole document grew with them and the rhythm
     between the steps is unchanged. */
  --step-0: clamp(1.09rem, 1.04rem + 0.22vw, 1.2rem);
  --step-1: clamp(1.26rem, 1.16rem + 0.44vw, 1.5rem);
  --step-2: clamp(1.5rem, 1.32rem + 0.86vw, 2.02rem);
  --step-3: clamp(1.84rem, 1.5rem + 1.6vw, 2.8rem);
  --step-4: clamp(2.2rem, 1.62rem + 2.7vw, 3.9rem);
  --step-5: clamp(2.5rem, 1.65rem + 4vw, 5.2rem);

  /* space */
  --gutter: clamp(1.15rem, 0.7rem + 2.2vw, 2.5rem);
  --section-y: clamp(3.75rem, 2.4rem + 6vw, 7.5rem);
  --max: 1220px;

  --radius: 4px;
  --radius-lg: 10px;

  --font-display: 'Sora', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-body: 'InterVar', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;

  --ease: cubic-bezier(0.2, 0.7, 0.3, 1);
  /* Overshoots ~3% before settling — the industrial register. */
  --ease-settle: cubic-bezier(0.34, 1.36, 0.64, 1);
}

/* --------------------------------------------------------- 03  reset/base */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 86px;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-wrap: break-word;
}

h1, h2, h3, h4, h5 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -0.022em;
  margin: 0 0 0.6em;
  text-wrap: balance;
}

h1 { font-size: var(--step-4); }
h2 { font-size: var(--step-3); }
h3 { font-size: var(--step-2); }
h4 { font-size: var(--step-1); }

p { margin: 0 0 1.15em; }
p:last-child { margin-bottom: 0; }

a { color: inherit; text-decoration: none; }

img, svg, video { display: block; max-width: 100%; height: auto; }

ul, ol { margin: 0 0 1.15em; padding-left: 1.15em; }
li { margin-bottom: 0.4em; }

table { border-collapse: collapse; width: 100%; }

::selection { background: var(--green-600); color: #fff; }

:focus-visible {
  outline: 2px solid var(--green-500);
  outline-offset: 3px;
  border-radius: 2px;
}

/* --------------------------------------------------------- 04  utilities */
.container {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.container--narrow { max-width: 840px; }

.section { padding-block: var(--section-y); }
.section--tight { padding-block: clamp(2.5rem, 1.8rem + 3.4vw, 4.5rem); }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  left: 0.75rem;
  top: -4rem;
  z-index: 200;
  background: var(--navy-900);
  color: #fff;
  padding: 0.7rem 1.1rem;
  border-radius: var(--radius);
  font-size: 0.9rem;
  transition: top 0.2s var(--ease);
}
.skip-link:focus { top: 0.75rem; }

/* Was a near-black band; it is a cool paper panel now. The class name is kept
   because it is written into every page and it still means the same thing —
   "the emphatic band" — it is simply no longer emphatic by being dark. */
.band--ink {
  background: var(--mist);
  color: var(--fg);
  position: relative;
  isolation: isolate;
  border-block: 1px solid var(--mist-line);
}
.band--ink h1, .band--ink h2, .band--ink h3, .band--ink h4 { color: var(--navy-900); }
.band--ink strong, .band--ink .prose strong { color: var(--navy-900); }
.band--paper2 { background: var(--paper-2); }

/* Fine grid so large flat areas keep some texture. Ink on paper now, at a
   twentieth of the strength the white-on-black version needed. */
.band--ink::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0.55;
  background-image:
    linear-gradient(rgba(6, 26, 48, 0.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(6, 26, 48, 0.035) 1px, transparent 1px);
  background-size: 56px 56px;
  -webkit-mask-image: radial-gradient(120% 80% at 50% 0%, #000 30%, transparent 78%);
  mask-image: radial-gradient(120% 80% at 50% 0%, #000 30%, transparent 78%);
}

/* -------------------------------------------------------- 05  typography */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  font-family: var(--font-display);
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--green-700);
  margin: 0 0 1.1rem;
}
.eyebrow::before {
  content: '';
  width: 26px;
  height: 1px;
  background: currentColor;
  flex: none;
}
/* Both of these sit on paper now, so they take the paper step of the ramp. */
.band--ink .eyebrow { color: var(--green-700); }
.pagehead .eyebrow { color: var(--green-700); }

.lede {
  font-size: var(--step-1);
  line-height: 1.55;
  color: var(--slate-500);
  max-width: 62ch;
}
.band--ink .lede { color: var(--slate-500); }

.muted { color: var(--muted); }
.band--ink .muted { color: var(--muted); }

.section-head { max-width: 66ch; margin-bottom: clamp(2rem, 1.4rem + 2vw, 3.4rem); }

/* ------------------------------------------------------------ 06  buttons */
.btn {
  --btn-bg: var(--green-600);
  --btn-fg: #fff;
  --btn-bd: var(--green-600);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: 0.82rem 1.5rem;
  border: 1px solid var(--btn-bd);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: var(--font-display);
  font-size: 0.905rem;
  font-weight: 600;
  border-radius: var(--radius);
  cursor: pointer;
  text-align: center;
  transition: transform 0.18s var(--ease), background-color 0.18s var(--ease),
    border-color 0.18s var(--ease), color 0.18s var(--ease);
}
.btn:hover { --btn-bg: var(--green-700); --btn-bd: var(--green-700); transform: translateY(-1px); }
.btn:active { transform: translateY(0); }

.btn--ghost { --btn-bg: transparent; --btn-fg: var(--navy-900); --btn-bd: var(--line-strong); }
.btn--ghost:hover { --btn-bg: var(--navy-900); --btn-fg: #fff; --btn-bd: var(--navy-900); }

.btn--onDark { --btn-bg: transparent; --btn-fg: #fff; --btn-bd: rgba(255, 255, 255, 0.28); }
.btn--onDark:hover { --btn-bg: #fff; --btn-fg: var(--navy-900); --btn-bd: #fff; }

.btn--sm { padding: 0.58rem 1.05rem; font-size: 0.83rem; }

/* .btn--ghost is drawn for paper: near-black type on a hairline. In the navy
   header that is a black button on a dark blue bar, so inside the header the
   ghost takes the on-dark treatment instead. */
.header .btn--ghost { --btn-fg: var(--navy-800); --btn-bd: var(--line-strong); }
.header .btn--ghost:hover { --btn-bg: var(--navy-800); --btn-fg: #fff; --btn-bd: var(--navy-800); }

.btn-row { display: flex; flex-wrap: wrap; gap: 0.75rem; }

.arrow-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--green-600);
  border-bottom: 1px solid transparent;
  transition: gap 0.2s var(--ease), border-color 0.2s var(--ease);
}
.arrow-link:hover { gap: 0.8rem; border-bottom-color: currentColor; }
.arrow-link svg { flex: none; }
.band--ink .arrow-link { color: var(--green-700); }

/* ------------------------------------------------------------- 07  header */
/* Two pieces. The utility strip carries the contact details and the
   registration number and scrolls away with the page; the bar below it is the
   only part that sticks, so the sticky furniture stays at 72px instead of the
   106px the two would come to together. */

.topbar {
  background: var(--mist-2);
  border-bottom: 1px solid var(--mist-line);
  font-size: 0.92rem;
}
.topbar__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  min-height: 38px;
}
.topbar__meta {
  margin: 0;
  color: var(--slate-500);
  letter-spacing: 0.01em;
  display: flex;
  align-items: center;
  gap: 0.55rem;
  min-width: 0;
}
.topbar__dot { color: var(--slate-400); }
.topbar__links { display: flex; align-items: center; gap: 1.6rem; flex: none; }
.topbar__links a {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--navy-700);
  transition: color 0.18s var(--ease);
}
.topbar__links a:hover { color: var(--green-700); }
.topbar__links svg { width: 15px; height: 15px; flex: none; color: var(--green-600); }

/* The strip is desktop-only. On a phone the fixed call bar at the foot of the
   screen already carries the phone number and WhatsApp, and repeating them at
   the top costs a row of screen on the one device that has none to spare. */
@media (max-width: 940px) {
  .topbar { display: none; }
}

.header {
  position: sticky;
  top: 0;
  z-index: 90;
  /* Paper, like everything else. The lockup this bar carries is the ink
     artwork from tools/build-logo-ink.py — the white original needed the navy
     panel behind it, this one does not. Translucent so the page shows through
     as it scrolls under, with a blur to keep the type legible over it. */
  background: rgba(251, 250, 248, 0.92);
  border-bottom: 1px solid var(--line);
}

/* The blur is the most expensive thing on the page during a scroll: a sticky
   bar with backdrop-filter makes the compositor re-sample and re-blur what is
   behind it on every frame, for the whole width of the viewport. On a desktop
   GPU that is free. On a mid-range phone it is the difference between a scroll
   that tracks the finger and one that does not — and a phone is where most of
   this site's traffic is.

   So it is asked for only where it is affordable AND visible: a wide viewport
   with a fine pointer. Under the 92%-opaque paper it was never doing much work
   anyway, which is why dropping it elsewhere costs nothing to look at. */
@media (min-width: 941px) and (pointer: fine) {
  .header {
    background: rgba(251, 250, 248, 0.86);
    -webkit-backdrop-filter: saturate(140%) blur(12px);
    backdrop-filter: saturate(140%) blur(12px);
  }
}

.header__bar {
  display: flex;
  align-items: stretch;
  justify-content: space-between;
  gap: clamp(1rem, 0.2rem + 2vw, 2.6rem);
  min-height: 72px;
}

.brand { display: flex; align-items: center; gap: 0.7rem; flex: none; }
.brand picture { display: flex; }
/* The artwork carries the company name, so it stands alone in both places —
   no type is set beside it. Sized by height so the wordmark inside it stays
   at a readable size; the width follows the artwork's own proportion.
   These are near 8:1, so height is what has to stay modest: at 38px the
   lockup is ~296px wide and its wordmark ~15px tall, which reads as a brand
   mark rather than competing with the navigation beside it. */
.brand__logo { height: 38px; width: auto; flex: none; }
/* The footer column is narrower than a 58px-tall wordmark is wide, and a
   fixed height with a width capped by max-width squashed it sideways. Cap the
   height instead and let the width lead, so the mark keeps its proportions. */
.brand__logo--footer { height: auto; max-height: 58px; max-width: 100%; }
.brand--lockup { display: block; }

/* The links run the full height of the bar so the active marker can sit on its
   bottom edge, flush with the border, instead of floating under the text where
   it read as a stray underline. Full height also gives each one a proper
   pointer target. */
.nav { display: flex; align-items: stretch; gap: 0; margin-inline: auto; }
.nav__link {
  /* "Catalytic Converters" is the longest item and the one that matters most:
     allowed to wrap it takes two lines and drags the whole bar taller. */
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  padding: 0 clamp(0.5rem, 0.05rem + 0.75vw, 0.95rem);
  font-size: 1.02rem;
  font-weight: 500;
  letter-spacing: -0.005em;
  color: var(--navy-700);
  position: relative;
  transition: color 0.18s var(--ease);
}
.nav__link:hover { color: var(--green-700); }
.nav__link[aria-current='page'] { color: var(--navy-900); font-weight: 600; }

/* One marker, two states: it wipes out from the centre on hover and stays put
   on the current page. Drawn on a pseudo-element so nothing reflows. */
.nav__link::after {
  content: '';
  position: absolute;
  left: clamp(0.5rem, 0.05rem + 0.75vw, 0.95rem);
  right: clamp(0.5rem, 0.05rem + 0.75vw, 0.95rem);
  bottom: 0;
  height: 2px;
  background: var(--green-300);
  transform: scaleX(0);
  transition: transform 0.24s var(--ease);
}
.nav__link:hover::after,
.nav__link[aria-current='page']::after { transform: scaleX(1); }

.header__actions { display: flex; align-items: center; gap: 0.6rem; flex: none; }

.nav-burger { display: none; }

@media (min-width: 941px) {
  /* Both wrappers dissolve, not just the outer one: the panel exists for the
     mobile dropdown, and while .header__panelInner stayed a box the nav was a
     block inside a stretched flex item — so the links sat at the top of the bar
     and the marker under the current one floated mid-air instead of landing on
     the bottom edge. With both at display:contents the nav is itself a flex
     child of .header__bar and stretches to the full 72px. */
  .header__panel,
  .header__panelInner { display: contents; }
  .header__actions--mob { display: none; }
}

/* The squeeze band. The nav gives up padding before it gives up a line, and
   the logo steps down a little with it. */
@media (min-width: 941px) and (max-width: 1179px) {
  .nav__link { font-size: 0.85rem; }
  .brand__logo { height: 34px; }
}

@media (max-width: 940px) {
  .header__bar { flex-wrap: wrap; align-items: center; min-height: 64px; gap: 0.75rem; }
  .brand { order: 1; }
  .nav-burger { order: 2; }
  .header__panel { order: 3; flex-basis: 100%; }
  .header__actions--desk { display: none; }
  .brand__logo { height: 36px; }
  .brand__logo--footer { max-height: 50px; }

  .nav-burger {
    display: inline-flex;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    width: 44px;
    height: 44px;
    padding: 0 10px;
    border: 1px solid var(--line-strong);
    border-radius: var(--radius);
    background: transparent;
    cursor: pointer;
  }
  .nav-burger span {
    display: block;
    height: 1.5px;
    background: var(--navy-800);
    transition: transform 0.25s var(--ease), opacity 0.2s var(--ease);
  }

  .header__panel {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 0.3s var(--ease);
  }
  /* `grid-template-rows: 0fr` collapses the panel to nothing to look at, but
     that is all it does: the five nav links and the two buttons inside keep
     their boxes, stay in the tab order and stay in the accessibility tree.
     With the menu shut, a keyboard user tabbing off the burger fell into
     seven controls they could not see, and a screen reader read the whole
     menu out twice.

     `visibility: hidden` is what actually takes them out of both. It is
     delayed by the length of the collapse so the links are still visible on
     the way down and only stop being reachable once the panel has finished
     closing; opening clears the delay so they are available immediately. */
  .header__panelInner {
    overflow: hidden;
    min-height: 0;
    visibility: hidden;
    transition: visibility 0s linear 0.3s;
  }

  .header.is-open .header__panel { grid-template-rows: 1fr; }
  .header.is-open .header__panelInner { visibility: visible; transition-delay: 0s; }
  .header.is-open .nav-burger span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
  .header.is-open .nav-burger span:nth-child(2) { opacity: 0; }
  .header.is-open .nav-burger span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

  .nav {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 0.35rem 0 1rem;
    border-top: 1px solid var(--line);
    margin-top: 0.35rem;
  }
  /* Stacked, the bottom-edge marker has no edge to sit on, so the current item
     is marked down its leading edge instead. */
  .nav__link {
    padding: 0.82rem 0 0.82rem 0.9rem;
    border-bottom: 1px solid var(--line);
    font-size: 1.1rem;
  }
  .nav__link::after {
    left: 0; right: auto; top: 0; bottom: 0;
    width: 2px; height: auto;
    transform: scaleY(0);
    transition: transform 0.22s var(--ease);
  }
  .nav__link:hover::after,
  .nav__link[aria-current='page']::after { transform: scaleY(1); }

  .header__actions--mob { display: flex; gap: 0.6rem; padding-bottom: 1.1rem; }
  .header__actions--mob .btn { flex: 1; }
}

/* ------------------------------------------------------ 08  hero / header */

/* The photograph pins to the top of the viewport while the copy and the stat
   bar ride up over it, then releases when the section ends. Pure CSS: no
   scroll listener, nothing to fall out of sync, and it costs nothing on a
   browser that does not support sticky (the image simply sits still). */

/* Pulled back over the pinned stage. The stat bar that follows is opaque, so
   it wipes the photograph away as it arrives. */

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.34rem 0.78rem;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 100px;
  font-size: 0.775rem;
  font-weight: 500;
  color: #e7e9ed;
  background: rgba(255, 255, 255, 0.045);
}
.chip__dot { width: 5px; height: 5px; border-radius: 50%; background: var(--green-400); flex: none; }

/* Opaque, and above the stage — this bar is what wipes the photograph away.
   It is the one place a light band has to work hard: it sits directly under a
   dark hero, so it needs an edge strong enough to read as a deliberate stop
   rather than the page running out. */
.stats {
  position: relative;
  z-index: 3;
  border-top: 3px solid var(--green-600);
  border-bottom: 1px solid var(--mist-line);
  background: var(--mist);
}
.stats__grid { display: grid; grid-template-columns: repeat(3, 1fr); }
.stats__item {
  padding: clamp(1.5rem, 1.1rem + 1.4vw, 2.4rem) clamp(1rem, 0.6rem + 1.2vw, 1.8rem);
  border-left: 1px solid var(--mist-line);
}
.stats__item:first-child { border-left: 0; padding-left: 0; }
.stats__value {
  font-family: var(--font-display);
  font-size: clamp(1.7rem, 1.3rem + 1.6vw, 2.5rem);
  font-weight: 600;
  letter-spacing: -0.03em;
  color: var(--navy-900);
  line-height: 1;
  margin-bottom: 0.45rem;
}
.stats__label { font-size: 0.98rem; font-weight: 600; color: var(--navy-700); }
.stats__note { font-size: 0.88rem; color: var(--muted); margin-top: 0.2rem; }

/* Three figures, so a phone stacks them rather than leaving an orphan. */
@media (max-width: 780px) {
  .stats__grid { grid-template-columns: 1fr; }
  .stats__item { border-left: 0; padding-left: 0; border-top: 1px solid var(--mist-line); }
  .stats__item:first-child { border-top: 0; }
}

/* The photograph stays; the scrim over it was flipped. It used to be 95% black
   at the left edge, which is what made every inner page open dark. It is now
   near-opaque paper on the side the type sits on, thinning towards the right so
   the image is still visible where nothing is written over it. */
.pagehead {
  position: relative;
  background: var(--paper);
  color: var(--fg);
  overflow: hidden;
  isolation: isolate;
  border-bottom: 1px solid var(--line);
}
.pagehead__media { position: absolute; inset: 0; z-index: -2; }
.pagehead__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Desaturated so the photograph sits behind the type instead of competing
     with it, the way the black scrim used to do by brute force. */
  filter: saturate(0.42) contrast(0.96) brightness(1.12);
}
.pagehead::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(96deg,
              rgba(251, 250, 248, 0.985) 0%,
              rgba(251, 250, 248, 0.955) 42%,
              rgba(251, 250, 248, 0.74) 100%);
}
.pagehead__inner { padding-bottom: clamp(3rem, 2.2rem + 4vw, 5.2rem); }
.pagehead h1 { margin-bottom: 0.4em; max-width: 22ch; color: var(--navy-900); }
.pagehead__lede { color: var(--slate-500); font-size: var(--step-1); max-width: 56ch; }

/* -------------------------------------------------------- 09  breadcrumbs */
.crumbs { padding-block: 1.15rem 1.6rem; }
.crumbs ol {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.1rem 0.45rem;
  font-size: 0.92rem;
}
.crumbs li { display: inline-flex; align-items: center; gap: 0.45rem; margin: 0; }
/* Every breadcrumb on the site is on paper now — the page headers included —
   so the default is ink and --onPaper is left in place only because it is
   written into the legal pages and the posts, where it now agrees with the
   default rather than correcting it. */
.crumbs a { color: var(--slate-500); transition: color 0.16s var(--ease); }
.crumbs a:hover { color: var(--green-700); }
.crumbs [aria-current='page'] { color: var(--navy-800); font-weight: 500; }
.crumbs__sep { color: var(--slate-400); }

.crumbs--onPaper a { color: var(--slate-500); }
.crumbs--onPaper a:hover { color: var(--green-600); }
.crumbs--onPaper [aria-current='page'] { color: var(--navy-800); }
.crumbs--onPaper .crumbs__sep { color: var(--slate-500); }

/* -------------------------------------------------------------- 10  cards */
.grid { display: grid; gap: clamp(1rem, 0.7rem + 1.1vw, 1.6rem); }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(272px, 1fr)); }

.feature {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.6rem 1.5rem 1.7rem;
  height: 100%;
  transition: border-color 0.22s var(--ease);
}
.feature:hover { border-color: var(--line-strong); }
.feature__num {
  font-family: var(--font-display);
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--green-600);
  display: block;
  margin-bottom: 0.9rem;
}
.feature h3 { font-size: 1.07rem; margin-bottom: 0.5rem; }
.feature p { font-size: 0.895rem; color: var(--slate-500); margin: 0; }

.band--ink .feature { background: rgba(255, 255, 255, 0.72); border-color: var(--mist-line); }
.band--ink .feature:hover { border-color: var(--green-400); }
.band--ink .feature p { color: var(--slate-500); }
.band--ink .feature__num { color: var(--green-600); }

.split { display: grid; gap: clamp(2rem, 1.2rem + 4vw, 4.5rem); align-items: center; grid-template-columns: 1fr; }
/* A grid item is min-width:auto by default, which means it refuses to shrink
   below its content — and .table has a 460px min-width so it can stay legible
   while .table-wrap scrolls it. Together those two pushed the whole product
   page sideways on a phone: the wrap never got the chance to scroll, because
   the column around it had already grown to 462px. Measured before the fix:
   360px overflowed by 136px, 390px by 107px. */
.split > *, .grid > * { min-width: 0; }
@media (min-width: 900px) {
  .split { grid-template-columns: 1.05fr 1fr; }
  .split--reverse .split__media { order: -1; }
}
.split__media { border-radius: var(--radius-lg); overflow: hidden; background: var(--paper-3); }
.split__media img { width: 100%; height: auto; }

/* Two columns of very different length. The text in these bands runs 589px to
   950px; a photograph at its own aspect in the other column is 293px to 417px.
   Centred, as the grid did by default, that left a 280–533px void split above
   and below every image and nothing on the band lined up with anything.

   So above the one-column breakpoint the media stretches to the height of the
   row and crops to fill it. Two consequences, both wanted: the top of the
   photograph lines up with the top of the heading beside it, and the band
   reads as two columns rather than as a paragraph with a stamp next to it.

   `max-height` is the safety rail. The About page's text column is 950px, and
   a 545px-wide box that tall would crop a 4:3 frame down to the middle 40% of
   its width — which is how you cut someone's face in half. Capped, the worst
   crop on the site keeps the middle 60%, and what is left of the void sits
   under the image where it reads as margin instead of as a mistake. */
@media (min-width: 900px) {
  .split__media {
    align-self: stretch;
    max-height: 640px;
  }
  .split__media picture { display: block; height: 100%; }
  .split__media img { height: 100%; object-fit: cover; }
}

/* ------------------------------------------------- 11  lists/tables/steps */
.ticks { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.72rem; }
.ticks li { position: relative; padding-left: 1.85rem; margin: 0; font-size: 0.945rem; line-height: 1.55; }
.ticks li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.42em;
  width: 15px;
  height: 9px;
  border-left: 1.8px solid var(--green-500);
  border-bottom: 1.8px solid var(--green-500);
  transform: rotate(-45deg);
}

.table-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius-lg); background: #fff; }
.table { font-size: 0.905rem; min-width: 460px; }
.table th, .table td { text-align: left; padding: 0.92rem 1.15rem; border-bottom: 1px solid var(--line); vertical-align: top; }
.table thead th {
  font-family: var(--font-display);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--slate-500);
  background: var(--paper-2);
  font-weight: 600;
}
.table tbody tr:last-child th, .table tbody tr:last-child td { border-bottom: 0; }
.table tbody th { font-weight: 500; color: var(--slate-500); width: 38%; font-family: inherit; }
.table td { color: var(--navy-800); }
.table code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.88em;
  background: var(--paper-2);
  padding: 0.1rem 0.4rem;
  border-radius: 3px;
}

/* Below the width where three columns fit, the table stops being a grid of
   columns and becomes a short stack per row: the metal and its symbol on one
   line, and what it does — the only column that says anything — across the
   full width underneath.

   It scrolled sideways before. .table has a 460px min-width so the columns
   stay legible, and .table-wrap scrolls it; on a 390px screen that put the
   third column off the right edge, behind a horizontal scrollbar that nothing
   on the page suggested was there. A supplier reading about rhodium on a
   phone saw the word "The scar…" and nothing else.

   The header row is hidden the accessible way rather than with display:none,
   so it stays in the accessibility tree with the <caption> and the scope
   attributes. Sighted readers do not need it: a metal, its two-letter symbol
   and a sentence about it need no column headings to be understood. */
@media (max-width: 700px) {
  .table-wrap { overflow-x: visible; }
  .table { min-width: 0; }

  .table thead {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
  }

  .table tbody tr {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: baseline;
    gap: 0.35rem 0.9rem;
    padding: 1.05rem 1.15rem;
    border-bottom: 1px solid var(--line);
  }
  .table tbody tr:last-child { border-bottom: 0; }

  .table tbody th,
  .table tbody td { border: 0; padding: 0; width: auto; }

  .table tbody th {
    grid-column: 1;
    font-family: var(--font-display);
    font-size: 1.06rem;
    font-weight: 600;
    color: var(--navy-900);
  }
  .table tbody td[data-label='Symbol'] { grid-column: 2; grid-row: 1; }
  .table tbody td[data-label='What it does'] {
    grid-column: 1 / -1;
    color: var(--slate-500);
    line-height: 1.6;
  }
}

.steps { list-style: none; padding: 0; margin: 0; display: grid; gap: 0; counter-reset: step; }
@media (min-width: 860px) { .steps { grid-template-columns: repeat(4, 1fr); } }
.steps li {
  counter-increment: step;
  margin: 0;
  padding: 1.7rem 0 1.9rem;
  border-top: 2px solid var(--line);
  position: relative;
}
@media (min-width: 860px) {
  .steps li { padding-left: 1.6rem; padding-right: 1.8rem; }
  .steps li:first-child { padding-left: 0; }
}
.steps li::before {
  content: '0' counter(step);
  font-family: var(--font-display);
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--green-600);
  display: block;
  margin-bottom: 0.75rem;
}
.steps li::after {
  content: '';
  position: absolute;
  top: -2px;
  left: 0;
  width: 34%;
  height: 2px;
  background: var(--green-500);
}
.steps h3 { font-size: 1.03rem; margin-bottom: 0.45rem; }
.steps p { font-size: 0.885rem; color: var(--slate-500); margin: 0; }
.band--ink .steps li { border-top-color: var(--mist-line); }
.band--ink .steps p { color: var(--slate-500); }
.band--ink .steps li::before { color: var(--green-600); }

.infolist { display: grid; gap: 0; border-top: 1px solid var(--line); }
.infolist > div {
  display: grid;
  gap: 0.15rem 1.2rem;
  padding: 0.95rem 0;
  border-bottom: 1px solid var(--line);
}
@media (min-width: 560px) { .infolist > div { grid-template-columns: 12rem 1fr; } }
.infolist dt { font-size: 0.86rem; color: var(--slate-500); }
.infolist dd { margin: 0; font-size: 0.95rem; color: var(--navy-900); font-weight: 500; }
.band--ink .infolist, .band--ink .infolist > div { border-color: var(--mist-line); }
.band--ink .infolist dt { color: var(--muted); }
.band--ink .infolist dd { color: var(--navy-900); }

/* ---------------------------------------------------------------- 12  faq */
.faq { border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  list-style: none;
  cursor: pointer;
  padding: 1.25rem 2.6rem 1.25rem 0;
  position: relative;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.18rem;
  letter-spacing: -0.012em;
  color: var(--navy-900);
  transition: color 0.18s var(--ease);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--green-600); }
.faq summary::after, .faq summary::before {
  content: '';
  position: absolute;
  right: 0.4rem;
  top: 50%;
  background: var(--green-500);
  transition: transform 0.25s var(--ease), opacity 0.25s var(--ease);
}
.faq summary::before { width: 13px; height: 1.6px; transform: translateY(-50%); }
.faq summary::after { width: 1.6px; height: 13px; right: 0.75rem; transform: translateY(-50%); }
.faq details[open] summary::after { transform: translateY(-50%) rotate(90deg); opacity: 0; }
.faq__answer { padding: 0 2.6rem 1.4rem 0; color: var(--slate-500); font-size: 1.06rem; max-width: 68ch; }

/* ---------------------------------------------------------------- 13  cta */
/* Same construction as .pagehead: the photograph stays, the scrim flipped from
   near-black to near-opaque paper. The green rule along the top is what keeps
   the band reading as a closing statement now that it is no longer darker than
   everything above it. */
.cta {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  background: var(--paper);
  color: var(--fg);
  border-top: 3px solid var(--green-600);
}
.cta__media { position: absolute; inset: 0; z-index: -2; }
.cta__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(0.42) contrast(0.96) brightness(1.12);
}
.cta::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(92deg,
              rgba(251, 250, 248, 0.975) 15%,
              rgba(251, 250, 248, 0.78) 100%);
}
.cta__inner { padding-block: clamp(3.2rem, 2.4rem + 4.4vw, 5.6rem); display: grid; gap: 2rem; align-items: center; }
@media (min-width: 900px) { .cta__inner { grid-template-columns: 1.5fr auto; } }
.cta h2 { margin-bottom: 0.5rem; color: var(--navy-900); }
.cta p { color: var(--slate-500); max-width: 52ch; margin: 0; }

/* secondary_cta() paints this button for a dark ground. The ground is paper. */
.cta .btn--onDark { --btn-fg: var(--navy-800); --btn-bd: var(--line-strong); }
.cta .btn--onDark:hover { --btn-bg: var(--navy-800); --btn-fg: #fff; --btn-bd: var(--navy-800); }

/* ------------------------------------------------------ 13b  heritage box */
/* One box, at the foot of the converter page. It is the only place the site
   mentions the metals and scrap trade the family has run for forty years, so
   it has to look like an aside and not like a second product pitch — hence a
   bordered panel inside the narrow container rather than a full-width band. */
.heritagebox {
  background: var(--mist);
  border: 1px solid var(--mist-line);
  border-left: 4px solid var(--green-600);
  border-radius: var(--radius-lg);
  padding: clamp(1.8rem, 1.3rem + 2.2vw, 3.2rem);
}
.heritagebox h2 { margin-bottom: 0.7em; }
.heritagebox p { color: var(--slate-500); max-width: 68ch; }
.heritagebox p + p { margin-top: 1.1rem; }
.heritagebox .ticks { margin-top: 1.8rem; }

/* --------------------------------------------------------------- 14  form */
.form { display: grid; gap: 1.05rem; }
.field { display: grid; gap: 0.42rem; }
.field label {
  font-size: 0.92rem;
  font-weight: 600;
  letter-spacing: 0.045em;
  text-transform: uppercase;
  color: var(--slate-500);
  font-family: var(--font-display);
}
.field input, .field select, .field textarea {
  width: 100%;
  padding: 0.78rem 0.95rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: #fff;
  font: inherit;
  font-size: 1.06rem;
  color: var(--navy-900);
  transition: border-color 0.18s var(--ease), box-shadow 0.18s var(--ease);
}
.field textarea { resize: vertical; min-height: 128px; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-color: var(--green-500);
  box-shadow: 0 0 0 3px rgba(198, 123, 52, 0.16);
}
.field input::placeholder, .field textarea::placeholder { color: var(--slate-300); }
.field--row { display: grid; gap: 1.05rem; grid-template-columns: 1fr; }
@media (min-width: 620px) { .field--row { grid-template-columns: 1fr 1fr; } }
.form__note { font-size: 0.92rem; color: var(--slate-500); margin: 0; }

.form__status {
  padding: 0.85rem 1.1rem;
  border-radius: var(--radius);
  font-size: 0.9rem;
  border: 1px solid var(--line-strong);
  background: var(--paper-2);
}
.form__status[data-state='ok'] { border-color: #9fd3c2; background: #eaf6f2; color: #14503f; }
.form__status[data-state='error'] { border-color: #e6b7a8; background: #fbeee9; color: #7a3720; }

/* Honeypot — hidden from people, tempting to bots. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ------------------------------------------------------------- 15  footer */
.footer {
  background: var(--mist-2);
  color: var(--slate-500);
  border-top: 1px solid var(--mist-line);
}
.footer .muted { color: var(--muted); }
.footer__top {
  display: grid;
  gap: clamp(2rem, 1.4rem + 2.6vw, 3.4rem);
  padding-block: clamp(3rem, 2.2rem + 3.4vw, 4.6rem);
  grid-template-columns: 1fr;
}
@media (min-width: 760px) { .footer__top { grid-template-columns: 1.6fr 1fr 1fr; } }
@media (min-width: 1040px) { .footer__top { grid-template-columns: 1.7fr 1fr 1fr 1.15fr; } }

.footer__blurb { font-size: 1rem; color: var(--slate-500); margin: 1.15rem 0 1.35rem; max-width: 34ch; }

.footer h2 {
  font-family: var(--font-display);
  font-size: 0.84rem;
  font-weight: 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--navy-700);
  margin-bottom: 1.1rem;
}
/* Footer links get 24px-tall hit areas (WCAG 2.2 target size) from padding
   rather than from a bigger gap, so the list keeps its old rhythm. */
.footer ul { list-style: none; padding: 0; margin: 0; display: grid; gap: calc(0.68rem - 0.25rem); }
.footer ul a { display: inline-block; padding-block: 0.125rem; }
.footer li { margin: 0; }
.footer a { font-size: 1rem; color: var(--slate-500); transition: color 0.18s var(--ease); }
.footer a:hover { color: var(--green-700); }
.footer address { font-style: normal; font-size: 1rem; line-height: 1.75; color: var(--slate-500); }

.footer__bottom {
  border-top: 1px solid var(--mist-line);
  padding-block: 1.5rem 1.8rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 1.5rem;
  align-items: center;
  justify-content: space-between;
  font-size: 0.93rem;
  color: var(--muted);
}
.footer__bottom p { margin: 0; }
.footer__bottom a { font-size: inherit; }
/* Legal links sit next to the copyright; the credit keeps the far right. */
.footer__legal { margin-right: auto; }
.footer__legal a { color: var(--muted); }
.footer__legal a:hover { color: var(--green-700); }
.footer__credit a {
  color: var(--green-700);
  font-weight: 600;
  border-bottom: 1px solid rgba(21, 119, 58, 0.35);
}
.footer__credit a:hover { border-bottom-color: var(--green-700); }

.social { display: flex; gap: 0.5rem; }
.social a {
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: var(--radius);
  transition: border-color 0.18s var(--ease), background-color 0.18s var(--ease);
}
.social a:hover { border-color: var(--green-400); background: rgba(92, 200, 111, 0.14); }
.social svg { width: 17px; height: 17px; }

/* ---------------------------------------------------------------- 16  404 */
.notfound { display: grid; place-items: center; text-align: center; padding-block: clamp(4rem, 3rem + 7vw, 8rem); }
.notfound__code {
  font-family: var(--font-display);
  font-size: clamp(4.5rem, 3rem + 12vw, 11rem);
  font-weight: 700;
  line-height: 0.86;
  letter-spacing: -0.05em;
  background: linear-gradient(150deg, var(--green-300), var(--green-600) 55%, var(--navy-700));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  margin-bottom: 1.2rem;
}
.notfound .lede { margin-inline: auto; }
.notfound__links { margin-top: 2.6rem; width: 100%; max-width: 820px; text-align: left; }

/* ------------------------------------------------------------- 17  motion */
.prose h2 { margin-top: 2.6rem; }
.prose h3 { margin-top: 2rem; font-size: var(--step-1); }
.prose > *:first-child { margin-top: 0; }
.prose p, .prose li { color: var(--slate-500); }
.prose strong { color: var(--navy-900); font-weight: 600; }
/* Inline prose links only — buttons and arrow links keep their own colours. */
.prose a:not(.btn):not(.arrow-link) {
  color: var(--green-600);
  border-bottom: 1px solid rgba(198, 123, 52, 0.35);
}
.prose a:not(.btn):not(.arrow-link):hover { border-bottom-color: var(--green-600); }

.rule { height: 1px; background: var(--line); border: 0; margin: 0; }
.band--ink .rule { background: var(--mist-line); }

/* Progressive reveal.
   Nothing is hidden by this stylesheet. main.js "arms" only those .reveal blocks
   that start below the fold, so content is visible by default and stays visible
   if the script never runs. */
/* Weighted reveal. Blocks start 7px high and *drop* into place with a small
   overshoot, so they read as mass coming to rest rather than as content
   floating up out of nowhere. The opacity ramp is short and finishes early —
   it exists only to stop the first frame flashing, not as the effect itself. */
.reveal--armed { opacity: 0; transform: translateY(-7px); }
.reveal--armed.is-visible {
  opacity: 1;
  transform: none;
  transition: opacity 0.18s linear, transform 0.42s var(--ease-settle);
  /* Grouped children arrive in sequence. main.js sets --i on each one; the
     step stays small so the last card in a row is never left waiting. */
  transition-delay: calc(var(--i, 0) * 55ms);
}

/* The process sequence draws its connector bars as you move through it.
   Only main.js adds .steps--armed, so with the script disabled every bar is
   simply drawn, exactly as before. Nothing here hides content on its own. */

/* Table rows land one after another. */
.table tbody tr { transition: transform 0.34s var(--ease-settle), opacity 0.18s linear; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal--armed, .reveal--armed.is-visible { opacity: 1; transform: none; transition: none; }
  /* Everything in the hero stops: the drift, the wiggle, the pinning. main.js
     never starts the mouse parallax under this setting either. */
  
  
  
  
  
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

@media print {
  .header, .footer, .cta, .skip-link, .crumbs { display: none !important; }
  body { background: #fff; color: #000; }
}

/* ------------------------------------------------------- 15  utilities */
/* Visible to a screen reader, not to the eye. Used on the <caption> of every
   data table: a table needs a caption to be navigable, and these tables carry
   a visible heading directly above them already. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* An aside under a block — smaller, quieter, still readable. */
.note {
  margin-top: 1.5rem;
  font-size: 0.9rem;
  color: var(--slate-500);
  max-width: 62ch;
}
.note a { color: var(--green-700); text-decoration: underline; text-underline-offset: 2px; }
.note a:hover { color: var(--green-600); }

/* ------------------------------------------------------------ 16  blog */
.post-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(310px, 1fr));
  gap: clamp(1.4rem, 1rem + 1.6vw, 2.4rem);
}

.post-card {
  display: flex;
  flex-direction: column;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: border-color 0.25s ease, transform 0.25s ease, box-shadow 0.25s ease;
}
.post-card:hover {
  border-color: var(--line-strong);
  transform: translateY(-2px);
  box-shadow: 0 14px 34px rgba(22, 28, 40, 0.07);
}
.post-card__media { display: block; aspect-ratio: 16 / 10; overflow: hidden; background: var(--paper-3); }
.post-card__media img { width: 100%; height: 100%; object-fit: cover; }
.post-card:hover .post-card__media img { transform: scale(1.03); }
.post-card__media img { transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1); }

.post-card__body {
  padding: 1.4rem 1.5rem 1.6rem;
  display: flex; flex-direction: column; gap: 0.55rem;
  flex: 1;
}
/* The date and the reading time are one phrase and wrap as one: with them as
   separate flex children the "· 5 min read" broke onto its own line and led
   with a stray middot. */
.post-card__meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.45rem 0.6rem;
  margin: 0;
  font-size: 0.775rem; color: var(--slate-400);
}
.post-card__when { white-space: nowrap; }
.post-card__cat {
  padding: 0.2rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: 100px;
  color: var(--green-700);
  font-weight: 500;
  letter-spacing: 0.02em;
}
.post-card h3 { font-size: var(--step-1); line-height: 1.22; margin: 0; }
.post-card h3 a { color: inherit; }
.post-card h3 a:hover { color: var(--green-700); }
.post-card__body > p { margin: 0; color: var(--slate-500); font-size: 0.92rem; line-height: 1.6; }

/* ---- a post ---- */
.post__head { padding: clamp(2.2rem, 1.4rem + 3vw, 4rem) 0 clamp(1.4rem, 1rem + 1.6vw, 2.2rem); }
.post__head h1 { font-size: var(--step-3); max-width: 20ch; margin-bottom: 0.7rem; }
.post__lede {
  font-size: var(--step-1);
  line-height: 1.5;
  color: var(--slate-500);
  max-width: 54ch;
  margin-bottom: 1.1rem;
}
.post__meta { font-size: 0.83rem; color: var(--slate-500); margin: 0; }

.post__media { margin-bottom: clamp(2rem, 1.4rem + 2vw, 3.2rem); }
.post__media picture, .post__media img { display: block; width: 100%; }
.post__media img {
  aspect-ratio: 21 / 9;
  object-fit: cover;
  border-radius: var(--radius-lg);
}

/* The body of a post is long-form: it needs a wider measure than a marketing
   block and tighter vertical rhythm than the section grid gives. */
.post__body { padding-bottom: clamp(2.5rem, 1.8rem + 2.5vw, 4rem); }
.post__body h2 {
  font-size: var(--step-2);
  margin-top: 2.4rem;
  margin-bottom: 0.7rem;
  scroll-margin-top: 118px;
}
.post__body h3 { font-size: var(--step-1); margin-top: 1.8rem; margin-bottom: 0.5rem; }
.post__body > *:first-child { margin-top: 0; }
.post__body p, .post__body li { max-width: 68ch; }
.post__body ul, .post__body ol { padding-left: 1.3rem; margin-bottom: 1.15em; }
.post__body li { margin-bottom: 0.5em; line-height: 1.65; }
.post__body a { color: var(--green-700); text-decoration: underline; text-underline-offset: 2px; }
.post__body a:hover { color: var(--green-600); }
.post__body strong { color: var(--navy-800); font-weight: 600; }

/* ---------------------------------------- 18  header at awkward widths */
/* The primary nav went from five items to seven when Recycling and Blog were
   added, and between the burger breakpoint (941px) and about 1120px the row
   no longer fits: measured on the built pages, 960px overflowed by 101px and
   1024px by 38px. The phone number is the widest thing that can go — it is
   still one tap away in the burger panel on smaller screens, it is in the
   footer on every page, and the Enquire button keeps the call to action in
   the bar. Above 1120px it comes back. */
@media (min-width: 941px) and (max-width: 1120px) {
  .header__actions--desk .btn--ghost { display: none; }
  .nav__link { padding-left: 0.62rem; padding-right: 0.62rem; }
}

/* ------------------------------------------- 19  quick contact bar */
/* Phone and WhatsApp pinned to the bottom of the viewport on handsets.
   Hidden from 941px up, which is the breakpoint where the burger goes away
   and the header shows the number again — above that the bar would be a
   second copy of something already on screen.

   `env(safe-area-inset-bottom)` keeps it clear of the iOS home indicator,
   and the same value is added to the footer's padding so the last line of
   the footer is never sitting underneath the bar. */
.callbar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 60;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 1px;
  background: var(--line-strong);
  border-top: 1px solid var(--line-strong);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  box-shadow: 0 -6px 22px rgba(11, 14, 20, 0.12);
}
.callbar__item {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  /* 52px of height plus the type: a comfortable tap target at the bottom
     edge of the screen, which is the hardest place on a phone to hit. */
  min-height: 52px;
  padding: 0.5rem 0.7rem;
  background: var(--navy-900);
  color: #fff;
  font-family: var(--font-display, inherit);
  font-size: 0.86rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-decoration: none;
  white-space: nowrap;
}
.callbar__item svg { flex: none; }
.callbar__item:hover,
.callbar__item:focus-visible { background: var(--navy-800); color: #fff; }
.callbar__item--wa { background: #1f7a4d; }
.callbar__item--wa:hover,
.callbar__item--wa:focus-visible { background: #196540; }

@media (min-width: 941px) {
  .callbar { display: none; }
}
@media (max-width: 940px) {
  .footer { padding-bottom: calc(3.2rem + 52px + env(safe-area-inset-bottom, 0px)); }
}

/* ---------------------------------------- 20  enquiry fallback panel */
/* Revealed by main.js on the mailto path only. Nothing can tell us whether
   the visitor's mail client actually opened, so this is worded as a question
   and offers the two routes that do not depend on one. */
.form__fallback {
  margin-top: 1rem;
  padding: 1rem 1.1rem 1.15rem;
  border: 1px solid var(--line-strong);
  border-left: 3px solid var(--green-500);
  border-radius: 10px;
  background: var(--paper-2);
}
.form__fallback p {
  margin: 0 0 0.85rem;
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--slate-500);
}
.form__fallback strong { color: var(--fg); }
.form__fallback .btn-row { gap: 0.5rem; flex-wrap: wrap; }

/* --------------------------------------------- 21  photographic plates */
/* A captioned figure used in two places: the six-frame walk through the
   plant on the converter page, and the three diagrams on the home page.

   The columns and the reveal stagger come from .grid / .grid--3, which
   main.js already sequences (SEQ in assets/js/main.js), so a plate row is
   written as `.grid .grid--3 .plates .reveal` and this block only has to
   describe one figure. */
.plates { margin-top: clamp(0.5rem, 0.2rem + 1vw, 1.2rem); }

.plate { margin: 0; display: grid; gap: 0.9rem; align-content: start; }
.plate__media {
  display: block;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--paper-3);
  /* Every plate is cut to 4:3 by tools/build-images.py, but the box is held
     open here too: the row keeps its rhythm while the images are still
     decoding, and one plate can never be a different height from its
     neighbour. */
  aspect-ratio: 4 / 3;
}
.plate__media img,
.plate__media picture { display: block; width: 100%; height: 100%; }
.plate__media img { object-fit: cover; }

.plate figcaption { font-size: 0.925rem; line-height: 1.55; color: var(--slate-500); }
.plate figcaption b {
  display: block;
  margin-bottom: 0.28rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.0rem;
  color: var(--navy-900);
}
/* Sits on its own line above the caption title, the way .feature__num does
   over a feature heading. Block rather than inline so the two never collide
   on a narrow column. */
.plate__num {
  display: block;
  margin-bottom: 0.3rem;
  font-family: var(--font-display);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--green-600);
}

/* The three process diagrams are flat artwork that tools/build-images.py has
   already composited onto --navy-800, so the tile behind them is painted the
   same navy and the plate has no visible edge. They are drawings, not
   photographs, so they are contained rather than cropped. */
.plate--dark .plate__media { background: var(--navy-800); }
.plate--dark .plate__media img { object-fit: contain; }
