/* BAS Construx — home. Foundation, hero, intro, plate, products, material, patterns, technical data, audience, form, pill, footer. */

/* ---------- Tokens ---------- */
/* ABC Areal and ABC Areal Mono (Dinamo), local woff2. The site uses three cuts only:
   Areal Regular and Medium, Areal Mono Regular. */
@font-face {
  font-family: "Areal";
  src: url("fonts/ABCAreal-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Areal";
  src: url("fonts/ABCAreal-Medium.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Areal Mono";
  src: url("fonts/ABCArealMono-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  --ground: #e9e7e3;
  --ink: #1a1816;
  --ink-2: #6b6764;
  --line: rgba(26, 24, 22, 0.72);
  --line-soft: rgba(26, 24, 22, 0.28);
  --line-light: rgba(255, 255, 255, 0.78);

  --grotesk: "Areal", "Helvetica Neue", Arial, sans-serif;
  --serif: "Source Serif 4", Georgia, "Times New Roman", serif;
  --mono: "Areal Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;

  --margin: clamp(20px, 2.78vw, 40px);
  --gutter: 24px;
  --tick: 9px;

  /* Type scale: seven steps, each far enough from the next to read as its own level.
     Which text takes which step is set once, under Type roles. */
  --t-display: clamp(34px, 3.4vw, 50px);
  --t-statement: clamp(24px, 2.2vw, 32px);
  --t-title: 20px;
  --t-body: 17px;
  --t-ui: 15px;
  --t-small: 13px;
  --t-meta: 12px;

  --ease: cubic-bezier(0.2, 0.6, 0.15, 1);
  --d-line: 600ms;
  --d-row: 500ms;
  --d-mask: 600ms;
  --stagger: 70ms;
}

/* ---------- Base ---------- */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  background: var(--ground);
  color: var(--ink);
  font-family: var(--grotesk);
  font-size: 16px;
  line-height: 1.4;
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scrollbar-color: var(--ink-2) var(--ground);
}

body {
  margin: 0;
  font-weight: 400;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

/* Lenis marks the root while it is driving the page; its easing replaces the CSS one */
html.lenis { scroll-behavior: auto; }

img, svg { display: block; max-width: 100%; }
img { height: auto; }

h1, h2, h3, p, dl, dd, figure, address { margin: 0; font-weight: 400; font-style: normal; }
ul { margin: 0; padding: 0; list-style: none; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 0.18em; text-decoration-thickness: 1px; }

::selection { background: var(--ink); color: var(--ground); }

:focus-visible { outline: 1px solid var(--ink); outline-offset: 4px; }
.hero :focus-visible, .head :focus-visible { outline-color: #fff; }

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

.skip {
  position: absolute; left: var(--margin); top: -100px; z-index: 50;
  padding: 10px 14px; background: var(--ground); color: var(--ink);
  border: 1px solid var(--ink); font-size: 14px;
}
.skip:focus { top: 12px; text-decoration: none; }

.arrow { display: inline-block; font-family: var(--grotesk); }

/* ---------- Type roles ----------
   Every piece of text on the site belongs to one role, and this is the only place type
   is sized. Each level differs from its neighbours in at least two ways (size and weight,
   size and family, family and case), so no two levels can be mistaken for each other.

   display    Areal 400, large: the one line that opens a page
   statement  Areal 400: the paragraph that opens a section
   title      Areal 500, capitals: the name on a row, a cell or a note
   body       Source Serif: paragraphs, with a small and a fine size
   ui         Areal 400: nav, captions, form labels, footer
   action     Areal 400, small capitals: a link that leads somewhere, with an arrow
   label      Areal Mono, capitals: the section label in the left column
   meta       Areal Mono: specs, tags, numbers, table heads

   Every label-shaped piece of type is set in capitals: section labels, row titles,
   note and pattern names, hotspot names. Sentences are never touched.
   Capitals need more room between letters than lowercase, so each role is tracked out. */
.label,
.row-title,
.note-name,
.cap-name,
.spot-name,
.group-name,
.sample-title { text-transform: uppercase; }

/* display */
.hero-line,
.opening-line {
  font-size: var(--t-display);
  font-weight: 400;
  line-height: 1.06;
  letter-spacing: -0.02em;
}

/* statement */
.statement {
  font-size: var(--t-statement);
  font-weight: 400;
  line-height: 1.22;
  letter-spacing: -0.015em;
  text-wrap: pretty;
  max-width: 34ch;
}

/* title: the row, cell or note sets the size; the name inside it carries the weight.
   A row's number and any note beside the name drop to meta, so the name stands alone. */
.row-btn,
.row-link,
.cell-head,
.cell-firm,
.note-name {
  font-size: var(--t-title);
  line-height: 1.2;
}
.row-title,
.note-name {
  font-weight: 500;
  letter-spacing: 0.03em;
}
/* the small title: the hero card and the pattern captions */
.sample-title,
.cap-name {
  font-size: var(--t-ui);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.04em;
}

/* body */
.body,
.cell-person {
  font-family: var(--serif);
  font-size: var(--t-body);
  line-height: 1.4;
  font-optical-sizing: auto;
  text-wrap: pretty;
}
/* the small serif: body text in narrow cells and on the hero card */
.note .body,
.cell .body,
.sample-body,
.form-note {
  font-family: var(--serif);
  font-size: var(--t-ui);
  line-height: 1.4;
}
/* the fine serif: disclaimers */
.disclaimer,
.foot-disclaimer {
  font-family: var(--serif);
  font-size: var(--t-small);
  line-height: 1.45;
  color: var(--ink-2);
}

/* ui */
.head-nav .box,
.head-toggle,
.cap,
.label-sub,
.field > label,
.field > legend,
.cell-lines,
.foot-grid { font-size: var(--t-ui); }

/* action: small capitals and an arrow, well below a title, so a link never reads as a heading */
.more,
.sample-link,
.submit {
  font-family: var(--grotesk);
  font-size: var(--t-small);
  line-height: 1.2;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* label and meta: Areal Mono */
.label,
.tag,
.pill,
.plate-spec,
.hero-name,
.spec,
.data,
.group-name,
.spot-mark,
.spot-name,
.cap-fact,
.split-cap,
.twelve-cap,
.row-num,
.row-note,
.cell-place,
.cell-contact,
.cell-address,
.label-link,
.clock,
.foot-reg {
  font-family: var(--mono);
  font-weight: 400;
  font-size: var(--t-meta);
  letter-spacing: 0.04em;
}
.label {
  font-size: var(--t-ui);
  line-height: 1.3;
  letter-spacing: 0.02em;
}
/* capitals at 12 px stand as tall as lowercase at 13 px, so the mono values that keep
   their lowercase (table values, phone numbers, addresses, the clock) take the 13 px step */
.data td,
.cell-contact,
.clock {
  font-size: var(--t-small);
  letter-spacing: 0.01em;
}
.row-num { color: var(--ink-2); }

/* ---------- Corner tick marks (crop marks where hairlines meet) ---------- */
.box { position: relative; }
.box::after {
  content: "";
  position: absolute;
  /* -5px, not -4px: this layer is laid against the padding box, so on a box with a 1px
     border -4px would start the ticks 1px inside the border they mark. Same reason
     .row-media, .note, .cell and .field offset their bordered side by 5px. */
  inset: -5px;
  pointer-events: none;
  --c: var(--line-light);
  background-image:
    linear-gradient(var(--c), var(--c)), linear-gradient(var(--c), var(--c)),
    linear-gradient(var(--c), var(--c)), linear-gradient(var(--c), var(--c)),
    linear-gradient(var(--c), var(--c)), linear-gradient(var(--c), var(--c)),
    linear-gradient(var(--c), var(--c)), linear-gradient(var(--c), var(--c));
  background-size:
    var(--tick) 1px, 1px var(--tick),
    var(--tick) 1px, 1px var(--tick),
    var(--tick) 1px, 1px var(--tick),
    var(--tick) 1px, 1px var(--tick);
  background-position:
    left 0 top 4px, left 4px top 0,
    right 0 top 4px, right 4px top 0,
    left 0 bottom 4px, left 4px bottom 0,
    right 0 bottom 4px, right 4px bottom 0;
  background-repeat: no-repeat;
}

/* ---------- Header ---------- */
/* --hp is the header's own progress, 0 over the hero and 1 after 300 px of scroll.
   Every part of the change reads from it, so the whole bar turns at one rate. */
.head {
  --hp: 0;
  position: fixed;
  z-index: 20;
  top: 18px;
  left: var(--margin);
  right: var(--margin);
  display: flex;
  align-items: flex-start;
  color: #fff;
  color: color-mix(in srgb, var(--ink) calc(var(--hp) * 100%), #fff);
  text-shadow: 0 0 18px rgba(0, 0, 0, calc(0.28 * (1 - var(--hp))));
}

.head .box {
  border: 1px solid var(--line-light);
  border-color: color-mix(in srgb, var(--line-soft) calc(var(--hp) * 100%), var(--line-light));
  /* over the photograph the boxes are clear; by 300 px they have settled on the page colour */
  background-color: rgba(233, 231, 227, var(--hp));
  background-color: color-mix(in srgb, var(--ground) calc(var(--hp) * 100%), transparent);
}
.head .box::after { --c: color-mix(in srgb, var(--line-soft) calc(var(--hp) * 100%), var(--line-light)); }
.head.is-stuck :focus-visible { outline-color: var(--ink); }

/* the logo box is the tall one; it closes down to the nav box height on the same 300 px */
.head-brand {
  flex: 1 1 auto;
  height: calc(64px - 18px * var(--hp));
  display: flex;
  align-items: center;
  padding: 0 22px;
}
.head-brand:hover { text-decoration: none; }
.head-brand .wordmark { height: 20px; width: auto; fill: currentColor; }
.head-brand .wordmark { flex-shrink: 0; }
.head-brand .brand-icon { display: none; flex-shrink: 0; height: 24px; width: auto; fill: currentColor; }
/* the brand box shrinks as the nav takes the row; once the full wordmark no longer fits
   at its own size, the header shows the icon alone instead of a shrunken wordmark */
.head-brand { container-type: inline-size; }
@container (max-width: 170px) {
  .head-brand .wordmark { display: none; }
  .head-brand .brand-icon { display: block; }
}

.head-nav { display: flex; }
.head-nav .box {
  width: 150px;
  height: 46px;
  display: flex;
  align-items: center;
  padding: 0 16px;
  margin-left: -1px;
  line-height: 1;
  transition: background-color 200ms var(--ease);
}
/* the hover tint travels with the bar: a white wash over the photograph,
   a shade deeper than the page colour once the bar has settled */
.head-nav .box:hover {
  text-decoration: none;
  background-color: rgba(255, 255, 255, 0.10);
  background-color: color-mix(in srgb, #dcd9d4 calc(var(--hp) * 100%), rgba(255, 255, 255, 0.10));
}

.head-toggle {
  display: none;
  height: 46px;
  padding: 0 16px;
  margin-left: -1px;
  line-height: 1;
}

/* ---------- Scroll parallax ----------
   The script writes an inline transform onto every [data-px] element on each frame.
   data-px      how far it drifts: a percentage of its own height, or a px value ("12px").
                Positive lags behind the scroll (background), negative outruns it (foreground).
   data-px-scale  a resting scale, so drift can never pull an edge into view.
   data-px-zoom   extra scale at the middle of the pass, for a slow push in.
   Everything is one transform, so it stays on the compositor.                            */
[data-px] { will-change: transform; backface-visibility: hidden; }

/* these two carry a transform in their entry reveal; the parallax owns transform instead,
   and the reveal keeps only its fade. Without this the 500 ms transition would smear
   every scroll frame. */
.reveal .label[data-px] { transition: opacity 500ms var(--ease); }
.twelve .twelve-num[data-px] { transition: opacity 600ms var(--ease); }

/* the macro photograph and its hotspots travel as one layer, so a spot never leaves its feature */
.macro-layer { position: absolute; inset: 0; }

@media (prefers-reduced-motion: reduce) {
  [data-px] { transform: none !important; will-change: auto; }
}

/* ---------- Hero ---------- */
.hero {
  position: relative;
  height: 100svh;
  min-height: 640px;
  overflow: hidden;
  color: #fff;
}

.hero-media,
.hero-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.hero-media img {
  object-fit: cover;
  object-position: 50% 62%;
  transform: scale(1.03);
  transition: transform 1800ms var(--ease);
}
.hero.is-in .hero-media img { transform: none; }

/* the foreground layer: line, tags and card. Same box as the hero, so every
   child keeps the position it had before the layer existed. */
.hero-fore { position: absolute; inset: 0; pointer-events: none; }
.hero-fore .sample { pointer-events: auto; }

/* dark wash under the header so white menu type stays legible over any photograph */
.hero-shade {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: clamp(190px, 26vh, 330px);
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.58) 0%,
    rgba(0, 0, 0, 0.38) 30%,
    rgba(0, 0, 0, 0.16) 62%,
    rgba(0, 0, 0, 0) 100%
  );
}

.hero-line {
  position: absolute;
  left: var(--margin);
  bottom: 12vh;
  white-space: nowrap;
  text-shadow: 0 0 40px rgba(0, 0, 0, 0.18);
  opacity: 0;
  transform: translateY(6px);
  transition: opacity var(--d-mask) var(--ease) 200ms, transform var(--d-mask) var(--ease) 200ms;
}
.hero.is-in .hero-line { opacity: 1; transform: none; }

.hero-tags { position: absolute; inset: 0; pointer-events: none; }
.tag {
  position: absolute;
  left: var(--x);
  top: var(--y);
  height: 32px;
  padding: 0 12px;
  display: inline-flex;
  align-items: center;
  background: var(--ink);
  color: var(--ground);
  line-height: 1;
  white-space: nowrap;
  opacity: 0;
  transition: opacity 400ms var(--ease);
}
/* tag positions sit on quiet parts of the photograph: wall edge, sea, boards */
.tag:nth-child(1) { --x: 21%; --y: 47%; }
.tag:nth-child(2) { --x: 63%; --y: 40%; }
.tag:nth-child(3) { --x: 47%; --y: 66%; }
.hero.is-in .tag:nth-child(1) { opacity: 1; transition-delay: 500ms; }
.hero.is-in .tag:nth-child(2) { opacity: 1; transition-delay: 570ms; }
.hero.is-in .tag:nth-child(3) { opacity: 1; transition-delay: 640ms; }

/* Sample request card: thin corner brackets, text only */
.sample {
  position: absolute;
  right: var(--margin);
  bottom: 12vh;
  width: 300px;
  padding: 20px 22px 18px;
  opacity: 0;
  transition: opacity 500ms var(--ease) 700ms;
}
.hero.is-in .sample { opacity: 1; }

.sample-frame { position: absolute; inset: 0; pointer-events: none; }
.sample-frame::before,
.sample-frame::after,
.sample::before,
.sample::after {
  content: "";
  position: absolute;
  width: 18px;
  height: 18px;
  border: 0 solid var(--line-light);
  pointer-events: none;
}
.sample::before { left: 0; top: 0; border-left-width: 1px; border-top-width: 1px; }
.sample::after { right: 0; top: 0; border-right-width: 1px; border-top-width: 1px; }
.sample-frame::before { left: 0; bottom: 0; border-left-width: 1px; border-bottom-width: 1px; }
.sample-frame::after { right: 0; bottom: 0; border-right-width: 1px; border-bottom-width: 1px; }

.sample-body { margin-top: 8px; opacity: 0.92; }
.sample-link { display: inline-block; margin-top: 14px; }
.sample-link .arrow { margin-left: 6px; transition: transform 300ms var(--ease); }
.sample-link:hover .arrow { transform: translateX(4px); }

/* ---------- Page grid ---------- */
.intro,
.section {
  padding-left: var(--margin);
  padding-right: var(--margin);
}

.intro {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  padding-top: 80px;
  padding-bottom: clamp(120px, 14vw, 220px);
}
.intro .statement { grid-column: 1 / 9; max-width: 38ch; }
.intro .stack { grid-column: 9 / 13; align-self: start; }

.section {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  padding-top: 0;
  padding-bottom: clamp(120px, 14vw, 220px);
}
.section .label { grid-column: 1 / 5; }
.section-body { grid-column: 5 / 13; }
.section-body .statement { max-width: 32ch; }
.section-body .stack { margin-top: 64px; }

/* every section opens the same way: label first, statement a beat later, then the module draws */
.reveal .label,
.reveal .label-sub,
.reveal .statement {
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 500ms var(--ease), transform 500ms var(--ease);
}
.reveal .statement,
.reveal .label-sub { transition-delay: 90ms; }
.reveal.is-in .label,
.reveal.is-in .label-sub,
.reveal.is-in .statement { opacity: 1; transform: none; }

/* ---------- Plate: full-width photograph with mono corner spec ---------- */
.plate {
  position: relative;
  margin: 0 var(--margin) clamp(120px, 14vw, 220px);
  aspect-ratio: 16 / 9;
  overflow: hidden;
}
.plate-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 45%;
  clip-path: inset(0 100% 0 0);
  transition: clip-path var(--d-mask) var(--ease);
}
.plate.is-in .plate-img { clip-path: inset(0); }

.plate-spec {
  position: absolute;
  right: 20px;
  bottom: 18px;
  display: grid;
  grid-template-columns: 96px auto;
  row-gap: 4px;
  column-gap: 12px;
  color: var(--ink);
  line-height: 1.2;
  opacity: 0;
  transition: opacity 400ms var(--ease) 500ms;
}
.plate.is-in .plate-spec { opacity: 1; }
/* on a dark photograph the corner spec reads in white */
.plate-dark .plate-spec { color: #fff; }

/* ---------- Accordion stack (outlined rows, corner ticks, one open) ---------- */
.stack { position: relative; }

/* outer left / right / bottom lines, drawn in from the left */
.stack::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  border: 1px solid var(--line);
  border-top: 0;
  clip-path: inset(0 100% 0 0);
  transition: clip-path var(--d-line) var(--ease) calc(var(--n, 4) * var(--stagger));
}
.reveal.is-in .stack::before { clip-path: inset(0); }

/* bottom corner ticks of the stack */
.stack::after {
  content: "";
  position: absolute;
  left: -4px; right: -4px; bottom: -4px;
  height: var(--tick);
  pointer-events: none;
  --c: var(--ink);
  background-image:
    linear-gradient(var(--c), var(--c)), linear-gradient(var(--c), var(--c)),
    linear-gradient(var(--c), var(--c)), linear-gradient(var(--c), var(--c));
  background-size: var(--tick) 1px, 1px var(--tick), var(--tick) 1px, 1px var(--tick);
  background-position: left 0 bottom 4px, left 4px bottom 0, right 0 bottom 4px, right 4px bottom 0;
  background-repeat: no-repeat;
  opacity: 0;
  transition: opacity 300ms var(--ease) calc(var(--n, 4) * var(--stagger) + 300ms);
}
.reveal.is-in .stack::after { opacity: 1; }

.row { position: relative; }

/* top hairline of every row, drawn in left to right, staggered */
.row::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 1px;
  background: var(--line);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--d-line) var(--ease) calc(var(--i) * var(--stagger));
}
.reveal.is-in .row::after { transform: scaleX(1); }

/* top corner ticks of every row */
.row::before {
  content: "";
  position: absolute;
  left: -4px; right: -4px; top: -4px;
  height: var(--tick);
  pointer-events: none;
  z-index: 1;
  --c: var(--ink);
  background-image:
    linear-gradient(var(--c), var(--c)), linear-gradient(var(--c), var(--c)),
    linear-gradient(var(--c), var(--c)), linear-gradient(var(--c), var(--c));
  background-size: var(--tick) 1px, 1px var(--tick), var(--tick) 1px, 1px var(--tick);
  background-position: left 0 top 4px, left 4px top 0, right 0 top 4px, right 4px top 0;
  background-repeat: no-repeat;
  opacity: 0;
  transition: opacity 300ms var(--ease) calc(var(--i) * var(--stagger) + 300ms);
}
.reveal.is-in .row::before { opacity: 1; }

.row-head { font-size: inherit; }
.row-btn {
  width: 100%;
  min-height: 50px;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 16px;
  text-align: left;
  opacity: 0;
  transition: opacity 400ms var(--ease) calc(var(--i) * var(--stagger) + 120ms);
}
.reveal.is-in .row-btn { opacity: 1; }

.row-num { font-variant-numeric: tabular-nums; }
.row-title {
  display: inline-block;
  transition: transform 300ms var(--ease);
}
/* "+" at the right end of every row: two hairlines. Turns 45° into "×" when the row is open. */
.plus {
  position: relative;
  flex: 0 0 auto;
  margin-left: auto;
  width: 16px;
  height: 16px;
  transition: transform var(--d-row) var(--ease);
}
.plus::before,
.plus::after {
  content: "";
  position: absolute;
  background: currentColor;
}
.plus::before { left: 0; right: 0; top: 50%; height: 1px; margin-top: -0.5px; }
.plus::after { top: 0; bottom: 0; left: 50%; width: 1px; margin-left: -0.5px; }
.row.is-open .plus { transform: rotate(45deg); }
.row:not(.is-open) .row-btn:hover .row-title { transform: translateX(6px); }
.row:not(.is-open) .row-btn:hover .plus { transform: rotate(90deg); }

/* panel opens by growing a grid track; visibility keeps closed content out of the tab order */
.row-panel {
  display: grid;
  grid-template-rows: 0fr;
  visibility: hidden;
  transition: grid-template-rows var(--d-row) var(--ease), visibility 0s linear var(--d-row);
}
.row.is-open .row-panel {
  grid-template-rows: 1fr;
  visibility: visible;
  transition: grid-template-rows var(--d-row) var(--ease), visibility 0s;
}
.row-inner { min-height: 0; overflow: hidden; }

/* intro value rows: text only */
.intro .row-inner .body { padding: 6px 16px 22px; max-width: 40ch; }

/* product rows: text left, photograph fills the right half of the whole row */
.row-text-wrap { width: 50%; }
/* the open product row's photograph covers the right half, so its "×" moves to the divider */
.products-stack .row.is-open .row-btn { width: 50%; }
.row-text {
  padding: 6px 20px 22px 16px;
  display: flex;
  flex-direction: column;
}
.row-text .body { max-width: 36ch; }

.spec {
  margin-top: 22px;
  display: grid;
  grid-template-columns: max-content 1fr;
  column-gap: 16px;
  line-height: 1.3;
}
.spec > div {
  display: grid;
  grid-template-columns: subgrid;
  grid-column: 1 / -1;
  padding: 5px 0;
  border-top: 1px solid var(--line-soft);
}
.spec > div:first-child { border-top: 0; padding-top: 0; }
.spec dt { color: var(--ink-2); }
@supports not (grid-template-columns: subgrid) {
  .spec > div { display: contents; }
  .spec dt, .spec dd { padding: 5px 0; border-top: 1px solid var(--line-soft); }
}

.more {
  margin-top: auto;
  padding-top: 22px;
  align-self: flex-start;
}
.more .arrow { margin-left: 4px; transition: transform 300ms var(--ease); }
.more:hover .arrow { transform: translateX(4px); }

.row-media {
  position: relative;
  position: absolute;
  top: 0; right: 0; bottom: 0;
  width: 50%;
  border-left: 1px solid var(--line);
  visibility: hidden;
  transition: visibility 0s linear var(--d-row);
}
.row.is-open .row-media { visibility: visible; transition: visibility 0s; }
.products-stack .row.is-open { min-height: 360px; }
.row-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  clip-path: inset(0 100% 0 0);
  transition: clip-path var(--d-mask) var(--ease) 80ms;
}
.reveal.is-in .row.is-open .row-media img { clip-path: inset(0); }

/* ticks where the text/photo divider meets the row lines */
.row-media::before,
.row-media::after {
  content: "";
  position: absolute;
  left: -5px;
  width: var(--tick);
  height: var(--tick);
  z-index: 1;
  pointer-events: none;
  --c: var(--ink);
  background-image: linear-gradient(var(--c), var(--c)), linear-gradient(var(--c), var(--c));
  background-size: var(--tick) 1px, 1px var(--tick);
  background-repeat: no-repeat;
}
.row-media::before { top: -4px; background-position: 0 4px, 4px 0; }
.row-media::after { bottom: -4px; background-position: 0 4px, 4px 0; }

/* ======================================================================
   Stage 2: material, colour and pattern, technical data, audience, form, pill
   ====================================================================== */

/* ---------- The material: still image with hotspots ---------- */
.macro { margin-top: 64px; }

.macro-frame {
  position: relative;
  aspect-ratio: 3 / 2;
  overflow: hidden;
}
.macro-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  clip-path: inset(0 100% 0 0);
  transition: clip-path var(--d-mask) var(--ease);
}
.reveal.is-in .macro-img { clip-path: inset(0); }

.spots { position: absolute; inset: 0; pointer-events: none; }
.spot {
  position: absolute;
  left: var(--x);
  top: var(--y);
  display: flex;
  align-items: center;
  transform: translate(-11px, -11px);
  opacity: 0;
  transition: opacity 300ms var(--ease) calc(500ms + var(--i) * 260ms);
}
.reveal.is-in .spot { opacity: 1; }
/* the mark lands first, then its name draws out to the right: fibre, resin, coating, in turn */
.spot-name {
  clip-path: inset(0 100% 0 0);
  transition: clip-path 450ms var(--ease) calc(650ms + var(--i) * 260ms);
}
.reveal.is-in .spot-name { clip-path: inset(-1px); }

.spot-mark,
.spot-name {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 22px;
  background: var(--ink);
  color: var(--ground);
  line-height: 1;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.35);
}
.spot-mark { width: 22px; }
.spot-mark::before { content: "+"; font-size: 14px; }
.spot-name {
  margin-left: 7px;
  padding: 0 10px;
  text-transform: uppercase;
  white-space: nowrap;
}

/* notes below the image: three outlined cells sharing hairlines */
.notes {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-top: 40px;
}
.notes::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  border: 1px solid var(--line);
  border-top: 0;
  clip-path: inset(0 100% 0 0);
  transition: clip-path var(--d-line) var(--ease) 240ms;
}
.reveal.is-in .notes::before { clip-path: inset(0); }
.notes::after {
  content: "";
  position: absolute;
  left: -4px; right: -4px; bottom: -4px;
  height: var(--tick);
  pointer-events: none;
  --c: var(--ink);
  background-image:
    linear-gradient(var(--c), var(--c)), linear-gradient(var(--c), var(--c)),
    linear-gradient(var(--c), var(--c)), linear-gradient(var(--c), var(--c));
  background-size: var(--tick) 1px, 1px var(--tick), var(--tick) 1px, 1px var(--tick);
  background-position: left 0 bottom 4px, left 4px bottom 0, right 0 bottom 4px, right 4px bottom 0;
  background-repeat: no-repeat;
  opacity: 0;
  transition: opacity 300ms var(--ease) 540ms;
}
.reveal.is-in .notes::after { opacity: 1; }

.note {
  position: relative;
  padding: 14px 16px 22px;
  border-left: 1px solid var(--line);
  margin-left: -1px;
}
.note:first-child { border-left: 0; margin-left: 0; }
.note::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 1px;
  background: var(--line);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--d-line) var(--ease) calc(var(--i) * var(--stagger));
}
.reveal.is-in .note::after { transform: scaleX(1); }
/* ticks at the top corners of each note: covers every top intersection */
.note::before {
  content: "";
  position: absolute;
  /* -5px on the left: the layer is laid against the padding box, so -4px would
     start the ticks 1px inside the note's own left border they mark. */
  left: -5px; right: -4px; top: -4px;
  height: var(--tick);
  z-index: 1;
  pointer-events: none;
  --c: var(--ink);
  background-image:
    linear-gradient(var(--c), var(--c)), linear-gradient(var(--c), var(--c)),
    linear-gradient(var(--c), var(--c)), linear-gradient(var(--c), var(--c));
  background-size: var(--tick) 1px, 1px var(--tick), var(--tick) 1px, 1px var(--tick);
  background-position: left 0 top 4px, left 4px top 0, right 0 top 4px, right 4px top 0;
  background-repeat: no-repeat;
  opacity: 0;
  transition: opacity 300ms var(--ease) calc(var(--i) * var(--stagger) + 300ms);
}
.note:first-child::before { left: -4px; } /* no left border to clear */
.reveal.is-in .note::before { opacity: 1; }
.note-name { margin-bottom: 10px; }
.note .body { max-width: 30ch; }
.note-name::before {
  content: attr(data-n);
  display: none;
}

/* ---------- Colour and pattern ---------- */
.grid3 {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  column-gap: var(--gutter);
  margin-top: 64px;
}
.pmedia {
  aspect-ratio: 4 / 5;
  overflow: hidden;
}
.pmedia img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  clip-path: inset(0 100% 0 0);
  transition: clip-path var(--d-mask) var(--ease) calc(var(--i) * 160ms); /* Loop, Rush, Custom open one after another */
}
.reveal.is-in .pmedia img { clip-path: inset(0); }

/* Rawlab caption: name in a narrow first column, one line beside it, fact beneath */
.cap {
  display: grid;
  grid-template-columns: 76px 1fr;
  column-gap: 12px;
  row-gap: 6px;
  margin-top: 14px;
  line-height: 1.3;
  opacity: 0;
  transition: opacity 400ms var(--ease) calc(var(--i) * 160ms + 300ms);
}
.reveal.is-in .cap { opacity: 1; }
.cap-desc { grid-column: 2; }
.cap-fact {
  grid-column: 2;
  line-height: 1.3;
  color: var(--ink-2);
}

.disclaimer {
  margin-top: 48px;
  max-width: 52ch;
  text-wrap: pretty;
}

/* ---------- Technical data ---------- */
.tonal {
  font-size: clamp(34px, 3.9vw, 56px);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: -0.015em;
  text-wrap: balance;
  max-width: 20ch;
}
.tonal > span {
  display: block;
  opacity: 0;
  transform: translateY(6px);
  /* the three lines step in grey to black, one clear beat apart */
  transition: opacity 500ms var(--ease) calc(var(--i) * 180ms), transform 500ms var(--ease) calc(var(--i) * 180ms);
}
.reveal.is-in .tonal > span { opacity: 1; transform: none; }
.tonal > span:nth-child(1) { color: #aaa6a1; }
.tonal > span:nth-child(2) { color: #6b6764; }
.tonal > span:nth-child(3) { color: var(--ink); }

/* Flexcoat: the headline sits in light grey and inks in black one letter at a time,
   scrubbed by the scroll. The script sets --p (0 to 1) on the heading; each letter reads
   its own place --n out of --total and darkens over a window of --w letters. */
.tonal.is-lettered > span { opacity: 1; transform: none; transition: none; }
.tonal .word { white-space: nowrap; }
.tonal .ch {
  --lp: clamp(0, calc((var(--p, 0) * (var(--total) + var(--w)) - var(--n)) / var(--w)), 1);
  color: var(--ink);
  color: color-mix(in srgb, var(--ink) calc(var(--lp) * 100%), #aaa6a1);
}

.datasheet {
  grid-column: 1 / 13;
  margin-top: 96px;
}
.group {
  position: relative;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  padding: 14px 0 40px;
}
/* one ink hairline across the full width above each product, drawn in */
.group::before {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 1px;
  background: var(--line);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--d-line) var(--ease) calc(var(--i) * var(--stagger));
}
.group.is-in::before { transform: scaleX(1); }
/* home: each product sits in the content column, name above its table, not out at the page edge */
.datasheet.is-inset { grid-column: 5 / 13; }
.datasheet.is-inset .group { display: block; }
.datasheet.is-inset .group-name { margin-bottom: 14px; }
.group-name {
  grid-column: 1 / 5;
  line-height: 1.3;
  padding-top: 5px;
}
.data {
  grid-column: 5 / 13;
  width: 100%;
  border-collapse: collapse;
  line-height: 1.4;
}
.data th,
.data td {
  vertical-align: top;
  text-align: left;
  padding: 9px 0;
  border-top: 1px solid var(--line-soft);
  font-weight: 400;
}
.data tr:first-child th,
.data tr:first-child td { border-top: 0; padding-top: 5px; }
.data th {
  width: 34%;
  padding-right: 16px;
  color: var(--ink-2);
  text-transform: uppercase;
  padding-top: 10px;
}
.data tr:first-child th { padding-top: 6px; }
.group .group-name {
  opacity: 0;
  transition: opacity 400ms var(--ease) calc(var(--i) * var(--stagger) + 160ms);
}
.group.is-in .group-name { opacity: 1; }
/* spec rows print in as each reaches the viewport; rows arriving together step in 45 ms apart (--r set by script) */
.data th,
.data td {
  opacity: 0;
  transition: opacity 350ms var(--ease) calc(var(--r, 0) * 45ms);
}
.data tr.is-in th,
.data tr.is-in td { opacity: 1; }

/* The one memorable moment: 12 000 across the full width, 600 mm ticks under it */
.twelve {
  grid-column: 1 / 13;
  margin-top: clamp(64px, 8vw, 120px);
}
.twelve-num {
  font-size: 22vw; /* replaced by script: fitted to the full width */
  font-weight: 400;
  line-height: 0.82;
  letter-spacing: -0.045em;
  white-space: nowrap;
  font-variant-numeric: lining-nums;
  margin-left: -0.03em;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 600ms var(--ease), transform 600ms var(--ease);
}
.twelve.is-in .twelve-num { opacity: 1; transform: none; }
.ruler { margin-top: 20px; height: 24px; }
.ruler-svg { width: 100%; height: 24px; display: block; overflow: visible; }
.ruler-svg line { stroke: var(--ink); stroke-width: 1; vector-effect: non-scaling-stroke; }
.ruler-line {
  transform: scaleX(0);
  transform-origin: 0 0;
  transition: transform var(--d-line) var(--ease) 100ms;
}
.twelve.is-in .ruler-line { transform: scaleX(1); }
.ruler-ticks line {
  opacity: 0;
  transition: opacity 200ms var(--ease) calc(100ms + var(--t) * 22ms);
}
.twelve.is-in .ruler-ticks line { opacity: 1; }
/* while the page is scrubbing the figure, the script drives the line and the ticks frame by frame */
.twelve.is-drawing .ruler-line,
.twelve.is-drawing .ruler-ticks line { transition: none; }
.twelve.is-drawing .twelve-num { transition: opacity 260ms var(--ease); transform: none; }
.twelve-cap {
  display: flex;
  justify-content: space-between;
  margin-top: 10px;
  line-height: 1.3;
  color: var(--ink-2);
  opacity: 0;
  transition: opacity 400ms var(--ease) 500ms;
}
.twelve.is-in .twelve-cap { opacity: 1; }
.twelve-cc { width: 5%; min-width: 80px; white-space: nowrap; }

/* ---------- Who we build for: four outlined cells ---------- */
.cells {
  position: relative;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin-top: 64px;
}
.cells::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  border: 1px solid var(--line);
  border-top: 0;
  clip-path: inset(0 100% 0 0);
  transition: clip-path var(--d-line) var(--ease) 240ms;
}
.reveal.is-in .cells::before { clip-path: inset(0); }
/* ticks along the bottom: both corners and the middle divider */
.cells::after {
  content: "";
  position: absolute;
  left: -4px; right: -4px; bottom: -4px;
  height: var(--tick);
  pointer-events: none;
  --c: var(--ink);
  background-image:
    linear-gradient(var(--c), var(--c)), linear-gradient(var(--c), var(--c)),
    linear-gradient(var(--c), var(--c)), linear-gradient(var(--c), var(--c)),
    linear-gradient(var(--c), var(--c)), linear-gradient(var(--c), var(--c));
  background-size: var(--tick) 1px, 1px var(--tick), var(--tick) 1px, 1px var(--tick), var(--tick) 1px, 1px var(--tick);
  background-position:
    left 0 bottom 4px, left 4px bottom 0,
    right 0 bottom 4px, right 4px bottom 0,
    /* the middle pair marks the divider. Its 1px border is drawn on the second cell with a
       -1px margin, so it sits half a pixel LEFT of dead centre; the ticks follow it there. */
    left calc(50% - 5px) bottom 4px, left calc(50% - 1px) bottom 0;
  background-repeat: no-repeat;
  opacity: 0;
  transition: opacity 300ms var(--ease) 540ms;
}
.reveal.is-in .cells::after { opacity: 1; }

.cell {
  position: relative;
  border-left: 1px solid var(--line);
  margin-left: -1px;
  display: flex;
  flex-direction: column;
}
.cell:nth-child(odd) { border-left: 0; margin-left: 0; }
.cell::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 1px;
  background: var(--line);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--d-line) var(--ease) calc(var(--i) * var(--stagger));
}
.reveal.is-in .cell::after { transform: scaleX(1); }
.cell::before {
  content: "";
  position: absolute;
  /* -5px on the left: the layer is laid against the padding box, so -4px would
     start the ticks 1px inside the cell's own left border they mark. */
  left: -5px; right: -4px; top: -4px;
  height: var(--tick);
  z-index: 1;
  pointer-events: none;
  --c: var(--ink);
  background-image:
    linear-gradient(var(--c), var(--c)), linear-gradient(var(--c), var(--c)),
    linear-gradient(var(--c), var(--c)), linear-gradient(var(--c), var(--c));
  background-size: var(--tick) 1px, 1px var(--tick), var(--tick) 1px, 1px var(--tick);
  background-position: left 0 top 4px, left 4px top 0, right 0 top 4px, right 4px top 0;
  background-repeat: no-repeat;
  opacity: 0;
  transition: opacity 300ms var(--ease) calc(var(--i) * var(--stagger) + 300ms);
}
.cell:nth-child(odd)::before { left: -4px; } /* no left border to clear */
.reveal.is-in .cell::before { opacity: 1; }

.cell-head {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 50px;
  padding: 0 16px;
  opacity: 0;
  transition: opacity 400ms var(--ease) calc(var(--i) * var(--stagger) + 120ms);
}
.reveal.is-in .cell-head { opacity: 1; }
.cell-head:hover { text-decoration: none; }
.cell-head .arrow {
  margin-left: auto;
  opacity: 0;
  transform: translateX(-6px);
  transition: opacity 250ms var(--ease), transform 300ms var(--ease);
}
.cell-head:hover .row-title,
.cell-head:focus-visible .row-title { transform: translateX(6px); }
.cell-head:hover .arrow,
.cell-head:focus-visible .arrow { opacity: 1; transform: none; }

.cell-media {
  aspect-ratio: 3 / 2;
  overflow: hidden;
  border-top: 1px solid var(--line);
}
.cell-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  clip-path: inset(0 100% 0 0);
  transition: clip-path var(--d-mask) var(--ease) calc(var(--i) * var(--stagger) + 80ms);
}
.reveal.is-in .cell-media img { clip-path: inset(0); }
.cell .body {
  padding: 14px 16px 22px;
  max-width: 36ch;
}

/* ---------- Sample request: label left, outlined field grid right ---------- */
.enquiry .label-col { grid-column: 1 / 5; }
.label-sub {
  line-height: 1.3;
  margin-top: 2px;
  color: var(--ink);
  max-width: 26ch;
}
.form { grid-column: 5 / 13; }

.fgrid {
  position: relative;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.fgrid::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  border: 1px solid var(--line);
  border-top: 0;
  clip-path: inset(0 100% 0 0);
  transition: clip-path var(--d-line) var(--ease) 240ms;
}
.reveal.is-in .fgrid::before { clip-path: inset(0); }
.fgrid::after {
  content: "";
  position: absolute;
  left: -4px; right: -4px; bottom: -4px;
  height: var(--tick);
  pointer-events: none;
  --c: var(--ink);
  background-image:
    linear-gradient(var(--c), var(--c)), linear-gradient(var(--c), var(--c)),
    linear-gradient(var(--c), var(--c)), linear-gradient(var(--c), var(--c));
  background-size: var(--tick) 1px, 1px var(--tick), var(--tick) 1px, 1px var(--tick);
  background-position: left 0 bottom 4px, left 4px bottom 0, right 0 bottom 4px, right 4px bottom 0;
  background-repeat: no-repeat;
  opacity: 0;
  transition: opacity 300ms var(--ease) 540ms;
}
.reveal.is-in .fgrid::after { opacity: 1; }

.field {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 88px;
  padding: 12px 16px 14px;
  margin: 0;
  border: 0;
  border-left: 1px solid var(--line);
  margin-left: -1px;
}
/* pairs sit at odd/even positions in source order; full-width rows never carry a left line */
.field:nth-child(odd),
.f-full { border-left: 0; margin-left: 0; }
.f-full { grid-column: 1 / -1; }
fieldset.field { min-width: 0; min-inline-size: 0; }

.field::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 1px;
  background: var(--line);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--d-line) var(--ease) calc(var(--i) * var(--stagger));
}
.reveal.is-in .field::after { transform: scaleX(1); }
.field::before {
  content: "";
  position: absolute;
  /* -5px on the left: the layer is laid against the padding box, so -4px would
     start the ticks 1px inside the field's own left border they mark. */
  left: -5px; right: -4px; top: -4px;
  height: var(--tick);
  z-index: 1;
  pointer-events: none;
  --c: var(--ink);
  background-image:
    linear-gradient(var(--c), var(--c)), linear-gradient(var(--c), var(--c)),
    linear-gradient(var(--c), var(--c)), linear-gradient(var(--c), var(--c));
  background-size: var(--tick) 1px, 1px var(--tick), var(--tick) 1px, 1px var(--tick);
  background-position: left 0 top 4px, left 4px top 0, right 0 top 4px, right 4px top 0;
  background-repeat: no-repeat;
  opacity: 0;
  transition: opacity 300ms var(--ease) calc(var(--i) * var(--stagger) + 300ms);
}
.field:nth-child(odd)::before,
.f-full::before { left: -4px; } /* no left border to clear */
.reveal.is-in .field::before { opacity: 1; }

.field > label,
.field > legend {
  font-weight: 400;
  line-height: 1.3;
  padding: 0;
  float: left; /* legend behaves like a label inside the fieldset flow */
  width: 100%;
}
.field input,
.field select,
.field textarea {
  width: 100%;
  margin-top: 6px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  font-family: var(--grotesk);
  font-size: var(--t-title);
  font-weight: 400;
  line-height: 1.25;
  outline: none;
  appearance: none;
  -webkit-appearance: none;
}
.field textarea { resize: vertical; min-height: 110px; line-height: 1.3; }
.field select {
  padding-right: 28px;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink) 50%), linear-gradient(135deg, var(--ink) 50%, transparent 50%);
  background-position: calc(100% - 13px) 55%, calc(100% - 8px) 55%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  cursor: pointer;
}
.field:focus-within { outline: 1px solid var(--ink); outline-offset: -1px; }
.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible { outline: none; }
.field.is-invalid { outline: 1px solid var(--ink); outline-offset: -1px; }

.checks { display: flex; flex-wrap: wrap; gap: 8px 32px; margin-top: 10px; }
.check {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: var(--t-title);
  line-height: 1.2;
  cursor: pointer;
}
.check input {
  width: 16px;
  height: 16px;
  margin: 0;
  border: 1px solid var(--ink);
  background: transparent;
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
  flex: 0 0 auto;
}
.check input:checked { background: var(--ink); box-shadow: inset 0 0 0 3px var(--ground); }
.check input:focus-visible { outline: 1px solid var(--ink); outline-offset: 3px; }

.f-foot {
  min-height: 0;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 32px;
  padding: 16px;
}
.consent { font-size: var(--t-small); line-height: 1.35; order: 2; }
.consent a { text-decoration: underline; text-underline-offset: 0.18em; text-decoration-thickness: 1px; }
.submit {
  order: 1;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 40px;
  padding: 0 16px;
  border: 1px solid var(--ink);
  line-height: 1;
  transition: background-color 200ms var(--ease), color 200ms var(--ease);
}
.submit:hover { background: var(--ink); color: var(--ground); }
.submit:disabled,
.submit:disabled:hover { opacity: 0.5; cursor: progress; background: none; color: inherit; }
.submit .arrow { transition: transform 300ms var(--ease); }
.submit:hover .arrow { transform: translateX(3px); }
.form-note {
  order: 3;
  flex-basis: 100%;
  max-width: 48ch;
}
.form-note:empty { display: none; }

/* ---------- Persistent sample pill ---------- */
.pill {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 30;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  height: 44px;
  padding: 0 18px;
  background: #fff;
  color: var(--ink);
  border: 1px solid var(--line);
  line-height: 1;
  white-space: nowrap;
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
  transition: opacity 300ms var(--ease), transform 300ms var(--ease);
}
.pill.is-shown { opacity: 1; transform: none; pointer-events: auto; }
.pill:hover { text-decoration: none; }
.pill .arrow { transition: transform 300ms var(--ease); }
.pill:hover .arrow { transform: translateX(3px); }

/* ---------- Footer ---------- */
.foot {
  padding: clamp(96px, 9vw, 140px) var(--margin) 36px;
  border-top: 1px solid var(--line);
  margin: 0 var(--margin);
  padding-left: 0;
  padding-right: 0;
}

.foot-top {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  align-items: end;
}
.foot-brand { grid-column: 1 / 5; }
.foot-brand:hover { text-decoration: none; }
.foot-brand .wordmark { height: clamp(28px, 3vw, 44px); width: auto; fill: currentColor; }
.foot-cta { grid-column: 5 / 9; font-family: var(--serif); font-size: var(--t-body); line-height: 1; padding-bottom: 6px; }
.foot-cta .arrow { margin-left: 4px; }

.foot-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  row-gap: 32px;
  margin-top: clamp(120px, 12vw, 180px);
  line-height: 1.5;
}
.foot-col:nth-child(1) { grid-column: 1 / 3; }
.foot-col:nth-child(2) { grid-column: 3 / 5; }
.foot-col:nth-child(3) { grid-column: 5 / 7; }
.foot-col:nth-child(4) { grid-column: 7 / 9; }
.foot-clock { grid-column: 11 / 13; display: flex; flex-direction: column; }
.clock { font-variant-numeric: tabular-nums; }

.foot-bottom {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  row-gap: 24px;
  margin-top: 96px;
  align-items: end;
}
.foot-reg {
  grid-column: 1 / 5;
  line-height: 1.55;
  color: var(--ink-2);
  text-transform: uppercase;
}
.foot-disclaimer {
  grid-column: 7 / 13;
  max-width: 52ch;
  text-wrap: pretty;
}

/* ---------- Motion safety ---------- */
html:not(.js) .hero-line,
html:not(.js) .tag,
html:not(.js) .sample,
html:not(.js) .label,
html:not(.js) .label-sub,
html:not(.js) .statement,
html:not(.js) .data th,
html:not(.js) .data td,
html:not(.js) .row-btn,
html:not(.js) .row::before,
html:not(.js) .stack::after,
html:not(.js) .plate-spec,
html:not(.js) .spot,
html:not(.js) .note::before,
html:not(.js) .notes::after,
html:not(.js) .cap,
html:not(.js) .tonal > span,
html:not(.js) .group-name,
html:not(.js) .data,
html:not(.js) .twelve-num,
html:not(.js) .ruler-ticks line,
html:not(.js) .twelve-cap,
html:not(.js) .cells::after,
html:not(.js) .cell::before,
html:not(.js) .cell-head,
html:not(.js) .fgrid::after,
html:not(.js) .field::before { opacity: 1; transform: none; }
html:not(.js) .row::after,
html:not(.js) .note::after,
html:not(.js) .group::before,
html:not(.js) .ruler-line,
html:not(.js) .cell::after,
html:not(.js) .field::after { transform: none; }
html:not(.js) .stack::before,
html:not(.js) .plate-img,
html:not(.js) .row-media img,
html:not(.js) .split-half img,
html:not(.js) .macro-img,
html:not(.js) .spot-name,
html:not(.js) .notes::before,
html:not(.js) .pmedia img,
html:not(.js) .cells::before,
html:not(.js) .cell-media img,
html:not(.js) .fgrid::before { clip-path: none; }
html:not(.js) .pill { display: none; }
html:not(.js) .head { position: absolute; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0.01ms !important; transition-delay: 0s !important; }
  html { scroll-behavior: auto; }
  .row-title, .arrow, .plus { transition: none; }
  .hero-media, .hero-fore { animation: none; }
  .hero-media img { transform: none; }
}

/* ---------- Narrow screens ---------- */
@media (max-width: 1100px) {
  .intro .statement { grid-column: 1 / 8; }
  .intro .stack { grid-column: 8 / 13; }
  .row-media { min-height: 320px; }
  .data th { width: 40%; }
}

/* hotspot labels give way to numbers once the frame gets narrow */
@media (max-width: 700px) {
  .spot-name { display: none; }
  .spot-mark::before { content: attr(data-n); font-size: var(--t-meta); }
  .note-name::before { display: inline; font-family: var(--mono); font-size: var(--t-meta); font-weight: 400; letter-spacing: 0.04em; margin-right: 10px; color: var(--ink-2); }
}

@media (max-width: 899px) {
  :root { --t-display: clamp(30px, 8vw, 38px); }
  .head { align-items: stretch; }
  .head-brand { height: calc(52px - 4px * var(--hp)); padding: 0 16px; }
  /* the wordmark gets too small to read here, so the header shows the icon alone */
  .head-brand .wordmark { display: none; }
  .head-brand .brand-icon { display: block; }
  .head-toggle { display: flex; align-items: center; height: auto; }
  .head-nav {
    display: none;
    position: absolute;
    left: 0; right: 0; top: calc(100% - 1px);
    flex-direction: column;
  }
  .head-nav.is-open { display: flex; }
  .head-nav .box {
    width: auto;
    height: 48px;
    margin-left: 0;
    margin-top: -1px;
    /* the drop-down sheet travels with the bar: dark over the photograph, white once the bar is white */
    background-color: rgba(26, 24, 22, 0.55);
    background-color: color-mix(in srgb, var(--ground) calc(var(--hp) * 100%), rgba(26, 24, 22, 0.55));
  }

  .hero { min-height: 600px; }
  /* the line and the card stack and sit on the floor of the hero. That stacking lives on
     .hero-fore, because .hero's own children are all absolutely positioned layers. */
  .hero-fore {
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    gap: 28px;
    padding: 0 var(--margin) 28px;
  }
  .hero-line,
  .sample { position: relative; z-index: 1; left: auto; right: auto; bottom: auto; }
  .hero-line { white-space: normal; max-width: 14ch; text-wrap: balance; }
  .sample { width: auto; }

  .intro,
  .section { display: block; }
  .intro { padding-top: 56px; }
  .intro .statement,
  .section-body .statement { max-width: 24ch; }
  .intro .stack { margin-top: 48px; }
  .section .label { margin-bottom: 20px; }
  .reveal .label[data-px] { transition: opacity 500ms var(--ease), transform 500ms var(--ease); } /* no drift here, so the entry rise comes back */
  .section-body .stack { margin-top: 44px; }

  .plate { aspect-ratio: auto; overflow: hidden; } /* hidden, not visible: the parallax scales .plate-img past its frame */
  .plate-img { aspect-ratio: 4 / 5; }
  .plate-spec { position: static; margin-top: 14px; grid-template-columns: 110px auto; }
  .plate-dark .plate-spec { color: var(--ink); } /* under the photo here, on the page ground */

  .row-text-wrap { width: auto; }
  .row-media {
    position: relative;
    width: auto;
    aspect-ratio: 4 / 5;
    border-left: 0;
    border-top: 1px solid var(--line);
    display: none;
  }
  /* the border moves from the left edge to the top edge here, so the ticks follow it */
  .row-media::before,
  .row-media::after { left: -4px; }
  .row-media::before { top: -5px; }
  .row.is-open .row-media { display: block; }
  .products-stack .row.is-open { min-height: 0; }
  .products-stack .row.is-open .row-btn { width: 100%; }
  .row-media::before,
  .row-media::after { display: none; }

  /* stage 2 sections, one column */
  .macro { margin-top: 44px; }
  .notes { grid-template-columns: 1fr; margin-top: 32px; }
  .note { border-left: 0; margin-left: 0; padding: 12px 14px 20px; }
  .note::before { left: -4px; } /* the left border is gone here too */
  .note .body { max-width: none; }

  .grid3 { grid-template-columns: 1fr; row-gap: 40px; margin-top: 44px; }
  .cap { grid-template-columns: 70px 1fr; }
  .disclaimer { margin-top: 40px; }

  .tonal { max-width: none; }
  .datasheet { margin-top: 64px; }
  .group { display: block; padding: 12px 0 36px; }
  .group-name { margin-bottom: 14px; }
  .data td { font-size: var(--t-meta); }
  .data th { width: 42%; padding-right: 12px; }
  .twelve { margin-top: 56px; }
  .twelve-cap { flex-direction: column; gap: 4px; }
  .twelve-cc { width: auto; }

  .cells { grid-template-columns: 1fr; margin-top: 44px; }
  .cell { border-left: 0; margin-left: 0; }
  .cell::before { left: -4px; } /* the left border is gone here too */
  .cells::after { background-size: var(--tick) 1px, 1px var(--tick), var(--tick) 1px, 1px var(--tick), 0 0, 0 0; }
  .cell-media { aspect-ratio: 4 / 3; }
  .cell .body { padding: 12px 14px 20px; max-width: none; }

  .enquiry .label { margin-bottom: 4px; }
  .enquiry .label-col { margin-bottom: 28px; }
  .fgrid { grid-template-columns: 1fr; }
  .field { border-left: 0; margin-left: 0; min-height: 80px; padding: 10px 14px 12px; }
  .field::before { left: -4px; }
  .f-foot { padding: 14px; }
  .consent { flex-basis: 100%; }

  .pill { right: 16px; bottom: 16px; height: 40px; padding: 0 14px; }

  .foot-top { display: block; }
  .foot-cta { display: inline-block; margin-top: 32px; }
  .foot-grid { grid-template-columns: 1fr 1fr; margin-top: 80px; }
  .foot-col,
  .foot-col:nth-child(3),
  .foot-col:nth-child(4),
  .foot-clock { grid-column: auto; }
  .foot-bottom { grid-template-columns: 1fr; margin-top: 64px; }
  .foot-reg,
  .foot-disclaimer { grid-column: auto; }
}

@media (max-width: 480px) {
  .tag:nth-child(1) { --x: 6%; --y: 22%; }
  .tag:nth-child(2) { --x: 52%; --y: 30%; }
  .tag:nth-child(3) { --x: 18%; --y: 38%; }
  :root { --t-title: 18px; }
  .row-btn { padding: 0 14px; }
  .row-text { padding: 4px 14px 20px; }
  .intro .row-inner .body { padding: 4px 14px 20px; }
  .spec { grid-template-columns: 1fr; column-gap: 0; }
  .spec > div { display: block; }
  .spec dd { padding-top: 2px; }
}

/* ======================================================================
   Flexcoat page (site/flexcoat/). Same grammar as home; only the pieces
   the home page does not have are added here.
   ====================================================================== */

/* the current page's nav box carries the hover tint at rest */
.head-nav .box[aria-current="page"] {
  background-color: rgba(255, 255, 255, 0.10);
  background-color: color-mix(in srgb, #dcd9d4 calc(var(--hp) * 100%), rgba(255, 255, 255, 0.10));
}

/* product name as a small mono line above the one hero sentence */
.hero-name {
  display: block;
  text-transform: uppercase;
  margin-bottom: 14px;
}

/* tag positions on the Flexcoat hero: the empty floor left of the applicators */
.hero-tags-flex .tag:nth-child(1) { --x: 12%; --y: 46%; }
.hero-tags-flex .tag:nth-child(2) { --x: 38%; --y: 56%; }
.hero-tags-flex .tag:nth-child(3) { --x: 24%; --y: 70%; }

/* a 3:2 plate for the roof photograph */
.plate-32 { aspect-ratio: 3 / 2; }

/* disclaimer directly under the datasheet, in the statement column */
.datasheet-note { grid-column: 5 / 13; margin-top: 8px; }

/* ---------- Reference project: two photographs, one spec ---------- */
.pair {
  display: grid;
  grid-template-columns: 2fr 1fr;
  column-gap: var(--gutter);
  row-gap: 14px;
  margin-top: 64px;
}
.pair-cell { overflow: hidden; }
.pair-wide { aspect-ratio: 3 / 2; }
.pair-tall { aspect-ratio: 3 / 4; }
.pair-cell img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  clip-path: inset(0 100% 0 0);
  transition: clip-path var(--d-mask) var(--ease) calc(var(--i) * 160ms);
}
.reveal.is-in .pair-cell img { clip-path: inset(0); }
.pair-spec {
  position: static;
  grid-column: 1 / -1;
  justify-self: end;
  transition: opacity 400ms var(--ease) 500ms;
}
.reveal.is-in .pair-spec { opacity: 1; }

/* a second project: its own statement and pair, mirrored, drawn when it reaches the viewport */
.project-next { margin-top: clamp(96px, 10vw, 160px); }
.pair-flip { grid-template-columns: 1fr 2fr; }
/* two equal photographs side by side */
.pair-even { grid-template-columns: 1fr 1fr; }
.pair-half { aspect-ratio: 16 / 9; }
.js .reveal .reveal:not(.is-in) .statement { opacity: 0; transform: translateY(6px); }
.js .reveal .reveal:not(.is-in) .pair-cell img { clip-path: inset(0 100% 0 0); }
.js .reveal .reveal:not(.is-in) .pair-spec { opacity: 0; }

/* ---------- Applicators: outlined cells of text, no photograph ---------- */
.cells-text .cell-head { cursor: default; }
.cell-place {
  margin-left: auto;
  color: var(--ink-2);
  white-space: nowrap;
}
.cell-lines {
  flex: 1 1 auto;
  padding: 14px 16px 22px;
  border-top: 1px solid var(--line);
  line-height: 1.4;
  opacity: 0;
  transition: opacity 400ms var(--ease) calc(var(--i) * var(--stagger) + 200ms);
}
.reveal.is-in .cell-lines { opacity: 1; }
.cell-person { margin-top: 12px; }
.cell-contact {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 4px;
  line-height: 1.4;
}
.cell-contact a { align-self: flex-start; }
.cell-address { font-style: normal; line-height: 1.4; }
/* Flexcoat applicators: names in the sans, contacts first, the address settles at the foot of the cell */
.cells-people .cell-lines { display: flex; flex-direction: column; }
.cells-people .cell-person { font-family: var(--grotesk); }
.cells-people .cell-person:first-child { margin-top: 0; }
.cells-people .cell-address { margin-top: auto; padding-top: 18px; color: var(--ink-2); }

/* ---------- Documents: outlined rows that are links, not accordions ---------- */
.row-link {
  width: 100%;
  min-height: 50px;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 16px;
  opacity: 0;
  transition: opacity 400ms var(--ease) calc(var(--i) * var(--stagger) + 120ms);
}
.reveal.is-in .row-link { opacity: 1; }
.row-link:hover { text-decoration: none; }
.row-link:hover .row-title,
.row-link:focus-visible .row-title { transform: translateX(6px); }
.row-note {
  margin-left: auto;
  color: var(--ink-2);
}
.row-link .arrow {
  opacity: 0;
  transform: translateX(-6px);
  transition: opacity 250ms var(--ease), transform 300ms var(--ease);
}
.row-link:hover .arrow,
.row-link:focus-visible .arrow { opacity: 1; transform: none; }

/* no-script: everything visible */
html:not(.js) .row-link,
html:not(.js) .cell-lines,
html:not(.js) .pair-spec { opacity: 1; }
html:not(.js) .pair-cell img { clip-path: none; }

@media (max-width: 899px) {
  .pair { grid-template-columns: 1fr; row-gap: 16px; margin-top: 44px; }
  .project-next { margin-top: 88px; }
  .pair-wide { aspect-ratio: 4 / 3; }
  .pair-tall { aspect-ratio: 1; }
  .pair-spec { justify-self: start; }
  .cell-lines { padding: 12px 14px 20px; }
}

@media (max-width: 480px) {
  .hero-tags-flex .tag:nth-child(1) { --x: 6%; --y: 22%; }
  .hero-tags-flex .tag:nth-child(2) { --x: 48%; --y: 30%; }
  .hero-tags-flex .tag:nth-child(3) { --x: 14%; --y: 38%; }
  .row-link { padding: 0 14px; }
}

/* ======================================================================
   Panels page (site/panels/). Same grammar as home and Flexcoat; only
   the hero tag positions are its own.
   ====================================================================== */

/* tag positions on the Panels hero: the lawn left of the screen, and the glass at the top right */
.hero-tags-panels .tag:nth-child(1) { --x: 9%; --y: 36%; }
.hero-tags-panels .tag:nth-child(2) { --x: 18%; --y: 52%; }
.hero-tags-panels .tag:nth-child(3) { --x: 74%; --y: 28%; }

/* the ruler caption's left cell carries a longer note on this page */
.page-panels .twelve-cc { width: auto; min-width: 0; margin-right: 24px; }

@media (max-width: 480px) {
  .hero-tags-panels .tag:nth-child(1) { --x: 6%; --y: 22%; }
  .hero-tags-panels .tag:nth-child(2) { --x: 48%; --y: 30%; }
  .hero-tags-panels .tag:nth-child(3) { --x: 14%; --y: 38%; }
}

/* ======================================================================
   Boards page (site/boards/). Same grammar as home, Flexcoat and Panels;
   only the hero tag positions and the installation download are its own.
   ====================================================================== */

/* tag positions on the Boards hero: the bare wall between the two plants, above the daybed */
.hero-tags-boards .tag:nth-child(1) { --x: 42%; --y: 26%; }
.hero-tags-boards .tag:nth-child(2) { --x: 58%; --y: 38%; }
.hero-tags-boards .tag:nth-child(3) { --x: 26%; --y: 38%; }

/* fastening captions: "T-profile" must not break at its hyphen */
.page-boards .cap { grid-template-columns: 96px 1fr; }
.page-boards .cap-name { white-space: nowrap; }

/* installation: one outlined download button under the statement */
.install-download { margin-top: 32px; }

@media (max-width: 480px) {
  .hero-tags-boards .tag:nth-child(1) { --x: 6%; --y: 22%; }
  .hero-tags-boards .tag:nth-child(2) { --x: 48%; --y: 30%; }
  .hero-tags-boards .tag:nth-child(3) { --x: 14%; --y: 38%; }
}

/* ======================================================================
   Documents page (site/documents/). Same grammar as the product pages,
   without a photograph under the bar: the header starts settled, and an
   opening block stands where the hero would be. The rows are the outlined
   document rows from the product pages; until a file is online each row
   leads into the request form and ticks its own box there.
   ====================================================================== */

/* a plain page: the bar is settled from the first frame (the script holds it there) */
.page-plain .head { --hp: 1; }
.page-plain .head :focus-visible { outline-color: var(--ink); }

/* ---------- Opening: page name and one line left, one paragraph in the statement column ---------- */
.opening {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  padding: clamp(150px, 22vh, 230px) var(--margin) clamp(96px, 10vw, 160px);
}
.opening-line {
  grid-column: 1 / 10;
  text-wrap: balance;
  max-width: 24ch;
}
.opening-line .hero-name { margin-bottom: 18px; }
.opening-body {
  grid-column: 5 / 11;
  margin-top: 44px;
  max-width: 46ch;
}
.reveal .opening-line,
.reveal .opening-body {
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 500ms var(--ease), transform 500ms var(--ease);
}
.reveal .opening-body { transition-delay: 120ms; }
.reveal.is-in .opening-line,
.reveal.is-in .opening-body { opacity: 1; transform: none; }

/* a low, wide band for the workshop photograph, cropped to the foot of the frame so the
   corner spec sits on the white table, not on the board. A gentler drift than the other
   plates, so the hand at the top of the crop never leaves the band. */
.plate-band { aspect-ratio: 2 / 1; }
.plate-band .plate-img { object-position: 50% 100%; }

/* ---------- Document groups: the product in the label column, numbered rows beside it ---------- */
.docs-index { padding-bottom: clamp(80px, 9vw, 140px); }
.docs-index .label-col { grid-column: 1 / 5; padding-top: 15px; } /* the label sits level with the first row's text */
.docs-index .section-body .stack { margin-top: 0; }
.label-link {
  display: block;
  width: max-content;
  max-width: 100%;
  margin-top: 16px;
  text-transform: uppercase;
  color: var(--ink-2);
}
.label-link + .label-link { margin-top: 6px; }
.label-link .arrow { margin-left: 4px; transition: transform 300ms var(--ease); }
.label-link:hover .arrow { transform: translateX(4px); }
.reveal .label-link { opacity: 0; transition: opacity 500ms var(--ease) 180ms; }
.reveal.is-in .label-link { opacity: 1; }

/* no-script: everything visible */
html:not(.js) .opening-line,
html:not(.js) .opening-body,
html:not(.js) .label-link { opacity: 1; transform: none; }

@media (max-width: 899px) {
  .opening { display: block; padding-top: 120px; }
  .opening-line { max-width: 14ch; }
  .opening-body { margin-top: 32px; max-width: none; }
  .plate-band { aspect-ratio: auto; } /* this rule sits after the narrow-screen reset above, so it has to repeat it */
  .plate-band .plate-img { aspect-ratio: 4 / 3; }
  .docs-index .label-col { padding-top: 0; margin-bottom: 28px; }
  .docs-index .label { margin-bottom: 4px; }
}

/* narrow rows: the "on request" note gives way ("PDF" stays), and the hover arrow,
   which never shows on a touch screen, gives its space back to the title */
@media (max-width: 700px) {
  .row-note-x { display: none; }
  .row-link .arrow { display: none; }
}

/* ======================================================================
   Contact page (site/contact/). A plain page like Documents: opening block,
   then the four channels as the outlined text cells from the applicator
   list, the workshop band, and the enquiry form. Nothing new in the grammar;
   the cells only carry a link in their first line.
   ====================================================================== */

/* the phone number and address are the first line of the cell: a link, no underline at rest */
.cells-contact .cell-firm a { text-decoration: none; }
.cells-contact .cell-firm a:hover,
.cells-contact .cell-firm a:focus-visible { text-decoration: underline; text-underline-offset: 0.14em; text-decoration-thickness: 1px; }
.cells-contact .cell-person { max-width: 34ch; }
.cells-contact .cell-contact { margin-top: 14px; }
.cells-contact .cell-contact .arrow { display: inline-block; margin-left: 4px; transition: transform 300ms var(--ease); }
.cells-contact .cell-contact a:hover .arrow { transform: translateX(4px); }

/* Flexcoat hero: the spray photograph is bright floor and plastic sheeting low down,
   so a floor wash (deepest behind the card) keeps the white line, tags and card legible */
.page-flexcoat .hero-media::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(ellipse 42% 55% at 86% 80%, rgba(0, 0, 0, 0.42) 0%, rgba(0, 0, 0, 0) 100%),
    linear-gradient(to top, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.26) 34%, rgba(0, 0, 0, 0) 64%);
}
@media (max-width: 699px) {
  .page-flexcoat .hero-media::after {
    background: linear-gradient(to top, rgba(0, 0, 0, 0.62) 0%, rgba(0, 0, 0, 0.36) 42%, rgba(0, 0, 0, 0) 72%);
  }
}

/* ---------- Home, 2026-10-05: What we make split photo, rows without photos ---------- */
.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  margin-top: 64px;
  border: 1px solid var(--line);
}
.split-half {
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;
}
.split-half + .split-half { border-left: 1px solid var(--line); }
.split-half img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  clip-path: inset(0 100% 0 0);
  transition: clip-path var(--d-mask) var(--ease) 80ms;
}
.split-half + .split-half img { transition-delay: 240ms; }
.reveal.is-in .split-half img { clip-path: inset(0); }
.split-cap {
  position: absolute;
  left: 16px;
  bottom: 14px;
  color: var(--ink);
}
.split + .products-stack { margin-top: 32px; }

/* product rows: copy left, spec right, now that the photos sit in the split above */
.products-stack .row-text-wrap { width: auto; }
.products-stack .row.is-open .row-btn { width: 100%; }
.products-stack .row-text {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: auto 1fr;
  column-gap: var(--gutter);
}
.products-stack .row-text .spec { grid-column: 2; grid-row: 1 / 3; margin-top: 0; }
.products-stack .row-text .more { grid-column: 1; grid-row: 2; }

/* the architects render is a wide frame; keep the building in the crop */
.cell-media img.pos-right { object-position: 78% 50%; }

@media (max-width: 700px) {
  .split { margin-top: 44px; }
  .products-stack .row-text { grid-template-columns: 1fr; }
  .products-stack .row-text .spec { grid-column: 1; grid-row: auto; margin-top: 22px; }
  .products-stack .row-text .more { grid-column: 1; grid-row: auto; }
}

/* ---------- Panels: two patterns, the custom line, why and packages cells ---------- */
@media (min-width: 900px) {
  .grid2 { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 66.6%; }
}
.pattern-custom { margin-top: 40px; max-width: 52ch; }
.pattern-custom a { display: block; width: fit-content; margin-top: 6px; }
.pattern-custom .arrow { display: inline-block; margin-left: 4px; transition: transform 300ms var(--ease); }
.pattern-custom a:hover .arrow { transform: translateX(4px); }
/* the mono tag sits on the name's baseline, not centred on the cell */
.cells-why .cell-head { flex-wrap: wrap; align-content: center; align-items: baseline; }
.cells-why .cell-person { max-width: 34ch; }
.cells-why .cell-contact { margin-top: 14px; }
.cells-why .cell-contact .arrow { display: inline-block; margin-left: 4px; transition: transform 300ms var(--ease); }
.cells-why .cell-contact a:hover .arrow { transform: translateX(4px); }

/* Packages: four product renders on the page ground, spec list under each */
.pkgs {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  column-gap: var(--gutter);
  row-gap: 48px;
  margin-top: 64px;
}
.pkg {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 500ms var(--ease) calc(var(--i) * 140ms), transform 500ms var(--ease) calc(var(--i) * 140ms);
}
.reveal.is-in .pkg { opacity: 1; transform: none; }
.pkg-media { aspect-ratio: 372 / 261; }
.pkg-media img { width: 100%; height: 100%; object-fit: contain; }
.pkg-name { margin-top: 18px; font-size: var(--t-title); line-height: 1.2; }
.pkg .spec { margin-top: 14px; }
html:not(.js) .pkg { opacity: 1; transform: none; }
@media (max-width: 1199px) { .pkgs { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 599px) { .pkgs { grid-template-columns: 1fr; margin-top: 44px; } }

/* ---------- Privacy: plain policy text, one section per question ---------- */
.policy { padding-bottom: clamp(72px, 8vw, 120px); }
.policy-body { max-width: 62ch; }
.policy-body > * + * { margin-top: 1em; }
.policy-body a { text-decoration: underline; text-underline-offset: 0.15em; }
.policy-list { padding-left: 1.1em; list-style: disc; }
.policy-list li + li { margin-top: 0.6em; }
.policy-list strong { font-weight: 500; }
.policy-date { font-family: var(--mono); font-size: var(--t-ui); text-transform: uppercase; letter-spacing: 0.04em; }
