/* ==========================================================================
   1. Design Tokens
   Values from Utility Branding Guidelines.pdf (marketing/3. TD Foundry/
   Utilities Website). Prometo (the brand's title font) isn't licensed for
   web use yet, so Archivo (a free, similarly geometric Google Font) stands
   in for it — same substitution the design draft makes. Swap
   --tdup-font-title below once/if a webfont licence for Prometo is bought.
   ========================================================================== */
:root {
	--tdup-red: #A0233E; /* official brand red (Lee, 2026-11-03). The old #A40C29 came from the guidelines PDF and does not match the printed booklets. White on this red is 7.4:1. */
	--tdup-red-dark: #7F1B31; /* hover / pressed */
	--tdup-charcoal: #44484B; /* official charcoal (Lee, 2026-11-03) */
	--tdup-charcoal-light: #4B5053;
	/* A darker tonal shade of the same charcoal (not a new hue) — used for
	   cells/panels laid on top of a charcoal band (e.g. the load-class
	   band, the tile-wall's dark variants) so they read as a layer, not
	   flat-on-flat with the section behind them. Added 2026-09-10 for the
	   redesign — see README/project memory for the fuller design-system
	   backstory. */
	--tdup-charcoal-2: #34373A; /* deep charcoal */
	/* The shadowed side of a casting: darkest surfaces, photo scrims, the footer. */
	--tdup-ink: #26292B;
	/* 2026-11-02 brand identity (DESIGN.md): the same darkest charcoal under
	   its DESIGN.md name. Used for the footer and nothing else dark. */
	--tdup-charcoal-deep: #34373A;
	/* "Band" tokens (2026-09-25, from td-corporate's design system): the
	   dark full-bleed bands — hero, load classes, story, closing band — all
	   share one surface colour and one hairline colour, so they read as one
	   family of dark chrome rather than several slightly different darks.
	   --tdup-red-light is the brand red lifted for small text on those dark
	   bands: the red itself is too dark to read at kicker size on charcoal
	   (it fails WCAG AA contrast), this passes. */
	/* Was near-black #2A2D2F. DESIGN.md: dark bands are the logo's charcoal
	   (#44484B), not black, which is what separates us from the group site. */
	--tdup-band: var(--tdup-charcoal);
	--tdup-band-border: rgba(255, 255, 255, 0.14);
	/* DESIGN.md: red text never goes on charcoal (it vibrates), so the "light
	   red" used for small text on dark bands is now plain white. The name is
	   kept so the ~30 rules that use it didn't all need renaming. */
	--tdup-red-light: #FFFFFF;
	--tdup-body-grey: #54595F;
	--tdup-mid-grey: #9AA0A4;
	--tdup-grey-3: #6E6E6E; /* tertiary text, 5.1:1 on white (brand's #7A7A7A is 4.3:1) */
	--tdup-rule: #D1CDCE;   /* the hairline rule from the logo: our only divider style */
	--tdup-border: #E3E5E7;
	--tdup-off-white: #F4F5F6;
	--tdup-surface: #EDEEEF;
	--tdup-white: #FFFFFF;
	--tdup-green: #1F7A44;

	--tdup-font-title: 'Archivo', system-ui, sans-serif;
	--tdup-font-body: 'Lato', system-ui, sans-serif;

	/* Type tokens (DESIGN.md). Display = H1/H2; label = nav, buttons, small
	   data labels. font-stretch needs the variable Archivo with a wdth axis
	   (self-hosted via fonts.css); until that file is in place the browser
	   just ignores the stretch and shows normal-width Archivo. */
	--tdup-display-stretch: 112%;
	--tdup-display-weight: 800;
	--tdup-display-tracking: 0.005em;
	--tdup-label-stretch: 125%;
	--tdup-label-weight: 500;
	--tdup-label-tracking: 0.22em;
	--tdup-label-size: 12.5px;
	--tdup-small-heading-stretch: 110%;

	/* Zeroed 2026-09-10: the approved redesign's whole visual identity is
	   flat "cast plate" edges — every card, button and table in every
	   approved mockup has square corners, shadow/border for depth instead
	   of radius. Rather than hunt down every individual component still
	   using the old 8px/5px values, zeroing the shared tokens they nearly
	   all reference fixes the bulk of the site (product cards, buttons,
	   filters, chips, spec tables, contact form, tech blocks, about-values,
	   CTA bands, empty states) in one place. A genuine circle (avatar
	   badges, the quote-count pill, social icons) uses an explicit 50%/px
	   value, not this token, so those are untouched. */
	--tdup-radius: 0;
	--tdup-radius-sm: 0;
	--tdup-container-width: 1200px;

	--tdup-transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1);
	--tdup-transition-slow: 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}

/* ==========================================================================
   2. Base
   ========================================================================== */
* { box-sizing: border-box; }

html { height: 100%; }

body {
	/* Sticky-footer trick: body is a full-viewport-height flex column and
	   the footer (its last child, after everything header.php/footer.php
	   and every template print as direct body children) gets
	   margin-top: auto — so on a short page the footer sits flush with
	   the bottom of the viewport instead of leaving a blank strip under
	   it, which is what a plain document flow does by default. */
	display: flex;
	flex-direction: column;
	min-height: 100vh;
	margin: 0;
	font-family: var(--tdup-font-body);
	color: var(--tdup-body-grey);
	line-height: 1.5;

	/* One flat warm off-white (2026-09-25). This used to carry a faint dot
	   grid plus two soft red/charcoal glows; the flat design language taken
	   from td-corporate gets its depth from real photography and dark
	   bands instead, and a single plain neutral avoids the "two slightly
	   different light greys" look td-corporate was criticised for. */
	background-color: #FBFAF8;
}

/* Headings (DESIGN.md "Typography").
   H1/H2 = display: expanded caps, weight 600, tracked, brand red on light
   backgrounds (white on charcoal, see the dark-band rules further down).
   H3 and below = Archivo 110%, 700, sentence case (no forced uppercase).
   The clamp()s are deliberately smaller than the old 900-weight sizes:
   expanded capitals are about 25% wider, so the same size would wrap badly
   at 375px. */
h1, h2, h3, h4 {
	font-family: var(--tdup-font-title);
	font-weight: 700;
	font-stretch: var(--tdup-small-heading-stretch);
	color: var(--tdup-charcoal);
	margin: 0 0 0.5em;
}
h1, h2 {
	font-stretch: var(--tdup-display-stretch);
	font-weight: var(--tdup-display-weight);
	text-transform: uppercase;
	letter-spacing: var(--tdup-display-tracking);
	color: var(--tdup-red);
	line-height: 1.1;
	overflow-wrap: break-word;
}
h1 { font-size: clamp(1.6rem, 4.6vw, 2.6rem); }
h2 { font-size: clamp(1.35rem, 3vw, 2rem); }
h3, h4 { text-transform: none; }

a { color: var(--tdup-red); text-decoration: none; }
a:hover { color: var(--tdup-red-dark); }

img { max-width: 100%; display: block; }

.screen-reader-text {
	position: absolute; width: 1px; height: 1px; overflow: hidden;
	clip: rect(1px,1px,1px,1px); white-space: nowrap;
}

/* Skip link (WCAG 2.4.1) — first focusable thing on every page (see
   header.php), so a keyboard/screen-reader visitor can jump straight past
   the header/nav to <main id="main-content"> instead of tabbing through
   every nav item first. Hidden like .screen-reader-text above until it
   actually receives focus, then dropped into view at the top-left corner. */
.tdup-skip-link {
	position: absolute; top: -100px; left: 12px; z-index: 100;
	background: var(--tdup-charcoal); color: var(--tdup-white);
	padding: 10px 18px; font-family: var(--tdup-font-title); font-weight: 700; font-size: 14px;
	transition: top var(--tdup-transition);
}
.tdup-skip-link:focus { top: 12px; }

.tdup-container {
	/* width: 100% is load-bearing, not decorative, now that body is a flex
	   column (for the sticky footer — see body{} below): a flex item with
	   auto cross-axis margins (the "margin: 0 auto" centering here) stops
	   being stretched to fill the row and instead shrinks to its content's
	   size, which starved every CSS Grid inside a .tdup-container of a
	   real width to lay out against (the product grid was collapsing to a
	   single narrow column because of exactly this). Setting width
	   explicitly sidesteps the stretch-vs-auto-margin ambiguity entirely.
	*/
	width: 100%;
	max-width: var(--tdup-container-width);
	margin: 0 auto;
	padding: 0 24px;
	box-sizing: border-box;
}

/* ==========================================================================
   2b. Design system (2026-09-25)
   Shared building blocks ported from td-corporate's design language and
   re-skinned in Utility Products' brand. The rules they follow:
     - flush and square: no rounded corners, no drop shadows;
     - things are separated by 1px hairlines, not floating cards;
     - left-aligned headers, heavy Archivo type, giant numerals;
     - one solid action per section, the rest are quieter text links;
     - dark "band" sections and light sections alternate down a page.
   README's "Design system" table lists what each one is for. Reuse these
   before writing new markup for a section.
   ========================================================================== */

/* Eyebrow / label style (DESIGN.md "Labels"): small expanded caps tracked
   wide, echoing the logo's spaced "U T I L I T Y". It labels data or a
   page type; it is NOT repeated above every heading (that's a template
   tell), so the homepage no longer uses it over its H2s. --band for dark
   sections. The old 22px bar in front of it is gone: the hairline under the
   heading does that job now. */
.tdup-eyebrow {
	display: block;
	font-family: var(--tdup-font-title); font-stretch: var(--tdup-label-stretch);
	font-weight: var(--tdup-label-weight); font-size: var(--tdup-label-size);
	letter-spacing: var(--tdup-label-tracking); text-transform: uppercase;
	color: var(--tdup-red); margin: 0 0 12px;
}
.tdup-eyebrow--band { color: var(--tdup-white); }

/* Section heading lockup (restyled 2026-11-03 to match the homepage's): the
   H2 in display caps (red on a light band, white on a dark one: the band sets
   --ip-h), then one plain Lato sentence. Stacked, left-aligned, used once per
   section. No hairline any more: the big caps carry it. The "view all" link
   (or carousel controls) sits on its own line underneath. Heading
   colour/stretch/tracking come from the global h2 rule; this sets the size and
   layout. For new pages prefer tdup_section_head() / .ip-head (see
   "Inner pages: shared system" at the end of this file); this older class
   stays so existing templates keep working and look the same. */
.tdup-section-heading { margin-bottom: clamp(24px, 3.5vw, 36px); }
.tdup-section-heading h2 {
	margin: 0; font-size: clamp(26px, 3vw, 40px); line-height: 1; text-wrap: balance;
	color: var(--ip-h, var(--tdup-red));
}
.tdup-section-heading > p:not(.tdup-eyebrow) {
	max-width: 62ch; margin: 12px 0 0;
	font-size: 17px; line-height: 1.6; color: var(--ip-text, var(--tdup-body-grey));
}
.tdup-section-heading > .tdup-text-link,
.tdup-section-heading > .tdup-carousel__nav { margin-top: 14px; }
.tdup-section-heading--band h2 { color: var(--tdup-white); }
.tdup-section-heading--band > p:not(.tdup-eyebrow) { color: rgba(255, 255, 255, 0.92); }

/* Text link: the quieter secondary action. Uppercase label with a 2px
   underline (the homepage's "View all" style), 44px tall to tap. Hover
   thickens the underline; on LIGHT sections it also turns red. --band is for
   charcoal / red sections: there hover only thickens the underline and keeps
   the colour (a red hover on red or charcoal makes the text vanish). */
.tdup-text-link {
	display: inline-flex; align-items: center; gap: 6px; min-height: 44px;
	font-family: var(--tdup-font-title); font-stretch: 118%;
	font-weight: 700; font-size: 13px;
	letter-spacing: 0.1em; text-transform: uppercase;
	color: var(--tdup-charcoal); border-bottom: 2px solid currentColor;
	white-space: nowrap;
}
.tdup-text-link:hover { color: var(--tdup-red); box-shadow: inset 0 -2px 0 currentColor; }
.tdup-text-link--band, .tdup-text-link--band:hover { color: var(--tdup-white); }

/* Figure row: giant numerals in a hairline grid — how key numbers are shown
   everywhere now, instead of boxed stat cards. --band for dark sections. */
.tdup-figure-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); border-top: 1px solid var(--tdup-border); }
.tdup-figure { padding: clamp(16px, 2.2vw, 26px) clamp(14px, 2vw, 24px) clamp(16px, 2.2vw, 26px) 0; border-bottom: 1px solid var(--tdup-border); }
.tdup-figure + .tdup-figure { padding-left: clamp(14px, 2vw, 24px); border-left: 1px solid var(--tdup-border); }
.tdup-figure__number {
	display: block; font-family: var(--tdup-font-title); font-weight: 700;
	font-size: clamp(2rem, 4vw, 3.3rem); line-height: 0.95; letter-spacing: -0.02em;
	color: var(--tdup-charcoal); white-space: nowrap; font-variant-numeric: tabular-nums;
}
.tdup-figure__label { display: block; margin-top: 10px; font-family: var(--tdup-font-title); font-weight: 700; font-size: 11px; letter-spacing: 0.09em; text-transform: uppercase; color: var(--tdup-mid-grey); }
.tdup-figure-row--band { border-top-color: var(--tdup-band-border); }
.tdup-figure-row--band .tdup-figure { border-color: var(--tdup-band-border); }
.tdup-figure-row--band .tdup-figure__number { color: var(--tdup-white); }
.tdup-figure-row--band .tdup-figure__label { color: rgba(255, 255, 255, 0.68); }
@media (max-width: 600px) {
	.tdup-figure-row { grid-template-columns: 1fr 1fr; }
	.tdup-figure + .tdup-figure { padding-left: 0; border-left: 0; }
	.tdup-figure:nth-child(even) { padding-left: 14px; border-left: 1px solid var(--tdup-border); }
	.tdup-figure-row--band .tdup-figure:nth-child(even) { border-left-color: var(--tdup-band-border); }
	/* Half a phone screen is ~150px: a value like "B125–F900" won't fit on
	   one line at full size, so it shrinks and may wrap instead of
	   overflowing its column. */
	.tdup-figure__number { font-size: clamp(1.5rem, 7.5vw, 2.2rem); white-space: normal; }
}

/* Split band: a flush, full-width 50/50 — text on one half, a photo filling
   the other half edge to edge. The text side's outer padding lines its copy
   up with every other section's .tdup-container edge (max() picks the
   bigger of the normal gutter or the space a centred 1200px container
   leaves). --media-left mirrors it; --dark is the dark-band version. */
.tdup-split-band {
	--split-outer: max(24px, calc((100vw - var(--tdup-container-width)) / 2 + 24px));
	display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	min-height: clamp(420px, 42vw, 580px); background: var(--tdup-white);
}
.tdup-split-band__copy { display: flex; flex-direction: column; justify-content: center; padding: clamp(40px, 6vw, 80px) clamp(28px, 5vw, 80px) clamp(40px, 6vw, 80px) var(--split-outer); }
.tdup-split-band__copy h2 { margin: 0; font-weight: 600; text-transform: uppercase; font-size: clamp(1.7rem, 3.2vw, 2.5rem); line-height: 1.02;font-stretch: 125%; letter-spacing: 0.06em;}
.tdup-split-band__copy p:not(.tdup-eyebrow) { margin: 16px 0 0; font-size: 15.5px; line-height: 1.7; max-width: 56ch; }
.tdup-split-band__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 16px 28px; margin-top: 28px; }
.tdup-split-band__media { position: relative; overflow: hidden; background: var(--tdup-band); min-height: 300px; }
.tdup-split-band__media > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.tdup-split-band--media-left .tdup-split-band__media { order: -1; }
.tdup-split-band--media-left .tdup-split-band__copy { padding-left: clamp(28px, 5vw, 80px); padding-right: var(--split-outer); }
.tdup-split-band--dark { background: var(--tdup-band); }
.tdup-split-band--dark h2 { color: var(--tdup-white); }
.tdup-split-band--dark p:not(.tdup-eyebrow) { color: rgba(255, 255, 255, 0.75); }
.tdup-split-band--dark .tdup-eyebrow { color: var(--tdup-red-light); }
@media (max-width: 900px) {
	.tdup-split-band { grid-template-columns: 1fr; min-height: 0; }
	.tdup-split-band__copy,
	.tdup-split-band--media-left .tdup-split-band__copy { padding: clamp(36px, 7vw, 56px) 24px; }
	.tdup-split-band__media { min-height: 0; aspect-ratio: 16 / 10; }
	.tdup-split-band--media-left .tdup-split-band__media { order: 0; }
}

/* Closing "where next" band — tdup_next_band() in functions.php. Restyled
   2026-11-03 to match the left side of the homepage contact band: deep
   charcoal, display-caps heading in white, a plain sentence, and the
   destinations as underlined rows on the right (the first one a red block:
   the main action). Hover never recolours text: a row gets a lighter fill and
   its label picks up an underline; the arrow slides. With .tdup-next-band--cut
   the top edge is angled (--cut), which needs the section ABOVE to carry
   class ip-before-cut (ANGLE RULE, see "Inner pages: shared system"). */
.tdup-next-band { position: relative; background: var(--tdup-charcoal-2); color: var(--tdup-white); padding: clamp(44px, 5vw, 72px) 0; }
.tdup-next-band--cut {
	padding-top: calc(clamp(44px, 5vw, 72px) + var(--cut));
	margin-top: calc(-1 * var(--cut));
	clip-path: polygon(0 var(--cut), 100% 0, 100% 100%, 0 100%);
}
.tdup-next-band__inner { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: clamp(32px, 6vw, 96px); align-items: center; }
.tdup-next-band__heading {
	margin: 0; color: var(--tdup-white); text-wrap: balance;
	font-size: clamp(28px, 3.6vw, 52px); line-height: 0.98;
}
.tdup-next-band__text { margin: 14px 0 0; max-width: 52ch; font-size: 18px; line-height: 1.55; color: rgba(255, 255, 255, 0.92); }
.tdup-next-band__links { list-style: none; margin: 0; padding: 0; border-bottom: 1px solid rgba(255, 255, 255, 0.28); }
.tdup-next-band__links li { border-top: 1px solid rgba(255, 255, 255, 0.28); }
.tdup-next-band__link, .tdup-next-band__link:hover {
	display: flex; align-items: center; justify-content: space-between; gap: 16px;
	min-height: 60px; padding: 12px 18px; color: var(--tdup-white); text-decoration: none;
	font-family: var(--tdup-font-title); font-stretch: 118%; font-weight: 700;
	font-size: clamp(0.9rem, 1.3vw, 1.05rem); letter-spacing: 0.08em; text-transform: uppercase;
	overflow-wrap: anywhere;
}
.tdup-next-band__link > span { border-bottom: 2px solid transparent; }
.tdup-next-band__link:hover { background: rgba(255, 255, 255, 0.1); }
.tdup-next-band__link:hover > span { border-bottom-color: currentColor; }
.tdup-next-band__link svg { flex-shrink: 0; transition: transform var(--tdup-transition); }
.tdup-next-band__link:hover svg { transform: translateX(6px); }
/* The first row is the main action: a solid red block. */
.tdup-next-band__links li:first-child .tdup-next-band__link { background: var(--tdup-red); }
.tdup-next-band__links li:first-child .tdup-next-band__link:hover { background: var(--tdup-red-dark); }
/* The footer's usual 60px top margin would leave a pale strip between this
   band and the footer; only removed when a page ends with the band. */
main:has(> .tdup-next-band:last-child) + .tdup-footer { margin-top: 0; }
@media (max-width: 800px) {
	.tdup-next-band__inner { grid-template-columns: 1fr; }
}

/* Pause/play button for anything that moves on its own (WCAG 2.2.2) — the
   hero slideshow. Shows a pause icon
   while playing and a play icon once paused (aria-pressed="true"). */
.tdup-motion-toggle {
	position: absolute; z-index: 5; width: 40px; height: 40px;
	display: flex; align-items: center; justify-content: center;
	background: rgba(0, 0, 0, 0.45); color: var(--tdup-white);
	border: 1px solid rgba(255, 255, 255, 0.35); cursor: pointer;
	transition: background var(--tdup-transition), border-color var(--tdup-transition);
}
.tdup-motion-toggle:hover { background: var(--tdup-red); border-color: var(--tdup-red); }
.tdup-motion-toggle__play { display: none; }
.tdup-motion-toggle[aria-pressed="true"] .tdup-motion-toggle__pause { display: none; }
.tdup-motion-toggle[aria-pressed="true"] .tdup-motion-toggle__play { display: block; }
/* White ring on dark backgrounds: the site-wide red focus outline would be
   nearly invisible against charcoal/photos. */
.tdup-motion-toggle:focus-visible { outline-color: var(--tdup-white); }

.tdup-button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	min-height: 48px; /* comfortably over the 44px touch target */
	padding: 12px 22px;
	border-radius: var(--tdup-radius-sm);
	/* Label style (DESIGN.md), the same as the homepage's .hp-btn: heavy,
	   expanded caps. .1em tracking, not the .22em of nav labels: wide
	   tracking made labels like "CHOOSE SIZE" wrap in narrow cards. */
	font-family: var(--tdup-font-title);
	font-stretch: 118%;
	font-weight: 700;
	font-size: 13px;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	text-decoration: none;
	border: 1px solid transparent;
	cursor: pointer;
}
/* No hover lift or glow: a hover is shown with the fill changing, never by
   turning the label the colour of its own background. The `a:hover` rule
   would otherwise recolour a link-styled button, so each one sets its label
   colour for hover too. */
/* Primary: red fill, white label. Secondary: charcoal outline. White: for
   red or charcoal bands (a red button would vanish on red). */
.tdup-button--primary, .tdup-button--primary:hover { color: var(--tdup-white); }
.tdup-button--primary { background: var(--tdup-red); }
.tdup-button--primary:hover { background: var(--tdup-red-dark); }
.tdup-button--secondary { background: transparent; color: var(--tdup-charcoal); box-shadow: inset 0 0 0 2px var(--tdup-charcoal); }
.tdup-button--secondary:hover { background: var(--tdup-charcoal); color: var(--tdup-white); }
.tdup-button--white, .tdup-button--white:hover { color: var(--tdup-charcoal); }
.tdup-button--white { background: var(--tdup-white); }
.tdup-button--white:hover { background: var(--tdup-sweep); }
.tdup-button--small { min-height: 44px; padding: 8px 14px; font-size: 12px; }
.tdup-button--dark, .tdup-button--dark:hover { color: var(--tdup-white); }
.tdup-button--dark { background: var(--tdup-charcoal); white-space: nowrap; }
.tdup-button--dark:hover { background: var(--tdup-charcoal-deep); }

/* Chips — the dark "D400"-style solid chip and the outlined
   "KITEMARK"-style chip, used on product cards, product detail, and the
   active-filters row. */
.tdup-chip-row { display: flex; gap: 6px; flex-wrap: wrap; }
/* Exact mockup values (.chips span/.pcard-chips span) — every chip here
   (load class, badge, feature) is the same plain solid-dark style with no
   forced uppercase, not the base .tdup-chip's uppercase/600-weight
   treatment, and not a separate outlined variant for badges/features
   (that distinction doesn't exist in the design — every chip in this row
   is uniformly solid). */
.tdup-chip-row .tdup-chip { font-weight: 700; text-transform: none; letter-spacing: normal; }
.tdup-chip {
	display: inline-flex; align-items: center;
	border-radius: 3px; padding: 4px 8px;
	font-size: 11px; font-family: var(--tdup-font-title); font-weight: 600;
	letter-spacing: 0.06em; text-transform: uppercase; line-height: 1.4;
}
.tdup-chip--solid { background: var(--tdup-charcoal); color: var(--tdup-white); }
/* Exact mockup values (.chip/.chip button) — a white outlined chip with
   only the remove "x" picked out in red, not a solid red/charcoal filled
   pill (that combination was two other chip variants stacked together,
   never an actual removable-filter style of its own). */
.tdup-chip--removable { background: var(--tdup-white); border: 1px solid var(--tdup-charcoal); color: var(--tdup-charcoal); font-weight: 700; font-size: 12px; text-transform: none; letter-spacing: normal; padding: 6px 10px; }
.tdup-chip--removable:hover { border-color: var(--tdup-red); }
.tdup-chip__remove { color: var(--tdup-red); font-weight: 700; margin-left: 2px; }

/* Load-class bar (DESIGN.md signature 1): five equal cells, B125 to F900,
   from tdup_load_class_bar() in functions.php. The product's class is filled
   red with a white label; the others are hairline-outlined grey labels.
   Label style type (expanded, tracked) but tight tracking at small size so
   five cells fit a card. Square, flat, no shadow. */
.tdup-class-bar { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); list-style: none; margin: 0; padding: 0; }
.tdup-class-bar__cell {
	display: flex; align-items: center; justify-content: center; min-width: 0;
	padding: 5px 0; margin-left: -1px; /* -1px so neighbouring borders share one line */
	border: 1px solid var(--tdup-rule); background: var(--tdup-white);
	font-family: var(--tdup-font-title); font-stretch: var(--tdup-label-stretch);
	font-weight: var(--tdup-label-weight); font-size: 10px; letter-spacing: 0.06em;
	line-height: 1.2; color: var(--tdup-grey-3);
}
.tdup-class-bar__cell:first-child { margin-left: 0; }
.tdup-class-bar__cell.is-current { position: relative; background: var(--tdup-red); border-color: var(--tdup-red); color: var(--tdup-white); font-weight: 700; }
/* Large version on the product page. */
.tdup-class-bar--large { max-width: 420px; margin: 14px 0 4px; }
.tdup-class-bar--large .tdup-class-bar__cell { padding: 9px 0; font-size: 12.5px; letter-spacing: 0.1em; }
/* Fit any card width. Each product card is a size container (see
   .tdup-product-card below), so the bar reacts to the width of ITS card, not
   the screen: a 2-column phone grid has ~160px cards, a desktop grid ~280px.
   Under ~220px the labels drop the expanded width and tracking so five
   equal cells always hold their text; under ~170px they shrink a touch more.
   (The cells already split the width equally via the grid above.) */
@container tdup-card (max-width: 220px) {
	.tdup-class-bar__cell { font-stretch: 100%; letter-spacing: 0; font-size: 10px; padding: 5px 0; }
}
@container tdup-card (max-width: 170px) {
	.tdup-class-bar__cell { font-size: 9px; }
}
/* The large bar is on the product page, not in a card: just ease it on phones. */
@media (max-width: 400px) {
	.tdup-class-bar--large .tdup-class-bar__cell { font-size: 11px; letter-spacing: 0.04em; }
}

/* Quantity stepper (−/+ either side of a number input). Exact mockup
   values (.qty-stepper) — a crisp charcoal-bordered control with
   transparent buttons, not a pale near-invisible border with an
   off-white button fill (which read as soft/washed-out against the
   design's flat, hard-edged industrial language). */
.tdup-qty-stepper { display: inline-flex; align-items: stretch; border: 1px solid var(--tdup-charcoal); overflow: hidden; }
.tdup-qty-stepper__btn { width: 34px; height: 40px; border: none; background: none; color: var(--tdup-charcoal); cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 16px; }
.tdup-qty-stepper__btn:hover { background: var(--tdup-off-white); }
.tdup-qty-stepper input { width: 44px; height: 40px; border: none; border-left: 1px solid var(--tdup-border); border-right: 1px solid var(--tdup-border); text-align: center; font-family: var(--tdup-font-title); font-weight: 700; color: var(--tdup-charcoal); -moz-appearance: textfield; }
.tdup-qty-stepper input::-webkit-outer-spin-button,
.tdup-qty-stepper input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* Wordmark — see tdup_logo() in functions.php. Plain styled text in the
   two real brand colours until a proper logo export exists; letter-
   spacing/weight give it enough presence to read as a mark rather than
   a stray label. */
.tdup-wordmark {
	font-family: var(--tdup-font-title);
	font-weight: 500;
	font-size: 18px;
	letter-spacing: 0.02em;
	white-space: nowrap;
	/* .tdup-header__logo .tdup-wordmark (below) forces height:40px onto
	   this span so it lines up with the real logo image at the same
	   selector — but a plain <span> has no vertical-centering of its own,
	   so its ~22px-tall text content sat at the TOP of that 40px box
	   instead of centered in it, same shape of bug as the cropped-image
	   logo (off-centre relative to the nav/search/Quote button beside it).
	   line-height matching the forced height centers a single line of text
	   within it — tried inline-flex first, but flexbox splits this span's
	   mixed text-node + <strong> children into separate flex items and
	   silently drops the literal space between "Utility" and "Products",
	   which line-height doesn't do. */
	line-height: 40px;
}
.tdup-wordmark strong { font-weight: 700; }
.tdup-wordmark--dark { color: var(--tdup-white); }
.tdup-wordmark--light { color: var(--tdup-charcoal); }

/* Real logo (Appearance > Customize > Site Identity > Logo) once one's
   set — see tdup_logo() in functions.php. Height-constrained, not
   width-, since the header/footer bar's height is fixed and the mark's
   aspect ratio (real vector export, not a re-crop) is trustworthy. */
.tdup-logo-image { height: 32px; width: auto; }

/* ==========================================================================
   3. Header / Promo strip
   ========================================================================== */
/* Dark, not red — the design review's "two competing reds" finding: this
   strip sat right above the hero's own dark overlay and red primary CTA
   button, so two solid red blocks fought for attention at the very top of
   the page. Keeping it in the same charcoal family as the header directly
   above it reads as one cohesive dark block instead of a second, separate
   red banner — the red accent stays, just on the "3pm" text itself, so
   the urgency message doesn't lose its emphasis entirely. */
.tdup-promo-strip { background: var(--tdup-red); color: var(--tdup-white); text-align: center; font-size: 13px; font-weight: 700; padding: 9px 0; }
.tdup-promo-strip strong { font-weight: 700; }
/* Message centred, group link pinned right (2026-10-13). The grid's empty
   first column balances the link so the message stays truly centred. */
.tdup-promo-strip__inner { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 16px; }
.tdup-promo-strip__message { grid-column: 2; }
.tdup-promo-strip__group { grid-column: 3; justify-self: end; color: var(--tdup-white); font-weight: 700; text-decoration: underline; text-underline-offset: 3px; white-space: nowrap; }
.tdup-promo-strip__group:hover, .tdup-promo-strip__group:focus-visible { color: var(--tdup-white); text-decoration-thickness: 2px; }
@media (max-width: 900px) {
	/* Not enough width for both side by side: stack them, both centred. */
	.tdup-promo-strip__inner { grid-template-columns: 1fr; gap: 4px; }
	.tdup-promo-strip__message, .tdup-promo-strip__group { grid-column: 1; justify-self: center; }
	.tdup-promo-strip__group { font-size: 12px; }
}

/* Sticky + frosted: needs real complexity behind it to read (a flat colour
   behind blur() is a no-op) — the hero photo sits directly under the header
   on load, and every other page has real content scrolling underneath.
   -webkit- prefix for Safari.
   Solid, not translucent (2026-09-10, fixing a real regression): the
   frosted/translucent version above was designed specifically to blur the
   hero's own background photo behind it — the redesigned hero has no
   photo any more (a light plain surface), so the same translucency just
   let that light background show through, making the header read as a
   washed-out grey instead of the brand's dark charcoal. Every approved
   design mockup shows this header solid. The scrolled state now only adds
   a shadow, since there's no opacity to raise any more. */
.tdup-header {
	position: sticky;
	top: 0;
	z-index: 50;
	background: var(--tdup-charcoal);
	color: var(--tdup-white);
	padding: 18px 0;
	border-bottom: 1px solid rgba(255, 255, 255, 0.1);
	transition: padding var(--tdup-transition-slow), box-shadow var(--tdup-transition-slow);
}
.tdup-header--scrolled { padding: 11px 0; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.22); }
/* flex-wrap stays nowrap above the mobile-menu breakpoint (@media max-width:
   1024px below re-enables it there) — this had been unconditional wrap,
   which meant real nav content slightly wider than the mockup's placeholder
   5-item nav (e.g. an extra real "Latest News" item) silently dropped the
   search box and Quote link onto their own second row on desktop widths
   instead of staying in one row like every approved design screen.
   No longer wrapped in .tdup-container either (mockup's .title-strip has
   no max-width cap at all, just its own 32px side padding) — the header
   bar is deliberately full-bleed edge-to-edge while the content sections
   below it sit inside the narrower centred container; sharing
   .tdup-container here was centring the whole row and leaving equal empty
   gutters either side instead of pinning the logo/quote to the real edges. */
.tdup-header__inner { display: flex; align-items: center; gap: 22px; flex-wrap: nowrap; padding: 0 32px; }
/* width: fit-content — belt-and-braces alongside the .tdup-wordmark
   inline-flex fix above: whatever was making this anchor render wider
   than its own logo/wordmark content (leaving a visible gap before the
   divider/nav), this guarantees the anchor can never be wider than
   whichever child (image or text) it's actually wrapping. */
.tdup-header__logo { color: var(--tdup-white); display: flex; align-items: center; width: fit-content; flex-shrink: 0; padding-right: 22px; border-right: 1px solid rgba(255, 255, 255, 0.14); }
.tdup-header__logo .tdup-logo-image, .tdup-header__logo .tdup-wordmark { height: 40px; transition: height var(--tdup-transition-slow); }
.tdup-header--scrolled .tdup-header__logo .tdup-logo-image { height: 32px; }
/* Flat rectangle, not a rounded pill (2026-09-10, matching the approved
   mockup's header exactly) — every rounded-pill control in the old header
   (this search bar, the quote-link below) goes square along with the rest
   of the "cast plate" identity. */
/* min-width dropped from 200px: the real primary nav has 6 items (the
   mockup's placeholder nav only had 5 — no "Latest News"), so holding the
   search box to 200px minimum was forcing the real nav to wrap internally
   even though the header row itself no longer wraps (see .tdup-header__inner
   above). flex:1 still lets it grow to fill whatever room is left. */
.tdup-header__search { display: flex; align-items: center; flex: 1 1 220px; max-width: 300px; min-width: 140px; background: rgba(255, 255, 255, 0.95); border: 1px solid rgba(255, 255, 255, 0.4); overflow: hidden; transition: box-shadow var(--tdup-transition); }
.tdup-header__search:focus-within { box-shadow: 0 0 0 3px rgba(160, 35, 62, 0.25); }
.tdup-header__search input { flex: 1; border: none; padding: 9px 12px; font-family: var(--tdup-font-body); background: transparent; outline: none; }
.tdup-header__search button { border: none; background: var(--tdup-red); color: var(--tdup-white); width: 36px; height: 36px; flex-shrink: 0; padding: 0; cursor: pointer; display: flex; align-items: center; justify-content: center; }
.tdup-header__quote-link { display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; font-family: var(--tdup-font-title); font-stretch: var(--tdup-label-stretch); font-weight: var(--tdup-label-weight); font-size: 12px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--tdup-white); white-space: nowrap; padding: 9px 16px; background: rgba(255, 255, 255, 0.08); border: 1px solid rgba(255, 255, 255, 0.16); transition: background var(--tdup-transition), border-color var(--tdup-transition), transform var(--tdup-transition); }
.tdup-header__quote-link:hover { color: var(--tdup-white); background: var(--tdup-red); border-color: var(--tdup-red); transform: translateY(-1px); }
.tdup-quote-count { display: inline-flex; align-items: center; justify-content: center; min-width: 20px; height: 20px; padding: 0 5px; background: var(--tdup-red); color: var(--tdup-white); border-radius: 10px; font-size: 12px; margin-left: 4px; transition: background var(--tdup-transition), color var(--tdup-transition); }
.tdup-header__quote-link:hover .tdup-quote-count { background: var(--tdup-white); color: var(--tdup-red); }

/* Matches the mockup's nav{flex:1} — nav (not just search) is meant to
   absorb the slack on wide viewports so the search box doesn't stretch
   past its own 300px cap and the Quote link stays pinned to the true
   right edge. flex-shrink stays 0 though (mockup's nav didn't need this —
   its placeholder had only 5 items — but the real menu has 6, e.g. an
   extra real "Latest News" entry, and without this the header row's flex
   layout would shrink the nav below its natural single-row width before
   giving up any room from the search box, which just pushed the ul's own
   wrap (its items never shrink, only wrap) down onto a second line). */
.tdup-primary-nav { flex-grow: 1; flex-shrink: 0; }
.tdup-primary-nav ul { list-style: none; display: flex; gap: 22px; margin: 0; padding: 0; flex-wrap: wrap; }
.tdup-primary-nav a { position: relative; color: rgba(255,255,255,0.92); font-family: var(--tdup-font-title); font-stretch: var(--tdup-label-stretch); font-weight: var(--tdup-label-weight); font-size: 12px; letter-spacing: 0.16em; text-transform: uppercase; padding-bottom: 4px; }
.tdup-primary-nav a::after { content: ''; position: absolute; left: 0; bottom: -3px; width: 100%; height: 2px; background: var(--tdup-red); transform: scaleX(0); transform-origin: left; transition: transform var(--tdup-transition-slow); }
.tdup-primary-nav a:hover { color: var(--tdup-white); }
.tdup-primary-nav a:hover::after { transform: scaleX(1); }
.tdup-primary-nav li { position: relative; }
.tdup-primary-nav ul ul { display: none; position: absolute; top: 100%; left: 0; background: var(--tdup-white); border: 1px solid var(--tdup-border); border-radius: var(--tdup-radius); padding: 10px; flex-direction: column; min-width: 200px; z-index: 10; box-shadow: 0 8px 24px rgba(0,0,0,0.12); }
.tdup-primary-nav ul ul a { color: var(--tdup-charcoal); }
/* `.tdup-primary-nav a:hover` above (2 classes: .tdup-primary-nav + :hover)
   has higher specificity than `.tdup-primary-nav ul ul a` (1 class, 3
   tags), so without this override, hovering a dropdown link turned its
   text white — same as the dark header links — against the dropdown's
   white background. Invisible text, not a fade; this restores a visible
   hover colour scoped to the dropdown specifically. */
.tdup-primary-nav ul ul a:hover { color: var(--tdup-red); }
/* :focus-within alongside :hover — a keyboard user tabbing through the
   nav (no mouse involved) needs the same dropdown reveal a mouse hover
   gets, otherwise its links exist in the DOM but are effectively
   unreachable at desktop widths (the mobile .tdup-submenu-toggle button
   below only exists under the 1024px breakpoint). */
.tdup-primary-nav li:hover > ul,
.tdup-primary-nav li:focus-within > ul { display: flex; }
/* Sibling of the <a>, output by TDUP_Primary_Nav_Walker only for an item
   with children — invisible on desktop (hover already reveals the
   dropdown, see above); becomes the only way to reach a submenu once the
   mobile breakpoint below hides the hover dropdown outright. */
.tdup-submenu-toggle { display: none; background: none; border: none; color: inherit; padding: 0; cursor: pointer; font-size: 16px; line-height: 1; }
.tdup-submenu-toggle[aria-expanded="true"] span { transform: rotate(45deg); }
.tdup-submenu-toggle span { display: inline-block; transition: transform var(--tdup-transition-slow); }

/* ==========================================================================
   4. Footer
   Restyled 2026-11-03 (the "catalogue cover" look): ink background, a charcoal
   slab behind the brand column cut at the wedge angle, a red wedge strip along
   the top edge, label-caps column headings, 44px tap targets. Every link still
   comes from the same places as before: the two nav columns are two separate
   wp_nav_menu() calls against two registered locations (see footer.php + the
   "footer_products" location in inc/theme-setup.php), each an editable menu;
   the phone/email/address/social links and the company line come from Site
   Settings; "Accredited To" is real certification data. Hover never recolours
   text: links stay white and thicken an underline instead.
   ========================================================================== */
.tdup-footer { position: relative; isolation: isolate; overflow: hidden; background: var(--tdup-ink); color: rgba(255, 255, 255, 0.82); margin-top: 60px; }
/* The charcoal slab, cut at the same angle family as every other diagonal. */
.tdup-footer::after { content: ''; position: absolute; z-index: -1; left: 0; top: 0; bottom: 0; width: 44%; background: var(--tdup-charcoal-deep); clip-path: polygon(0 0, 72% 0, 100% 100%, 0 100%); }
/* The red wedge strip along the top. */
.tdup-footer::before { content: ''; position: absolute; z-index: 0; top: 0; left: 0; width: 38%; height: 12px; background: var(--tdup-red); clip-path: polygon(0 0, 100% 0, calc(100% - 20px) 100%, 0 100%); }
/* padding-top/bottom only, never the `padding:` shorthand: this element is
   also a .tdup-container, and a shorthand here (same specificity, later in
   the file) wiped out the container's side gutter, so on a phone the footer
   text sat flush against the screen edge. */
.tdup-footer__grid { display: grid; grid-template-columns: 1.5fr 1fr 1fr 1fr; gap: 32px clamp(32px, 4vw, 64px); padding-top: 64px; padding-bottom: 32px; }
/* line-height: 34px overrides .tdup-wordmark's own 40px (header context). */
.tdup-footer__brand img, .tdup-footer__brand .tdup-wordmark { height: 34px; line-height: 34px; width: auto; display: block; margin-bottom: 16px; }
.tdup-footer__brand p { margin: 0 0 18px; font-size: 15px; line-height: 1.6; max-width: 34ch; }
.tdup-footer a { color: rgba(255, 255, 255, 0.9); text-decoration: none; }
.tdup-footer a:hover { color: var(--tdup-white); text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 4px; }
/* The Group link sits inline inside a sentence (the group endorsement), so it
   is always underlined to read as a link. */
.tdup-footer__brand p a { color: var(--tdup-white); text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
.tdup-footer__brand p a:hover { text-decoration-thickness: 3px; }
.tdup-footer__contact { list-style: none; margin: 0 0 18px; padding: 0; display: flex; flex-direction: column; gap: 4px; font-size: 15px; }
.tdup-footer__contact li { display: flex; align-items: center; gap: 10px; min-height: 44px; }
.tdup-footer__contact li:first-child { align-items: flex-start; padding-top: 10px; }
.tdup-footer__contact svg { color: var(--tdup-white); flex-shrink: 0; }
.tdup-footer__contact li:first-child svg { margin-top: 3px; }
.tdup-footer__contact a { display: inline-flex; align-items: center; min-height: 44px; overflow-wrap: anywhere; }
.tdup-footer__social { display: flex; gap: 8px; }
.tdup-footer__social a { width: 44px; height: 44px; background: rgba(255, 255, 255, 0.1); display: flex; align-items: center; justify-content: center; color: var(--tdup-white); }
.tdup-footer__social a:hover { background: var(--tdup-red); color: var(--tdup-white); text-decoration: none; }
.tdup-footer-nav ul { list-style: none; display: flex; flex-direction: column; gap: 0; margin: 0; padding: 0; font-size: 15px; }
.tdup-footer-nav a { display: inline-flex; align-items: center; min-height: 44px; }
/* Column headings: the label style (expanded caps, tracked), with a hairline. */
/* h2 since 2026-11-10 (was h4, which skipped heading levels); line-height and colour set here so global h2 styles don't leak in. */
.tdup-footer-nav h2, .tdup-footer__col h2 {
	line-height: 1.4; text-wrap: wrap;
	margin: 0 0 6px; padding-bottom: 14px; border-bottom: 1px solid rgba(255, 255, 255, 0.22);
	color: var(--tdup-white); font-family: var(--tdup-font-title); font-stretch: 125%;
	font-size: 12px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase;
}
.tdup-footer__badges { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; font-size: 15px; }
.tdup-footer__badges li { display: flex; align-items: center; gap: 8px; min-height: 44px; color: rgba(255, 255, 255, 0.9); }
.tdup-footer__badges svg { color: var(--tdup-white); flex-shrink: 0; }
.tdup-footer__bottom { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 4px 24px; border-top: 1px solid rgba(255, 255, 255, 0.22); padding-top: 12px; padding-bottom: 12px; font-size: 14px; } /* top/bottom only: also a .tdup-container, see .tdup-footer__grid */
.tdup-footer__copyright { margin: 0; color: rgba(255, 255, 255, 0.8); }
.tdup-footer__legal { display: flex; flex-wrap: wrap; gap: 0 24px; margin-left: auto; }
.tdup-footer__legal a { display: inline-flex; align-items: center; min-height: 44px; }
/* Company details line (registered number, office, VAT). White at 78% on the ink footer is about 9:1, well above the 4.5:1 WCAG minimum. */
.tdup-footer__company { margin: 0; padding-top: 0; padding-bottom: 24px; font-size: 13px; line-height: 1.55; max-width: 120ch; color: rgba(255, 255, 255, 0.78); }
.tdup-footer__totop { display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; background: rgba(255, 255, 255, 0.1); border: 0; color: var(--tdup-white); cursor: pointer; }
.tdup-footer__totop:hover { background: var(--tdup-red); }
@media (max-width: 1000px) {
	.tdup-footer__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.tdup-footer__brand { grid-column: 1 / -1; }
}
@media (max-width: 560px) {
	.tdup-footer__grid { grid-template-columns: 1fr; padding-top: 52px; }
	.tdup-footer::after { width: 70%; }
	.tdup-footer::before { width: 60%; }
	.tdup-footer__legal { margin-left: 0; }
}

/* ==========================================================================
   5. Page hero / breadcrumbs
   The inner-page header band (tdup_page_hero() in inc/page-layout.php) is
   styled in "Inner pages: shared system" at the end of this file. Only the
   plain breadcrumb trail used on LIGHT backgrounds lives here.
   ========================================================================== */
/* Spacing the old header band used to supply with its own bottom margin, for
   pages whose content starts straight after it (old-style templates). */
.tdup-page-hero + .tdup-page { padding-top: 32px; }
/* Technical Resources follows the header with another full-bleed band (the
   "Download the full Product Guide" cta-band, the first thing inside <main
   class="tdup-page">); between two flush colour bands the extra top padding
   just shows as a pale gap. Scoped to that exact adjacency. */
.tdup-page-hero + .tdup-page > .tdup-cta-band:first-child { margin-top: -32px; }
.tdup-breadcrumbs { font-size: 13px; color: var(--tdup-body-grey); margin-bottom: 12px; }
.tdup-breadcrumbs a { color: var(--tdup-charcoal); text-decoration: underline; text-decoration-color: var(--tdup-rule); text-underline-offset: 3px; }
.tdup-breadcrumbs a:hover { color: var(--tdup-charcoal); text-decoration-color: currentColor; text-decoration-thickness: 2px; }

/* ==========================================================================
   6. Homepage
   ========================================================================== */
/* Section headings (.tdup-section-heading) moved to "2b. Design system"
   above, since inner pages use them too. */


/* Stat cards — no longer used on the homepage (its numbers moved into the
   hero's .tdup-figure-row). Kept only because the About page still uses
   them; they'll be replaced by .tdup-figure-row there too in the inner-page
   pass, and this block deleted then. */
.tdup-stats__item {
	background: var(--tdup-white); border: 1px solid var(--tdup-border); box-shadow: 0 16px 34px rgba(68, 72, 75, 0.1);
	padding: 22px 30px; margin: 0 -14px 20px 0; position: relative; z-index: 1;
	display: flex; flex-direction: column; gap: 4px;
	transition: background var(--tdup-transition);
}
.tdup-stats__item:nth-child(2) { transform: rotate(-1deg); z-index: 2; }
.tdup-stats__item:nth-child(3) { transform: rotate(0.8deg); }
.tdup-stats__item:nth-child(4) { transform: rotate(-0.6deg); }
/* Three-selector overrides so the scroll-reveal's own transform reset
   (.tdup-fade-in.is-visible, later in the file, same specificity as a
   two-selector rule) can't flatten the rotation above. */
.tdup-stats__item.is-visible:nth-child(2) { transform: rotate(-1deg); }
.tdup-stats__item.is-visible:nth-child(3) { transform: rotate(0.8deg); }
.tdup-stats__item.is-visible:nth-child(4) { transform: rotate(-0.6deg); }
.tdup-stats__item:hover { background: var(--tdup-off-white); }
.tdup-stats__number { font-family: var(--tdup-font-title); font-weight: 700; font-size: clamp(1.5rem, 3.2vw, 2.4rem); color: var(--tdup-charcoal); font-variant-numeric: tabular-nums; white-space: nowrap; }
.tdup-stats__label { font-size: 11px; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase; color: var(--tdup-mid-grey); }

/* Section heading, inline variant (homepage, 2026-11-02): the same logo
   lockup (H2, hairline, one sentence) but with the "view all" link on the
   right of the heading row instead of on its own line, which saves about
   40px per section on a page with nine of them. Stacks again on phones. */
.tdup-section-heading--inline { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 24px; align-items: end; margin-bottom: 20px; }
.tdup-section-heading--inline h2 { grid-column: 1 / -1; }
.tdup-section-heading--inline > p:not(.tdup-eyebrow) { grid-column: 1; margin-top: 12px; max-width: 76ch; }
.tdup-section-heading--inline > .tdup-text-link { grid-column: 2; grid-row: 2; justify-self: end; margin-top: 12px; }
/* A heading with just a link and no sentence: the link sits on the H2's row. */
.tdup-section-heading--inline > h2:first-child + .tdup-text-link { grid-column: 2; grid-row: 1; align-self: center; margin: 0 0 14px; }
.tdup-section-heading--inline:has(> h2 + .tdup-text-link) h2 { grid-column: 1; }
@media (max-width: 700px) {
	.tdup-section-heading--inline { grid-template-columns: 1fr; }
	.tdup-section-heading--inline > .tdup-text-link,
	.tdup-section-heading--inline > h2:first-child + .tdup-text-link { grid-column: 1; grid-row: auto; justify-self: start; margin: 12px 0 0; }
	.tdup-section-heading--inline:has(> h2 + .tdup-text-link) h2 { grid-column: 1; }
}


/* The heading sits in its own .tdup-container (front-page.php); the tile
   wall below it deliberately runs full width. */
.tdup-categories { padding: clamp(40px, 5vw, 56px) 0 0; }

/* Products archive landing view (archive-tdup_product.php) — categories
   as the primary, largest content (Baymard: subcategory nav must be the
   first, most prominent thing on a category page), a small "Featured
   This Month" strip clearly secondary beneath. Photography grounded with
   a real drop-shadow (reads the image's own alpha channel, so the
   shadow follows the actual product silhouette) instead of floating
   shadowless on a plain background — a background-removed product with
   no shadow beneath it reads as amateurish, and this theme's product
   photography already has real transparency to work with. Images sized
   to fill most of their card (not a small thumbnail with heavy padding)
   — see tdup_render_product_photo() in functions.php for the full
   reasoning and history of what didn't work before this. */
.tdup-products-landing { padding-top: 44px; padding-bottom: 50px; } /* top/bottom only: also a .tdup-container, see .tdup-footer__grid */
.tdup-products-landing__head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 22px; }
.tdup-products-landing__head h3 { font-family: var(--tdup-font-title); font-weight: 700; font-size: clamp(1.3rem, 3vw, 1.8rem); margin: 0; color: var(--tdup-charcoal); }
.tdup-products-landing__head a { font-weight: 700; font-size: 13px; letter-spacing: 0.04em; color: var(--tdup-red); border-bottom: 2px solid var(--tdup-red); padding-bottom: 2px; white-space: nowrap; }
.tdup-products-landing__head a:hover { color: var(--tdup-red-dark); border-color: var(--tdup-red-dark); }

/* 4 columns (2026-10-02, per client feedback): 7 categories sit in two rows. */
.tdup-photo-card__stage--empty { color: var(--tdup-mid-grey); font-size: 10.5px; font-style: italic; }

/* ==========================================================================
   Products landing: load-class lens + drawing-sheet range cards
   (see tdup_render_category_cards() in functions.php for the reasoning).
   ========================================================================== */
.tdup-lens { margin-bottom: 22px; padding: 16px 0 18px; border-top: 1px solid var(--tdup-border); border-bottom: 1px solid var(--tdup-border); }
.tdup-lens__label { margin: 0 0 12px; font: 700 12px/1.3 var(--tdup-font-title); text-transform: uppercase; letter-spacing: 0.06em; color: var(--tdup-charcoal); }
.tdup-lens__label span { margin-left: 8px; font: 400 13px/1.3 var(--tdup-font-body); text-transform: none; letter-spacing: 0; color: var(--tdup-mid-grey); }
.tdup-lens__buttons { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.tdup-lens__button { display: inline-flex; align-items: baseline; gap: 8px; padding: 9px 14px; background: var(--tdup-white); border: 1px solid var(--tdup-charcoal); color: var(--tdup-charcoal); font: inherit; cursor: pointer; transition: background var(--tdup-transition), color var(--tdup-transition); }
.tdup-lens__button b { font: 700 15px/1 var(--tdup-font-title); }
.tdup-lens__button span { font-size: 12px; }
.tdup-lens__button:hover { background: var(--tdup-off-white); }
.tdup-lens__button[aria-pressed="true"] { background: var(--tdup-charcoal); color: var(--tdup-white); }
.tdup-lens__button:focus-visible, .tdup-lens__reset:focus-visible { outline: 3px solid var(--tdup-red); outline-offset: 2px; }
.tdup-lens__reset { background: none; border: 0; padding: 9px 6px; font: 700 13px/1 var(--tdup-font-body); color: var(--tdup-red); text-decoration: underline; cursor: pointer; }
.tdup-lens__reset[hidden] { display: none; }

/* 2 per row, bigger and bolder, as Chris Corbett asked on 2026-09-16. */
.tdup-range-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
.tdup-range-card { position: relative; display: flex; flex-direction: column; background: var(--tdup-white); border: 1px solid var(--tdup-border); padding: 16px 16px 16px; transition: border-color var(--tdup-transition), background var(--tdup-transition); }
.tdup-range-card:hover, .tdup-range-card:focus-within { border-color: var(--tdup-charcoal); }
.tdup-range-card__link { display: flex; flex-direction: column; color: inherit; text-decoration: none; }
/* The whole card is clickable; the sub-category links below sit above this layer. */
.tdup-range-card__link::after { content: ''; position: absolute; inset: 0; }
.tdup-range-card__link:focus-visible { outline: none; }
.tdup-range-card__link:focus-visible::after { outline: 3px solid var(--tdup-red); outline-offset: -3px; }
.tdup-range-card__ref { margin-bottom: 10px; font: 700 10.5px/1 var(--tdup-font-title); letter-spacing: 0.1em; text-transform: uppercase; color: var(--tdup-red); }
.tdup-range-card__stage { position: relative; aspect-ratio: 4 / 3; }
/* Positioned out of flow so the photo's own size can never stretch the card.
   multiply lets a photo that still has a white background sit on the card
   instead of showing as a white box. */
.tdup-range-card__stage img { position: absolute; inset: 0; margin: auto; max-width: 80%; max-height: 80%; width: auto; height: auto; object-fit: contain; mix-blend-mode: multiply; filter: drop-shadow(0 12px 10px rgba(0, 0, 0, 0.18)); transition: transform 0.35s ease, filter 0.35s ease; }
.tdup-range-card__nophoto { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 11px; font-style: italic; color: var(--tdup-mid-grey); }
/* Corner registration ticks, like the marks on a drawing sheet: they sit just
   inside the photo area and open out to the edge, turning red, on hover/focus. */
.tdup-range-card__stage::before {
	content: ''; position: absolute; inset: 0; pointer-events: none; transform: scale(0.93); transition: transform 0.3s ease;
	--tick: 14px; --line: 1.5px; --colour: var(--tdup-charcoal);
	background:
		linear-gradient(var(--colour), var(--colour)) top left / var(--tick) var(--line) no-repeat,
		linear-gradient(var(--colour), var(--colour)) top left / var(--line) var(--tick) no-repeat,
		linear-gradient(var(--colour), var(--colour)) top right / var(--tick) var(--line) no-repeat,
		linear-gradient(var(--colour), var(--colour)) top right / var(--line) var(--tick) no-repeat,
		linear-gradient(var(--colour), var(--colour)) bottom left / var(--tick) var(--line) no-repeat,
		linear-gradient(var(--colour), var(--colour)) bottom left / var(--line) var(--tick) no-repeat,
		linear-gradient(var(--colour), var(--colour)) bottom right / var(--tick) var(--line) no-repeat,
		linear-gradient(var(--colour), var(--colour)) bottom right / var(--line) var(--tick) no-repeat;
}
.tdup-range-card:hover .tdup-range-card__stage::before, .tdup-range-card:focus-within .tdup-range-card__stage::before { transform: scale(1); --colour: var(--tdup-red); }
.tdup-range-card:hover .tdup-range-card__stage img, .tdup-range-card:focus-within .tdup-range-card__stage img { transform: translateY(-3px) scale(1.04); }
.tdup-range-card__name { margin-top: 14px; font: 700 clamp(20px, 2.2vw, 28px)/1.15 var(--tdup-font-title); text-transform: uppercase; color: var(--tdup-charcoal); }
.tdup-range-card__arrow { display: inline-block; opacity: 0; transform: translateX(-6px); transition: opacity var(--tdup-transition), transform var(--tdup-transition); }
.tdup-range-card:hover .tdup-range-card__arrow, .tdup-range-card:focus-within .tdup-range-card__arrow { opacity: 1; transform: translateX(0); }
.tdup-range-card__meta { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 4px 12px; margin: 8px 0 0; font-size: 12px; color: var(--tdup-mid-grey); }
.tdup-range-card__meta b { color: var(--tdup-red); }
.tdup-range-card__classes { font-weight: 700; letter-spacing: 0.02em; }
.tdup-range-card__subs { position: relative; z-index: 2; display: flex; flex-wrap: wrap; gap: 6px; margin: 12px 0 0; padding: 0; list-style: none; }
.tdup-range-card__subs a { display: inline-block; padding: 4px 9px; border: 1px solid var(--tdup-border); font-size: 11.5px; font-weight: 700; color: var(--tdup-charcoal); text-decoration: none; transition: border-color var(--tdup-transition), color var(--tdup-transition); }
.tdup-range-card__subs a:hover, .tdup-range-card__subs a:focus-visible { border-color: var(--tdup-red); color: var(--tdup-red); }
.tdup-range-card__match { margin: 10px 0 0; font: 700 11px/1.3 var(--tdup-font-title); text-transform: uppercase; letter-spacing: 0.06em; }
.tdup-range-card__match[hidden] { display: none; }
.tdup-range-card--empty .tdup-range-card__name { color: var(--tdup-mid-grey); }
/* Lens states. Text states ("available" / "no products") carry the meaning; the
   styling below only reinforces it, and text keeps its full contrast. */
.tdup-range-card.is-match { border-color: var(--tdup-red); }
.tdup-range-card.is-match .tdup-range-card__match { color: var(--tdup-red); }
.tdup-range-card.is-dim { background: var(--tdup-off-white); }
.tdup-range-card.is-dim .tdup-range-card__stage img { filter: grayscale(1) opacity(0.5); }
.tdup-range-card.is-dim .tdup-range-card__match { color: var(--tdup-charcoal); }
@media (max-width: 420px) { .tdup-range-grid { grid-template-columns: 1fr; } .tdup-lens__button span { display: none; } }
@media (prefers-reduced-motion: reduce) {
	.tdup-range-card__stage::before, .tdup-range-card__stage img, .tdup-range-card__arrow { transition: none; }
	.tdup-range-card:hover .tdup-range-card__stage img, .tdup-range-card:focus-within .tdup-range-card__stage img { transform: none; }
}

/* Secondary strip — deliberately small and visually distinct from the
   category grid above (Baymard: a curated section must never carry
   equal weight with navigation). */
.tdup-featured-strip { display: flex; align-items: center; gap: 16px; margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--tdup-border); flex-wrap: wrap; }
.tdup-featured-strip__label { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--tdup-mid-grey); white-space: nowrap; }
.tdup-featured-strip__items { display: flex; gap: 10px; flex-wrap: wrap; }
.tdup-featured-strip__item { display: flex; align-items: center; gap: 10px; background: #fff; border: 1px solid var(--tdup-border); padding: 6px 14px 6px 6px; transition: border-color .15s; }
.tdup-featured-strip__item:hover { border-color: var(--tdup-red); }
.tdup-featured-strip__img { width: 44px; height: 44px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; }
.tdup-featured-strip__img img { width: 100%; height: 100%; object-fit: contain; filter: drop-shadow(0 5px 4px rgba(0,0,0,0.18)); }
.tdup-featured-strip__item span { font-size: 11.5px; font-weight: 700; color: var(--tdup-charcoal); }

@media (max-width: 760px) {
}
@media (max-width: 480px) {
	.tdup-products-landing__head, .tdup-featured-strip { padding-left: 0; padding-right: 0; }
	.tdup-featured-strip { flex-direction: column; align-items: flex-start; }
}
/* Redesigned 2026-09-10 — an "anti-slip tile wall": the literal checker-
   plate/anti-slip texture cast into a real grating surface, tessellated
   edge-to-edge with zero gaps, instead of a bordered card grid with gutters
   between cards. Deliberately breaks out of .tdup-container to run full
   width — tessellation reads as fake if it stops short of the viewport
   edge. Which category gets the large 2x2 tile is computed from each
   term's own real `$term->count` in front-page.php (highest product count
   wins) rather than a fixed category name — this is genuine catalogue-
   depth data, not a hardcoded "featured" pick. */
/* Homepage category grid (reworked 2026-10-13).
   - Sits inside the page's content column, so its edges line up with the
     heading above and every other section. It used to run edge to edge
     while the rest of the page didn't, which looked out of place.
   - 4 per row: 8 categories make 2 tidy rows. (Chris Corbett's "2 per line,
     bigger/bolder" request of 2026-09-16 was about the PRODUCTS page
     categories, see .tdup-range-grid, and was wrongly applied here on
     2026-10-08.)
   - Dense, content-forward tiles: the product photo fills the top of the
     tile at a fixed height, with name and count underneath, small padding,
     and hairline rules between tiles. Every tile has the same structure, so
     names line up across the row.
   Baymard: category tiles should show what's inside, in a consistent style,
   and be the first thing after the hero. */
.tdup-categories__wall { margin-top: 4px; }
.tdup-categories__grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); border-top: 1px solid var(--tdup-charcoal); border-left: 1px solid var(--tdup-charcoal); }
.tdup-categories__card {
	position: relative; display: flex; flex-direction: column;
	padding: 0 16px 16px; border-right: 1px solid var(--tdup-charcoal); border-bottom: 1px solid var(--tdup-charcoal);
	background: var(--tdup-white); color: var(--tdup-charcoal);
	transition: background var(--tdup-transition), color var(--tdup-transition);
}
/* Hover (changed 2026-10-13, Chris disliked the dark fill): a red inner
   outline, the name turns red and the arrow slides in. The photo zooms
   slightly. Nothing changes colour behind the photo. */
.tdup-categories__card:hover, .tdup-categories__card:focus-visible { box-shadow: inset 0 0 0 2px var(--tdup-red); outline: none; }
.tdup-categories__card:hover .tdup-categories__card-label, .tdup-categories__card:focus-visible .tdup-categories__card-label { color: var(--tdup-red); }
/* Photo area: fixed height (capped, so it never grows with the screen), the
   photo filling most of it. */
.tdup-categories__card-image {
	height: clamp(140px, 13vw, 190px); margin: 0 -16px 12px; overflow: hidden;
	display: flex; align-items: center; justify-content: center;
	background-image: radial-gradient(circle, rgba(68, 72, 75, 0.07) 1px, transparent 1.3px); background-size: 14px 14px;
}
/* multiply blends any white photo background into the tile, so it never
   shows as a white box on the dark hover state. */
.tdup-categories__card-image img { max-width: 84%; max-height: 86%; width: auto; height: auto; object-fit: contain; mix-blend-mode: multiply; transition: transform var(--tdup-transition-slow); }
.tdup-categories__card:hover .tdup-categories__card-image img { transform: scale(1.06); }
.tdup-categories__card-image--empty { flex-direction: column; gap: 8px; color: var(--tdup-mid-grey); font-size: 11px; font-style: italic; }
.tdup-categories__card-ref { font-size: 10.5px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--tdup-red); }
.tdup-categories__card-label { margin-top: 4px; font-family: var(--tdup-font-title); font-weight: 700; text-transform: uppercase; font-size: clamp(15px, 1.25vw, 18px); line-height: 1.15; color: var(--tdup-charcoal); }
.tdup-categories__card-arrow { display: inline-block; opacity: 0; transform: translateX(-6px); transition: all var(--tdup-transition); }
.tdup-categories__card:hover .tdup-categories__card-arrow { opacity: 1; transform: translateX(0); }
/* margin-top:auto pins the count to the bottom, so counts line up across a
   row even when one name wraps onto two lines. */
.tdup-categories__card-sku { margin-top: auto; padding-top: 8px; font-size: 11.5px; font-weight: 700; color: var(--tdup-mid-grey); }
.tdup-categories__card-sku b { color: var(--tdup-red); }
/* "All Products": a slim bar across the bottom of the grid. */
.tdup-categories__card--all { grid-column: span var(--tdup-all-span, 1); flex-direction: row; align-items: center; justify-content: center; padding: 16px; }
.tdup-categories__card--all .tdup-categories__card-label { margin-top: 0; font-size: 14px; }
@media (max-width: 900px) {
	.tdup-categories__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.tdup-categories__card-image { height: 120px; }
	.tdup-categories__card--all { grid-column: 1 / -1; }
}
@media (min-width: 901px) {
	/* Products page category cards: a shorter photo area (2 per row there). */
	.tdup-range-card__stage { aspect-ratio: 2 / 1; }
}

/* Sectors (homepage) — a two-column hairline list of big row links (name,
   real product count, arrow), replacing a loose cloud of outlined chips:
   denser, easy to scan down, and each whole row is the click target. The
   hairlines come from the list's top border plus each row's bottom one. */
.tdup-sectors { background: var(--tdup-white); padding: clamp(56px, 7vw, 88px) 0; border-top: 1px solid var(--tdup-border); }
.tdup-sector-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(24px, 4vw, 56px); }
.tdup-sector-list li { border-bottom: 1px solid var(--tdup-border); }
.tdup-sector-list a {
	display: grid; grid-template-columns: 1fr auto 20px; align-items: center; gap: 16px;
	padding: 16px 4px; color: var(--tdup-charcoal);
}
.tdup-sector-list__name { font-family: var(--tdup-font-title); font-weight: 700; font-size: 15.5px; }
.tdup-sector-list__count { font-size: 12px; font-weight: 700; color: var(--tdup-mid-grey); white-space: nowrap; }
.tdup-sector-list svg { color: var(--tdup-red); transition: transform var(--tdup-transition); }
.tdup-sector-list a:hover { color: var(--tdup-red); }
.tdup-sector-list a:hover svg { transform: translateX(5px); }
@media (max-width: 700px) {
	.tdup-sector-list { grid-template-columns: 1fr; }
}

.tdup-popular-products { padding: clamp(56px, 7vw, 88px) 0; }
/* Popular Products as a carousel rather than a static grid — there are far
   more real SKUs than fit a 4-up grid. Native scroll-snap (not a
   reimplemented slider), so it stays swipeable by touch/trackpad for
   free; the arrows and auto-advance (initProductCarousel() in the JS
   file) just nudge that same native scroll position. Reuses
   .tdup-product-card as-is — only the track around it is new. */
.tdup-carousel__track { display: flex; gap: 20px; overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth; padding-bottom: 6px; scrollbar-width: none; }
.tdup-carousel__track::-webkit-scrollbar { display: none; }
.tdup-carousel__track .tdup-product-card { scroll-snap-align: start; flex: 0 0 260px; }
/* The product photo zooms slightly on hover. (The card itself no longer
   lifts or casts a shadow — flat hover, 2026-09-25.) */
.tdup-carousel__track .tdup-product-card__image img { transition: transform var(--tdup-transition-slow); }
.tdup-carousel__track .tdup-product-card:hover .tdup-product-card__image img { transform: scale(1.08); }
.tdup-carousel__nav { display: flex; align-items: center; gap: 14px; }
.tdup-carousel__arrows { display: flex; gap: 8px; }
.tdup-carousel__arrow { width: 38px; height: 38px; border: 1px solid var(--tdup-charcoal); background: var(--tdup-white); display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all var(--tdup-transition); color: var(--tdup-charcoal); }
.tdup-carousel__arrow:hover { background: var(--tdup-charcoal); color: var(--tdup-white); border-color: var(--tdup-charcoal); }
.tdup-carousel__arrow--prev svg { transform: scaleX(-1); }


.tdup-video-slot { padding: 0 0 72px; }
.tdup-video-slot__frame {
	position: relative; height: 340px; border-radius: var(--tdup-radius); overflow: hidden;
	display: flex;
}
/* The thumbnail lives on its own element (not the frame's own
   background), so it — and only it — can scale on hover while the frame
   itself stays a fixed clipping box, matching the mockup's <img>-based
   zoom rather than trying to animate background-size directly. */
.tdup-video-slot__bg { position: absolute; inset: 0; background-size: cover; background-position: center; transition: transform var(--tdup-transition-slow); }
.tdup-video-slot__frame:hover .tdup-video-slot__bg { transform: scale(1.03); }
.tdup-video-slot__overlay { position: absolute; inset: 0; background: rgba(20,21,22,0.45); }
.tdup-video-slot__content { position: relative; margin: auto; display: flex; flex-direction: column; align-items: center; gap: 16px; text-align: center; padding: 20px; }
/* Frosted glass (needs the video thumbnail behind it to read) plus a
   pulsing ring — the file's first @keyframes block; nothing else in this
   stylesheet animates continuously like this yet. */
.tdup-video-slot__play {
	position: relative; width: 76px; height: 76px; border-radius: 50%;
	background: rgba(255, 255, 255, 0.22); backdrop-filter: blur(12px) saturate(180%); -webkit-backdrop-filter: blur(12px) saturate(180%);
	border: 1px solid rgba(255, 255, 255, 0.5); color: var(--tdup-white);
	display: flex; align-items: center; justify-content: center;
	transition: transform var(--tdup-transition), background var(--tdup-transition);
}
.tdup-video-slot__frame:hover .tdup-video-slot__play { transform: scale(1.08); background: rgba(255, 255, 255, 0.32); }
.tdup-video-slot__play::before { content: ''; position: absolute; inset: -14px; border-radius: 50%; border: 1px solid rgba(255, 255, 255, 0.35); animation: tdup-pulse-ring 2.6s ease-out infinite; }
@keyframes tdup-pulse-ring {
	0% { transform: scale(0.9); opacity: 0.8; }
	100% { transform: scale(1.35); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
	.tdup-video-slot__play::before { animation: none; display: none; }
}
.tdup-video-slot__title { font-family: var(--tdup-font-title); font-weight: 700; font-size: 18px; color: var(--tdup-white); }
.tdup-video-slot__placeholder { font-size: 13px; color: rgba(255,255,255,0.75); font-style: italic; }

/* Page background, between the white sectors band and the dark closing
   band: light sections alternate between the page background and pure
   white only, never a third, slightly different grey. */
.tdup-latest-news { padding: clamp(56px, 7vw, 88px) 0; }
/* Nothing published yet — a full-height band around one sentence read as
   an accidental gap, so this state gets its own tighter, framed treatment
   instead of inheriting the padding sized for a 3-up news grid. */
.tdup-latest-news--empty { padding: 40px 0 56px; }

/* Shared "nothing here yet" component — used anywhere content genuinely
   doesn't exist yet (no news posts, no products matching a filter, a
   fallback 404/index view), so every such state looks like one deliberate
   pattern site-wide instead of a mix of styled boxes and bare <p> tags. */
.tdup-empty-state {
	display: flex; flex-direction: column; align-items: center; gap: 10px; text-align: center;
	max-width: 400px; margin: 0 auto; padding: 32px 24px; background: var(--tdup-white);
	border: 1px dashed #C7CBCD; border-radius: var(--tdup-radius); color: var(--tdup-mid-grey);
}
.tdup-empty-state p { margin: 0; font-size: 14px; }
.tdup-empty-state .tdup-button { margin-top: 6px; }
/* Default background is white, which reads as a card on the off-white
   .tdup-latest-news band it was designed for — but on a plain white page
   or product-listing grid a white box would disappear into the page, so
   those two contexts get the off-white surface colour instead. */
.tdup-product-listing__grid .tdup-empty-state,
.tdup-page .tdup-empty-state { background: var(--tdup-off-white); grid-column: 1 / -1; }


/* ==========================================================================
   7. Product listing (archive / taxonomy / search)
   ========================================================================== */
.tdup-product-listing { display: grid; grid-template-columns: 240px 1fr; gap: 32px; padding-bottom: 60px; flex: 1; }
.tdup-filters { background: var(--tdup-off-white); border-radius: var(--tdup-radius); padding: 18px; }
.tdup-filters fieldset { border: none; padding: 0; margin: 0 0 20px; }
.tdup-filters fieldset:last-of-type { margin-bottom: 16px; }
.tdup-filters legend { font-family: var(--tdup-font-title); font-weight: 700; font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--tdup-mid-grey); margin-bottom: 10px; padding: 0; }
.tdup-filters label { display: flex; align-items: center; font-size: 14px; margin-bottom: 10px; color: var(--tdup-charcoal); cursor: pointer; }
/* Custom checkbox — native OS checkboxes (blue square, system-drawn tick)
   read as generic/unbranded next to the rest of the site. appearance:none
   drops the native rendering entirely; the tick itself is a clip-path
   shape (no image/SVG needed) that scales in on check, animated instead of
   just popping — see the "15. Animations" comment for why hover/check
   transitions like this stay outside the reduced-motion gate. */
.tdup-filters input[type="checkbox"] {
	appearance: none;
	-webkit-appearance: none;
	width: 18px;
	height: 18px;
	flex-shrink: 0;
	margin: 0 10px 0 0;
	border: 1.5px solid var(--tdup-mid-grey);
	border-radius: 4px;
	background: var(--tdup-white);
	display: inline-grid;
	place-content: center;
	cursor: pointer;
	transition: border-color var(--tdup-transition), background var(--tdup-transition);
}
.tdup-filters input[type="checkbox"]::before {
	content: "";
	width: 10px;
	height: 10px;
	transform: scale(0);
	transition: transform 0.15s ease-in-out;
	box-shadow: inset 1em 1em var(--tdup-white);
	clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
}
.tdup-filters input[type="checkbox"]:checked {
	background: var(--tdup-red);
	border-color: var(--tdup-red);
}
.tdup-filters input[type="checkbox"]:checked::before { transform: scale(1); }
.tdup-filters input[type="checkbox"]:hover { border-color: var(--tdup-red); }
.tdup-filters input[type="checkbox"]:focus-visible { outline: 2px solid var(--tdup-red); outline-offset: 2px; }
.tdup-filters label:hover { color: var(--tdup-red); }
.tdup-filters input[type="checkbox"]:disabled { opacity: 0.45; cursor: default; }
.tdup-filters input[type="checkbox"]:disabled:hover { border-color: var(--tdup-mid-grey); }
/* A term with 0 products (e.g. "Domestic" right now) — shown rather than
   hidden, so this list stays consistent with the homepage's category grid
   (which shows every category regardless of product count), but disabled
   and visibly greyed since checking it would only ever return nothing. */
.tdup-filters__empty-term { color: var(--tdup-mid-grey); cursor: default; }
.tdup-filters__empty-term:hover { color: var(--tdup-mid-grey); }
.tdup-filters__empty-term span { font-size: 12px; }
/* The one hierarchical sub-category relationship (Boundary Boxes under
   Surface Boxes — see tdup_render_filter_sidebar() in functions.php),
   shown as a plain indent rather than a nested <fieldset>: still a flat
   checkbox list underneath, just visually grouped under its real parent. */
.tdup-filters__child-term { padding-left: 22px; }
.tdup-filters .tdup-button { width: 100%; }
/* Exact mockup values (.bespoke-callout/.plate-base) — sits below "Apply
   Filters" (see tdup_render_filter_sidebar()), not above it, and its
   heading is bold uppercase like every other small heading in this
   design, not plain title-case text. */
.tdup-filters__bespoke { background: var(--tdup-white); border: 1px solid var(--tdup-border); box-shadow: 0 12px 26px rgba(68, 72, 75, 0.1); padding: 18px; display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }
.tdup-filters__bespoke-title { font-family: var(--tdup-font-title); font-weight: 700; text-transform: uppercase; font-size: 13px; color: var(--tdup-charcoal); }
.tdup-filters__bespoke-text { font-size: 12.5px; color: var(--tdup-body-grey); line-height: 1.5; }
.tdup-filters__bespoke a { font-size: 12.5px; font-weight: 700; color: var(--tdup-red); }

/* ==========================================================================
   7a. Collapsible filter groups
   A native <details>/<summary> per taxonomy (see tdup_render_filter_sidebar())
   instead of a JS-built accordion, so collapse/expand keeps working with
   JavaScript disabled — the browser handles open/closed on its own; this
   just adds a rotating chevron and a soft fade-in on top of that.
   ========================================================================== */
.tdup-filter-group { border-bottom: 1px solid var(--tdup-border); }
.tdup-filter-group:last-of-type { border-bottom: none; }
.tdup-filter-group__summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	list-style: none; /* hides Chrome/Safari's default triangle marker */
	cursor: pointer;
	padding: 14px 2px;
	font-family: var(--tdup-font-title);
	font-weight: 700;
	font-size: 11.5px;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--tdup-charcoal);
	transition: color var(--tdup-transition);
}
.tdup-filter-group__summary::-webkit-details-marker { display: none; } /* Safari's own marker */
.tdup-filter-group__summary:hover { color: var(--tdup-red); }
.tdup-filter-group__summary svg { flex-shrink: 0; transition: transform 0.2s ease; }
.tdup-filter-group[open] .tdup-filter-group__summary svg { transform: rotate(90deg); }
/* Overrides the generic ".tdup-filters fieldset" spacing above — this
   fieldset sits inside a <details> panel now, so the <details> itself
   (not the fieldset) owns the spacing between groups. */
.tdup-filters .tdup-filter-group__panel { margin: 0; padding: 0 2px 16px; }
@media (prefers-reduced-motion: no-preference) {
	/* Replays automatically every time a group's content goes from "not
	   rendered" (closed) to rendered (open) — no JS trigger needed. */
	.tdup-filter-group[open] .tdup-filter-group__panel { animation: tdup-filter-panel-in 0.2s ease; }
	@keyframes tdup-filter-panel-in {
		from { opacity: 0; transform: translateY(-4px); }
		to { opacity: 1; transform: translateY(0); }
	}
}

.tdup-active-filters { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 20px; }
.tdup-active-filters .tdup-chip { font-size: 12px; padding: 6px 10px; }

.tdup-product-listing__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 20px; align-content: start; }
.tdup-product-listing__grid--four { grid-template-columns: repeat(4, minmax(0, 1fr)); }

.tdup-bespoke-callout {
	background: var(--tdup-off-white); border: 1px dashed #C7CBCD; border-radius: var(--tdup-radius);
	padding: 20px 24px; display: flex; align-items: center; justify-content: space-between; gap: 24px;
	margin-top: 24px; flex-wrap: wrap;
}
.tdup-bespoke-callout__title { display: block; font-family: var(--tdup-font-title); font-weight: 700; font-size: 15px; color: var(--tdup-charcoal); }
.tdup-bespoke-callout__text { display: block; font-size: 13px; line-height: 1.5; }

/* WordPress's default the_posts_pagination() markup — a plain nav with
   .page-numbers links/spans — had no styling at all until now, which is
   why it rendered as bare underlined browser-default links. */
.pagination { margin-top: 32px; }
.pagination .nav-links { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.pagination .page-numbers {
	display: inline-flex; align-items: center; justify-content: center;
	min-width: 36px; height: 36px; padding: 0 10px;
	border: 1px solid var(--tdup-border); border-radius: var(--tdup-radius-sm);
	font-family: var(--tdup-font-title); font-weight: 600; font-size: 14px;
	color: var(--tdup-charcoal);
}
.pagination a.page-numbers:hover { border-color: var(--tdup-red); color: var(--tdup-red); }
.pagination .page-numbers.current { background: var(--tdup-charcoal); border-color: var(--tdup-charcoal); color: var(--tdup-white); }
.pagination .page-numbers.dots { border: none; color: var(--tdup-mid-grey); }
/* "Go to page" jump — was in the ProductsArchive design canvas but missed
   on first implementation: with 367+ products the archive can run to
   dozens of pages, so a visitor who knows roughly where a product sits (or
   was handed a link to "page 14") shouldn't have to click Next thirteen
   times. tdup_posts_pagination() (functions.php) splices this in as the
   last child of .nav-links itself, so it's an extra item in the same flex
   row the page-number links already use, set apart with a divider. */
.pagination__jump { display: flex; align-items: center; gap: 8px; margin-left: 14px; padding-left: 14px; border-left: 1px solid var(--tdup-border); font-size: 13px; color: var(--tdup-mid-grey); }
.pagination__jump input { width: 52px; height: 36px; border: 1px solid var(--tdup-border); border-radius: var(--tdup-radius-sm); text-align: center; font-family: var(--tdup-font-title); font-weight: 700; font-size: 13px; color: var(--tdup-charcoal); }
.pagination__jump input:focus { outline: none; border-color: var(--tdup-charcoal); box-shadow: 0 0 0 3px rgba(68, 72, 75,0.12); }
.pagination__jump button { width: auto; height: 36px; padding: 0 14px; border: 1px solid var(--tdup-charcoal); border-radius: var(--tdup-radius-sm); background: var(--tdup-charcoal); color: var(--tdup-white); font-family: var(--tdup-font-title); font-weight: 700; font-size: 13px; cursor: pointer; transition: background .2s; }
.pagination__jump button:hover { background: #2d3031; }

.tdup-product-card { container: tdup-card / inline-size; position: relative; border: 1px solid var(--tdup-border); border-radius: var(--tdup-radius); display: flex; flex-direction: column; overflow: hidden; transition: border-color .15s, box-shadow .15s; }
/* Overlaid on the card's top-right corner — z-index above the image/link so
   it stays clickable without triggering the card's own <a> navigation
   (label + checkbox is its own focusable/clickable unit, separate from the
   card link underneath it). */
.tdup-compare-checkbox { position: absolute; top: 10px; right: 10px; z-index: 2; display: flex; align-items: center; gap: 5px; background: rgba(255,255,255,0.92); border: 1px solid var(--tdup-border); border-radius: var(--tdup-radius-sm); padding: 5px 9px; font-size: 11px; font-weight: 700; font-family: var(--tdup-font-title); color: var(--tdup-charcoal); cursor: pointer; }
/* Same custom-checkbox treatment as the filter sidebar (appearance:none +
   a clip-path tick, see ".tdup-filters input[type=checkbox]" above) —
   the native browser checkbox this used to fall back to rendered with
   the OS's own blue tick, which didn't match the brand's red anywhere
   else a checkbox appears on the site. Sized down slightly (14px vs the
   sidebar's 18px) to fit this compact corner badge. */
.tdup-compare-checkbox input[type="checkbox"] {
	appearance: none;
	-webkit-appearance: none;
	width: 14px;
	height: 14px;
	margin: 0;
	flex-shrink: 0;
	border: 1.5px solid var(--tdup-mid-grey);
	border-radius: 3px;
	background: var(--tdup-white);
	display: inline-grid;
	place-content: center;
	cursor: pointer;
	transition: border-color var(--tdup-transition), background var(--tdup-transition);
}
.tdup-compare-checkbox input[type="checkbox"]::before {
	content: "";
	width: 8px;
	height: 8px;
	transform: scale(0);
	transition: transform 0.15s ease-in-out;
	box-shadow: inset 1em 1em var(--tdup-white);
	clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
}
.tdup-compare-checkbox input[type="checkbox"]:checked {
	background: var(--tdup-red);
	border-color: var(--tdup-red);
}
.tdup-compare-checkbox input[type="checkbox"]:checked::before { transform: scale(1); }
.tdup-compare-checkbox:hover input[type="checkbox"] { border-color: var(--tdup-red); }
.tdup-compare-checkbox input[type="checkbox"]:focus-visible { outline: 2px solid var(--tdup-red); outline-offset: 2px; }
.tdup-product-card:hover { border-color: var(--tdup-red); }
.tdup-product-card__link { display: flex; flex-direction: column; flex: 1; color: inherit; }
/* Exact values from pages-product-flow.html's .pcard-image/.pcard-code/
   .pcard-name — this shared card is used across the Product Archive,
   Popular Products and related-products, so all three were rendering
   the plain untextured image, grey non-bold code and title-case name
   at once. */
.tdup-product-card__image { height: 150px; background-color: var(--tdup-off-white); background-image: repeating-linear-gradient(45deg, rgba(68, 72, 75, 0.04) 0 2px, transparent 2px 14px); display: flex; align-items: center; justify-content: center; }
.tdup-product-card__image img { max-height: 120px; width: auto; object-fit: contain; }
.tdup-product-card__body { padding: 14px 14px 0; display: flex; flex-direction: column; gap: 8px; flex: 1; }
.tdup-product-card h3 { font-weight: 700; font-size: 14px; margin: 0; line-height: 1.35; }
.tdup-product-card__code { font-size: 11px; font-weight: 700; color: var(--tdup-red); letter-spacing: 0.04em; }
.tdup-product-card .tdup-quick-add { margin: 12px 14px 14px; white-space: nowrap; }
/* In a narrow card (2-column phone grid) trim the button's width and padding
   so the label stays on one line. */
@container tdup-card (max-width: 220px) {
	.tdup-product-card .tdup-quick-add { padding-left: 6px; padding-right: 6px; font-stretch: 100%; letter-spacing: 0.06em; font-size: 12px; }
}
/* Datasheet / spec sheet link on product cards (2026-10-13). Sits just above
   the card's button; margin-top:auto pins it to the same height on every card
   in a row even when titles wrap differently. */
.tdup-product-card__download { display: inline-flex; align-items: center; gap: 6px; margin: auto 14px 0; padding-top: 10px; font-size: 12px; font-weight: 700; color: var(--tdup-red); text-decoration: none; }
.tdup-product-card__download:hover, .tdup-product-card__download:focus-visible { text-decoration: underline; color: var(--tdup-red-dark); }
.tdup-product-card__download + .tdup-quick-add { margin-top: 10px; }

/* ==========================================================================
   8. Single product
   ========================================================================== */
.tdup-product__layout { display: grid; grid-template-columns: 1fr 1fr; gap: 48px; padding-bottom: 60px; flex: 1; }
.tdup-product__gallery { display: flex; flex-direction: column; gap: 12px; align-self: start; }
/* Square + the anti-slip diamond texture, matching the mockup exactly —
   was a plain rectangle with no texture at all, and taller than wide when
   this used `aspect-ratio: 1` directly (a real photo's own natural
   width/height HTML attributes made the percentage max-height on the <img>
   below resolve against an indefinite reference in this flex/grid
   context, so the square never actually applied and the box stretched to
   whatever height the gallery column's other content forced). The
   padding-top:100% trick forces a genuinely square box regardless of
   parent layout mode — percentage padding always resolves against width,
   with no such ambiguity. */
.tdup-product__image { position: relative; width: 100%; background-color: var(--tdup-off-white); background-image: repeating-linear-gradient(45deg, rgba(68, 72, 75, 0.05) 0 2px, transparent 2px 14px); border: 1px solid var(--tdup-border); overflow: hidden; }
.tdup-product__image::before { content: ''; display: block; padding-top: 100%; }
.tdup-product__image img { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); max-width: 78%; max-height: 78%; width: auto; height: auto; object-fit: contain; }
.tdup-product__thumbnails { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; }
.tdup-product__thumbnail { height: 76px; background: var(--tdup-off-white); border: 1px solid var(--tdup-border); display: flex; align-items: center; justify-content: center; padding: 6px; overflow: hidden; }
.tdup-product__thumbnail img { max-width: 100%; max-height: 100%; object-fit: contain; }
.tdup-product__thumbnail--active { border-color: var(--tdup-charcoal); border-width: 2px; }
/* Thumbnails are real buttons (links without JS); every one is keyboard reachable. */
button.tdup-product__thumbnail { cursor: pointer; font: inherit; }
.tdup-product__thumbnail:focus-visible { outline: 2px solid var(--tdup-red); outline-offset: 2px; }
.tdup-product__thumbnails[hidden] { display: none; }
.tdup-product__image img { transition: opacity 0.25s ease; }
.tdup-product__image img.is-swapping { opacity: 0; }
@media (prefers-reduced-motion: reduce) { .tdup-product__image img { transition: none; } }
.tdup-product__top-row { display: flex; align-items: center; justify-content: space-between; }
/* Exact mockup values (.product-code/.product-layout h1) — the code is a
   bold red identifier, not muted grey text, and the title is the same
   heavy black uppercase treatment as every other big heading in this
   design, not the plain h1 default (font-weight: 700, no case transform,
   no size clamp). */
.tdup-product__code { font-size: 12.5px; font-weight: 700; letter-spacing: 0.04em; color: var(--tdup-red); }
.tdup-product__details h1 { font-weight: 600; text-transform: uppercase; font-size: clamp(1.5rem, 3vw, 2.1rem); margin-top: 6px;font-stretch: 125%; letter-spacing: 0.06em;}

/* Exact mockup values (table.spec) — a plain definition-list-style table
   (no card background/rounding, both columns left-aligned) with small
   uppercase tracked labels, not a shaded "boxed" table with right-aligned
   values. */
.tdup-spec-table { width: 100%; border-collapse: collapse; margin-top: 22px; }
.tdup-spec-table tr { border-bottom: 1px solid var(--tdup-border); }
.tdup-spec-table tr:last-child { border-bottom: none; }
.tdup-spec-table th, .tdup-spec-table td { text-align: left; padding: 9px 0; }
.tdup-spec-table th { font-weight: 700; font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--tdup-mid-grey); width: 40%; }
.tdup-spec-table td { font-weight: 700; font-size: 13.5px; color: var(--tdup-charcoal); }
.tdup-spec-table__row--empty { display: none; }

/* Every true feature flag gets its own line with a check mark, rather than
   the old single comma-separated "Features" row a real attribute (e.g.
   Locked) could get lost inside. */
.tdup-spec-checklist { list-style: none; margin: 16px 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 8px 16px; }
.tdup-spec-checklist li { display: flex; align-items: center; gap: 8px; font-weight: 700; font-size: 13.5px; color: var(--tdup-charcoal); }
.tdup-spec-checklist svg { flex-shrink: 0; color: var(--tdup-red); }

/* Exact mockup values (.option-group .label/.option) — the label is
   smaller/tighter-tracked, and the pill's resting border is charcoal
   (visibly outlined), not the near-invisible light grey --tdup-border. */
.tdup-product__options-label { display: block; font-family: var(--tdup-font-title); font-weight: 700; font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--tdup-mid-grey); margin-bottom: 10px; }
.tdup-option-list { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 24px; }
.tdup-option { position: relative; border: 1px solid var(--tdup-charcoal); border-radius: var(--tdup-radius-sm); padding: 8px 14px; cursor: pointer; font-size: 13px; font-weight: 700; transition: border-color var(--tdup-transition), background var(--tdup-transition), color var(--tdup-transition); }
.tdup-option:hover { border-color: var(--tdup-red); }
.tdup-option:has(input:checked) { border-color: var(--tdup-charcoal); background: var(--tdup-charcoal); color: var(--tdup-white); }
/* The pill's own border/background already fully communicates selection
   (see :has(input:checked) above), so the native radio dot next to the
   label text was pure clutter — visually hidden here (not display:none,
   which would break keyboard/screen-reader access), with a focus ring on
   the pill itself standing in for the native control's own focus outline. */
.tdup-option input {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}
.tdup-option:has(input:focus-visible) { outline: 2px solid var(--tdup-red); outline-offset: 2px; }

/* Exact mockup values (.doc-links/.doc-links a) — a plain inline row of
   red text links, not a bordered box of full-width list rows. */
.tdup-product__documents { margin-bottom: 24px; }
.tdup-product__documents .tdup-product__options-label { margin-bottom: 8px; }

/* Family product variant picker (see initVariantPicker() in
   td-utility-main.js) — Size/Depth/Shape/Marking reuse the existing
   .tdup-option-list/.tdup-option button styling as-is; only the
   independent feature toggles (Locked, Sealing, etc — not wrapped in a
   radiogroup list, just one checkbox each) and the two extra states
   below need their own rules. */
.tdup-product__options--toggle { margin-bottom: 16px; }
.tdup-product__options--toggle .tdup-option { display: inline-flex; }
.tdup-product__variant-tiebreak { margin-top: -8px; }
.tdup-product__variant-unavailable { font-size: 13px; color: var(--tdup-red); margin: -8px 0 20px; }
/* (Older markup, kept for products not re-imported since 2026-10-21; the
   optional extras are now one tick-box list, see initVariantPicker().)
   Fitting-choice groups (Locking/Screw Type/Vented) are visually identical
   to a real variant group — the "same code either way" distinction is a
   data-model/quote-line concern, not something a visitor needs to see as a
   different kind of control. A hard rule hides any group whose
   data-depends-on condition isn't met yet (toggled by initVariantPicker()
   adding/removing [hidden] — see "Phase 5 top-down" in td-utility-main.js). */
.tdup-product__options[data-fitting-group][hidden] { display: none; }
.tdup-option__tbc-hint { display: block; margin-top: 2px; font-size: 10.5px; font-weight: 700; text-transform: none; letter-spacing: 0; color: var(--tdup-red); }
.tdup-option:has(input:checked) .tdup-option__tbc-hint { color: var(--tdup-red-light, #ff8a9c); }
.tdup-product__variant-tbc { font-size: 13px; color: var(--tdup-charcoal); background: var(--tdup-off-white); border: 1px solid var(--tdup-border); border-radius: var(--tdup-radius-sm); padding: 10px 12px; margin: -8px 0 20px; }
.tdup-product__variant-tbc strong { font-family: var(--tdup-font-title); }
/* An option a visitor could still select, but which can't produce a real
   order code (a dead end given what's chosen so far) — the "top-down"
   half of the picker rework: disabled rather than merely left to fail
   silently after the fact, same spirit as .tdup-filters input:disabled. */
.tdup-option:has(input:disabled) { opacity: 0.4; cursor: not-allowed; }
.tdup-option:has(input:disabled):hover { border-color: var(--tdup-charcoal); }
.tdup-document-link { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 700; color: var(--tdup-red); text-decoration: none; margin-right: 16px; }
.tdup-document-link:hover { color: var(--tdup-red-dark); }
.tdup-product__documents-placeholder { margin: 0; font-size: 12.5px; font-style: italic; color: var(--tdup-mid-grey); max-width: 48ch; }
.tdup-product__documents-placeholder a { color: var(--tdup-red); font-style: normal; font-weight: 700; }
.tdup-product__documents-placeholder a:hover { color: var(--tdup-red-dark); }

/* Options now lives inside this form (see single-tdup_product.php for why),
   so the form itself stacks vertically — Options full-width on top, then
   the quantity+button pair as their own row, which is what used to be the
   whole form's own flex layout before Options moved in. */
.tdup-add-to-quote { display: flex; flex-direction: column; gap: 16px; padding-top: 8px; border-top: 1px solid var(--tdup-border); }
.tdup-add-to-quote__row { display: flex; align-items: flex-end; gap: 16px; }
.tdup-add-to-quote label { display: flex; flex-direction: column; gap: 6px; font-size: 13px; color: var(--tdup-charcoal); font-family: var(--tdup-font-title); font-weight: 600; }

/* --------------------------------------------------------------------------
   Product page review fixes (2026-10-13)
   -------------------------------------------------------------------------- */
/* Photo stays in view while the customer works down the options on desktop,
   instead of the left half of the page going blank. Top offset clears the
   sticky header. Phones stack the columns, so this only applies side by side. */
/* Desktop: photo with the spec table, downloads and help box under it on
   the left, the options on the right (2026-10-13). Phones keep the source
   order: photo, options, then the info. */
@media (min-width: 801px) {
	.tdup-product__layout { grid-template-rows: auto 1fr; align-items: start; }
	.tdup-product__gallery { grid-column: 1; grid-row: 1; }
	.tdup-product__details { grid-column: 2; grid-row: 1 / span 2; }
	.tdup-product__info { grid-column: 1; grid-row: 2; }
}
/* Features: a row of chips, each with a visible box that ticks when chosen,
   so they read as "add this" switches rather than another size choice. */
.tdup-product__features .tdup-option-list { gap: 8px; }
.tdup-option--feature { display: inline-flex; align-items: center; gap: 8px; }
.tdup-option--feature::before {
	content: ''; width: 14px; height: 14px; flex-shrink: 0; border: 1.5px solid currentColor; border-radius: 2px;
	background: transparent no-repeat center / 10px 10px;
}
.tdup-option--feature:has(input:checked)::before {
	border-color: var(--tdup-white);
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12l5 5L20 6'/%3E%3C/svg%3E");
}
/* Locked ON (it comes as standard with the choices so far): shown as included,
   at full strength, not faded like an option that isn't made. */
.tdup-option:has(input:disabled:checked) { opacity: 1; cursor: default; background: var(--tdup-charcoal); }
.tdup-option:has(input:disabled:checked)::after { content: "included"; margin-left: 2px; font-size: 10.5px; font-weight: 700; text-transform: lowercase; color: rgba(255, 255, 255, 0.75); }
/* Not made with the choices so far: faded and struck through. */
.tdup-option:has(input:disabled:not(:checked)) { text-decoration: line-through; text-decoration-thickness: 1px; }
.tdup-product__picker-hint { margin: -8px 0 16px; font-size: 12px; color: var(--tdup-mid-grey); }
/* The form styles every label inside it as a stacked column (that rule is for
   the quantity box); the option chips must stay on one line. */
.tdup-add-to-quote .tdup-option { flex-direction: row; align-items: center; }
.tdup-add-to-quote .tdup-option--feature { display: inline-flex; gap: 8px; }
/* Quantity + "Add to Quote" stick to the bottom of the screen while the
   customer is still working through the options, so the button is always one
   tap away. position: sticky keeps it inside the form, so it settles back into
   place once the form has scrolled past. */
.tdup-add-to-quote__row {
	position: sticky; bottom: 0; z-index: 5;
	padding: 12px 0; margin-top: -4px;
	background: var(--tdup-white); border-top: 1px solid var(--tdup-border);
	box-shadow: 0 -8px 16px -12px rgba(0, 0, 0, 0.25);
}
/* Spec table and downloads now sit below the quote form. */
.tdup-add-to-quote + .tdup-spec-table, .tdup-add-to-quote ~ .tdup-spec-table { margin-top: 32px; }
.tdup-product__details > .tdup-product__documents { margin-top: 20px; }

.tdup-related-products { margin-top: 56px; padding-top: 40px; border-top: 1px solid var(--tdup-border); }
.tdup-related-products h2 { font-weight: 600; text-transform: uppercase; font-size: 1.4rem; margin-bottom: 22px;font-stretch: 125%; letter-spacing: 0.06em;}

/* Exact mockup values, and identical across BOTH real usages — the
   homepage trust strip (access-cover-blueprint.html's .trust) and the
   single-product compliance strip (pages-product-flow.html's
   .compliance-strip): a thin white bordered band, not the bigger
   off-white card this used to default to (that card styling never
   actually matched either mockup — there was no third context it was
   correct for). */
.tdup-compliance-strip { background: var(--tdup-white); padding: 16px 0; display: flex; align-items: center; justify-content: center; gap: 10px 28px; flex-wrap: wrap; border-top: 1px solid var(--tdup-border); border-bottom: 1px solid var(--tdup-border); }
.tdup-compliance-strip__item { display: flex; align-items: center; gap: 8px; font-size: 12.5px; font-weight: 700; color: var(--tdup-mid-grey); transition: color var(--tdup-transition); }
.tdup-compliance-strip__item b { color: var(--tdup-charcoal); }
.tdup-compliance-strip__item svg { color: var(--tdup-red); }
.tdup-compliance-strip__item:hover { color: var(--tdup-charcoal); }

/* ==========================================================================
   9. Quote builder page
   ========================================================================== */
.tdup-quote-page { display: grid; grid-template-columns: 1fr 360px; gap: 40px; padding-bottom: 60px; align-items: start; flex: 1; }
/* Real fix (2026-09-10): this used to be the grid's own first column
   content with no wrapper — see the PHP comment in page-quote.php for why
   that left CSS Grid's auto-placement scattering the print button, the
   basket, and the form across the 2-column template incorrectly. Wrapping
   the print-only block/button/#tdup-quote-lines together as one grid item
   fixes the placement; the plate/shadow treatment matches the rest of the
   redesign's card language. */
.tdup-quote-basket { background: var(--tdup-white); border: 1px solid var(--tdup-border); border-radius: var(--tdup-radius); box-shadow: 0 16px 34px rgba(68, 72, 75, 0.1); padding: 22px 24px; }
.tdup-quote-line { display: flex; align-items: center; gap: 14px; border: 1px solid var(--tdup-border); border-radius: var(--tdup-radius); padding: 14px; margin-bottom: 12px; background: var(--tdup-white); }
.tdup-quote-line img { width: 64px; height: 54px; object-fit: contain; background: var(--tdup-off-white); border-radius: 4px; padding: 4px; }
/* Exact mockup values (.quote-line-name/.quote-line-code) — the name is a
   distinct bold uppercase line, not the same small grey text as the code
   underneath it. */
.tdup-quote-line__details { flex: 1; display: flex; flex-direction: column; gap: 2px; }
.tdup-quote-line__details strong { font-family: var(--tdup-font-title); font-weight: 700; text-transform: uppercase; font-size: 13px; color: var(--tdup-charcoal); }
.tdup-quote-line__details span { font-size: 11px; color: var(--tdup-mid-grey); }
.tdup-quote-line button[data-tdup-remove-line] { border: none; background: none; color: var(--tdup-red); cursor: pointer; font-size: 13px; font-family: var(--tdup-font-title); font-weight: 600; }

.tdup-quote-form { background: var(--tdup-white); border: 1px solid var(--tdup-border); border-top: 4px solid var(--tdup-red); box-shadow: 0 16px 34px rgba(68, 72, 75, 0.1); border-radius: var(--tdup-radius); padding: 24px; display: flex; flex-direction: column; gap: 14px; }
.tdup-quote-form h2 { font-weight: 600; text-transform: uppercase; font-size: 1.2rem; margin-bottom: 18px;font-stretch: 125%; letter-spacing: 0.06em;}
.tdup-quote-form label { display: flex; flex-direction: column; font-size: 12.5px; gap: 5px; color: var(--tdup-charcoal); font-weight: 700; }
.tdup-quote-form input { padding: 11px; border: 1px solid var(--tdup-border); border-radius: var(--tdup-radius-sm); font-family: var(--tdup-font-body); font-weight: 400; }
.tdup-quote-form .tdup-button { margin-top: 6px; }
.tdup-quote-message { background: var(--tdup-white); border: 1px solid var(--tdup-border); border-radius: var(--tdup-radius-sm); padding: 12px; font-size: 14px; }

/* ==========================================================================
   10. News archive
   ========================================================================== */
/* News list cards (restyled 2026-11-03). Markup: tdup_render_news_grid() in
   inc/page-layout.php. A hairline grid like the homepage category wall: white
   cards, the picture filling the top of each card, the date as a label, the
   title in bold normal case. The newest post is a wide "lead" card on page 1, and
   one red tile fills whatever cells are left in the last row (--s3 / --s2 are
   set inline from the post count), so the grid never ends in a gap. A hover
   puts a red bar under the card and underlines the title; it never recolours
   text. */
/* 2026-11-04 (Lee: "hard to tell where one article ends and another
   begins"): the cards used to touch, split only by a 2px pale seam, so one
   story's photo sat right against the next story's text and the grid read
   as one slab. Now each card is its own white panel with a real gap and a
   hairline edge around it. */
.tdup-news-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(16px, 1.6vw, 24px); margin-bottom: 40px; }
.tdup-news-grid__card, .tdup-news-grid__card:hover { position: relative; display: flex; flex-direction: column; min-width: 0; background: var(--tdup-white); color: var(--tdup-charcoal); text-decoration: none; overflow: hidden; border: 1px solid var(--tdup-rule); }
.tdup-news-grid__card:hover { box-shadow: inset 0 -6px 0 var(--tdup-red); }
.tdup-news-grid__photo { display: block; aspect-ratio: 16 / 10; overflow: hidden; background: var(--tdup-sweep); }
.tdup-news-grid__photo img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.35s ease; }
.tdup-news-grid__card:hover .tdup-news-grid__photo img { transform: scale(1.04); }
/* A post with no picture: a charcoal panel with a red wedge, so the card
   keeps its size and the grid stays even. */
.tdup-news-grid__nophoto { position: relative; display: flex; align-items: flex-end; width: 100%; height: 100%; padding: 16px; background: var(--tdup-charcoal); color: var(--tdup-white); font-family: var(--tdup-font-title); font-stretch: 125%; font-weight: 600; font-size: 12px; letter-spacing: 0.18em; text-transform: uppercase; }
.tdup-news-grid__nophoto::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 44%; background: var(--tdup-red); clip-path: polygon(0 0, 30% 0, 100% 100%, 0 100%); }
.tdup-news-grid__nophoto { z-index: 0; }
.tdup-news-grid__body { display: flex; flex-direction: column; gap: 8px; flex: 1; padding: 18px 18px 22px; }
.tdup-news-grid__date { font-family: var(--tdup-font-title); font-stretch: 125%; font-weight: 600; font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--tdup-red); }
/* Headlines are whole sentences, so they are set in normal case at a bold
   (not extra-bold) weight: long lines of heavy capitals are slow to read and
   were what made the page feel harsh. Short labels elsewhere keep the caps. */
.tdup-news-grid__card h3 { margin: 0; font-family: var(--tdup-font-title); font-stretch: 106%; font-weight: 700; font-size: clamp(19px, 1.45vw, 22px); line-height: 1.2; color: var(--tdup-charcoal); overflow-wrap: break-word; hyphens: auto; }
.tdup-news-grid__card:hover h3 { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 4px; }
/* Excerpts stop at three lines so cards in a row stay a similar height and
   the story ends where the card ends. */
.tdup-news-grid__card p { margin: 0; font-size: 15px; line-height: 1.55; color: var(--tdup-body-grey); display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden; }
.tdup-news-grid__more { margin-top: auto; padding-top: 6px; align-self: flex-start; font-weight: 700; font-size: 15px; color: var(--tdup-charcoal); text-decoration: underline; text-decoration-color: var(--tdup-red); text-decoration-thickness: 2px; text-underline-offset: 4px; }
/* Lead card: two cells wide, picture left and text right. */
.tdup-news-grid__card.is-lead { grid-column: span 2; flex-direction: row; }
.tdup-news-grid__card.is-lead .tdup-news-grid__photo { flex: 0 0 55%; aspect-ratio: auto; min-height: 340px; }
.tdup-news-grid__card.is-lead .tdup-news-grid__body { justify-content: center; padding: 28px; gap: 12px; }
.tdup-news-grid__card.is-lead h3 { font-size: clamp(24px, 2.1vw, 32px); line-height: 1.15; }
.tdup-news-grid__card.is-lead p { font-size: 17px; -webkit-line-clamp: 5; line-clamp: 5; }
/* The red tile that closes the grid. */
.tdup-news-grid__tile, .tdup-news-grid__tile:hover { grid-column: span var(--s3, 1); display: flex; flex-direction: column; justify-content: space-between; gap: 12px; min-height: 200px; padding: 22px; background: var(--tdup-red); color: var(--tdup-white); text-decoration: none; }
.tdup-news-grid__tile:hover { background: var(--tdup-red-dark); }
.tdup-news-grid__tile .ip-cap { font-size: clamp(24px, 2.4vw, 34px); line-height: 1; max-width: 14ch; }
.tdup-news-grid__tile > span:not(.ip-cap) { font-size: 17px; max-width: 36ch; }
.tdup-news-grid__tile .hp-arr { width: 34px; height: 34px; }
@media (max-width: 1000px) {
	.tdup-news-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.tdup-news-grid__tile, .tdup-news-grid__tile:hover { grid-column: span var(--s2, 1); }
}
@media (max-width: 640px) {
	.tdup-news-grid { grid-template-columns: 1fr; }
	.tdup-news-grid__card.is-lead { grid-column: auto; flex-direction: column; }
	.tdup-news-grid__card.is-lead .tdup-news-grid__photo { flex: none; aspect-ratio: 16 / 10; min-height: 0; }
	.tdup-news-grid__card.is-lead .tdup-news-grid__body { padding: 18px 18px 22px; }
	.tdup-news-grid__tile, .tdup-news-grid__tile:hover { grid-column: auto; }
}

/* ==========================================================================
   11. Generic page content
   ========================================================================== */
.tdup-page { padding-bottom: 60px; flex: 1; }
.tdup-page__content { max-width: 760px; }
.tdup-page__content h2 { margin-top: 1.6em; }
.tdup-page__content ul { padding-left: 1.2em; }
/* text-align: left, not center — per the design review, centred body copy
   past 1-2 lines is harder to read since the eye has to re-locate the
   start of each new line. The block itself stays centred as a narrow
   column (margin: auto within .tdup-page__content's 760px max-width);
   only the text alignment inside it changes. */
.tdup-page__content--about { margin: 0 auto 56px; text-align: left; }

/* Sectors & Applications hub (page-templates/page-sectors.php) — redesigned
   2026-09-10 from a flat card grid into a real cross-reference matrix
   (sector x category), computed from real product/taxonomy data in the
   template (see the PHP comment there) rather than a hand-typed mapping. */
/* margin-top/bottom only — a shorthand `margin: 40px 0` here was zeroing
   out .tdup-container's own `margin: 0 auto` (both are single-class
   selectors, so this one — declared later in the file — won the cascade
   for the margin property), which is why the whole table sat flush left
   with a large empty gap on the right instead of being centred. */
.tdup-sectors-matrix-wrap { margin-top: 40px; margin-bottom: 40px; overflow-x: auto; }
.tdup-sectors-matrix { width: 100%; border-collapse: collapse; min-width: 760px; }
.tdup-sectors-matrix th, .tdup-sectors-matrix td { border: 1px solid var(--tdup-border); text-align: center; padding: 10px 8px; font-size: 12px; }
.tdup-sectors-matrix thead th { background: var(--tdup-charcoal); color: var(--tdup-white); font-family: var(--tdup-font-title); font-weight: 700; text-transform: uppercase; font-size: 10.5px; letter-spacing: 0.03em; padding: 12px 8px; }
.tdup-sectors-matrix thead th:first-child { background: var(--tdup-charcoal-2); }
.tdup-sectors-matrix tbody th { text-align: left; font-family: var(--tdup-font-title); font-weight: 700; text-transform: uppercase; font-size: 12px; background: var(--tdup-off-white); white-space: nowrap; padding: 12px 16px; }
.tdup-sectors-matrix__count { display: block; font-family: var(--tdup-font-body); font-weight: 700; text-transform: none; font-size: 10.5px; color: var(--tdup-red); margin-top: 2px; }
.tdup-sectors-matrix td a { display: inline-flex; width: 22px; height: 22px; align-items: center; justify-content: center; background: var(--tdup-red); color: var(--tdup-white); font-weight: 700; text-decoration: none; }
.tdup-sectors-matrix tbody tr:hover td:not(:empty) { background: rgba(160, 35, 62, 0.06); }

/* Full-width bands (true top-level <section>s with an inner .tdup-container
   for the actual content — see page-about.php/page-careers.php) rather
   than nested inside the page's own .tdup-container and bled out with a
   negative margin, which only ever reached the edge of the 1200px content
   column, not the real viewport edge — every full-width band elsewhere on
   the site (the homepage's support/video/promo bands) is a true top-level
   section, so these follow the same real pattern instead of faking it. */
.tdup-about-values { background: var(--tdup-off-white); padding: 56px 0; margin-bottom: 56px; }
/* Exact mockup values — left-aligned (not centred), bold uppercase like
   every other heading in this design, not the plain centred text this
   defaulted to. */
.tdup-about-values h2 { font-weight: 600; text-transform: uppercase; font-size: 1.4rem; margin-bottom: 28px;font-stretch: 125%; letter-spacing: 0.06em;}
/* Rotated overlapping plates (mockup's .values-grid/.value-item), the same
   "cast plate" device as the homepage's stats/props — was a perfectly
   flat, evenly-gapped grid with no rotation/overlap at all. */
.tdup-about-values__grid { display: flex; flex-wrap: wrap; gap: 0; margin: 34px 0 44px; }
.tdup-about-values__item { background: var(--tdup-white); border: 1px solid var(--tdup-border); box-shadow: 0 12px 26px rgba(68, 72, 75, 0.1); padding: 22px 20px; flex: 1 1 220px; margin: 0 -10px 20px 0; position: relative; z-index: 1; display: flex; flex-direction: column; gap: 0; }
.tdup-about-values__item:nth-child(2) { transform: rotate(-1deg); z-index: 2; }
.tdup-about-values__item:nth-child(3) { transform: rotate(0.8deg); }
.tdup-about-values__item:nth-child(4) { transform: rotate(-0.6deg); }
/* Same fade-in/rotation specificity clash as the homepage's stats cards
   (see .tdup-stats__item.is-visible:nth-child above) — these three
   selectors outrank .tdup-fade-in.is-visible regardless of source order. */
.tdup-about-values__item.is-visible:nth-child(2) { transform: rotate(-1deg); }
.tdup-about-values__item.is-visible:nth-child(3) { transform: rotate(0.8deg); }
.tdup-about-values__item.is-visible:nth-child(4) { transform: rotate(-0.6deg); }
.tdup-about-values__item svg { color: var(--tdup-red); }
.tdup-about-values__title { font-family: var(--tdup-font-title); font-weight: 700; text-transform: uppercase; font-size: 13px; color: var(--tdup-charcoal); margin: 10px 0 6px; }
.tdup-about-values__item p { margin: 0; font-size: 12.5px; color: var(--tdup-body-grey); line-height: 1.5; }

/* Same overlapping-plates technique as .tdup-stats__item (mockup's
   .about-stats), not an evenly-gapped flat grid. */
.tdup-about-stats { display: flex; flex-wrap: wrap; gap: 0; text-align: center; margin: 34px 0 56px; }

/* "Guides for this range" on category pages (2026-10-13): small cover +
   title tiles, clearly secondary to the product grid above them. */
.tdup-category-guides { margin-top: 36px; padding-top: 24px; border-top: 1px solid var(--tdup-border); }
.tdup-category-guides h2 { font-weight: 600; text-transform: uppercase; font-size: 1.1rem; margin-bottom: 14px;font-stretch: 125%; letter-spacing: 0.06em;}
.tdup-category-guides ul { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 12px; }
.tdup-category-guides a { display: flex; align-items: center; gap: 12px; height: 100%; padding: 10px; border: 1px solid var(--tdup-border); background: var(--tdup-white); color: var(--tdup-charcoal); text-decoration: none; transition: border-color var(--tdup-transition); }
.tdup-category-guides a:hover, .tdup-category-guides a:focus-visible { border-color: var(--tdup-charcoal); }
.tdup-category-guides img { width: 44px; height: 60px; object-fit: cover; flex-shrink: 0; border: 1px solid var(--tdup-border); }
.tdup-category-guides__icon { width: 44px; height: 60px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; background: var(--tdup-off-white); color: var(--tdup-red); }
.tdup-category-guides__text { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--tdup-mid-grey); }
.tdup-category-guides__text strong { font-size: 13.5px; color: var(--tdup-charcoal); }

/* About page photo strip (2026-10-13): four real photos under the intro so the
   page isn't only text. Captions sit on a dark gradient for contrast. */
.tdup-about-photos { list-style: none; margin: 8px 0 56px; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
.tdup-about-photos__item { position: relative; aspect-ratio: 4 / 5; overflow: hidden; background: var(--tdup-charcoal); }
.tdup-about-photos__item img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tdup-about-photos__caption { position: absolute; inset: auto 0 0 0; padding: 32px 14px 12px; background: linear-gradient(to top, rgba(0, 0, 0, 0.75), transparent); color: var(--tdup-white); font: 700 13px/1.2 var(--tdup-font-title); text-transform: uppercase; letter-spacing: 0.04em; }
@media (max-width: 800px) { .tdup-about-photos { grid-template-columns: repeat(2, minmax(0, 1fr)); } .tdup-about-photos__item { aspect-ratio: 1; } }
.tdup-about-group { background: var(--tdup-charcoal); color: var(--tdup-white); padding: 48px 0; margin-bottom: 56px; }
.tdup-about-group h2 { font-weight: 600; text-transform: uppercase; font-size: 1.3rem; color: var(--tdup-white);font-stretch: 125%; letter-spacing: 0.06em;}
/* Was `.tdup-about-group > p` — never matched anything since the <p> sits
   inside .tdup-container (a grandchild, not a direct child), so this rule
   was a silent no-op and the paragraph rendered at full container width
   instead of wrapping at the mockup's 64ch. */
.tdup-about-group p { max-width: 64ch; margin-top: 8px; color: rgba(255,255,255,0.68); font-size: 14px; }
.tdup-about-group__list { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 20px; }
.tdup-about-group__list span { background: none; border: 1px solid rgba(255,255,255,0.3); border-radius: 0; padding: 8px 16px; font-family: var(--tdup-font-body); font-weight: 700; font-size: 13px; }

/* Exact mockup values (.timeline/.timeline-item/.timeline-item .year) — a
   ruled strip with oversized stamped years, reading like a cast date mark
   on a casting, not off-white rounded cards with a photo and a small red
   year number. */
.tdup-about-heritage { margin-bottom: 56px; }
.tdup-about-heritage h2 { font-weight: 600; text-transform: uppercase; font-size: 1.4rem; margin-top: 36px;font-stretch: 125%; letter-spacing: 0.06em;}
.tdup-about-heritage__timeline { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: var(--tdup-charcoal); margin: 30px 0; }
.tdup-about-heritage__item { background: var(--tdup-white); padding: 22px 20px; }
.tdup-about-heritage__item img { width: 100%; height: 120px; object-fit: cover; margin-bottom: 12px; }
.tdup-about-heritage__year { display: block; font-family: var(--tdup-font-title); font-weight: 700; font-size: 2rem; color: var(--tdup-red); letter-spacing: -0.01em; }
.tdup-about-heritage__item p { font-size: 12.5px; color: var(--tdup-body-grey); margin-top: 8px; }
@media (max-width: 760px) {
	.tdup-about-heritage__timeline { grid-template-columns: repeat(2, 1fr); }
}

/* Technical Resources page — standards/testing/despatch/sustainability
   content blocks. One generic block class with --tint/--dark modifiers
   (same off-white/charcoal banding rhythm as the About page) rather than
   a bespoke class per section, since they're all "heading + body copy". */
.tdup-tech-block { padding-top: 48px; padding-bottom: 48px; } /* top/bottom only: can also be a .tdup-container, see .tdup-footer__grid */
.tdup-tech-block--tint { background: var(--tdup-off-white); }
.tdup-tech-block--dark { background: var(--tdup-charcoal); color: var(--tdup-white); }
.tdup-tech-block--dark h2 { color: var(--tdup-white); }
.tdup-tech-block h2 { font-weight: 600; text-transform: uppercase; font-size: 1.4rem; margin-bottom: 14px;font-stretch: 125%; letter-spacing: 0.06em;}
.tdup-tech-block__body { max-width: 760px; font-size: 14px; line-height: 1.7; }
.tdup-tech-block__body p { margin: 0 0 14px; }
.tdup-tech-block--dark .tdup-tech-block__body { color: rgba(255,255,255,0.85); }

/* Exact mockup values (.load-class-band/.load-class-row) — big Archivo
   Black numerals on dark cast-plate cells with a centre divider marking
   the light/heavy-duty split, matching the homepage's own load-classes
   row exactly (same real EN124-2 standard, same treatment) instead of
   small bordered photo swatches. */
/* Guides & Downloads. Headline documents are cards that show the real front
   page of the PDF (the first is the big "start here" card), the rest are a
   compact list. The whole card is the link. */
.tdup-library { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; margin-top: 22px; }
.tdup-doc { display: grid; grid-template-columns: 96px minmax(0, 1fr); gap: 16px; padding: 16px; background: var(--tdup-white); border: 1px solid var(--tdup-border); color: var(--tdup-charcoal); transition: border-color var(--tdup-transition); }
.tdup-doc:hover, .tdup-doc:focus-visible { border-color: var(--tdup-red); }
.tdup-doc__cover { display: block; align-self: start; box-shadow: 0 6px 14px rgba(68, 72, 75, 0.22); transition: transform 0.3s ease; background: var(--tdup-white); }
.tdup-doc__cover img { display: block; width: 100%; height: auto; }
.tdup-doc:hover .tdup-doc__cover, .tdup-doc:focus-visible .tdup-doc__cover { transform: translateY(-3px) rotate(-1deg); }
/* No cover picture: the card is just text, full width, with no empty box. */
.tdup-doc--plain, .tdup-doc--lead.tdup-doc--plain { grid-template-columns: minmax(0, 1fr); }
.tdup-doc__body { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.tdup-doc__kicker { font: 700 10.5px/1 var(--tdup-font-title); letter-spacing: 0.1em; text-transform: uppercase; color: var(--tdup-red); }
.tdup-doc__title { font: 700 15px/1.25 var(--tdup-font-title); text-transform: uppercase; }
.tdup-doc__text { font-size: 13px; line-height: 1.5; color: var(--tdup-mid-grey); }
.tdup-doc__meta { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 4px 12px; margin-top: auto; padding-top: 10px; border-top: 1px solid var(--tdup-border); font-size: 11.5px; font-weight: 700; color: var(--tdup-mid-grey); }
.tdup-doc__cta { color: var(--tdup-red); text-transform: uppercase; letter-spacing: 0.04em; }
.tdup-doc--lead { grid-column: 1 / -1; grid-template-columns: minmax(150px, 230px) minmax(0, 1fr); gap: 28px; padding: 24px; border-color: var(--tdup-charcoal); }
.tdup-doc--lead .tdup-doc__body { justify-content: center; gap: 10px; }
.tdup-doc--lead .tdup-doc__title { font-size: clamp(1.3rem, 2.6vw, 1.9rem); }
.tdup-doc--lead .tdup-doc__text { font-size: 15px; max-width: 56ch; }
.tdup-doc--lead .tdup-doc__meta { margin-top: 6px; padding-top: 14px; max-width: 56ch; }
.tdup-library__subheading { margin: 34px 0 6px; font: 700 12px/1.3 var(--tdup-font-title); text-transform: uppercase; letter-spacing: 0.08em; color: var(--tdup-mid-grey); }
.tdup-notes { margin: 0; padding: 0; list-style: none; border-top: 1px solid var(--tdup-border); }
.tdup-notes li { display: grid; grid-template-columns: minmax(180px, 1fr) minmax(0, 2fr) auto; gap: 4px 20px; align-items: baseline; padding: 12px 0; border-bottom: 1px solid var(--tdup-border); font-size: 13.5px; }
.tdup-notes a { font-weight: 700; color: var(--tdup-charcoal); text-decoration: none; border-bottom: 2px solid transparent; justify-self: start; }
.tdup-notes a:hover, .tdup-notes a:focus-visible { color: var(--tdup-red); border-color: var(--tdup-red); }
.tdup-notes__text { color: var(--tdup-mid-grey); }
.tdup-notes__meta { font-size: 11.5px; font-weight: 700; color: var(--tdup-mid-grey); white-space: nowrap; }
@media (max-width: 900px) {
	.tdup-library { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.tdup-notes li { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
	.tdup-library { grid-template-columns: 1fr; }
	.tdup-doc--lead { grid-template-columns: 110px minmax(0, 1fr); gap: 16px; padding: 16px; }
}
@media (prefers-reduced-motion: reduce) {
	.tdup-doc__cover { transition: none; }
	.tdup-doc:hover .tdup-doc__cover, .tdup-doc:focus-visible .tdup-doc__cover { transform: none; }
}

/* Datasheets by category: native details/summary, so keyboard, screen readers
   and find-in-page work without any script. */
.tdup-docs__tools { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 12px 24px; margin: 18px 0 14px; }
.tdup-docs__search { display: flex; flex-direction: column; gap: 4px; font: 700 11px/1 var(--tdup-font-title); text-transform: uppercase; letter-spacing: 0.06em; color: var(--tdup-mid-grey); }
.tdup-docs__search input { width: min(340px, 100%); padding: 10px 12px; border: 1px solid var(--tdup-charcoal); background: var(--tdup-white); font: 400 14px/1.2 var(--tdup-font-body); color: var(--tdup-charcoal); }
.tdup-docs__search input:focus-visible { outline: 3px solid var(--tdup-red); outline-offset: 1px; }
.tdup-docs__buttons { display: flex; gap: 8px; }
.tdup-docs__buttons button { padding: 9px 14px; background: var(--tdup-white); border: 1px solid var(--tdup-charcoal); color: var(--tdup-charcoal); font: 700 12.5px/1 var(--tdup-font-body); cursor: pointer; }
.tdup-docs__buttons button:hover { background: var(--tdup-off-white); }
.tdup-docs__buttons button:focus-visible { outline: 3px solid var(--tdup-red); outline-offset: 2px; }
.tdup-docs__group { border-bottom: 1px solid var(--tdup-border); }
.tdup-docs__group:first-of-type { border-top: 1px solid var(--tdup-border); }
.tdup-docs__group > summary { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; padding: 16px 4px; cursor: pointer; list-style: none; }
.tdup-docs__group > summary::-webkit-details-marker { display: none; }
.tdup-docs__group > summary::before { content: '+'; flex: none; width: 22px; font: 700 20px/1 var(--tdup-font-title); color: var(--tdup-red); }
.tdup-docs__group[open] > summary::before { content: '\2212'; }
.tdup-docs__group > summary:hover .tdup-docs__name { color: var(--tdup-red); }
.tdup-docs__group > summary:focus-visible { outline: 3px solid var(--tdup-red); outline-offset: -3px; }
.tdup-docs__name { flex: 1; font: 700 16px/1.2 var(--tdup-font-title); text-transform: uppercase; }
.tdup-docs__count { font-size: 12px; font-weight: 700; color: var(--tdup-mid-grey); }
.tdup-docs__panel { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4px 40px; padding: 4px 4px 22px 38px; }
.tdup-docs__product h3 { margin: 14px 0 4px; font: 700 13px/1.3 var(--tdup-font-title); }
.tdup-docs__product ul { margin: 0; padding: 0; list-style: none; }
.tdup-docs__product li { padding: 5px 0; border-bottom: 1px solid var(--tdup-border); font-size: 13px; }
.tdup-docs__product a { color: var(--tdup-red); font-weight: 700; text-decoration: none; }
.tdup-docs__product a:hover, .tdup-docs__product a:focus-visible { text-decoration: underline; }
.tdup-docs__product li span { margin-left: 6px; font-size: 11.5px; color: var(--tdup-mid-grey); }
@media (max-width: 760px) { .tdup-docs__panel { grid-template-columns: 1fr; padding-left: 4px; } }
/* Six load classes can't fit one row on a phone: 3 x 2, and drop the centre divider line that only suits the single row. */
@media (max-width: 600px) {
	.tdup-tech-block .tdup-tech-load-classes { grid-template-columns: repeat(3, minmax(0, 1fr)); }
	.tdup-tech-block .tdup-tech-load-classes::after { display: none; }
}
.tdup-tech-load-classes { display: grid; grid-template-columns: repeat(6, 1fr); gap: 1px; background: var(--tdup-charcoal); position: relative; margin: 24px 0 8px; }
.tdup-tech-load-classes::after { content: ''; position: absolute; left: 50%; top: 0; bottom: 0; width: 2px; background: var(--tdup-red); }
.tdup-tech-load-classes__item { background: var(--tdup-charcoal-2); padding: 20px 10px; text-align: center; }
.tdup-tech-load-classes__code { display: block; font-family: var(--tdup-font-title); font-weight: 700; font-size: 22px; color: var(--tdup-white); }
.tdup-tech-load-classes__caption { display: block; font-size: 11px; font-weight: 700; margin-top: 6px; color: #ff8a9c; }

.tdup-tech-clearances img { max-width: 100%; border-radius: var(--tdup-radius); border: 1px solid var(--tdup-border); margin-top: 12px; }

/* Exact mockup values (.doc-category) — this whole block had no CSS at
   all, rendering as default unstyled browser <ul>/<li>. */
.tdup-tech-resources__category { margin-bottom: 24px; }
.tdup-tech-resources__category h2 { font-weight: 600; text-transform: uppercase; font-size: 13px; margin-bottom: 10px;font-stretch: 125%; letter-spacing: 0.06em;}
.tdup-tech-resources__category ul { list-style: none; margin: 0; padding: 0; }
.tdup-tech-resources__category li { font-size: 13px; padding: 6px 0; border-bottom: 1px solid var(--tdup-border); }
.tdup-tech-resources__category a { color: var(--tdup-red); text-decoration: none; font-weight: 700; }
.tdup-tech-resources__category a:hover { color: var(--tdup-red-dark); }
.tdup-tech-resources__category span { color: var(--tdup-mid-grey); font-size: 11.5px; margin-left: 6px; }

/* Generic closing CTA band — reused across every content page (About,
   Careers, and the plain-page fallback) rather than each having its own
   near-duplicate, so a page with just a paragraph or two of real content
   still ends on a deliberate note instead of a wall of empty space above
   the footer. */
/* A true top-level section (not nested inside .tdup-container the way it
   used to be), so its background spans the full viewport like every other
   band on the site (the homepage's support/video/promo bands) — bleeding
   only to the edge of the 1200px content column via a negative margin
   left it looking like a boxed card floating in whitespace on anything
   wider than that, not an actual banner. */
/* Exact mockup values (.cta-band) — the mockup treats this as a solid red
   band (used at the bottom of Sectors/Technical Resources/About), not the
   pale off-white strip this defaulted to (which matched neither of the
   mockup's two real closing-band treatments). Restyled 2026-11-03: display
   caps title, a white button. Prefer tdup_next_band() on new pages. */
/* No margin-bottom here — tdup_cta_band() is reused in two real, different
   positions: the closing CTA right before the footer (Sectors/Technical
   Resources/About/Careers), AND the "Download the full Product Guide"
   band partway down Technical Resources, which is followed by an entire
   page of content, not the footer. A blanket -60px here overlapped the
   very next section whenever the band wasn't actually the page's last
   element. The pull-flush-to-the-footer behaviour is scoped below to only
   when it truly is the last child. */
.tdup-cta-band { background: var(--tdup-red); color: var(--tdup-white); padding: 36px 0; }
/* .tdup-page has its own padding-bottom (for pages that don't end in a CTA
   band) — that padding can't collapse with the band's negative margin, so
   it's removed here specifically in the one case that needs the margin. */
.tdup-page:has(> .tdup-cta-band:last-child) { padding-bottom: 0; }
.tdup-page > .tdup-cta-band:last-child { margin-bottom: -60px; }
.tdup-cta-band__inner { display: flex; align-items: center; justify-content: space-between; gap: 24px; flex-wrap: wrap; }
.tdup-cta-band__title { display: block; font-family: var(--tdup-font-title); font-stretch: 112%; font-weight: 800; text-transform: uppercase; font-size: clamp(1.3rem, 2.4vw, 1.9rem); line-height: 1; color: var(--tdup-white); }
.tdup-cta-band__text { display: block; font-size: 16px; color: rgba(255, 255, 255, 0.92); margin-top: 8px; }
/* The band is red, so its button is white (a charcoal button also reads well,
   but white matches the homepage's red bands). */
.tdup-cta-band .tdup-button--dark, .tdup-cta-band .tdup-button--dark:hover { color: var(--tdup-charcoal); }
.tdup-cta-band .tdup-button--dark { background: var(--tdup-white); }
.tdup-cta-band .tdup-button--dark:hover { background: var(--tdup-sweep); }

/* ==========================================================================
   13. Contact page
   ========================================================================== */
.tdup-contact__layout { display: flex; gap: 56px; margin-bottom: 56px; }
.tdup-contact__details { width: 340px; flex-shrink: 0; display: flex; flex-direction: column; gap: 28px; }
.tdup-contact__block { display: flex; flex-direction: column; gap: 10px; }
.tdup-contact__label { font-family: var(--tdup-font-title); font-weight: 700; font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--tdup-mid-grey); }
.tdup-contact__row { display: flex; align-items: center; gap: 10px; }
.tdup-contact__row svg { color: var(--tdup-red); flex-shrink: 0; }
.tdup-contact__placeholder { font-size: 14px; font-style: italic; color: var(--tdup-mid-grey); }
.tdup-contact__row a { color: inherit; font-size: 14px; }
.tdup-contact__map { border-radius: var(--tdup-radius); display: block; }
.tdup-contact__map-placeholder { height: 200px; background: var(--tdup-off-white); border: 1px dashed #C7CBCD; border-radius: var(--tdup-radius); display: flex; align-items: center; justify-content: center; padding: 16px; }
.tdup-contact__map-placeholder span { font-size: 13px; color: var(--tdup-mid-grey); font-style: italic; text-align: center; }
/* Click-to-load map: same 200px height as the map, so nothing jumps when the iframe replaces it. */
.tdup-map-consent { min-height: 200px; box-sizing: border-box; background: var(--tdup-off-white); border: 1px solid var(--tdup-border); padding: 16px; display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 12px; }
.tdup-map-consent__text { margin: 0; font-size: 13px; color: var(--tdup-body-grey); }
.tdup-map-consent__link { font-size: 13px; color: var(--tdup-charcoal); text-decoration: underline; text-underline-offset: 2px; }
.tdup-map-consent .tdup-button:focus-visible,
.tdup-map-consent__link:focus-visible { outline: 3px solid var(--tdup-red); outline-offset: 2px; }
/* Privacy sentence just above the contact and quote form submit buttons. */
.tdup-form-privacy { margin: 0; font-size: 13px; color: var(--tdup-body-grey); }
.tdup-form-privacy a { color: var(--tdup-charcoal); text-decoration: underline; text-underline-offset: 2px; }

.tdup-contact__form-wrap { flex: 1; max-width: 640px; }
.tdup-contact__form-wrap h2 { font-weight: 600; text-transform: uppercase; font-size: 1.3rem; margin-bottom: 18px;font-stretch: 125%; letter-spacing: 0.06em;}
.tdup-contact__intro { margin-bottom: 20px; font-size: 14px; }
.tdup-contact-form { display: flex; flex-direction: column; gap: 16px; }
.tdup-contact-form label { display: flex; flex-direction: column; gap: 6px; font-size: 13px; font-weight: 700; font-family: var(--tdup-font-title); color: var(--tdup-charcoal); }
.tdup-contact-form input,
.tdup-contact-form select,
.tdup-contact-form textarea { font-family: var(--tdup-font-body); font-weight: 400; font-size: 14px; padding: 12px; border: 1px solid var(--tdup-border); border-radius: var(--tdup-radius-sm); }
.tdup-contact-form__row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
/* [hidden] gotcha: an author display:flex rule beats the browser's own
   [hidden]{display:none} UA rule at equal specificity (author styles win
   ties over UA styles), so without this the distributor-only fields
   showed regardless of which enquiry type was actually selected —
   initContactForm()'s JS toggle was setting the hidden attribute
   correctly the whole time, CSS was just ignoring it. */
.tdup-contact-form__distributor-fields { display: flex; flex-direction: column; gap: 16px; padding: 16px; background: var(--tdup-off-white); border-radius: var(--tdup-radius-sm); border: 1px solid var(--tdup-border); }
.tdup-contact-form__distributor-fields[hidden] { display: none; }

/* ==========================================================================
   14. Careers page
   ========================================================================== */
/* Same off-white-band treatment as .tdup-about-values — kept as its own
   class (rather than reusing that one directly) so a future reader of
   page-careers.php isn't looking at class="tdup-about-values" on a page
   that has nothing to do with About Us. The card grid inside it
   (.tdup-about-values__grid/__item) IS reused as-is — that part really is
   just a generic icon+title+text card, not About-specific. */
.tdup-careers-benefits { background: var(--tdup-off-white); padding: 56px 0; margin-bottom: 56px; }
.tdup-careers-benefits h2 { font-weight: 600; text-transform: uppercase; font-size: 1.4rem; margin-bottom: 28px;font-stretch: 125%; letter-spacing: 0.06em;}

.tdup-careers-vacancies { margin-bottom: 56px; }
.tdup-careers-vacancies h2 { font-weight: 600; text-transform: uppercase; font-size: 1.4rem; margin-bottom: 16px;font-stretch: 125%; letter-spacing: 0.06em;}
.tdup-careers-vacancies__empty {
	background: var(--tdup-off-white); border: 1px dashed #C7CBCD; border-radius: var(--tdup-radius);
	padding: 48px 24px; display: flex; flex-direction: column; align-items: center; gap: 14px; text-align: center; color: var(--tdup-mid-grey);
}
.tdup-careers-vacancies__empty p { max-width: 480px; margin: 0; font-size: 14px; }

.tdup-stockist-teaser { background: var(--tdup-off-white); padding: 40px 0; margin-bottom: -60px; }
.tdup-stockist-teaser__inner { display: flex; align-items: center; justify-content: space-between; gap: 24px; flex-wrap: wrap; }
.tdup-stockist-teaser__title { display: block; font-family: var(--tdup-font-title); font-weight: 700; text-transform: uppercase; font-size: 14px; color: var(--tdup-charcoal); }
.tdup-stockist-teaser__text { display: block; font-size: 13px; color: var(--tdup-body-grey); }
.tdup-button--disabled { opacity: 0.55; cursor: not-allowed; }

@media (max-width: 800px) {
	.tdup-contact__layout { flex-direction: column; }
	.tdup-contact__details { width: 100%; }
	.tdup-contact-form__row { grid-template-columns: 1fr; }
}

/* ==========================================================================
   12. Responsive
   ========================================================================== */
@media (max-width: 900px) {
	.tdup-categories__grid,
	.tdup-product-listing__grid--four {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
	/* The old flexbox footer wrapped naturally on narrow screens; this
	   fixed-column grid replacement needs an explicit stack rule or its 4
	   columns just overflow/clip past the viewport edge. */
}

@media (max-width: 800px) {
	.tdup-product-listing,
	.tdup-quote-page,
	.tdup-product__layout {
		grid-template-columns: 1fr;
	}
	/* .tdup-categories__grid deliberately NOT here: it stays 2-up on
	   phones (set in the 900px rule above). Its big tile spans 2 columns,
	   and inside a 1-column grid that span forces the browser to invent
	   extra implicit columns, which showed as thin slivers of tiles down
	   the left edge. */
	.tdup-product-listing__grid--four {
		grid-template-columns: 1fr;
	}
}

/* ==========================================================================
   15. Animations
   Scroll-reveal REMOVED 2026-11-02 (DESIGN.md "Motion": no fade-up on
   scroll). It was a template tell, and it left content invisible (opacity 0)
   in thumbnails, screenshots and throttled background tabs. The classes
   .tdup-fade-in / .tdup-slide-in-left / .tdup-slide-in-right / .tdup-scale-in
   and .tdup-delay-1..6 are still on many templates, but they now have NO
   styles, so they do nothing and all content is always visible. (The JS
   observer that added .is-visible is gone too.) Safe to delete them from
   templates whenever each template is next touched. The hero slideshow
   crossfade is separate (see .hp-hero__slide) and stays.
   ========================================================================== */

/* Hover/focus transitions — previously almost every interactive element
   (buttons, cards, nav/footer links, chips) changed state instantly with
   no easing at all, which read as static/unpolished even before any
   scroll animation is added. These are transform/colour/shadow only
   (never layout-affecting properties), so they're left out of the
   reduced-motion gate above — a smoothed hover, unlike a sliding scroll
   reveal, isn't the kind of motion that guidance is meant to suppress. */
.tdup-button { transition: background var(--tdup-transition), color var(--tdup-transition), border-color var(--tdup-transition), transform var(--tdup-transition), box-shadow var(--tdup-transition); }
.tdup-button:active { transform: scale(0.97); }
a, .tdup-categories__card, .tdup-product-card, .tdup-news-grid__card,
.tdup-quick-add, .tdup-primary-nav a, .tdup-footer a,
.tdup-about-values__item, .tdup-option, .tdup-product__thumbnail {
	transition: background var(--tdup-transition), color var(--tdup-transition), border-color var(--tdup-transition), box-shadow var(--tdup-transition), transform var(--tdup-transition);
}
/* No hover lifts on cards (2026-09-25): the flat design language shows
   hover with colour alone. .tdup-about-values__item keeps its lift until
   the About/Careers pages get their own pass. */
.tdup-about-values__item:hover { transform: translateY(-3px); }
.tdup-header__logo { transition: opacity var(--tdup-transition); }
.tdup-header__logo:hover { opacity: 0.85; }

/* ==========================================================================
   16. Form & selection branding
   Every text input/select/textarea across the site (header search, quote
   form, contact form) fell back to the browser's default blue focus ring
   and, for <select>, the OS's own dropdown arrow — the last unbranded
   "generic Windows page" controls once the checkbox/option pills above
   were fixed. This section re-brands all of them in one place rather than
   per-form, so a new form added later inherits the same look for free.
   ========================================================================== */
input[type="text"], input[type="email"], input[type="tel"], input[type="search"],
input[type="date"], input[type="number"], select, textarea {
	transition: border-color var(--tdup-transition), box-shadow var(--tdup-transition);
}
input[type="text"]:focus, input[type="email"]:focus, input[type="tel"]:focus,
input[type="search"]:focus, input[type="date"]:focus, input[type="number"]:focus,
select:focus, textarea:focus {
	outline: none;
	border-color: var(--tdup-ink);
	box-shadow: 0 0 0 2px #fff, 0 0 0 5px var(--tdup-ink);
}
/* A plain 2px outline (rather than the box-shadow ring above) for anything
   that isn't a boxed form field — links, buttons, cards — so keyboard
   navigation is clearly visible everywhere, not just inside forms. The
   checkbox/option pills define their own more specific version of this
   above; this is the site-wide fallback. */
a:focus-visible, button:focus-visible, .tdup-button:focus-visible, summary:focus-visible {
	/* White outline + dark ink ring: visible on red, charcoal and white (never a red ring). */
	outline: 3px solid #fff;
	outline-offset: 2px;
	box-shadow: 0 0 0 6px var(--tdup-ink);
}

/* Custom <select> arrow — appearance:none drops the OS-drawn one entirely;
   the replacement is the same chevron glyph as tdup_icon('chevron', ...)
   used elsewhere, encoded inline so no extra HTTP request is needed for
   one small background image. */
select {
	appearance: none;
	-webkit-appearance: none;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2354595F' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 6 6 6-6 6' transform='rotate(90 12 12)'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 12px center;
	background-size: 16px;
	padding-right: 36px !important;
	cursor: pointer;
}

/* The native date-picker calendar icon can only be tinted (not recoloured
   to an exact hex) cross-browser — this nudges it toward the charcoal
   palette instead of leaving the OS's default black/grey icon sitting in
   an otherwise fully-branded field. Firefox's date input isn't
   restyleable this way at all; it's left at its own default there rather
   than risked with a hack that could make it *less* usable. */
input[type="date"]::-webkit-calendar-picker-indicator {
	filter: invert(28%) sepia(4%) saturate(1092%) hue-rotate(169deg) brightness(94%) contrast(89%);
	cursor: pointer;
}

/* Selection highlight — the OS default (usually blue) on TDUP's own red
   would otherwise be the one remaining "generic browser" touch left on
   the page even after every visible control is branded. */
::selection { background: var(--tdup-red); color: var(--tdup-white); }

/* ==========================================================================
   17. Mobile navigation
   The design review flagged two related gaps: no collapsed nav state at
   all below 800px (nav links just wrapped onto extra lines, pushing
   ~250px of chrome above the fold on a phone before any real content),
   and no intermediate breakpoint — at tablet/mid widths (~880px) the same
   wrapping happened, just less badly (the "Quote 0" badge dropped to its
   own line). Both are fixed by the same mechanism, from 1024px down: the
   toggle button (header.php) becomes visible, and initMobileNav()
   (td-utility-main.js) adds/removes .tdup-header--open on click, which is
   what actually shows the nav/search/quote — deliberately collapsed by
   default at this width, not just left to wrap.
   ========================================================================== */
.tdup-header__menu-toggle { display: none; background: none; border: none; padding: 6px; color: var(--tdup-white); cursor: pointer; margin-left: auto; }

@media (max-width: 1024px) {
	.tdup-header__menu-toggle { display: flex; align-items: center; justify-content: center; }
	.tdup-header__inner { flex-wrap: wrap; }
	/* Hidden by default at this width — DOM order (nav, then search, then
	   quote link) is what decides their stacking order once opened, since
	   each becomes a full-width flex item that wraps onto its own line. */
	.tdup-primary-nav,
	.tdup-header__search,
	.tdup-header__quote-link {
		display: none;
		width: 100%;
	}
	.tdup-header--open .tdup-primary-nav { display: block; }
	.tdup-header--open .tdup-header__search { display: flex; }
	.tdup-header--open .tdup-header__quote-link { display: flex; }
	.tdup-primary-nav ul { flex-direction: column; gap: 0; width: 100%; padding: 12px 0 4px; }
	.tdup-primary-nav li { border-top: 1px solid rgba(255,255,255,0.12); }
	.tdup-primary-nav a { display: block; padding: 12px 2px; }
	.tdup-header__quote-link { justify-content: center; padding: 12px 0; border-top: 1px solid rgba(255,255,255,0.12); margin-top: 4px; margin-bottom: 12px; }
	/* The hover-only dropdown pattern (.tdup-primary-nav ul ul, ~line 223)
	   doesn't fire on touch at all, so a submenu is opened here by the
	   .tdup-submenu-toggle button instead (see initMobileSubmenus() in
	   td-utility-main.js) — hidden by default, shown only once its item is
	   expanded via [aria-expanded="true"]. */
	.tdup-primary-nav li.menu-item-has-children > a { display: inline-block; width: auto; }
	.tdup-submenu-toggle { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; float: right; }
	.tdup-primary-nav ul ul { position: static; display: none; box-shadow: none; border: none; padding-left: 12px; }
	.tdup-primary-nav .tdup-submenu-toggle[aria-expanded="true"] ~ ul { display: flex; }
}

/* ==========================================================================
   18. Mobile filter drawer
   The design review's #3 critical issue: below 800px — the same width
   .tdup-product-listing already collapses to a single column at (see
   "12. Responsive") — the filter <aside> used to just reflow to full
   width and land directly above the product grid, so a visitor had to
   scroll past Category, Load Class, a 7+ item Sector list and
   Certification before reaching a single product. Elements here are
   invisible above 800px by default (this is a mobile-only pattern); the
   toggle/backdrop only exist in the DOM via tdup_filters_drawer_controls()
   on the three product-listing templates, and initFilterDrawer() in
   td-utility-main.js is what actually adds .tdup-filters-open to <body>.
   ========================================================================== */
.tdup-filters-toggle { display: none; }
.tdup-filters-backdrop { display: none; }
.tdup-filters__close { display: none; }

@media (max-width: 800px) {
	.tdup-filters-toggle {
		display: flex; align-items: center; justify-content: center; gap: 8px;
		width: 100%; padding: 12px; margin-bottom: 20px;
		background: var(--tdup-white); border: 1px solid var(--tdup-border); border-radius: var(--tdup-radius);
		font-family: var(--tdup-font-title); font-weight: 700; font-size: 14px; color: var(--tdup-charcoal);
		cursor: pointer;
	}
	.tdup-filters-backdrop {
		display: block; position: fixed; inset: 0; background: rgba(0,0,0,0.5);
		z-index: 40; opacity: 0; pointer-events: none; transition: opacity var(--tdup-transition);
	}
	.tdup-filters-drawer {
		position: fixed; top: 0; left: 0; bottom: 0; width: 85%; max-width: 340px;
		background: var(--tdup-white); z-index: 41; overflow-y: auto; padding: 20px;
		transform: translateX(-100%); transition: transform 0.3s ease;
	}
	/* The drawer panel itself is now the white/scrollable/positioned
	   surface, so the filter form inside it drops its own (redundant)
	   off-white rounded box — otherwise it'd be a box inside a box. */
	.tdup-filters-drawer .tdup-filters { background: none; padding: 12px 0 0; }
	.tdup-filters__close {
		display: flex; align-items: center; justify-content: center;
		position: absolute; top: 16px; right: 16px; z-index: 1;
		background: none; border: none; color: var(--tdup-charcoal); cursor: pointer;
	}

	body.tdup-filters-open { overflow: hidden; } /* stop the page scrolling behind an open drawer */
	body.tdup-filters-open .tdup-filters-backdrop { opacity: 1; pointer-events: auto; }
	body.tdup-filters-open .tdup-filters-drawer { transform: translateX(0); box-shadow: 8px 0 24px rgba(0,0,0,0.2); }
}

/* ==========================================================================
   19. Compare tool
   The floating bar (footer.php) is one instance site-wide, hidden until
   JS (renderCompareBar() in td-utility-main.js) shows it — same "always in
   the DOM, visibility driven by localStorage state" approach as the
   header's quote-count badge. The table itself only exists on the Compare
   page (page-templates/page-compare.php).
   ========================================================================== */
.tdup-compare-bar {
	position: fixed; left: 50%; bottom: 20px; transform: translateX(-50%); z-index: 50;
	display: flex; align-items: center; gap: 16px;
	background: var(--tdup-charcoal); color: var(--tdup-white);
	border-radius: var(--tdup-radius); padding: 12px 18px;
	box-shadow: 0 12px 32px rgba(0,0,0,0.25);
	font-family: var(--tdup-font-title); font-weight: 700; font-size: 13px;
	max-width: calc(100vw - 32px);
}
/* The [hidden] attribute is how JS shows/hides this bar (see
   renderCompareBar() in td-utility-main.js), but the plain `display: flex`
   above is an author-stylesheet rule, which always wins over the browser's
   own default `[hidden] { display: none }` regardless of source order —
   without this override the bar stayed visible ("0 selected to compare")
   on every page, whether or not anything was actually selected. */
.tdup-compare-bar[hidden] { display: none; }
.tdup-compare-bar__thumbs { display: flex; gap: 6px; }
.tdup-compare-bar__thumbs img { width: 32px; height: 32px; object-fit: cover; border-radius: var(--tdup-radius-sm); border: 1px solid rgba(255,255,255,0.25); }
.tdup-compare-bar__clear { background: none; border: none; color: rgba(255,255,255,0.65); font-weight: 700; font-size: 13px; cursor: pointer; text-decoration: underline; }
.tdup-compare-bar__clear:hover { color: var(--tdup-white); }

@media (max-width: 640px) {
	.tdup-compare-bar { flex-wrap: wrap; justify-content: center; text-align: center; }
	.tdup-compare-bar__thumbs { display: none; } /* not enough width to show these and stay readable */
}

.tdup-compare-empty { text-align: center; padding: 60px 20px; color: var(--tdup-mid-grey); }
.tdup-compare-table-wrap { overflow-x: auto; margin: 20px 0 60px; }
.tdup-compare-table { width: 100%; border-collapse: collapse; }
.tdup-compare-table th, .tdup-compare-table td { border: 1px solid var(--tdup-border); padding: 12px 16px; text-align: left; font-size: 13px; vertical-align: top; }
.tdup-compare-table thead th { background: var(--tdup-off-white); min-width: 160px; }
.tdup-compare-table thead th img { display: block; width: 100%; max-width: 120px; height: 90px; object-fit: contain; margin-bottom: 8px; }
.tdup-compare-table thead th button { background: none; border: 1px solid var(--tdup-border); border-radius: var(--tdup-radius-sm); padding: 4px 10px; font-size: 12px; cursor: pointer; }
.tdup-compare-table thead th button:hover { border-color: var(--tdup-red); color: var(--tdup-red); }
.tdup-compare-table tbody th { font-family: var(--tdup-font-title); font-weight: 700; text-transform: uppercase; color: var(--tdup-charcoal); background: var(--tdup-off-white); white-space: nowrap; }
/* The product-name cell's <a> otherwise inherits the sitewide red link
   colour, but the mockup's compare table shows it as plain body text. */
.tdup-compare-table td a { color: var(--tdup-charcoal); text-decoration: none; }
.tdup-compare-table td a:hover { color: var(--tdup-red); }

/* ==========================================================================
   20. Print styles
   Only the Quote page needs to print cleanly — everything else on the
   site printing is a non-goal. .tdup-quote-print-only is invisible on
   screen (this is the ONLY place it's shown) and exists purely to give the
   printed page/PDF a heading + date, since the real on-screen page has no
   equivalent to reuse (the hero is a large decorative band that doesn't
   belong on a printed quote).
   ========================================================================== */
.tdup-quote-print-only { display: none; }

@media print {
	.tdup-header, .tdup-promo-strip, .tdup-page-hero, .ip-hero, .tdup-footer, .tdup-compare-bar, .tdup-quote-print-button, #tdup-quote-form, .tdup-quote-line button, .tdup-quote-line input { display: none !important; }
	.tdup-quote-print-only { display: block; margin-bottom: 20px; }
	/* Looks like the h1 this used to be (a <p> now, so the page keeps a single H1). */
	.tdup-quote-print-title { font-family: var(--tdup-font-title); font-weight: 700; font-size: 2em; color: var(--tdup-charcoal); margin: 0 0 0.5em; }
	.tdup-quote-line { break-inside: avoid; border-bottom: 1px solid #ccc; padding: 10px 0; }
}

/* Homepage product rows on phones (2026-10-13): two-up rather than one tall
   column. Popular Products used to be a sideways carousel; as a one-column
   grid its four cards took about 1,660px of scrolling. Only the homepage
   rows: category and search pages keep their own layout. */
@media (max-width: 800px) {
	.tdup-popular-products .tdup-product-listing__grid--four { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
	.tdup-popular-products .tdup-product-card h3 { font-size: 13px; }
	.tdup-popular-products .tdup-product-card .tdup-quick-add { margin: 10px; }
}

/* ==========================================================================
   Product option picker (rebuilt 2026-10-13, see initVariantPicker()).
   Numbered steps that appear one at a time; the step waiting for an answer
   is highlighted, answered steps stay visible (and changeable) above it.
   ========================================================================== */
.tdup-picker { margin: 4px 0 8px; }
.tdup-picker__section + .tdup-picker__section { margin-top: 18px; padding-top: 16px; border-top: 1px dashed var(--tdup-border); }
.tdup-picker__heading { margin: 0 0 10px; font: 700 13px/1.2 var(--tdup-font-title); text-transform: uppercase; letter-spacing: 0.08em; color: var(--tdup-charcoal); }
.tdup-picker__steps { list-style: none; margin: 0; padding: 0; counter-reset: tdup-step; display: grid; gap: 10px; }
.tdup-picker__step { counter-increment: tdup-step; position: relative; padding: 12px 14px 12px 46px; border: 1px solid var(--tdup-border); background: var(--tdup-white); animation: tdup-step-in 0.25s ease; }
.tdup-picker__step::before { content: counter(tdup-step); position: absolute; left: 12px; top: 12px; width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center; font: 700 11px/1 var(--tdup-font-title); background: var(--tdup-off-white); color: var(--tdup-charcoal); border: 1px solid var(--tdup-border); }
.tdup-picker__step.is-current { border-color: var(--tdup-red); box-shadow: inset 3px 0 0 var(--tdup-red); }
.tdup-picker__step.is-current::before { background: var(--tdup-red); color: var(--tdup-white); border-color: var(--tdup-red); }
.tdup-picker__step.is-answered::before { content: '\2713'; background: var(--tdup-charcoal); color: var(--tdup-white); border-color: var(--tdup-charcoal); }
.tdup-picker__step fieldset { border: 0; margin: 0; padding: 0; min-width: 0; }
.tdup-picker__step legend { padding: 0; margin-bottom: 8px; font: 700 11px/1.2 var(--tdup-font-title); text-transform: uppercase; letter-spacing: 0.06em; color: var(--tdup-mid-grey); }
.tdup-picker__step .tdup-option-list { margin-bottom: 0; gap: 6px; }
.tdup-picker__section--extras .tdup-picker__step::before { content: '+'; }
.tdup-picker__status { margin: 10px 0 0; min-height: 1em; font-size: 12.5px; font-weight: 700; color: var(--tdup-charcoal); }
.tdup-picker__noscript { font-size: 13px; }
.tdup-picker__noscript-list { font-size: 12.5px; padding-left: 18px; }
@keyframes tdup-step-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .tdup-picker__step { animation: none; } }

/* "Anything custom?": always available, right above Add to Quote. */
.tdup-picker__custom { margin: 14px 0 4px; }
.tdup-picker__custom label { display: flex; align-items: baseline; gap: 8px; margin-bottom: 6px; font: 700 12px/1.2 var(--tdup-font-title); text-transform: uppercase; letter-spacing: 0.06em; color: var(--tdup-charcoal); flex-direction: row; }
.tdup-picker__custom label span { font-weight: 600; text-transform: none; letter-spacing: 0; color: var(--tdup-mid-grey); }
.tdup-picker__custom textarea { width: 100%; padding: 10px 12px; border: 1px solid var(--tdup-border); font: inherit; font-size: 14px; resize: vertical; background: var(--tdup-white); }
.tdup-picker__custom textarea:focus-visible { outline: 2px solid var(--tdup-red); outline-offset: 1px; }
.tdup-picker__custom-hint { margin: 4px 0 0; font-size: 12px; color: var(--tdup-mid-grey); }

/* Key features: prominent tick list under the product description. */
.tdup-key-features { margin: 14px 0 18px; padding: 14px 16px; background: var(--tdup-off-white); border-left: 3px solid var(--tdup-red); }
.tdup-key-features__heading { margin: 0 0 8px; font: 700 12px/1.2 var(--tdup-font-title); text-transform: uppercase; letter-spacing: 0.08em; color: var(--tdup-charcoal); }
.tdup-key-features__list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px 18px; }
.tdup-key-features__list li { display: inline-flex; align-items: center; gap: 6px; font-weight: 700; font-size: 14px; color: var(--tdup-charcoal); }
.tdup-key-features__list svg { color: var(--tdup-red); flex-shrink: 0; }
/* Add to Quote stays visibly unavailable until the picker lands on a code. */
.tdup-add-to-quote button[type="submit"]:disabled { opacity: 0.45; cursor: not-allowed; }

/* Answered steps collapse to one line (2026-10-13): "Size  420x420  Change". */
.tdup-picker__step.is-collapsed { padding-top: 9px; padding-bottom: 9px; }
.tdup-picker__step.is-collapsed::before { top: 8px; }
.tdup-picker__summary { display: flex; align-items: baseline; gap: 10px; min-height: 22px; }
.tdup-picker__summary-label { font: 700 11px/1.2 var(--tdup-font-title); text-transform: uppercase; letter-spacing: 0.06em; color: var(--tdup-mid-grey); min-width: 92px; }
.tdup-picker__summary strong { font-size: 14px; color: var(--tdup-charcoal); }
.tdup-picker__change { margin-left: auto; border: 0; background: none; padding: 2px 4px; font: 700 12.5px/1 var(--tdup-font-body, inherit); color: var(--tdup-red); text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.tdup-picker__change:hover, .tdup-picker__change:focus-visible { color: var(--tdup-red-dark); }
.tdup-picker__change:focus-visible { outline: 2px solid var(--tdup-red); outline-offset: 2px; }

/* Product info under the photo: spec table, downloads, help box. */
.tdup-product__info .tdup-spec-table { margin-top: 0; }
.tdup-product__info .tdup-product__documents { margin-top: 18px; }
.tdup-product__help { margin-top: 20px; padding: 16px 18px; background: var(--tdup-charcoal); color: var(--tdup-white); }
.tdup-product__help h2 { margin: 0 0 6px; font: 700 15px/1.2 var(--tdup-font-title); text-transform: uppercase; letter-spacing: 0.04em; color: var(--tdup-white); }
.tdup-product__help p { margin: 0 0 12px; font-size: 13.5px; color: rgba(255, 255, 255, 0.85); }
.tdup-product__help ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px 20px; }
.tdup-product__help a { display: inline-flex; align-items: center; gap: 8px; color: var(--tdup-white); font-weight: 700; font-size: 14px; text-decoration: none; }
.tdup-product__help a:hover, .tdup-product__help a:focus-visible { color: var(--tdup-white); text-decoration: underline; text-underline-offset: 3px; }
.tdup-product__help svg { color: var(--tdup-red-light, #ff8a9c); flex-shrink: 0; }

/* Technical Resources: photos/video beside each section's text (2026-10-13). */
.tdup-tech-block__split.has-media { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 32px; align-items: start; }
.tdup-tech-block__split.has-media .tdup-tech-block__body { max-width: none; }
.tdup-tech-media { display: grid; gap: 10px; }
.tdup-tech-media__video video, .tdup-tech-media__video iframe { width: 100%; aspect-ratio: 16 / 9; height: auto; display: block; background: #000; border: 0; }
.tdup-tech-media__photos { display: grid; gap: 10px; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.tdup-tech-media__photos img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block; }
/* One photo: full width. Three: the first one large across the top. */
.tdup-tech-media__photos--1 { grid-template-columns: 1fr; }
.tdup-tech-media__photos--1 img { aspect-ratio: 16 / 10; }
.tdup-tech-media__photos--3 img:first-child { grid-column: 1 / -1; aspect-ratio: 16 / 9; }
@media (max-width: 800px) { .tdup-tech-block__split.has-media { grid-template-columns: 1fr; } }

/* About page (2026-10-13): figures band, site cards, quality band. */
.tdup-about-figures { margin: 0 0 56px; }
.tdup-about-figures__list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); border-top: 2px solid var(--tdup-charcoal); border-bottom: 1px solid var(--tdup-border); }
.tdup-about-figures__list li { padding: 20px 16px; border-right: 1px solid var(--tdup-border); }
.tdup-about-figures__list li:last-child { border-right: 0; }
.tdup-about-figures__list strong { display: block; white-space: nowrap; font: 700 clamp(20px, 2.1vw, 32px)/1 var(--tdup-font-title); color: var(--tdup-red); }
.tdup-about-figures__list span { display: block; margin-top: 6px; font-size: 13px; font-weight: 700; color: var(--tdup-charcoal); }
.tdup-about-site { margin-bottom: 56px; }
.tdup-about-site__grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
.tdup-about-site__card { background: var(--tdup-white); border: 1px solid var(--tdup-border); display: flex; flex-direction: column; }
.tdup-about-site__card img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block; }
.tdup-about-site__body { padding: 14px 16px 16px; }
.tdup-about-site__body h3 { margin: 0 0 6px; font: 700 15px/1.2 var(--tdup-font-title); color: var(--tdup-charcoal); }
.tdup-about-site__body p { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--tdup-charcoal); }
.tdup-about-quality { background: var(--tdup-charcoal); color: var(--tdup-white); padding: clamp(40px, 5vw, 64px) 0; margin-bottom: 56px; }
.tdup-about-quality__inner { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); gap: 40px; align-items: start; }
.tdup-about-quality h2 { color: var(--tdup-white); font-weight: 600; text-transform: uppercase; font-size: clamp(1.6rem, 3vw, 2.4rem); margin: 4px 0 0;font-stretch: 125%; letter-spacing: 0.06em;}
.tdup-about-quality__text p { color: rgba(255, 255, 255, 0.88); font-size: 15px; line-height: 1.65; }
.tdup-about-quality__text .tdup-button { margin-top: 8px; }
@media (max-width: 900px) {
	.tdup-about-site__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.tdup-about-quality__inner { grid-template-columns: 1fr; gap: 12px; }
}
@media (max-width: 480px) { .tdup-about-site__grid { grid-template-columns: 1fr; } }


/* ===========================================================================
   FAQs page (page-templates/page-faq.php), 2026-10-21.
   Questions grouped by topic; each is a <details> that opens on click, so the
   page reads as a short scannable list. A topic link row at the top jumps to
   each group. Flat with hairlines, like the rest of the site.
   ========================================================================= */
.tdup-faq__intro { font-size: 17px; color: var(--tdup-body-grey); margin: 0 0 20px; }
.tdup-faq__topics { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 8px; }
.tdup-faq__topics a {
	display: inline-block; padding: 6px 12px; border: 1px solid var(--tdup-border);
	font: 700 13px/1.3 var(--tdup-font-title); color: var(--tdup-charcoal); text-decoration: none;
}
.tdup-faq__topics a:hover, .tdup-faq__topics a:focus-visible { border-color: var(--tdup-red); color: var(--tdup-red); }
.tdup-faq__group { scroll-margin-top: 120px; }
.tdup-faq__group h2 { margin: 1.6em 0 0.4em; }
.tdup-faq__item { border-bottom: 1px solid var(--tdup-border); }
.tdup-faq__item:first-of-type { border-top: 1px solid var(--tdup-border); }
.tdup-faq__item summary {
	cursor: pointer; list-style: none; position: relative;
	padding: 16px 40px 16px 0; min-height: 24px;
	font: 700 16px/1.4 var(--tdup-font-title); color: var(--tdup-charcoal);
}
.tdup-faq__item summary::-webkit-details-marker { display: none; }
/* A plus that turns into a minus when the answer is open. */
.tdup-faq__item summary::after {
	content: "+"; position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
	font: 400 24px/1 var(--tdup-font-body); color: var(--tdup-red);
}
.tdup-faq__item[open] summary::after { content: "\2212"; }
.tdup-faq__item summary:hover, .tdup-faq__item summary:focus-visible { color: var(--tdup-red); }
.tdup-faq__answer { padding: 0 0 18px; color: var(--tdup-body-grey); }
.tdup-faq__answer > :first-child { margin-top: 0; }
.tdup-faq__answer > :last-child { margin-bottom: 0; }

/* ===========================================================================
   Certifications page (page-templates/page-certifications.php).
   "Certificates & Approvals" panel, 2026-10-21, after Chris Corbett's own
   artwork: a charcoal panel with a red diagonal down the left, one row per
   standard. Left: the standard and what it covers. Right: the white BSI
   mark(s) with the certificate number under each. The three Kitemarks sit
   side by side in one row.
   ========================================================================= */
.tdup-certs__intro { margin-bottom: 8px; }

.tdup-approvals { position: relative; isolation: isolate; overflow: hidden; margin: 32px 0 48px; padding: 36px 40px 40px; background: var(--tdup-charcoal); color: var(--tdup-white); }
/* The red diagonal: wider at the bottom than the top, as in the artwork. */
.tdup-approvals::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--tdup-red); clip-path: polygon(0 0, 20% 0, 32% 100%, 0 100%); }
.tdup-approvals__heading { margin: 0 0 8px; font: 700 clamp(26px, 3vw, 36px)/1.1 var(--tdup-font-title); color: var(--tdup-white); }
.tdup-approvals__list { list-style: none; margin: 0; padding: 0; }
/* Each row: text left, marks right, a hairline between rows. */
.tdup-approvals__row { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: 24px 40px; align-items: center; padding: 22px 0; border-top: 1px solid var(--tdup-band-border); }
.tdup-approvals__row:first-child { border-top: 0; }
.tdup-approvals__name { margin: 0 0 6px; font: 700 22px/1.2 var(--tdup-font-title); color: var(--tdup-white); }
.tdup-approvals__scope { margin: 0; max-width: 34ch; font-size: 16px; line-height: 1.5; color: rgba(255, 255, 255, 0.9); }
/* Marks line up from the left of their column, so every row's first mark
   starts on the same edge; the three Kitemarks sit in one line beside it. */
.tdup-approvals__marks { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 16px 28px; }
.tdup-approvals__mark { display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center; }
.tdup-approvals__mark img { display: block; width: 172px; height: auto; }
.tdup-approvals__number { font: 700 15px/1.2 var(--tdup-font-title); letter-spacing: 0.04em; color: var(--tdup-white); }
.tdup-approvals__issuer { font-size: 14px; color: rgba(255, 255, 255, 0.85); }
.tdup-approvals__link { font-size: 13.5px; font-weight: 700; color: var(--tdup-red-light); }
.tdup-approvals__link:hover, .tdup-approvals__link:focus-visible { color: var(--tdup-white); }

/* Tablet: stack the text above the marks; the diagonal becomes a thin red edge so text isn't half on red. */
@media (max-width: 900px) {
	.tdup-approvals { padding: 28px 24px 28px 32px; }
	.tdup-approvals::before { clip-path: polygon(0 0, 8px 0, 8px 100%, 0 100%); }
	.tdup-approvals__row { grid-template-columns: 1fr; }
}
/* Phone: marks smaller so two fit side by side. */
@media (max-width: 560px) {
	.tdup-approvals { padding: 24px 16px 24px 24px; }
	.tdup-approvals__marks { gap: 16px 12px; }
	.tdup-approvals__mark img { width: 128px; }
	.tdup-approvals__number { font-size: 14px; }
}

/* ==========================================================================
   HOMEPAGE: the "brochure cover" design (2026-11-03)

   Built from the approved mock-up ("50 - Layout Plans/Homepage bold
   2026-11-03/homepage-bold.html"; its comments explain each decision).
   Layout idea: the company's printed covers (a charcoal field, a red wedge
   cutting in from the left, heavy white capitals) become the website's
   surface. The page STRUCTURE is the standard trade homepage.

   Everything here is scoped under main.tdup-home and uses an hp- prefix, so
   no other page is touched. Markup: tdup_render_home_*() in inc/homepage.php.
   The old homepage CSS (.tdup-hero, .tdup-classes, .tdup-quick-order,
   .tdup-proof, .tdup-resources, .tdup-news-feature ...) was deleted when this
   replaced it.

   Rules that hold across the whole block (learned in the mock-up reviews):
   1. ANGLE RULE. A band with an angled top is pulled up by --cut, so the
      section above must add --cut to its bottom padding. Then the angle only
      ever cuts photos, never buttons, labels or text.
   2. A hover never turns text the colour of its own background. Underline
      links on dark or red bands thicken their underline instead; only links
      on LIGHT sections also turn red.
   3. Focus is a white outline with a dark ink ring outside it: visible on
      red, charcoal and white alike. Never a red ring (it vanished on red).
   4. Product images are never drawn above their own size (1x): CSS only sets
      maximums, never widths, on product pictures.
   5. Every anchor sets its colour for the normal AND the :hover state,
      because the site-wide `a:hover` rule would otherwise recolour it.
   ========================================================================== */

/* The wedge angle, shared by every diagonal so they all read as one cut. */
.tdup-home {
	--cut: clamp(32px, 7vw, 110px);
	--hp-ch: var(--tdup-charcoal);
	--hp-chd: var(--tdup-charcoal-2);
	--hp-ink: var(--tdup-ink);
	--hp-red: var(--tdup-red);
	--hp-redd: var(--tdup-red-dark);
	--hp-sweep: #E7E8E9;  /* light studio sweep behind products */
	--hp-sf: #F4F5F6;     /* pale surface */
	--hp-rule: var(--tdup-rule);
	--hp-g2: #54595F;
	--hp-g3: #6E6E6E;
	background: var(--hp-chd);
	color: var(--hp-ch);
	font-family: var(--tdup-font-body);
	font-size: 17px;
	line-height: 1.55;
	overflow-x: hidden;
}
/* The site footer is deep "ink" under the contact band (and flush against it). */
.tdup-home + .tdup-footer { margin-top: 0; background: var(--tdup-ink); }
.tdup-home [id] { scroll-margin-top: 96px; } /* anchors land below the sticky header */

/* Homepage content column: up to 1552px of content (1680 minus the gutters),
   so wide screens are used instead of leaving big empty side margins. A
   modifier on .tdup-container, so the global container is untouched. */
.tdup-container--wide {
	max-width: 1680px;
	padding-left: max(16px, env(safe-area-inset-left, 0px));
	padding-right: max(16px, env(safe-area-inset-right, 0px));
}
@media (min-width: 900px) {
	.tdup-container--wide {
		padding-left: max(clamp(32px, 3.5vw, 64px), env(safe-area-inset-left, 0px));
		padding-right: max(clamp(32px, 3.5vw, 64px), env(safe-area-inset-right, 0px));
	}
}

.tdup-home :where(h1, h2, h3, p, ul, ol, figure) { margin: 0; }
.tdup-home :where(ul, ol) { padding: 0; list-style: none; }
.tdup-home :where(img) { display: block; max-width: 100%; height: auto; }
.tdup-home :where(a), .tdup-home :where(a):hover { color: inherit; }
.tdup-home :where(button, input, select, textarea) { font: inherit; color: inherit; }
.tdup-home :focus-visible { outline: 3px solid #fff; outline-offset: 2px; box-shadow: 0 0 0 6px var(--hp-ink); }

/* ---- Type roles ---- */
/* Headings: Archivo 800, 112% wide, uppercase (the printed brochures' titles). */
.tdup-home .hp-cap { font-family: var(--tdup-font-title); font-stretch: 112%; font-weight: 800; text-transform: uppercase; letter-spacing: .005em; line-height: .98; overflow-wrap: break-word; }
.tdup-home .hp-lab { font-family: var(--tdup-font-title); font-stretch: 125%; font-weight: 600; text-transform: uppercase; letter-spacing: .18em; font-size: 12px; line-height: 1.3; }
.tdup-home .hp-h2 { font-size: clamp(30px, 4vw, 54px); text-wrap: balance; }
.tdup-home .hp-lede { font-size: 18px; max-width: 58ch; }

/* ---- Buttons ---- */
.hp-btn { display: inline-flex; align-items: center; justify-content: center; gap: 12px; min-height: 52px; padding: 0 24px; border: 0; cursor: pointer; text-decoration: none;
	font-family: var(--tdup-font-title); font-stretch: 118%; font-weight: 700; font-size: 14px; letter-spacing: .1em; text-transform: uppercase; white-space: nowrap; }
.hp-btn--red, .hp-btn--red:hover { background: var(--hp-red); color: #fff; }
.hp-btn--red:hover { background: var(--hp-redd); }
.hp-btn--white, .hp-btn--white:hover { background: #fff; color: var(--hp-ch); }
.hp-btn--white:hover { background: var(--hp-sweep); }
.hp-btn--line, .hp-btn--line:hover { background: transparent; color: var(--hp-ch); box-shadow: inset 0 0 0 2px var(--hp-ch); }
.hp-btn--line:hover { background: var(--hp-ch); color: #fff; }
.hp-btn:disabled { background: #6B7073; color: #fff; cursor: default; }
.hp-arr { width: 16px; height: 16px; flex: none; }

/* Section heading lockup: big caps, then a short plain line beside it. */
.hp-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 12px 32px; margin-bottom: 28px; }
.hp-head > div { min-width: 0; }
.hp-head p { margin-top: 10px; }
.hp-more, .hp-more:hover { font-family: var(--tdup-font-title); font-stretch: 118%; font-weight: 700; font-size: 13px; letter-spacing: .1em; text-transform: uppercase; text-decoration: none; color: inherit;
	display: inline-flex; align-items: center; gap: 8px; min-height: 44px; border-bottom: 2px solid currentColor; }
/* Hover thickens the underline instead of changing colour, so a link on a red
   or charcoal band can't turn red-on-red and vanish. Only the light sections
   also turn it red. */
.hp-more:hover { box-shadow: inset 0 -2px 0 currentColor; }
.tdup-home .hp-range .hp-more:hover, .tdup-home .hp-popular .hp-more:hover { color: var(--hp-red); }

/* ==========================================================================
   1. HERO: the brochure cover
   Layers, back to front:
     1. the charcoal field (the section background)
     2. Chris's ordinary photos (JPEGs), each toned dark on the text side
     3. Chris's renders / cut-outs, bleeding off the right and bottom, as on
        the printed brochures
     4. the text
   (The red wedge that used to sit between 2 and 3 was removed on 2026-11-03
   at Chris's request. The wedge is still used by "Need it today?" below.)
   Gallery order is kept (the slideshow script sorts the two layers back into
   it). A render is never laid on top of a photo, which made a single cover
   look pasted on.
   ========================================================================== */
/* The hero field. Chris (3 Nov) felt the castings sat badly on the plain dark
   background: black iron on flat charcoal turns murky. So the field is lit like
   a studio shot: a pool of light behind and under the castings (right), fading
   to the brand charcoal on the left where the text sits, so the text keeps its
   contrast. It also fixes an editor's white-background render (blended with
   "multiply", its white takes this lit grey). The photo slides cover it. */
.hp-hero { position: relative; color: #fff; isolation: isolate; overflow: hidden;
	background: var(--hp-ch) radial-gradient(ellipse 46% 88% at 79% 76%, #C4C8CA 0%, #9DA2A5 28%, #6C7174 56%, var(--hp-ch) 84%) no-repeat; }
.hp-hero__photos { position: absolute; inset: 0; z-index: 1; }
.hp-hero__slide { opacity: 0; }
.hp-hero__slide.is-leaving { opacity: 1; }
.hp-hero__slide.is-active { opacity: 1; transition: opacity 1.8s ease-in-out; }
/* Fading OUT. Photo to photo, the outgoing photo stays at full strength
   underneath while the new one fades in on top (no dip in the middle). But the
   render is its own layer ABOVE the photos, so it can't be covered: it fades
   out itself while the photo fades in beneath it. And a photo making way for
   the render fades out too, so the lit field behind the castings appears
   gradually instead of jumping in when the photo is removed. */
.hp-hero__render { transition: opacity 1.8s ease-in-out; }
.hp-hero__render.is-leaving { opacity: 0; }
.hp-hero:has(.hp-hero__render.is-active) .hp-hero__photo.is-leaving { opacity: 0; transition: opacity 1.8s ease-in-out; }
.hp-hero__photo { position: absolute; inset: 0; }
.hp-hero__photo.is-active { z-index: 1; }
.hp-hero__photo img { width: 100%; height: 100%; object-fit: cover; }
/* Photos keep their own colour (Lee, 3 Nov: not every image needs the same
   heavy darkening). The text side is already shaded by .hp-hero::after above
   every slide, so each photo only gets a light, even tint for depth. */
.hp-hero__photo::after { content: ""; position: absolute; inset: 0; background: rgba(38, 41, 43, .18); }
/* the render: its own layer above the photos, faded in from the left and top
   so it melts into the field instead of sitting in a box */
/* A soft charcoal shade on the text side, ABOVE the castings and below the
   text (z-index 3), so white text always has strong contrast whatever is
   behind it (the render's bright highlights, or a pale photo). It fades out
   before the middle, so the lit castings on the right are untouched. */
.hp-hero::after { content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none;
	background: linear-gradient(90deg, rgba(52, 55, 58, .9) 0%, rgba(52, 55, 58, .8) 40%, rgba(52, 55, 58, .4) 54%, rgba(52, 55, 58, 0) 64%); }
.hp-hero__render { position: absolute; z-index: 2; right: 0; bottom: 0; width: min(66%, 1150px);
	-webkit-mask-image: linear-gradient(to right, transparent 0, #000 40%), linear-gradient(to bottom, transparent 0, #000 22%);
	-webkit-mask-composite: source-in;
	mask-image: linear-gradient(to right, transparent 0, #000 40%), linear-gradient(to bottom, transparent 0, #000 22%);
	mask-composite: intersect; }
.hp-hero__render img { width: 100%; max-width: none; }
/* A render on a white background (like Marketing's exhibition render, the
   built-in default): "multiply" makes its white take the lit field behind it,
   and the castings keep their own floor shadows. Because the picture was
   never cut out, there's no rough fringe round the castings (the dark cut-out
   used before showed one once the field was lit, 3 Nov). */
.hp-hero__render--blend { mix-blend-mode: multiply; }
.hp-hero__inner { position: relative; z-index: 4; display: grid; grid-template-columns: minmax(0, 1fr); padding-top: 56px; padding-bottom: 0; min-height: min(640px, 80vh); align-content: space-between; }
.hp-hero__copy { padding-bottom: 40px; max-width: clamp(760px, 50vw, 900px); min-width: 0; }
/* The eyebrow is the first thing people read, so it is bigger than a normal
   label: 14px on phones (two lines at most), growing to 18px on wide screens
   (15px at 1440). Full white, no fade, and slightly tighter letter-spacing
   than .hp-lab so the longer line still fits. */
.tdup-home .hp-hero__eyebrow { color: #fff; font-size: clamp(14px, 1.05vw, 18px); letter-spacing: .14em; line-height: 1.35; }
.tdup-home .hp-hero h1 { color: #fff; font-size: clamp(36px, 4.3vw, 66px); margin-top: 16px; text-wrap: balance; }
/* Chris's slogan: wide caps under the headline (no decoration after it). */
.hp-hero__strap { margin-top: 18px; font-family: var(--tdup-font-title); font-stretch: 125%; font-weight: 600; text-transform: uppercase; letter-spacing: .14em; font-size: clamp(13px, 1.15vw, 16px); line-height: 1.35; }
.hp-hero__sub { margin-top: 20px; font-size: 19px; line-height: 1.5; max-width: 52ch; color: rgba(255, 255, 255, .92); }
.hp-hero__sub strong { color: #fff; }
.hp-hero__actions { margin-top: 28px; display: flex; flex-wrap: wrap; align-items: center; gap: 12px 18px; }
.hp-hero__note { font-size: 15px; color: rgba(255, 255, 255, .9); }
.hp-hero__routes { display: flex; flex-wrap: wrap; gap: 10px 28px; margin-top: 16px; }
.hp-route, .hp-route:hover { display: flex; flex-direction: column; gap: 2px; text-decoration: none; color: #fff; }
.hp-route__label { font-family: var(--tdup-font-title); font-stretch: 118%; font-weight: 700; font-size: 13px; letter-spacing: .1em; text-transform: uppercase; align-self: flex-start; padding: 12px 0 2px; border-bottom: 2px solid currentColor; }
.hp-route:hover .hp-route__label { box-shadow: inset 0 -2px 0 currentColor; }
.hp-route__text { font-size: 13.5px; color: rgba(255, 255, 255, .9); }
/* The certificates line along the bottom of the hero. A dark band behind it
   keeps it readable where it crosses the render. */
.hp-hero__proof { position: relative; display: flex; flex-wrap: wrap; gap: 6px 28px; padding-top: 14px; padding-bottom: 16px; }
.hp-hero__proof::before { content: ""; position: absolute; top: 0; bottom: 0; left: -100vw; right: -100vw; background: rgba(38, 41, 43, .72); border-top: 1px solid rgba(255, 255, 255, .16); z-index: -1; }
.hp-hero__proof li { font-family: var(--tdup-font-title); font-stretch: 118%; font-weight: 600; font-size: 12px; letter-spacing: .08em; text-transform: uppercase; color: rgba(255, 255, 255, .88); }
.hp-hero__proof b { color: #fff; font-weight: 800; }
/* Pause / play (WCAG 2.2.2) */
.tdup-motion-toggle.hp-pause { z-index: 5; right: max(16px, env(safe-area-inset-right, 0px)); top: 16px; width: 44px; height: 44px; border: 0; background: rgba(0, 0, 0, .35); }
.tdup-motion-toggle.hp-pause:hover { background: rgba(0, 0, 0, .6); border-color: transparent; }
/* Narrow laptops: the text takes more of the width, so the castings get a
   smaller share and the text-side shade reaches further. */
@media (min-width: 981px) and (max-width: 1279px) {
	.hp-hero__render { width: 54%; }
	.hp-hero::after { background: linear-gradient(90deg, rgba(52, 55, 58, .9) 0%, rgba(52, 55, 58, .82) 50%, rgba(52, 55, 58, .4) 62%, rgba(52, 55, 58, 0) 72%); }
}
@media (max-width: 980px) {
	.hp-hero__inner { min-height: 0; padding-top: 40px; }
	/* on tablets and phones the render sits under the text, full width */
	.hp-hero__copy { padding-bottom: clamp(200px, 56vw, 430px); }
	/* On tablets and phones the text runs most of the way down, over the
	   photos, so the shade reaches further and photos get more tone. */
	.hp-hero::after { background: linear-gradient(180deg, rgba(52, 55, 58, .9) 0%, rgba(52, 55, 58, .86) 62%, rgba(52, 55, 58, 0) 82%); }
	.hp-hero__photo::after { background: rgba(38, 41, 43, .5); }
	.hp-hero { background-image: radial-gradient(ellipse 90% 45% at 55% 88%, #C4C8CA 0%, #9DA2A5 26%, #6C7174 55%, var(--hp-ch) 85%); }
	.hp-hero__render { width: 100%; bottom: 40px; -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 30%); mask-image: linear-gradient(to bottom, transparent 0, #000 30%); }
}
@media (max-width: 560px) {
	.tdup-home .hp-hero h1 { font-size: clamp(34px, 10vw, 44px); }
	.hp-hero__sub { font-size: 17px; }
	.hp-hero__routes { gap: 4px 18px; }
	.hp-route__label { font-size: 11.5px; }
	.hp-hero__proof { gap: 4px 16px; }
	.hp-hero__proof li { font-size: 11px; }
	.hp-hero__render { bottom: 66px; }
}

/* ==========================================================================
   2. BROWSE THE RANGE: an EVEN wall of products on a light studio sweep.
   Middle ground after Chris asked for the old wall back: his even grid (every
   category the same size, 4 across, 2 on phones) with our studio sweep and
   charcoal name tab. Adds --cut to its bottom padding (ANGLE RULE: the red
   load class band is pulled up over it).
   ========================================================================== */
.hp-range { background: var(--hp-sf); padding-top: 56px; padding-bottom: calc(48px + var(--cut)); color: var(--hp-ch); }
.tdup-home .hp-range .hp-h2 { color: var(--hp-red); }
.hp-range .hp-lede { color: var(--hp-g2); }
.hp-wall { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 2px; background: var(--hp-rule); border: 2px solid var(--hp-rule); }
.hp-wall > li { display: flex; min-width: 0; }
.hp-wall a, .hp-wall a:hover { position: relative; flex: 1; display: grid; grid-template-rows: 1fr auto; min-height: 250px; min-width: 0; text-decoration: none; color: var(--hp-ch);
	background: radial-gradient(120% 90% at 50% 38%, #fff 0%, var(--hp-sweep) 70%, #DADCDD 100%); overflow: hidden; }
.hp-wall__ph { display: flex; align-items: center; justify-content: center; padding: 22px 22px 6px; }
/* maximums only: a picture never grows past its own size */
/* multiply: a render saved with a white background (Ancillary Products) takes the
   sweep colour instead of showing as a white box; dark castings stay as they are.
   The tile (a) is its own stacking context (isolation) so the blend sees the sweep. */
.hp-wall a { isolation: isolate; }
.hp-wall img { width: auto; height: auto; max-width: min(100%, 300px); max-height: 170px; object-fit: contain; mix-blend-mode: multiply; transition: transform .35s ease; }
.hp-wall a:hover img { transform: scale(1.06) translateY(-4px); }
/* THE NAME TAB. Every tab is exactly the same height, whatever the name:
   the name box is always two lines tall (the longest real names,
   "Surface, Stop Tap & Boundary Boxes" and "Rainwater Drainage Castings",
   need two), and the count always sits on its own line underneath, so name
   and count line up across every tile. The 2.2em is two lines at the 1.1
   line-height below. If a name ever needed three lines the tab would grow,
   so the font sizes in the media queries are chosen to keep the longest on
   two lines (measured at 375, 768, 1440 and 1920). */
.hp-wall__nm { display: flex; flex-direction: column; justify-content: flex-start; gap: 4px; padding: 14px 16px 14px; background: var(--hp-ch); color: #fff; transition: background .2s; }
.hp-wall a:hover .hp-wall__nm { background: var(--hp-redd); }
.hp-wall__nm strong { display: block; min-height: 2.2em; font-family: var(--tdup-font-title); font-stretch: 112%; font-weight: 800; font-size: clamp(14px, 1.15vw, 19px); line-height: 1.1; text-transform: uppercase; }
.hp-wall__nm span { font-size: 13.5px; line-height: 1.3; color: rgba(255, 255, 255, .88); }
@media (max-width: 980px) {
	.hp-wall { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.hp-wall__nm strong { font-size: 17px; }
}
@media (max-width: 560px) {
	.hp-range { padding-top: 72px; padding-bottom: calc(48px + var(--cut)); }
	.hp-wall a, .hp-wall a:hover { min-height: 190px; }
	.hp-wall__ph { padding: 16px 12px 4px; }
	.hp-wall__nm { padding: 10px 12px 12px; }
	.hp-wall__nm strong { font-size: 12.5px; font-stretch: 100%; letter-spacing: 0; }
	.hp-wall__nm span { font-size: 12.5px; }
}

/* ==========================================================================
   3. LOAD CLASS: a red band holding a row of white spec-sheet cells.
   Middle ground after Chris asked for the old row back: the band stays red
   with its angled top edge (that is the brand), but each class is a white
   ruled cell again (bar, drawing, code, where, one sentence, count), because
   the company's drawings were drawn for white. The code is big but one weight
   down from a poster, so the cell reads like a spec sheet. The top edge is cut
   at the wedge angle and the band is pulled up over the one above it.
   ========================================================================== */
.hp-lc { background: var(--hp-red); color: #fff; padding-top: calc(56px + var(--cut)); padding-bottom: 56px; clip-path: polygon(0 var(--cut), 100% 0, 100% 100%, 0 100%); margin-top: calc(-1 * var(--cut)); position: relative; }
.tdup-home .hp-lc .hp-h2 { color: #fff; }
.hp-lc .hp-lede { color: rgba(255, 255, 255, .92); }
/* --n (set in the PHP) = number of cells; the 2px gaps show the dark rule behind */
.hp-lc__row { display: grid; grid-template-columns: repeat(var(--n, 5), minmax(0, 1fr)); gap: 1px; background: var(--hp-rule); border: 2px solid rgba(0, 0, 0, .22); }
/* The street drawing: each cell's stretch runs edge to edge across the top of
   its cell (cancelling the cell's 16px padding), on a light "sky", so the five
   stretches join up into one street across the row. 1px gaps between cells
   (above, the logo's light hairline, so the dividers don't cut through the drawing) keep the join reading as one line. Hovering a cell tints its stretch. */
.hp-lc__street { display: block; width: calc(100% + 32px); max-width: none; height: auto; margin: -16px -16px 14px; background: var(--hp-sf); transition: background .2s; }
.hp-lc__row a:hover .hp-lc__street { background: #F3E4E7; }
.hp-lc__row > li { display: flex; min-width: 0; }
/* The cell: white, dark text. Hover only lightens the white to the pale
   surface, so the text never changes colour. Focus is drawn INSIDE the cell
   (dark ring outside a white ring) because the row can scroll on phones and a
   ring outside the cell would be clipped there. */
.hp-lc__row a, .hp-lc__row a:hover { flex: 1; display: flex; flex-direction: column; min-width: 0; background: #fff; text-decoration: none; color: var(--hp-ch); padding: 16px 16px 14px; transition: background .2s; }
.hp-lc__row a:hover { background: var(--hp-sf); }
.hp-lc__row a:focus-visible { outline: 3px solid #fff; outline-offset: -6px; box-shadow: inset 0 0 0 3px var(--hp-ink); }
/* the 5-segment bar: this class red, the rest grey (same bar as the product cards) */
.hp-lc__bar { display: grid; grid-template-columns: repeat(5, 1fr); gap: 3px; }
.hp-lc__bar i { height: 6px; background: var(--hp-rule); }
.hp-lc__bar i.on { background: var(--hp-red); }
/* Same-height box for every drawing (they have different proportions), so
   the code and text underneath line up across the row. They sit on the cell's
   white, which they were drawn for. */
.hp-lc__img { margin: 12px 0 8px; display: flex; align-items: center; justify-content: center; aspect-ratio: 360 / 217; }
.hp-lc__img img { width: auto; max-width: 100%; height: auto; }
.tdup-home .hp-lc__code { font-size: clamp(28px, 2.5vw, 40px); letter-spacing: -.01em; line-height: 1; color: var(--hp-ch); }
.hp-lc__kn { font-family: var(--tdup-font-title); font-stretch: 118%; font-weight: 600; font-size: 12px; letter-spacing: .06em; text-transform: uppercase; margin-top: 6px; color: var(--hp-g2); }
.hp-lc__where { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--hp-rule); font-family: var(--tdup-font-title); font-stretch: 108%; font-weight: 800; font-size: 15px; line-height: 1.25; text-transform: uppercase; color: var(--hp-ch); }
.hp-lc__detail { margin-top: 6px; font-size: 14px; line-height: 1.45; color: var(--hp-g2); }
.hp-lc__n { margin-top: auto; padding-top: 12px; font-size: 14px; font-weight: 700; display: flex; justify-content: space-between; gap: 8px; color: var(--hp-red); }
.hp-lc__n > span:first-child { padding-top: 10px; border-top: 1px solid var(--hp-rule); flex: 1; }
.hp-lc__go { transition: transform .2s; align-self: flex-end; }
.hp-lc__row a:hover .hp-lc__go { transform: translateX(4px); }
.hp-lc__note { margin-top: 18px; font-size: 15px; color: rgba(255, 255, 255, .95); }
/* Tablets: 3 across, and the second row stretches over what's left, so there
   is never an empty cell. The 2px gaps still show the rule colour. */
@media (max-width: 1099px) {
	.hp-lc__row { display: flex; flex-wrap: wrap; }
	.hp-lc__row > li { flex: 1 1 calc(33.333% - 2px); }
}
/* Phones: a swipe row, one cell nearly full width with the next peeking in, so
   every cell keeps room for its sentence and they all stay the same height. */
@media (max-width: 699px) {
	.hp-lc__row { display: grid; grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: 80%; overflow-x: auto; scroll-snap-type: x mandatory; overscroll-behavior-x: contain; }
	.hp-lc__row > li { scroll-snap-align: start; }
}

/* ==========================================================================
   4. SECTORS: a two-column ruled list on deep charcoal.
   Middle ground after Chris asked for the old list back: his structure (a row
   per sector: name, count, arrow; two columns; easy to scan) with a small photo
   at the start of each row so it still looks like our site.
   ========================================================================== */
.hp-sectors { background: var(--hp-chd); color: #fff; padding-top: 56px; padding-bottom: 56px; }
.tdup-home .hp-sectors .hp-h2 { color: #fff; }
.hp-sectors .hp-lede { color: rgba(255, 255, 255, .88); }
/* Two columns split by a gutter; each row has its own rule underneath. */
.hp-sl { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(24px, 4vw, 56px); border-top: 2px solid rgba(255, 255, 255, .35); }
.hp-sl > li { border-bottom: 1px solid rgba(255, 255, 255, .2); min-width: 0; }
/* an odd last row spans both columns, so there is never an empty cell */
.hp-sl > li:last-child:nth-child(odd) { grid-column: 1 / -1; }
/* The row. Hover lightens the row background a little (white text stays
   readable on it); it never changes the text colour. */
.hp-sl a, .hp-sl a:hover { display: flex; align-items: center; gap: 16px; min-height: 76px; padding: 6px 12px 6px 0; text-decoration: none; color: #fff; transition: background .2s, padding .2s; }
.hp-sl a:hover { background: rgba(255, 255, 255, .1); padding-left: 8px; }
.hp-sl__ph { flex: none; width: 64px; height: 64px; overflow: hidden; background: var(--hp-ink); }
.hp-sl__ph img { width: 100%; height: 100%; max-width: none; object-fit: cover; }
.hp-sl__name { flex: 1; min-width: 0; font-family: var(--tdup-font-title); font-stretch: 108%; font-weight: 800; font-size: 19px; line-height: 1.15; text-transform: uppercase; }
.hp-sl__n { flex: none; font-size: 14px; color: rgba(255, 255, 255, .88); white-space: nowrap; }
/* the arrow: white on a red chip (a bare red arrow is too faint on charcoal) that slides right on hover */
.hp-sl__go { flex: none; display: flex; align-items: center; justify-content: center; width: 36px; height: 36px; background: var(--hp-red); color: #fff; transition: transform .2s; }
.hp-sl a:hover .hp-sl__go { transform: translateX(6px); }
/* The closing row: a red strip after the list, so the question has its own
   weight and the list above never ends on an odd cell. */
.hp-sl__ask { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px 24px; margin-top: 24px; padding: 16px 20px; background: var(--hp-red); }
.hp-sl__ask p { font-family: var(--tdup-font-title); font-stretch: 112%; font-weight: 800; font-size: clamp(17px, 1.6vw, 22px); line-height: 1.15; text-transform: uppercase; }
@media (max-width: 760px) {
	.hp-sl { grid-template-columns: 1fr; }
	.hp-sl > li:last-child:nth-child(odd) { grid-column: auto; }
	.hp-sl__name { font-size: 16px; }
	.hp-sl__ph { width: 56px; height: 56px; }
	.hp-sl a, .hp-sl a:hover { gap: 12px; }
	.hp-sl__ask .hp-btn { width: 100%; white-space: normal; text-align: center; }
}

/* ==========================================================================
   5. POPULAR PRODUCTS: Chris's four picks, dense cards
   ========================================================================== */
.hp-popular { background: var(--hp-sf); padding-top: 56px; padding-bottom: 56px; color: var(--hp-ch); }
.tdup-home .hp-popular .hp-h2 { color: var(--hp-red); }
.hp-popular .hp-lede { color: var(--hp-g2); }
.hp-cards { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
.hp-card { display: flex; flex-direction: column; background: #fff; border: 1px solid var(--hp-rule); min-width: 0; }
.hp-card__ph { position: relative; display: flex; align-items: center; justify-content: center; padding: 28px 18px 18px; aspect-ratio: 4 / 3;
	background: radial-gradient(120% 90% at 50% 40%, #fff 0%, var(--hp-sweep) 75%); }
.hp-card__ph { isolation: isolate; }
/* multiply: white-background photos blend into the studio sweep (see .hp-wall img) */
.hp-card__ph img { max-height: 100%; width: auto; max-width: 100%; object-fit: contain; mix-blend-mode: multiply; }
.tdup-home .hp-card__class { position: absolute; left: 0; top: 0; background: var(--hp-ch); color: #fff; padding: 6px 10px 5px; font-size: 18px; }
.hp-card__body { padding: 14px 16px 16px; display: flex; flex-direction: column; gap: 6px; flex: 1; }
.tdup-home .hp-card h3 { font-family: var(--tdup-font-title); font-stretch: 110%; font-weight: 800; font-size: 19px; line-height: 1.15; text-transform: uppercase; color: var(--hp-ch); margin: 0; }
.hp-card h3 a { text-decoration: none; }
.hp-card h3 a:hover { text-decoration: underline; }
.hp-card__meta { font-size: 15px; color: var(--hp-g2); }
.hp-card__tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }
.hp-card__tags span { font-size: 12px; font-weight: 700; padding: 3px 8px; background: var(--hp-sf); border: 1px solid var(--hp-rule); }
/* The load-class bar (DESIGN.md): where this class sits on the B125 to F900 scale */
.hp-bar { display: grid; grid-template-columns: repeat(5, 1fr); gap: 2px; margin-top: 6px; }
.hp-bar i { height: 6px; background: var(--hp-rule); }
.hp-bar i.on { background: var(--hp-red); }
.hp-bar-k { display: flex; justify-content: space-between; font-size: 10px; color: var(--hp-g3); font-weight: 700; letter-spacing: .04em; margin-top: 3px; }
.hp-card__act { display: flex; gap: 8px; margin-top: auto; padding-top: 12px; }
.hp-card__act .hp-btn { flex: 1; min-height: 46px; padding: 0 12px; font-size: 12.5px; }
.hp-card__ds, .hp-card__ds:hover { flex: none; width: 46px; min-height: 46px; display: flex; align-items: center; justify-content: center; border: 2px solid var(--hp-ch); color: var(--hp-ch); text-decoration: none; font: 800 11px var(--tdup-font-title); }
.hp-card__ds:hover { background: var(--hp-ch); color: #fff; }
@media (max-width: 1080px) { .hp-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 480px) {
	.hp-cards { gap: 10px; }
	.tdup-home .hp-card h3 { font-size: 15px; }
	.hp-card__body { padding: 10px 12px 12px; }
	.hp-card__meta { font-size: 13px; }
	.hp-card__act { flex-direction: column; }
	.hp-card__ds, .hp-card__ds:hover { width: 100%; }
	/* narrow two-up cards: keep the button label on one line */
	.hp-card__act .hp-btn { font-size: 11px; letter-spacing: .05em; padding: 0 8px; }
	.hp-card__act .hp-btn .hp-arr { display: none; }
}

/* ==========================================================================
   6. NEED IT TODAY: the brochure wedge again, holding a huge live countdown
   to the despatch cut-off. The photo's left edge is cut at the wedge angle.
   ========================================================================== */
.hp-today { position: relative; background: var(--hp-ch); color: #fff; isolation: isolate; overflow: hidden; }
.hp-today::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 58%; background: var(--hp-red); z-index: -1; clip-path: polygon(0 0, 100% 0, 82% 100%, 0 100%); }
.hp-today__wrap { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr) minmax(320px, 440px); gap: 32px; padding-top: 56px; padding-bottom: calc(56px + var(--cut)); }
.tdup-home .hp-today .hp-h2 { color: #fff; }
/* the photo runs the full height of the band (cancels the band padding) */
.hp-today__ph { position: relative; margin: -56px 0 calc(-56px - var(--cut)) -32px; min-height: 320px; overflow: hidden; clip-path: polygon(22% 0, 100% 0, 100% 100%, 0 100%); }
.hp-today__ph img { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; object-fit: cover; object-position: 35% 60%; }
.hp-today .hp-lede { color: rgba(255, 255, 255, .92); margin-top: 12px; }
/* The countdown. The script (initDespatchCountdown) fills these three
   elements; the look is all here. "status" is the words above the clock. */
.hp-today .tdup-despatch__status { margin-top: 26px; font-family: var(--tdup-font-title); font-stretch: 125%; font-weight: 600; font-size: 13px; letter-spacing: .14em; text-transform: uppercase; line-height: 1.4; }
.hp-today .tdup-despatch__status em { font-style: normal; display: block; margin-top: 4px; }
.hp-today .tdup-despatch__timer, .hp-today .tdup-despatch__inline-timer { display: block; margin: 6px 0 0; font-family: var(--tdup-font-title); font-stretch: 100%; font-weight: 800; font-size: clamp(52px, 7vw, 104px); line-height: .95; letter-spacing: -.02em; font-variant-numeric: tabular-nums; color: #fff; }
.hp-today .tdup-despatch__timer:empty, .hp-today .tdup-despatch__timer[hidden] { display: none; }
.hp-today .tdup-despatch__units { display: flex; gap: 0; margin-top: 8px; font-family: var(--tdup-font-title); font-stretch: 125%; font-weight: 600; font-size: 11px; letter-spacing: .18em; text-transform: uppercase; }
.hp-today .tdup-despatch__units[hidden] { display: none; }
.hp-today .tdup-despatch__units span + span { margin-left: 1.6em; }
.hp-today .tdup-despatch__note { margin-top: 14px; font-size: 15px; color: rgba(255, 255, 255, .95); max-width: 46ch; }
/* quick add panel */
.hp-qa { background: var(--hp-chd); padding: 24px; align-self: center; border-top: 6px solid #fff; min-width: 0; }
.tdup-home .hp-qa h3 { font-size: 26px; color: #fff; }
.hp-qa > p { margin-top: 8px; font-size: 15px; color: rgba(255, 255, 255, .88); }
.hp-qa__form { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.hp-qa__form input { flex: 1; min-width: 0; min-height: 56px; border: 0; padding: 0 16px; background: #fff; color: var(--hp-ch); font-family: var(--tdup-font-title); font-weight: 700; font-size: 22px; letter-spacing: .12em; border-radius: 0; }
.hp-qa__form input::placeholder { letter-spacing: .04em; font-weight: 400; font-size: 16px; font-family: var(--tdup-font-body); color: var(--hp-g3); }
.hp-qa__form .hp-qa__qty { flex: none; width: 72px; padding: 0 8px; text-align: center; font-size: 18px; letter-spacing: 0; }
.hp-qa__form .hp-btn { flex: 1 0 auto; padding: 0 18px; }
/* The code box must always show all six digits (Lee, 10 Nov 2026: "we can't see the code
   entered"). It only got what was left after the quantity and the button (122px at
   1440px, 102px at 1100px) while the digits needed 127px, so the start scrolled out of
   view. Now the digits are a touch smaller and tighter, and the box never goes below the
   width of six digits; if the row can't fit all three, the button drops to its own
   full-width line underneath (flex-wrap above), the same as on phones. */
.hp-qa__form input:not(.hp-qa__qty) { flex: 1 1 8em; min-width: 8em; font-size: 20px; letter-spacing: .08em; padding: 0 14px; }
.hp-qa__match { min-height: 44px; margin-top: 10px; display: flex; gap: 12px; align-items: center; font-size: 15px; padding: 8px 10px; background: rgba(255, 255, 255, .08); border-left: 4px solid rgba(255, 255, 255, .4); }
.hp-qa__match.is-found { border-left-color: #fff; }
.hp-qa__match img { width: 40px; height: 40px; max-width: none; object-fit: contain; flex: none; background: #fff; }
.hp-qa__match strong { font-family: var(--tdup-font-title); color: #fff; }
.hp-qa__match a, .hp-qa__match a:hover { font-weight: 700; color: #fff; text-decoration: underline; }
.hp-qa__match a:hover { text-decoration-thickness: 3px; }
.hp-qa__foot { margin-top: 10px; display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-start; gap: 10px 16px; font-size: 14px; }
.hp-qa__try { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.hp-qa__try button { min-height: 32px; padding: 0 8px; background: none; border: 1px solid rgba(255, 255, 255, .5); color: #fff; cursor: pointer; }
.hp-qa__try button:hover { background: #fff; color: var(--hp-ch); }
.hp-qa__basket { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 10px; }
.hp-qa__basket ul { font-size: 13px; line-height: 1.5; }
.hp-qa__basket .hp-more { min-height: 32px; font-size: 12px; }
.hp-qa__lines { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 16px; margin-top: 14px; border-top: 1px solid rgba(255, 255, 255, .18); padding-top: 14px; }
.hp-qa__lines li { display: flex; align-items: center; gap: 10px; font-size: 14px; color: rgba(255, 255, 255, .9); min-width: 0; }
.hp-qa__lines img { width: 40px; height: 40px; max-width: none; object-fit: cover; flex: none; }
.hp-qa__lines li b { display: block; font-family: var(--tdup-font-title); font-stretch: 118%; font-weight: 700; font-size: 12px; letter-spacing: .1em; text-transform: uppercase; color: #fff; }
@media (min-width: 981px) and (max-width: 1180px) {
	.hp-today__wrap { grid-template-columns: minmax(0, 1fr) minmax(320px, 420px); }
	.hp-today__ph { grid-column: 1 / -1; grid-row: 2; margin: 0 0 calc(-56px - var(--cut)); height: 280px; min-height: 0; clip-path: none; }
}
@media (max-width: 980px) {
	.hp-today::before { width: 100%; clip-path: polygon(0 0, 100% 0, 100% 46%, 0 62%); }
	.hp-today__wrap { grid-template-columns: 1fr; gap: 28px; }
	.hp-today__ph { margin: 0; min-height: 0; height: clamp(200px, 50vw, 340px); clip-path: none; }
}
@media (max-width: 480px) {
	.hp-qa { padding: 18px; }
	.hp-qa__form { flex-wrap: wrap; }
	.hp-qa__form input:not(.hp-qa__qty) { flex: 1 1 100%; }
	.hp-qa__form .hp-qa__qty { flex: 0 0 72px; }
	.hp-qa__form .hp-btn { flex: 1; }
	.hp-qa__lines { grid-template-columns: 1fr; }
}

/* ==========================================================================
   7. PROOF: the photo filling half the band, text and marks beside it. Light
   band, charcoal type. Adds --cut to its bottom padding (ANGLE RULE: the red
   catalogues band is pulled up over it).
   ========================================================================== */
.hp-proof { background: #fff; color: var(--hp-ch); }
/* The break between "Need it today?" and this section (Chris, 3 Nov: they
   butted together). It is the page's own angled edge, sloping the same way as
   the catalogues band below, rather than a flat strip, which read as a stray
   extra band. This section is pulled up by --cut so its slanted top cuts into
   the bottom of "Need it today?", which has --cut of extra bottom padding for
   it (ANGLE RULE: the angle only ever cuts the despatch photo, never text).
   The text half gets --cut more top padding, because the slant is lowest on
   the right, and the photo's label is dropped below the slant. */
.hp-today + .hp-proof { position: relative; margin-top: calc(-1 * var(--cut)); clip-path: polygon(0 0, 100% var(--cut), 100% 100%, 0 100%); }
.hp-today + .hp-proof .hp-proof__txt { padding-top: calc(56px + var(--cut)); }
/* A 6px white line along the slant, drawn at the bottom of "Need it today?"
   just above where the proof section starts, so where the despatch photo
   meets the load-test photo there's still a crisp edge between them. The
   proof section's top edge, in this band's own box, runs from
   (0, 100% - cut) to (100%, 100%); this strip is the 6px above it. */
.hp-today:has(+ .hp-proof)::after { content: ""; position: absolute; inset: 0; z-index: 5; pointer-events: none; background: #fff;
	clip-path: polygon(0 calc(100% - var(--cut) - 6px), 100% calc(100% - 6px), 100% 100%, 0 calc(100% - var(--cut))); }
/* The photo label sits just under the slant (the edge is never lower than --cut). */
.hp-today + .hp-proof .hp-proof__ph > p { top: var(--cut); }
.hp-proof__grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); min-height: 520px; }
.hp-proof__ph { position: relative; overflow: hidden; background: var(--hp-ink); }
.hp-proof__ph > img { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; object-fit: cover; }
/* label sits at the TOP: the catalogues band's angle cuts across the photo's bottom */
.hp-proof__ph > p { position: absolute; left: 0; top: 0; background: var(--hp-red); color: #fff; padding: 10px 16px; }
/* Chris's installed photos, if he has set any: first one largest */
.hp-proof__gallery { position: absolute; inset: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-rows: 1fr; gap: 4px; }
.hp-proof__gallery figure { position: relative; overflow: hidden; }
.hp-proof__gallery figure:first-child { grid-column: 1 / -1; grid-row: span 2; }
.hp-proof__gallery figure:last-child:nth-child(even) { grid-column: 1 / -1; }
.hp-proof__gallery img { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; object-fit: cover; }
.hp-proof__txt { padding: 56px max(16px, env(safe-area-inset-right, 0px)) calc(56px + var(--cut)) 48px; max-width: 640px; min-width: 0; }
.tdup-home .hp-proof .hp-h2 { color: var(--hp-red); }
.hp-proof .hp-lede { color: var(--hp-g2); margin-top: 14px; }
.hp-figs { display: flex; flex-wrap: wrap; gap: 4px 24px; margin-top: 18px; padding: 10px 0; border-top: 1px solid var(--hp-rule); border-bottom: 1px solid var(--hp-rule); font-size: 15px; }
.hp-figs strong { font: 700 17px/1.4 var(--tdup-font-title); color: var(--hp-ch); }
.hp-figs span { color: var(--hp-g2); }
.hp-facts { margin-top: 24px; border-top: 2px solid var(--hp-ch); }
.hp-facts li { display: grid; grid-template-columns: 160px minmax(0, 1fr); gap: 16px; padding: 12px 0; border-bottom: 1px solid var(--hp-rule); }
.hp-facts .k { font-family: var(--tdup-font-title); font-stretch: 118%; font-weight: 800; font-size: 14px; letter-spacing: .06em; text-transform: uppercase; }
.hp-facts .v { font-size: 16px; }
.hp-marks { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 22px; }
.hp-marks li { background: var(--hp-ch); padding: 12px 14px; display: flex; align-items: center; }
.hp-marks img { height: 42px; width: auto; }
.hp-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 24px; }
@media (max-width: 980px) {
	.hp-proof__grid { grid-template-columns: 1fr; min-height: 0; }
	.hp-proof__ph { height: clamp(220px, 56vw, 380px); }
	.hp-proof__txt { padding: 40px max(16px, env(safe-area-inset-right, 0px)) calc(48px + var(--cut)) max(16px, env(safe-area-inset-left, 0px)); max-width: none; }
	.hp-facts li { grid-template-columns: 1fr; gap: 2px; }
}

/* ==========================================================================
   8. CATALOGUES + NEWS on red: the real brochure covers in a rack, then the
   news. The top edge is cut at the wedge angle and pulled up over the proof
   band.
   ========================================================================== */
.hp-docs { background: var(--hp-red); color: #fff; padding-top: calc(56px + var(--cut)); padding-bottom: 56px; clip-path: polygon(0 0, 100% var(--cut), 100% 100%, 0 100%); margin-top: calc(-1 * var(--cut)); position: relative; }
.tdup-home .hp-docs .hp-h2 { color: #fff; }
.hp-docs .hp-lede { color: rgba(255, 255, 255, .92); }
.hp-rack { display: grid; grid-template-columns: repeat(var(--n, 7), minmax(0, 1fr)); gap: 14px; }
.hp-rack a, .hp-rack a:hover { display: flex; flex-direction: column; gap: 8px; text-decoration: none; color: #fff; min-width: 0; }
.hp-rack img { width: 100%; max-width: none; aspect-ratio: 640 / 906; object-fit: cover; object-position: top; box-shadow: 0 14px 24px rgba(0, 0, 0, .3); transition: transform .25s; }
.hp-rack__plain { display: block; aspect-ratio: 640 / 906; background: var(--hp-chd); box-shadow: 0 14px 24px rgba(0, 0, 0, .3); transition: transform .25s; }
.hp-rack a:hover img, .hp-rack a:hover .hp-rack__plain { transform: translateY(-6px) rotate(-1deg); }
.hp-rack strong { font-size: 14px; line-height: 1.3; }
.hp-rack span:not(.hp-rack__plain):not(.screen-reader-text) { font-size: 12px; opacity: .9; }
.hp-news-head { display: flex; justify-content: space-between; align-items: flex-end; gap: 16px; margin-top: 48px; margin-bottom: 16px; }
.tdup-home .hp-news-head h3 { font-size: 30px; color: #fff; }
.hp-news { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) minmax(0, 1fr); gap: 2px; background: rgba(0, 0, 0, .2); }
.hp-news a, .hp-news a:hover { background: var(--hp-redd); padding: 20px; text-decoration: none; color: #fff; display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.hp-news a:first-child { background: var(--hp-chd); }
.hp-news a:hover { background: var(--hp-ink); }
.hp-news time { font-size: 13px; opacity: .9; }
.hp-news strong { font-family: var(--tdup-font-title); font-stretch: 108%; font-weight: 800; font-size: 19px; line-height: 1.2; text-transform: uppercase; }
.hp-news p { font-size: 15px; opacity: .92; }
@media (max-width: 1080px) { .hp-rack { grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: 150px; overflow-x: auto; padding-bottom: 12px; } }
@media (max-width: 860px) { .hp-news { grid-template-columns: 1fr; } }

/* ==========================================================================
   9. CONTACT: grouped channels + the real form, deep charcoal
   ========================================================================== */
.hp-contact { position: relative; background: var(--hp-chd); color: #fff; }
.hp-contact__wrap { display: grid; grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr); gap: 48px; padding-top: 56px; padding-bottom: 56px; }
.tdup-home .hp-contact .hp-h2 { color: #fff; }
.hp-contact .hp-lede { color: rgba(255, 255, 255, .92); margin-top: 12px; }
.hp-chan { margin-top: 24px; display: grid; gap: 2px; background: rgba(255, 255, 255, .1); }
.hp-chan li { background: var(--hp-chd); padding: 14px 0; display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: 12px; }
.hp-chan .k { font-family: var(--tdup-font-title); font-stretch: 118%; font-weight: 700; font-size: 12px; letter-spacing: .12em; text-transform: uppercase; color: rgba(255, 255, 255, .85); padding-top: 3px; }
.hp-chan .v { font-size: 17px; font-weight: 700; overflow-wrap: anywhere; }
.hp-chan .v small { display: block; font-weight: 400; font-size: 14px; color: rgba(255, 255, 255, .85); }
.hp-chan a { text-decoration: underline; text-underline-offset: 3px; }
.hp-chan a:hover { text-decoration-thickness: 3px; }
.hp-contact__links { display: flex; flex-wrap: wrap; gap: 4px 24px; margin-top: 20px; }
.hp-frm { background: #fff; color: var(--hp-ch); padding: 28px; border-top: 8px solid var(--hp-red); min-width: 0; align-self: start; }
.hp-frm__form { display: block; }
.hp-seg { display: flex; flex-wrap: wrap; border: 2px solid var(--hp-ch); margin: 0 0 18px; padding: 0; min-width: 0; }
.hp-seg label { flex: 1 1 33%; position: relative; }
.hp-seg input { position: absolute; opacity: 0; }
.hp-seg span { display: flex; align-items: center; justify-content: center; min-height: 46px; padding: 0 10px; font-family: var(--tdup-font-title); font-stretch: 112%; font-weight: 700; font-size: 13px; text-transform: uppercase; letter-spacing: .06em; cursor: pointer; text-align: center; }
.hp-seg input:checked + span { background: var(--hp-ch); color: #fff; }
.hp-seg input:focus-visible + span { outline: 3px solid #fff; outline-offset: -3px; box-shadow: inset 0 0 0 6px var(--hp-ink); }
.hp-f2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.hp-fld { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.hp-fld--msg { margin-top: 14px; }
.hp-fld label { font-weight: 700; font-size: 15px; }
.hp-fld input, .hp-fld textarea { border: 1px solid #9A9EA1; padding: 12px; min-height: 48px; font-size: 16px; background: #fff; color: var(--hp-ch); width: 100%; border-radius: 0; }
.hp-fld textarea { min-height: 110px; resize: vertical; }
.hp-fld input:focus-visible, .hp-fld textarea:focus-visible { border-color: var(--hp-ink); }
.hp-frm .tdup-quote-message { margin-top: 14px; background: var(--hp-sf); border: 0; border-left: 4px solid var(--hp-ink); font-size: 15px; }
.hp-frm .tdup-quote-message[hidden] { display: none; }
.hp-frm .tdup-form-privacy { margin-top: 14px; font-size: 13px; color: var(--hp-g2); }
.hp-frm .tdup-form-privacy a { color: var(--hp-ch); text-decoration: underline; }
.hp-frm .hp-btn { margin-top: 18px; width: 100%; }
.hp-small { font-size: 13px; color: var(--hp-g2); margin-top: 10px; }
@media (max-width: 980px) { .hp-contact__wrap { grid-template-columns: 1fr; gap: 32px; } }
@media (max-width: 560px) { .hp-f2 { grid-template-columns: 1fr; } .hp-frm { padding: 18px; } .hp-chan li { grid-template-columns: 1fr; gap: 2px; } }

@media (prefers-reduced-motion: reduce) {
	.tdup-home *, .tdup-home *::before, .tdup-home *::after { transition: none !important; animation: none !important; }
}

/* ==========================================================================
   18. Inner pages: shared system  (added 2026-11-03)
   The building blocks every page EXCEPT the homepage is made from, so the
   product pages and content pages share one look: Utility Products' printed
   catalogue covers (charcoal field, red wedge from the left, heavy white caps,
   red and charcoal as BIG surfaces, square corners, dense layouts).
   Class names start with ip- ("inner page"). The homepage has its own hp-
   block (section 6 / the end of section "HOMEPAGE") and is not touched.
   PHP that prints this markup: inc/page-layout.php (tdup_page_hero(),
   tdup_section_head(), tdup_help_card(), ...) and tdup_next_band() in
   functions.php.

   HOW A PAGE IS BUILT (top to bottom):
     tdup_page_hero( array(...) )             the header band (before <main>)
     <main class="ip-main" id="main-content">
       <section class="ip-band ip-band--light ip-before-cut"> ... </section>
       <section class="ip-band ip-band--red ip-band--cut"> ... </section>
       tdup_next_band( array( ..., 'cut' => true ) )          the closing band
     </main>
   Inside a band, put a container: <div class="tdup-container tdup-container--wide">.

   BANDS (colour):
     .ip-band--light    pale grey surface (#F4F5F6). Default. Cards/forms on it are white.
     .ip-band--sweep    the light studio sweep (for product renders on a soft light)
     .ip-band--white    plain white (use sparingly: Lee found "too much white" boring)
     .ip-band--charcoal brand charcoal #44484B, white text
     .ip-band--deep     deep charcoal #34373A, white text
     .ip-band--red      brand red #A0233E, white text
   A band sets --ip-h (heading colour) and --ip-text (sentence colour), so
   .ip-h2 / .ip-lede / .ip-link are red/grey on light bands and white on dark
   ones with no extra classes.

   ANGLED BAND EDGE:  .ip-band--cut  (height: --cut, clamp 32-110px)
     ANGLE RULE: a band with an angled top is pulled up by --cut so the angle
     overlaps the section above it. THAT SECTION MUST ADD --cut TO ITS BOTTOM
     PADDING: give it the class .ip-before-cut (works on .ip-band, on the
     header band via tdup_page_hero( 'before_cut' => true ), and
     tdup_next_band passes 'cut' => true for its own angle). Then the angle
     only ever slices through empty padding or a photo, never a button, label
     or text. Check it by MEASURING (the gap between the last piece of text
     and the angle), not by eye. A section that has BOTH an angled top and an
     angled-top section after it gets both classes: ip-band--cut ip-before-cut.

   CONTENT WIDTH:
     .tdup-container--wide  the homepage's wide column: content up to 1552px,
        gutters clamp(32px, 3.5vw, 64px) (16px on phones). Defined in the
        homepage block, shared here. Use it for listing and grid pages.
     .ip-measure            keeps long-form text to a readable ~70 characters a
        line INSIDE the wide column. .ip-prose already includes it.

   HEADINGS / LINKS / BUTTONS:
     .ip-head > div > h2.ip-h2 + p.ip-lede, then an optional a.ip-link
     .ip-cap  display caps (Archivo 800, 112% wide)   .ip-lab  small label caps
     .ip-link underline link (thickens on hover; red on hover only on light bands)
     .tdup-button--primary | --secondary | --white | --dark | --small
   INTERACTION RULES (held site-wide): hover never turns text the colour of its
   own background; on red / charcoal an underline link thickens its underline
   instead of changing colour; focus is a white outline with a dark ink ring
   (never red); targets are at least 44px.
   ========================================================================== */

:root {
	--cut: clamp(32px, 7vw, 110px);   /* height of every angled band edge; the same value the homepage uses */
	--ip-pad: 56px;                    /* a band's top and bottom padding (40px on phones) */
	--tdup-sweep: #E7E8E9;             /* the light studio sweep behind product renders */
}
@media (max-width: 700px) { :root { --ip-pad: 40px; } }

/* ---- Type roles (the homepage's .hp-cap / .hp-lab, usable on any page) ---- */
.ip-cap { font-family: var(--tdup-font-title); font-stretch: 112%; font-weight: 800; text-transform: uppercase; letter-spacing: 0.005em; line-height: 0.98; overflow-wrap: break-word; }
.ip-lab { font-family: var(--tdup-font-title); font-stretch: 125%; font-weight: 600; text-transform: uppercase; letter-spacing: 0.18em; font-size: 12px; line-height: 1.3; margin: 0; }

/* ---- Main area ---- */
/* flex: 1 keeps the footer at the bottom of a short page (body is a flex column). */
.ip-main { flex: 1 0 auto; background: var(--tdup-off-white); }
/* A page that ends in a band sits flush on the footer: no pale strip between. */
main:has(> .ip-band:last-child) + .tdup-footer { margin-top: 0; }

/* ---- Bands ---- */
.ip-band {
	--ip-h: var(--tdup-red);            /* heading colour: red on a light band */
	--ip-text: var(--tdup-body-grey);   /* the plain sentence under a heading */
	--ip-link: var(--tdup-charcoal);
	position: relative;
	padding-top: var(--ip-pad); padding-bottom: var(--ip-pad);
	background: var(--tdup-off-white); color: var(--tdup-charcoal);
}
.ip-band--light { background: var(--tdup-off-white); }
.ip-band--white { background: var(--tdup-white); }
.ip-band--sweep { background: radial-gradient(120% 90% at 50% 38%, #fff 0%, var(--tdup-sweep) 70%, #DADCDD 100%); }
.ip-band--charcoal, .ip-band--deep, .ip-band--red {
	--ip-h: var(--tdup-white); --ip-text: rgba(255, 255, 255, 0.92); --ip-link: var(--tdup-white);
	color: var(--tdup-white);
}
.ip-band--charcoal { background: var(--tdup-charcoal); }
.ip-band--deep { background: var(--tdup-charcoal-2); }
.ip-band--red { background: var(--tdup-red); }
/* Angled top: pulled up by --cut over the section above; the clip makes the
   slope (low on the left, high on the right, as on the homepage). The top
   padding includes --cut so nothing inside is ever near the slope. */
.ip-band--cut {
	padding-top: calc(var(--ip-pad) + var(--cut));
	margin-top: calc(-1 * var(--cut));
	clip-path: polygon(0 var(--cut), 100% 0, 100% 100%, 0 100%);
}
/* The section BEFORE an angled band adds --cut to its bottom padding (ANGLE RULE). */
/* Only the angle's own height plus a small margin: the normal section
   padding on top of --cut left 130-170px of empty band above each angle. */
.ip-band.ip-before-cut { padding-bottom: calc(32px + var(--cut)); }
.ip-hero.ip-before-cut .ip-hero__inner { padding-bottom: calc(28px + var(--cut)); }

/* ---- Section heading lockup ---- */
.ip-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 12px 32px; margin-bottom: 28px; }
.ip-head > div { min-width: 0; }
.ip-h2 { margin: 0; font-family: var(--tdup-font-title); font-stretch: 112%; font-weight: 800; text-transform: uppercase; letter-spacing: 0.005em; line-height: 0.98; font-size: clamp(28px, 3.6vw, 48px); text-wrap: balance; color: var(--ip-h, var(--tdup-red)); overflow-wrap: break-word; }
.ip-lede { margin: 10px 0 0; font-size: 18px; line-height: 1.55; max-width: 58ch; color: var(--ip-text, var(--tdup-body-grey)); }

/* Underline link. Hover thickens the underline; only on LIGHT bands does it
   also turn red (a red hover on a red or charcoal band would make the text
   vanish). Every state sets its own colour because the site-wide a:hover rule
   would otherwise recolour it. */
.ip-link, .ip-link:hover {
	display: inline-flex; align-items: center; gap: 8px; min-height: 44px;
	font-family: var(--tdup-font-title); font-stretch: 118%; font-weight: 700; font-size: 13px;
	letter-spacing: 0.1em; text-transform: uppercase; text-decoration: none;
	color: var(--ip-link, var(--tdup-charcoal)); border-bottom: 2px solid currentColor;
}
.ip-link:hover { box-shadow: inset 0 -2px 0 currentColor; }
.ip-band--light .ip-link:hover, .ip-band--white .ip-link:hover, .ip-band--sweep .ip-link:hover, .ip-main > .ip-band--light .ip-link:hover { color: var(--tdup-red); }

/* ---- Readable text ---- */
/* ~70 characters a line (Lato at 17px+; ch scales with the font). */
.ip-measure { max-width: 70ch; }
.ip-prose { max-width: 70ch; font-size: clamp(17px, 1.05vw, 19px); line-height: 1.65; color: var(--tdup-charcoal); min-width: 0; }
.ip-prose > :first-child { margin-top: 0; }
.ip-prose > :last-child { margin-bottom: 0; }
.ip-prose h2 { font-size: clamp(24px, 2.4vw, 34px); margin: 1.8em 0 0.5em; line-height: 1; text-wrap: balance; }
.ip-prose h3 { font-family: var(--tdup-font-title); font-stretch: 112%; font-weight: 800; text-transform: uppercase; font-size: clamp(17px, 1.5vw, 21px); line-height: 1.1; color: var(--tdup-charcoal); margin: 1.6em 0 0.4em; }
.ip-prose h4 { font-size: 17px; margin: 1.4em 0 0.3em; }
.ip-prose p, .ip-prose ul, .ip-prose ol { margin: 0 0 1em; }
.ip-prose ul, .ip-prose ol { padding-left: 1.3em; }
.ip-prose li { margin-bottom: 0.35em; }
.ip-prose a { color: var(--tdup-red); font-weight: 700; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
.ip-prose a:hover { color: var(--tdup-red-dark); text-decoration-thickness: 3px; }
.ip-prose img { max-width: 100%; height: auto; }
.ip-prose blockquote { margin: 1.4em 0; padding: 4px 0 4px 20px; border-left: 6px solid var(--tdup-red); font-size: 1.1em; }
.ip-prose table { width: 100%; border-collapse: collapse; margin: 1.2em 0; font-size: 15px; }
.ip-prose th { background: var(--tdup-charcoal); color: var(--tdup-white); text-align: left; padding: 10px 12px; }
.ip-prose td { padding: 10px 12px; border-bottom: 1px solid var(--tdup-rule); }
.ip-prose hr { border: 0; border-top: 1px solid var(--tdup-rule); margin: 2em 0; }

/* ---- Text page layout: text left, a side column right ---- */
/* The text keeps its ~70ch measure; the side column takes the rest of the
   wide column (up to 480px) so a short text page does not leave a big empty
   area on a wide screen. */
.ip-split { display: grid; grid-template-columns: minmax(0, 76ch) minmax(300px, 480px); justify-content: space-between; gap: 32px clamp(32px, 4vw, 64px); align-items: start; }
.ip-split__aside { display: grid; gap: 16px; position: sticky; top: 104px; min-width: 0; } /* sticky: below the 70px sticky header, so it stays in view while the text scrolls */
@media (max-width: 980px) {
	.ip-split { grid-template-columns: minmax(0, 1fr); }
	.ip-split__aside { position: static; }
}
/* White "paper" panel (a form, a list, a card): 1px rule, a heavy charcoal top edge. */
.ip-panel { background: var(--tdup-white); border: 1px solid var(--tdup-rule); border-top: 6px solid var(--tdup-charcoal); padding: 18px 20px 12px; min-width: 0; }
.ip-panel > .ip-lab { color: var(--tdup-charcoal); padding-bottom: 6px; }
/* A list of links inside a panel: a hairline between rows, 44px+ tall, the
   title underlines on hover (the text colour never changes). */
.ip-newslist ul { list-style: none; margin: 0 0 6px; padding: 0; }
.ip-newslist li { border-top: 1px solid var(--tdup-rule); }
.ip-newslist li a, .ip-newslist li a:hover { display: flex; flex-direction: column; gap: 2px; min-height: 48px; justify-content: center; padding: 10px 0; color: var(--tdup-charcoal); text-decoration: none; }
.ip-newslist li time { font-family: var(--tdup-font-title); font-stretch: 125%; font-weight: 600; font-size: 11.5px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--tdup-red); }
.ip-newslist li a > span { font-weight: 700; font-size: 16px; line-height: 1.3; }
.ip-newslist li a:hover > span { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 3px; }
.ip-newslist > .ip-link { margin: 4px 0 8px; }
/* A news post: the picture sits above the text, filling the text column. */
.ip-article { min-width: 0; }
.ip-article__photo { margin: 0 0 24px; }
.ip-article__photo img { width: 100%; height: auto; max-height: 460px; object-fit: cover; }

/* ---- "Need a hand?" card: a big red surface, white text ---- */
.ip-help { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; padding: 22px 22px 24px; background: var(--tdup-red); color: var(--tdup-white); }
.ip-help__title { margin: 0; font-size: 28px; color: var(--tdup-white); }
.ip-help__text { margin: 0; font-size: 16.5px; line-height: 1.5; color: rgba(255, 255, 255, 0.95); }
.ip-help a.ip-help__phone, .ip-help a.ip-help__phone:hover { font-family: var(--tdup-font-title); font-stretch: 112%; font-weight: 800; font-size: 30px; line-height: 1.1; color: var(--tdup-white); text-decoration: underline; text-decoration-thickness: 3px; text-underline-offset: 5px; }
.ip-help a.ip-help__phone:hover { text-decoration-thickness: 6px; }
.ip-help a.ip-help__email, .ip-help a.ip-help__email:hover { color: var(--tdup-white); font-weight: 700; font-size: 16px; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; overflow-wrap: anywhere; display: inline-flex; align-items: center; min-height: 44px; }
.ip-help a.ip-help__email:hover { text-decoration-thickness: 3px; }
.ip-help .tdup-button { margin-top: 6px; }

/* ==========================================================================
   Page hero: the compact "catalogue cover" (tdup_page_hero())
   Layers, back to front: charcoal field (the background) > optional photo under
   a charcoal tone (z 1) > the red wedge, ::after (z 2) > optional cut-out
   render (z 3) > the text (z 4). Same order as the homepage .hp-hero.
   The wedge is narrow at the top and wide at the bottom, like the printed
   covers. --ip-wt is its width at the top, --ip-run how far it leans
   across; the run is set per height so the ANGLE stays the same as the
   homepage's (about 30 degrees off vertical) on every size of header.
   ========================================================================== */
.ip-hero {
	--ip-wt: clamp(120px, 20vw, 360px);
	--ip-run: 120px;
	--ip-hero-h: 200px;
	position: relative; isolation: isolate; overflow: hidden;
	background: var(--tdup-charcoal); color: var(--tdup-white);
}
.ip-hero--standard { --ip-run: 160px; --ip-hero-h: 270px; }
.ip-hero--crumbs { --ip-run: 40px; --ip-hero-h: 0px; --ip-wt: clamp(80px, 12vw, 200px); }
.ip-hero::after {
	content: ''; position: absolute; z-index: 2; left: 0; top: 0; bottom: 0;
	width: calc(var(--ip-wt) + var(--ip-run)); background: var(--tdup-red);
	clip-path: polygon(0 0, var(--ip-wt) 0, 100% 100%, 0 100%);
}
.ip-hero__inner {
	position: relative; z-index: 4; display: flex; flex-direction: column; justify-content: flex-end;
	min-height: var(--ip-hero-h); padding-top: 4px; padding-bottom: 28px;
}
.ip-hero--crumbs .ip-hero__inner { padding-bottom: 0; }
/* The breadcrumbs sit at the top of the band, the title block at the bottom. */
.ip-hero .tdup-breadcrumbs {
	margin: 0 0 auto; color: var(--tdup-white);
	font-family: var(--tdup-font-title); font-stretch: 125%; font-weight: 600; font-size: 11.5px;
	letter-spacing: 0.14em; line-height: 1.2; text-transform: uppercase;
}
.ip-hero .tdup-breadcrumbs a, .ip-hero .tdup-breadcrumbs a:hover {
	display: inline-block; padding: 13px 0; color: var(--tdup-white);
	text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px;
}
.ip-hero .tdup-breadcrumbs a:hover { text-decoration-thickness: 3px; }
.ip-hero .tdup-breadcrumbs span { display: inline-block; padding: 13px 0; }
.ip-hero--crumbs .tdup-breadcrumbs { margin: 0; }
/* The page's real, descriptive title: display caps, white. */
.ip-hero__title {
	margin: 10px 0 0; max-width: 24ch; text-wrap: balance;
	font-size: clamp(28px, 3.4vw, 48px); line-height: 0.98; color: var(--tdup-white);
}
.ip-hero--standard .ip-hero__title { max-width: 26ch; font-size: clamp(32px, 4.4vw, 64px); }
.ip-hero__intro { margin: 10px 0 0; max-width: 62ch; font-size: 17px; line-height: 1.5; color: rgba(255, 255, 255, 0.95); }
.ip-hero--standard .ip-hero__intro { font-size: 19px; margin-top: 14px; }
/* With a picture on the right, keep the text out of its way. */
.ip-hero--has-render .ip-hero__title, .ip-hero--has-render .ip-hero__intro,
.ip-hero--has-photo .ip-hero__title, .ip-hero--has-photo .ip-hero__intro { max-width: min(62ch, 58%); }

/* A photo: under the wedge, toned dark on the text side. */
.ip-hero__photo { position: absolute; inset: 0; z-index: 1; }
.ip-hero__photo img { width: 100%; height: 100%; object-fit: cover; filter: grayscale(0.35) contrast(1.05); }
.ip-hero__photo::after { content: ''; position: absolute; inset: 0; background: linear-gradient(100deg, rgba(52, 55, 58, 0.94) 0%, rgba(68, 72, 75, 0.88) 45%, rgba(68, 72, 75, 0.68) 100%); }

/* A render (transparent cut-out): ABOVE the wedge, anchored bottom right and
   bleeding off the bottom and right edges, faded in from the left so it melts
   into the field. Sized by the header's height, so it works at both sizes. */
.ip-hero__render { position: absolute; z-index: 3; top: 0; right: 0; bottom: 0; width: min(46%, 760px);
	-webkit-mask-image: linear-gradient(to right, transparent 0, #000 35%);
	mask-image: linear-gradient(to right, transparent 0, #000 35%); pointer-events: none; }
.ip-hero__render img { position: absolute; right: -3%; bottom: -14%; height: 128%; width: auto; max-width: none; filter: brightness(1.22) contrast(1.06); }

@media (max-width: 700px) {
	.ip-hero { --ip-wt: 34%; --ip-run: 90px; --ip-hero-h: 0px; }
	.ip-hero--standard { --ip-run: 110px; }
	.ip-hero__inner { padding-bottom: 22px; }
	.ip-hero--has-render .ip-hero__title, .ip-hero--has-render .ip-hero__intro,
	.ip-hero--has-photo .ip-hero__title, .ip-hero--has-photo .ip-hero__intro { max-width: 100%; }
	.ip-hero__intro, .ip-hero--standard .ip-hero__intro { font-size: 16px; }
	/* A cut-out render is decoration and would sit behind the heading on a
	   phone: it is dropped there (the heading and intro are what matter). */
	.ip-hero__render { display: none; }
}

/* ==========================================================================
   404 page pieces (also reusable): search form, category tiles, load classes
   ========================================================================== */
.ip-find { display: flex; flex-wrap: wrap; gap: 0; max-width: 760px; margin: 0 0 28px; }
.ip-find input[type="search"] { flex: 1 1 260px; min-width: 0; min-height: 56px; padding: 0 16px; font-size: 18px; background: var(--tdup-white); color: var(--tdup-charcoal); border: 2px solid var(--tdup-charcoal); border-right: 0; border-radius: 0; }
.ip-find .tdup-button { min-height: 56px; padding: 0 28px; }

/* Category tiles: a small picture, the name and the count. Hairline grid. */
.ip-tiles { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 2px; background: var(--tdup-rule); border: 2px solid var(--tdup-rule); }
.ip-tiles > li { display: contents; }
.ip-tiles a, .ip-tiles a:hover { display: grid; grid-template-columns: 96px minmax(0, 1fr); min-height: 96px; background: var(--tdup-white); color: var(--tdup-charcoal); text-decoration: none; overflow: hidden; }
.ip-tiles__ph { display: flex; align-items: center; justify-content: center; padding: 8px; background: radial-gradient(120% 90% at 50% 38%, #fff 0%, var(--tdup-sweep) 70%, #DADCDD 100%); }
.ip-tiles__ph img { width: auto; height: auto; max-width: 100%; max-height: 80px; object-fit: contain; }
.ip-tiles__nm { display: flex; flex-direction: column; justify-content: center; gap: 2px; padding: 10px 14px; min-width: 0; transition: background 0.2s; }
.ip-tiles__nm strong { font-family: var(--tdup-font-title); font-stretch: 112%; font-weight: 800; font-size: 15px; line-height: 1.1; text-transform: uppercase; overflow-wrap: anywhere; }
.ip-tiles__nm span { font-size: 13.5px; color: var(--tdup-body-grey); }
.ip-tiles a:hover .ip-tiles__nm { background: var(--tdup-charcoal); color: var(--tdup-white); }
.ip-tiles a:hover .ip-tiles__nm span { color: rgba(255, 255, 255, 0.92); }
/* The red tile that closes the grid takes the free cells in the last row. */
.ip-tiles .ip-tiles__all { display: block; grid-column: span var(--s4, 1); }
.ip-tiles .ip-tiles__all a, .ip-tiles .ip-tiles__all a:hover { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 16px 20px; background: var(--tdup-red); color: var(--tdup-white); height: 100%; }
.ip-tiles .ip-tiles__all a:hover { background: var(--tdup-red-dark); }
.ip-tiles__all strong { font-size: 22px; flex: none; }
.ip-tiles__all span { flex: 1; font-size: 15px; }
.ip-tiles__all .hp-arr { width: 30px; height: 30px; }
@media (max-width: 1100px) {
	.ip-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.ip-tiles .ip-tiles__all { grid-column: span var(--s2, 1); }
}
@media (max-width: 600px) {
	.ip-tiles { grid-template-columns: 1fr; }
	.ip-tiles .ip-tiles__all { grid-column: auto; }
	.ip-tiles__all span { display: none; }
}

/* Load class cells: the class code set huge, as lettering cast into a lid.
   For a red or charcoal band (white text). */
.ip-classes { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 2px; background: rgba(0, 0, 0, 0.18); }
.ip-classes > li { display: flex; min-width: 0; }
.ip-classes a, .ip-classes a:hover { flex: 1; display: flex; flex-direction: column; gap: 10px; padding: 18px 18px 20px; background: var(--tdup-red); color: var(--tdup-white); text-decoration: none; min-width: 0; transition: background 0.2s; }
.ip-classes a:hover { background: var(--tdup-red-dark); }
.ip-classes__code { font-size: clamp(34px, 4.2vw, 60px); letter-spacing: -0.01em; }
.ip-classes__text { display: flex; flex-direction: column; gap: 6px; flex: 1; }
.ip-classes__text strong { font-size: 17px; line-height: 1.3; }
.ip-classes__n { margin-top: auto; padding-top: 12px; font-size: 14px; border-top: 1px solid rgba(255, 255, 255, 0.3); }
@media (max-width: 700px) {
	.ip-classes { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.ip-classes > li:last-child:nth-child(odd) { grid-column: span 2; }
}

/* ---- Printing: the header band is hidden, as the old one was ---- */
@media print { .ip-hero, .ip-find { display: none !important; } }

@media (prefers-reduced-motion: reduce) {
	.ip-tiles__nm, .ip-classes a, .tdup-news-grid__photo img { transition: none; }
}


/* ==========================================================================
   Cookie choice banner + footer "Cookie settings" link
   (markup: inc/analytics.php, behaviour: assets/js/analytics-consent.js)

   Only exists on the page when Google Analytics is switched on. The banner is
   fixed to the bottom, charcoal, with two identical white buttons so "No
   thanks" is exactly as easy as "Accept". Focus rings come from the global
   rule (white outline + ink ring), not a red one.
   ========================================================================== */
.tdup-consent {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 1000; /* above the sticky header and the compare bar */
	background: var(--tdup-charcoal);
	color: var(--tdup-white);
	border-top: 1px solid rgba(255, 255, 255, 0.3); /* edge against the dark hero */
	box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.25);
	animation: tdup-consent-in 0.2s ease-out;
}
.tdup-consent[hidden] { display: none; }
.tdup-consent__inner { display: flex; align-items: center; justify-content: space-between; gap: 12px 32px; padding-top: 14px; padding-bottom: 14px; }
.tdup-consent__title { margin: 0 0 2px; font-size: 16px; font-weight: 700; }
.tdup-consent__body { margin: 0; font-size: 14px; line-height: 1.45; max-width: 70ch; }
.tdup-consent__body a { color: var(--tdup-white); text-decoration: underline; text-underline-offset: 2px; white-space: nowrap; }
/* Both buttons get the same width and weight (equal choice). */
.tdup-consent__actions { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; flex-shrink: 0; } /* 1fr 1fr = both columns as wide as the wider button */
.tdup-consent__actions .tdup-button { justify-content: center; }

/* Phones: text on top, the two buttons side by side underneath, so the
   banner stays well under a third of the screen. */
@media (max-width: 640px) {
	.tdup-consent__inner { flex-direction: column; align-items: stretch; gap: 10px; padding-top: 12px; padding-bottom: 12px; }
	.tdup-consent__body { font-size: 13px; line-height: 1.4; }
	.tdup-consent__actions { gap: 8px; }
	.tdup-consent__actions .tdup-button { padding-left: 8px; padding-right: 8px; }
}

/* While the banner is showing, give the footer room so its last line isn't
   hidden behind it. The script sets --tdup-consent-height to the banner's
   real height. */
body.tdup-consent-open .tdup-footer { padding-bottom: var(--tdup-consent-height, 160px); }

/* "Cookie settings" is a <button> but should look like the footer's links. */
.tdup-footer__cookie-settings {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding: 0;
	border: 0;
	background: none;
	font: inherit;
	color: rgba(255, 255, 255, 0.9);
	cursor: pointer;
}
.tdup-footer__cookie-settings:hover { color: var(--tdup-white); text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 4px; }

@keyframes tdup-consent-in { from { transform: translateY(100%); } to { transform: none; } }
@media (prefers-reduced-motion: reduce) { .tdup-consent { animation: none; } }

/* Spam-trap field in the quote and contact forms (inc/form-guard.php). Moved off-screen rather than display:none, which some bots skip. Real visitors never see or reach it. */
.tdup-hp { position: absolute; left: -9999px; top: auto; width: 1px; height: 1px; overflow: hidden; }
