/* Gusto Locks theme — build 1.5.5 */
/* ===========================================================================
   Gusto Locks
   Sections alternate between dark (product photography, hero, CTA) and paper
   (reading, specifications, forms). The one piece of orchestrated motion is
   the padlock loader; everything else stays still unless a person acts.
   =========================================================================== */

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
	margin: 0;
	background: var(--paper);
	color: var(--ink);
	font-family: var(--font-body);
	font-size: var(--fs-body);
	line-height: 1.6;
	font-variation-settings: "wdth" 100;
	-webkit-font-smoothing: antialiased;
}

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

a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: 3px; }

:focus-visible {
	outline: 2px solid var(--brass);
	outline-offset: 3px;
	border-radius: 2px;
}

.skip-link {
	position: absolute; left: -9999px; top: 0; z-index: 999;
	background: var(--brass); color: var(--ink); padding: 12px 20px; font-weight: 600;
}
.skip-link:focus { left: 0; }

/* --- Type ---------------------------------------------------------------- */

h1, h2, h3, h4 {
	font-family: var(--font-display);
	font-variation-settings: "wdth" 112;
	font-weight: 700;
	line-height: 1.05;
	letter-spacing: -0.015em;
	margin: 0 0 0.5em;
	text-wrap: balance;
}
h1 { font-size: var(--fs-h1); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); line-height: 1.25; }

p { margin: 0 0 1em; max-width: 68ch; }

.lead { font-size: 1.15rem; color: var(--slate); line-height: 1.55; }
.dark .lead { color: var(--steel); }

.section-intro { max-width: 62ch; margin-bottom: clamp(24px, 3vw, 42px); }

/* --- Layout -------------------------------------------------------------- */

.container { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }

.section { padding-block: var(--section-y); }
.section.dark { background: var(--ink); color: var(--paper); }
/* A third ground, for when two light sections have to sit one on top of the
   other. A hairline alone is not enough at this scale: the eye reads the two
   as one long band and the second heading looks like part of the first
   answer. Lifting the band to white separates them the way dark does, without
   a third dark stripe on a page that already alternates. */
.section--raised {
	background: var(--paper-raised);
	border-block: 1px solid var(--paper-line);
}
.section.dark h1, .section.dark h2, .section.dark h3 { color: var(--paper); }

.grid { display: grid; gap: clamp(20px, 2.6vw, 34px); }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fill, minmax(258px, 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); }

.split { display: grid; gap: clamp(28px, 5vw, 72px); align-items: center; grid-template-columns: 1fr; }
@media (min-width: 900px) { .split { grid-template-columns: 1.05fr 0.95fr; } }
.split--top { align-items: start; }

/* --- Buttons ------------------------------------------------------------- */

.btn {
	display: inline-flex; align-items: center; gap: 10px;
	padding: 14px 26px;
	font-family: var(--font-display);
	font-variation-settings: "wdth" 104;
	font-weight: 600; font-size: 0.94rem; line-height: 1;
	border: 1px solid transparent; border-radius: var(--radius);
	background: var(--brass); color: var(--ink);
	text-decoration: none; cursor: pointer;
	transition: background var(--fast) var(--ease), color var(--fast) var(--ease), border-color var(--fast) var(--ease);
}
.btn:hover { background: var(--brass-deep); }
.btn--ghost { background: transparent; color: currentColor; border-color: currentColor; }
.btn--ghost:hover { background: var(--brass); border-color: var(--brass); color: var(--ink); }
.btn--sm { padding: 10px 18px; font-size: 0.84rem; }
.btn--block { width: 100%; justify-content: center; }

/* --- Header -------------------------------------------------------------- */

.site-header {
	position: sticky; top: 0; z-index: 60;
	background: rgba(18, 16, 15, 0.94);
	backdrop-filter: saturate(140%) blur(8px);
	border-bottom: 1px solid var(--ink-line);
	color: var(--paper);
}
.header-inner { display: flex; align-items: center; gap: 18px; min-height: 74px; flex-wrap: nowrap; }
.header-actions .btn { white-space: nowrap; }
.site-brand { display: flex; align-items: center; gap: 12px; text-decoration: none; margin-right: auto; }
.site-brand img { max-height: 60px; width: auto; }
.site-brand .wordmark { font-family: var(--font-display); font-variation-settings: "wdth" 112; font-weight: 700; font-size: 1.35rem; color: var(--paper); }

.nav { display: none; gap: 20px; align-items: center; }
@media (min-width: 1180px) { .nav { display: flex; } }
@media (min-width: 1320px) { .nav { gap: 28px; } }
.nav ul { display: flex; gap: 18px; list-style: none; margin: 0; padding: 0; align-items: center; }
@media (min-width: 1320px) { .nav ul { gap: 26px; } }
.nav > ul > li > a { white-space: nowrap; }
.nav a { text-decoration: none; font-size: 0.92rem; color: var(--paper); padding-block: 6px; border-bottom: 2px solid transparent; }
.nav a:hover, .nav .current-menu-item > a { border-bottom-color: var(--brass); }

.header-actions { display: flex; align-items: center; gap: 12px; }
.header-phone { display: none; font-size: 0.9rem; text-decoration: none; color: var(--steel); }
@media (min-width: 1320px) { .header-phone { display: block; } }
.header-phone strong { color: var(--paper); display: block; font-size: 0.98rem; white-space: nowrap; }

.nav-toggle {
	display: grid; place-items: center; width: 44px; height: 44px;
	background: none; border: 1px solid var(--ink-line); border-radius: var(--radius);
	color: var(--paper); cursor: pointer;
}
@media (min-width: 1180px) { .nav-toggle { display: none; } }
.nav-toggle span { display: block; width: 18px; height: 1.5px; background: currentColor; position: relative; }
.nav-toggle span::before, .nav-toggle span::after { content: ""; position: absolute; left: 0; width: 18px; height: 1.5px; background: currentColor; }
.nav-toggle span::before { top: -6px; }
.nav-toggle span::after { top: 6px; }

.mobile-nav { display: none; border-top: 1px solid var(--ink-line); padding-block: 16px 24px; }
.mobile-nav.is-open { display: block; }
.mobile-nav ul { list-style: none; margin: 0; padding: 0; }
.mobile-nav a { display: block; padding: 13px 0; text-decoration: none; border-bottom: 1px solid var(--ink-line); font-size: 1.02rem; }

/* --- Hero ---------------------------------------------------------------- */

.hero { position: relative; background: var(--ink); color: var(--paper); overflow: hidden; }
.hero-inner {
	display: grid; gap: clamp(32px, 5vw, 64px); align-items: center;
	grid-template-columns: 1fr;
	padding-block: clamp(36px, 4.5vw, 56px);
}
@media (min-width: 960px) { .hero-inner { grid-template-columns: 1.02fr 0.98fr; } }

.hero h1 {
	font-size: var(--fs-display);
	font-variation-settings: "wdth" 118;
	line-height: 1.02;
	max-width: 15ch;
	letter-spacing: -0.025em;
	margin-bottom: 22px;
}
.hero p { color: var(--steel); font-size: 1.1rem; max-width: 46ch; }
.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 30px; }

.hero-figure { position: relative; }
.hero-figure img { width: 100%; max-height: 50vh; object-fit: contain; border-radius: var(--radius-lg); background: #fff; }
.hero-rule { width: 64px; height: 3px; background: var(--brass); margin-bottom: 26px; }

/* Dimension callout, borrowed from the engineering drawings in the catalogue */
.hero-callout {
	position: absolute; right: 4%; bottom: 7%;
	background: rgba(18, 16, 15, 0.86);
	border: 1px solid var(--ink-line); border-left: 3px solid var(--brass);
	padding: 12px 16px; font-size: var(--fs-micro); color: var(--steel);
	line-height: 1.5; letter-spacing: 0.02em;
}
.hero-callout strong { display: block; color: var(--paper); font-size: 0.9rem; font-weight: 600; letter-spacing: 0; }
@media (max-width: 720px) { .hero-callout { display: none; } }

/* --- Numbers strip ------------------------------------------------------- */

.stats { border-block: 1px solid var(--ink-line); background: var(--ink); color: var(--paper); }
.stats-grid { display: grid; grid-template-columns: repeat(2, 1fr); }
@media (min-width: 800px) { .stats-grid { grid-template-columns: repeat(4, 1fr); } }
.stat { padding: clamp(24px, 3.4vw, 40px) 0; }
.stat + .stat { border-left: 1px solid var(--ink-line); padding-left: clamp(20px, 3vw, 40px); }
@media (max-width: 799px) { .stat:nth-child(odd) { border-left: 0; padding-left: 0; } .stat:nth-child(n+3) { border-top: 1px solid var(--ink-line); } }
.stat b {
	display: block; font-family: var(--font-display); font-variation-settings: "wdth" 118;
	font-size: clamp(1.9rem, 3.6vw, 2.9rem); font-weight: 700; line-height: 1; color: var(--brass);
}
.stat span { display: block; margin-top: 8px; font-size: var(--fs-small); color: var(--steel); }

/* --- Product cards ------------------------------------------------------- */

.product-card {
	display: flex; flex-direction: column;
	background: var(--paper-raised);
	border: 1px solid var(--paper-line);
	border-radius: var(--radius);
	overflow: hidden;
	transition: border-color var(--fast) var(--ease);
}
.product-card:hover { border-color: var(--ink); }
.dark .product-card { background: var(--ink-raised); border-color: var(--ink-line); }
.dark .product-card:hover { border-color: var(--brass); }

.product-card__media { position: relative; aspect-ratio: 1; background: #fff; }
.product-card__media img { width: 100%; height: 100%; object-fit: contain; padding: 10%; }
.product-card__badge {
	position: absolute; top: 10px; left: 10px;
	background: var(--ink); color: var(--brass);
	font-size: var(--fs-micro); font-weight: 600; letter-spacing: 0.03em;
	padding: 5px 9px; border-radius: 2px;
}
.product-card__body { padding: 18px 18px 20px; display: flex; flex-direction: column; flex: 1; }
.product-card__code { font-size: var(--fs-micro); color: var(--slate); letter-spacing: 0.06em; margin-bottom: 6px; }
.dark .product-card__code { color: var(--steel); }
.product-card__title { font-size: 1.08rem; margin: 0 0 8px; }
.product-card__title a { text-decoration: none; }
.product-card__title a::after { content: ""; position: absolute; inset: 0; z-index: 1; }
.product-card { position: relative; }
.product-card__desc { font-size: var(--fs-small); color: var(--slate); margin: 0 0 14px; }
.dark .product-card__desc { color: var(--steel); }
/* The card title's ::after stretches over the whole card to make it clickable.
   Anything interactive inside the card has to sit above that overlay. */
.product-card [data-cart-add],
.product-card button,
.product-card__body a:not(.product-card__title a) { position: relative; z-index: 3; }

.product-card__meta { margin-top: auto; display: flex; gap: 8px; flex-wrap: wrap; font-size: var(--fs-micro); color: var(--slate); }
.dark .product-card__meta { color: var(--steel); }
.product-card__meta span { border: 1px solid var(--paper-line); border-radius: 2px; padding: 3px 7px; }
.dark .product-card__meta span { border-color: var(--ink-line); }

/* --- Filter bar ---------------------------------------------------------- */

.filter-bar { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-bottom: 32px; }
.filter-chip {
	background: none; cursor: pointer;
	border: 1px solid var(--paper-line); border-radius: 999px;
	padding: 9px 17px; font: inherit; font-size: var(--fs-small); color: var(--slate);
	text-decoration: none; transition: all var(--fast) var(--ease);
}
.filter-chip:hover { border-color: var(--ink); color: var(--ink); }
.filter-chip[aria-pressed="true"],
.filter-chip[aria-current="page"] { background: var(--ink); border-color: var(--ink); color: var(--brass); }
.filter-search {
	margin-left: auto; min-width: 220px; flex: 1 1 220px; max-width: 320px;
	padding: 10px 14px; font: inherit; font-size: var(--fs-small);
	border: 1px solid var(--paper-line); border-radius: var(--radius); background: var(--paper-raised);
}
.filter-count { width: 100%; font-size: var(--fs-small); color: var(--slate); }
.is-hidden { display: none !important; }

/* --- Product detail ------------------------------------------------------ */

.product-hero { display: grid; gap: clamp(28px, 4.5vw, 60px); grid-template-columns: 1fr; }
@media (min-width: 940px) { .product-hero { grid-template-columns: 1.02fr 0.98fr; align-items: start; } }

.product-gallery__main { background: #fff; border: 1px solid var(--paper-line); border-radius: var(--radius); aspect-ratio: 1; }
.product-gallery__main img { width: 100%; height: 100%; object-fit: contain; padding: 6%; }
.product-thumbs { display: flex; gap: 10px; margin-top: 12px; flex-wrap: wrap; }
.product-thumbs button {
	width: 74px; height: 74px; padding: 6px; cursor: pointer;
	background: #fff; border: 1px solid var(--paper-line); border-radius: var(--radius);
}
.product-thumbs button[aria-current="true"] { border-color: var(--ink); }
.product-thumbs img { width: 100%; height: 100%; object-fit: contain; }

.product-code-line { font-size: var(--fs-small); color: var(--slate); letter-spacing: 0.06em; margin-bottom: 10px; }
.product-terms { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 22px; }
.product-terms a { font-size: var(--fs-micro); text-decoration: none; border: 1px solid var(--paper-line); border-radius: 999px; padding: 4px 11px; color: var(--slate); }
.product-terms a:hover { border-color: var(--ink); color: var(--ink); }

.feature-list { list-style: none; margin: 0 0 26px; padding: 0; display: grid; gap: 10px; }
.feature-list li { position: relative; padding-left: 24px; font-size: 0.98rem; }
.feature-list li::before {
	content: ""; position: absolute; left: 0; top: 0.55em;
	width: 10px; height: 2px; background: var(--brass);
}

.size-chips { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 26px; }
.size-chips span { border: 1px solid var(--paper-line); border-radius: var(--radius); padding: 7px 13px; font-size: var(--fs-small); }

.product-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 8px; }

/* Specification and dimension tables, set like a drawing schedule */
.spec-table { width: 100%; border-collapse: collapse; font-size: 0.95rem; }
.spec-table th, .spec-table td { text-align: left; padding: 12px 14px; border-bottom: 1px solid var(--paper-line); }
.spec-table td { font-family: var(--font-mono); font-size: 0.88rem; }
.spec-table th { width: 38%; font-weight: 600; color: var(--slate); font-size: var(--fs-small); }
.spec-table tr:last-child th, .spec-table tr:last-child td { border-bottom: 0; }

.dim-table { width: 100%; border-collapse: collapse; font-family: var(--font-mono); font-size: 0.86rem; font-variant-numeric: tabular-nums; }
.dim-table th, .dim-table td { padding: 11px 12px; text-align: left; border: 1px solid var(--paper-line); }
.dim-table thead th { background: var(--ink); color: var(--brass); font-size: var(--fs-micro); letter-spacing: 0.08em; border-color: var(--ink); }
.dim-table tbody tr:nth-child(even) { background: rgba(0,0,0,0.02); }
.dim-note { font-size: var(--fs-micro); color: var(--slate); margin-top: 10px; }

.panel { background: var(--paper-raised); border: 1px solid var(--paper-line); border-radius: var(--radius); padding: clamp(20px, 3vw, 32px); }
.panel + .panel { margin-top: 24px; }
.panel h3 { margin-bottom: 16px; }

/* --- Forms --------------------------------------------------------------- */

.form-grid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.form-field { display: flex; flex-direction: column; gap: 6px; }
.form-field--wide { grid-column: 1 / -1; }
.form-field label { font-size: var(--fs-small); font-weight: 600; }
.form-field .hint { font-size: var(--fs-micro); color: var(--slate); font-weight: 400; }
.form-field input, .form-field select, .form-field textarea {
	font: inherit; font-size: 0.97rem; padding: 12px 14px;
	border: 1px solid var(--paper-line); border-radius: var(--radius);
	background: var(--paper-raised); color: var(--ink); width: 100%;
}
.form-field textarea { min-height: 120px; resize: vertical; }
/* A checkbox is not a text field: it must not take the field width or padding,
   or it stretches across the row and the label floats away from it. */
.form-field input[type="checkbox"], .form-field input[type="radio"] {
	flex: 0 0 auto; width: 17px; height: 17px; min-width: 17px;
	padding: 0; border-radius: 3px; accent-color: var(--brass-deep);
}
.form-field input[type="radio"] { border-radius: 50%; }
.form-consent { display: flex; gap: 10px; align-items: flex-start; font-size: var(--fs-small); font-weight: 400; color: var(--slate); line-height: 1.5; }
.form-consent input[type="checkbox"] { margin: 2px 0 0; }
.form-consent > span { flex: 1 1 auto; }
/* The policy link has to read as a link, or the consent is worth less. */
.form-consent a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.form-consent a:hover { color: var(--ink); }
.dark .form-consent a:hover, .site-footer .form-consent a:hover { color: var(--brass); }
.honeypot { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form-note { padding: 13px 16px; border-radius: var(--radius); font-size: 0.95rem; margin-bottom: 20px; }
.form-note--ok { background: #EAF6EC; border-left: 3px solid #2E7D4F; color: #1D4F32; }
.form-note--warn { background: #FDF3D8; border-left: 3px solid var(--brass-deep); color: #5C4A00; }

/* --- Cards for text content --------------------------------------------- */

.tile { border: 1px solid var(--paper-line); border-radius: var(--radius); padding: clamp(20px, 2.6vw, 30px); background: var(--paper-raised); }
.dark .tile { background: var(--ink-raised); border-color: var(--ink-line); }
.tile h3 { margin-bottom: 10px; }
.tile p { font-size: 0.95rem; color: var(--slate); margin: 0; }
.dark .tile p { color: var(--steel); }

/* The process is a real sequence, so it gets numbered. Nothing else does. */
.step { position: relative; padding-left: 56px; }
.step__n {
	position: absolute; left: 0; top: 0;
	font-family: var(--font-display); font-variation-settings: "wdth" 118;
	font-size: 2rem; font-weight: 700; line-height: 1; color: var(--brass); opacity: 0.85;
}

.category-tile {
	position: relative; display: block; text-decoration: none;
	border: 1px solid var(--ink-line); border-radius: var(--radius);
	background: var(--ink-raised); overflow: hidden;
	transition: border-color var(--fast) var(--ease);
}
.category-tile:hover { border-color: var(--brass); }
.category-tile img { aspect-ratio: 4/3; width: 100%; object-fit: contain; padding: 12%; background: #fff; }
.category-tile__label { padding: 16px 18px; display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.category-tile__label strong { font-family: var(--font-display); font-variation-settings: "wdth" 108; font-size: 1.02rem; }
.category-tile__label em { font-style: normal; font-size: var(--fs-micro); color: var(--steel); }

/* --- Downloads ----------------------------------------------------------- */

.download-row {
	display: flex; gap: 20px; align-items: center; flex-wrap: wrap;
	border: 1px solid var(--paper-line); border-radius: var(--radius);
	padding: 20px; background: var(--paper-raised);
}
.download-row__icon { width: 46px; height: 58px; border: 1px solid var(--paper-line); border-radius: 2px; display: grid; place-items: center; font-size: var(--fs-micro); color: var(--slate); flex: none; }
.download-row__text { flex: 1 1 240px; }
.download-row__text h3 { margin: 0 0 4px; font-size: 1.05rem; }
.download-row__text p { margin: 0; font-size: var(--fs-small); color: var(--slate); }

dialog.gate {
	border: 1px solid var(--paper-line); border-radius: var(--radius-lg);
	padding: clamp(24px, 3.4vw, 36px); max-width: 480px; width: calc(100% - 32px);
	background: var(--paper-raised); color: var(--ink);
}
dialog.gate::backdrop { background: rgba(18, 16, 15, 0.72); }
dialog.gate h3 { margin-bottom: 6px; }
dialog.gate .gate-sub { font-size: var(--fs-small); color: var(--slate); margin-bottom: 20px; }
dialog.gate .gate-close { position: absolute; top: 12px; right: 14px; background: none; border: 0; font-size: 1.4rem; cursor: pointer; color: var(--slate); line-height: 1; }

/* --- WhatsApp button ----------------------------------------------------- */

.wa-float {
	position: fixed; right: 18px; bottom: 18px; z-index: 70;
	display: inline-flex; align-items: center; gap: 10px;
	background: #1FAF54; color: #fff; text-decoration: none;
	padding: 13px 18px; border-radius: 999px; font-size: 0.9rem; font-weight: 600;
	box-shadow: 0 6px 22px rgba(0,0,0,0.24);
}
.wa-float span { display: none; }
@media (min-width: 720px) { .wa-float span { display: inline; } }

/* Mobile corrections ------------------------------------------------------- */

@media (max-width: 719px) {
	/* The floating bubble is fixed, so anything full width at the same height
	   sits underneath it. Shrink it and keep interactive elements clear. */
	.wa-float { right: 14px; bottom: 14px; padding: 12px; }

	.filter-search { padding-right: 62px; }
	.filter-bar { padding-bottom: 8px; }

	/* Give the last thing on a product page room to breathe above the bubble. */
	.product-actions { margin-bottom: 68px; }

	/* Column E was touching the edge. Tighter cells, and let the panel scroll. */
	.dim-table th, .dim-table td { padding: 9px 8px; font-size: 0.8rem; }
	.panel { padding-inline: 16px; }
}

/* --- Fact list ----------------------------------------------------------- */
/* A ruled label-and-answer list, used beside a section heading where the
   heading would otherwise sit alone against a column of prose. Reads as a
   short specification rather than a second paragraph. */

.fact-list { margin: clamp(24px, 3vw, 36px) 0 0; border-top: 1px solid var(--paper-line); }
.fact-list__row { display: grid; gap: 2px; padding-block: 13px; border-bottom: 1px solid var(--paper-line); }
@media (min-width: 560px) {
	.fact-list__row { grid-template-columns: 10.5rem 1fr; gap: 20px; align-items: baseline; }
}
.fact-list dt {
	margin: 0;
	font-family: var(--font-display); font-variation-settings: "wdth" 104;
	font-size: var(--fs-micro); font-weight: 600;
	letter-spacing: 0.1em; text-transform: uppercase; color: var(--slate);
}
.fact-list dd { margin: 0; font-size: var(--fs-small); line-height: 1.5; color: var(--ink); }

.dark .fact-list, .dark .fact-list__row { border-color: var(--ink-line); }
.dark .fact-list dt { color: var(--steel); }
.dark .fact-list dd { color: var(--paper); }

/* --- Capability strip ---------------------------------------------------- */

.capability { display: grid; gap: clamp(20px, 2.6vw, 40px); grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }
.capability__item h3 { font-size: 1rem; margin-bottom: 8px; position: relative; padding-top: 14px; }
.capability__item h3::before { content: ""; position: absolute; top: 0; left: 0; width: 26px; height: 2px; background: var(--brass); }
.capability__item p { font-size: var(--fs-small); color: var(--slate); margin: 0; }

/* --- Factory video ------------------------------------------------------- */

.video-facade { position: relative; aspect-ratio: 16/9; background: #000; border-radius: var(--radius); overflow: hidden; cursor: pointer; }
.video-facade img { width: 100%; height: 100%; object-fit: cover; opacity: 0.82; transition: opacity var(--fast) var(--ease); }
.video-facade:hover img { opacity: 1; }
.video-facade iframe { width: 100%; height: 100%; border: 0; display: block; }
.video-facade__play {
	position: absolute; inset: 0; margin: auto;
	width: 66px; height: 66px; display: grid; place-items: center;
	border: 0; border-radius: 50%; cursor: pointer;
	background: var(--brass); color: var(--ink);
	transition: transform var(--fast) var(--ease);
}
.video-facade:hover .video-facade__play { transform: scale(1.06); }

/* --- Testimonials -------------------------------------------------------- */

.quote-card { display: flex; flex-direction: column; margin: 0; }
.quote-card__stars { color: var(--brass); letter-spacing: 0.14em; font-size: 0.9rem; margin-bottom: 12px; }
.quote-card blockquote { margin: 0 0 18px; font-size: 0.98rem; color: var(--ink); }
.quote-card blockquote p { margin: 0 0 0.6em; }
.quote-card figcaption { margin-top: auto; display: flex; gap: 12px; align-items: center; padding-top: 16px; border-top: 1px solid var(--paper-line); }
.quote-card__avatar { width: 42px; height: 42px; border-radius: 50%; object-fit: cover; flex: none; }
.quote-card__avatar--initial {
	display: grid; place-items: center; background: var(--ink); color: var(--brass);
	font-family: var(--font-display); font-weight: 700; font-size: 1.05rem;
}
.quote-card figcaption strong { display: block; font-size: 0.95rem; }
.quote-card figcaption em { font-style: normal; font-size: var(--fs-micro); color: var(--slate); }

/* --- Enquiry list -------------------------------------------------------- */

.cart-link { position: relative; }
/* [hidden] is display:none in the UA sheet, but any display declaration
   here outranks it. Without this the empty badge shows 0 permanently. */
.cart-count[hidden] { display: none !important; }

.cart-count {
	display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 5px;
	margin-left: 2px; border-radius: 999px; background: var(--ink); color: var(--brass);
	font-size: var(--fs-micro); font-weight: 700;
	animation: countPop 200ms var(--ease);
}
@keyframes countPop { from { transform: scale(0.7); } to { transform: scale(1); } }

.cart-add.is-added { background: var(--brass); border-color: var(--brass); color: var(--ink); }

.enquiry-layout { display: grid; gap: clamp(24px, 4vw, 48px); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 900px) { .enquiry-layout { grid-template-columns: 1.15fr 0.85fr; } }

.cart-row {
	display: flex; gap: 16px; align-items: center; flex-wrap: wrap;
	border: 1px solid var(--paper-line); border-radius: var(--radius);
	background: var(--paper-raised); padding: 16px 18px;
}
.cart-row__text { flex: 1 1 180px; }
.cart-row__text strong { display: block; font-size: 1rem; }
.cart-row__code { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--slate); }
.cart-row__qty { display: flex; flex-direction: column; gap: 4px; }
.cart-row__qty span { font-size: var(--fs-micro); color: var(--slate); }
.cart-row__qty input { width: 130px; padding: 9px 12px; font: inherit; font-size: 0.92rem; border: 1px solid var(--paper-line); border-radius: var(--radius); }
.cart-row__remove { background: none; border: 0; font-size: 1.4rem; line-height: 1; color: var(--slate); cursor: pointer; padding: 4px 8px; }
.cart-row__remove:hover { color: var(--ink); }

/* --- Exploded assembly ---------------------------------------------------
   Every part carries its own --dx / --dy / --rot. A single scroll-driven
   --t on the stage drives all of them, so the whole animation is one
   variable and the browser can composite it on the GPU.
   ------------------------------------------------------------------------ */

.exploded-stage { position: relative; }
.exploded-stage svg { width: 100%; max-width: 380px; margin-inline: auto; display: block; overflow: visible; }

.exploded-stage { --t: 0; }

.ex-part {
	--dx: 0; --dy: 0; --rot: 0;
	transform:
		translate( calc(var(--dx) * var(--t) * 1px), calc(var(--dy) * var(--t) * 1px) )
		rotate( calc(var(--rot) * var(--t) * 1deg) );
	transform-box: fill-box;
	transform-origin: center;
	transition: transform 120ms linear;
}

.ex-part path,
.ex-part rect,
.ex-part circle { fill: none; stroke: #CFCBC5; stroke-width: 4; stroke-linecap: round; stroke-linejoin: round; }

.ex-shackle path { stroke: #E6E3DE; stroke-width: 7; }
.ex-shackle .ex-hint { stroke: var(--brass); stroke-width: 7; opacity: calc(var(--t) * 0.9); }

.ex-body rect { stroke: #CFCBC5; }
.ex-body .ex-inner { stroke: var(--ink-line); stroke-width: 2; }

.ex-cyl circle, .ex-cyl path { stroke: var(--brass); }
.ex-levers rect { stroke: #9A958E; stroke-width: 5; }
.ex-key rect, .ex-key path { stroke: #E6E3DE; stroke-width: 3.5; }

.ex-grid line { stroke: var(--ink-line); stroke-width: 1; stroke-dasharray: 3 7; }
.ex-leaders line {
	stroke: var(--brass); stroke-width: 1; stroke-dasharray: 2 5;
	opacity: calc(var(--t) * 0.75);
}

.exploded-key { list-style: none; margin: 26px 0 0; padding: 0; display: grid; gap: 16px; counter-reset: none; }
.exploded-key li { display: grid; grid-template-columns: 34px 1fr; gap: 4px 12px; align-items: baseline; }
.exploded-key__n {
	grid-row: span 2; font-family: var(--font-mono); font-size: var(--fs-micro);
	color: var(--brass); padding-top: 3px;
}
.exploded-key strong { font-size: 0.98rem; color: var(--paper); }
.exploded-key em { font-style: normal; font-size: var(--fs-small); color: var(--steel); }

/* --- Hero tilt -----------------------------------------------------------
   Pointer parallax on the hero product. Pointer devices only, and switched
   off entirely for reduced motion. Never on touch, where it cannot work and
   would only cost battery.
   ------------------------------------------------------------------------ */

.hero-figure { --rx: 0; --ry: 0; }

@media (hover: hover) and (pointer: fine) {
	.hero-figure img {
		transform: perspective(1100px) rotateX(calc(var(--rx) * 1deg)) rotateY(calc(var(--ry) * 1deg));
		transition: transform 260ms var(--ease);
		will-change: transform;
	}
	.hero-figure::after {
		content: ""; position: absolute; inset: 0; border-radius: var(--radius-lg);
		pointer-events: none;
		background: linear-gradient(
			calc(105deg + var(--ry) * 2deg),
			transparent 38%,
			rgba(255, 255, 255, 0.28) 50%,
			transparent 62%
		);
		opacity: 0; transition: opacity 300ms var(--ease);
	}
	.hero-figure:hover::after { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
	.ex-part { transform: none !important; transition: none !important; }
	.ex-leaders line, .ex-shackle .ex-hint { opacity: 0.6 !important; }
	.hero-figure img { transform: none !important; }
}

/* --- Top bar -------------------------------------------------------------- */

.topbar { background: #0A0908; color: var(--steel); font-size: var(--fs-small); border-bottom: 1px solid var(--ink-line); }
.topbar__inner { display: flex; align-items: center; justify-content: space-between; gap: 16px; min-height: 52px; flex-wrap: wrap; }
.topbar__note { margin: 0; }
.topbar__links { display: flex; align-items: center; gap: 22px; }
.topbar__links a { text-decoration: none; }
.topbar__links a:hover { color: var(--brass); }
@media (max-width: 980px) { .topbar__note { display: none; } .topbar__inner { justify-content: center; } }
@media (max-width: 520px) {
	.topbar { font-size: var(--fs-micro); }
	.topbar__inner { min-height: 44px; gap: 10px; }
	.topbar__links { gap: 12px; flex-wrap: wrap; justify-content: center; }
}

/* --- Social icons --------------------------------------------------------- */

/* The footer sets a grid on every ul, which stacked these vertically. */
.social-row,
.site-footer .social-row,
.mobile-nav .social-row { display: flex; flex-wrap: wrap; gap: 12px; list-style: none; margin: 20px 0 0; padding: 0; }
.social-row--sm, .topbar .social-row { margin: 0; gap: 8px; }
.social-row__link { display: grid; place-items: center; width: 44px; height: 44px; border: 1px solid var(--ink-line); border-radius: 50%; color: var(--steel); background: transparent; transition: color var(--fast) var(--ease), background var(--fast) var(--ease), border-color var(--fast) var(--ease), transform 220ms var(--ease); }
.social-row__link svg { width: 20px; height: 20px; transition: transform 220ms var(--ease); }
.social-row--sm .social-row__link { width: 30px; height: 30px; border-color: transparent; }
.social-row--sm .social-row__link svg { width: 16px; height: 16px; }
.social-row__link:hover, .social-row__link:focus-visible { color: var(--ink); background: var(--brass); border-color: var(--brass); transform: translateY(-3px); }
.social-row__link:hover svg { transform: scale(1.12); }
.social-row__link.is-placeholder { opacity: 0.55; cursor: default; }
.social-row__link.is-placeholder:hover { opacity: 1; color: var(--steel); background: transparent; border-color: var(--steel); transform: translateY(-2px); }

/* --- Nav dropdown --------------------------------------------------------- */

.nav li { position: relative; }
.nav .has-dropdown > a::after {
	content: ""; display: inline-block; width: 5px; height: 5px; margin-left: 7px;
	border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
	transform: translateY(-2px) rotate(45deg);
}
.nav .sub-menu {
	position: absolute; top: 100%; left: -18px; z-index: 50;
	min-width: 250px; margin: 0; padding: 8px; list-style: none;
	background: var(--ink-raised); border: 1px solid var(--ink-line); border-radius: var(--radius);
	box-shadow: 0 18px 40px rgba(0,0,0,0.45);
	display: block; opacity: 0; visibility: hidden; transform: translateY(6px);
	transition: opacity var(--fast) var(--ease), transform var(--fast) var(--ease), visibility var(--fast);
}
.nav li:hover > .sub-menu,
.nav li:focus-within > .sub-menu { opacity: 1; visibility: visible; transform: none; }
.nav .sub-menu a {
	display: flex; justify-content: space-between; align-items: baseline; gap: 14px;
	padding: 10px 12px; border-bottom: 0; border-radius: 2px; font-size: 0.9rem;
}
.nav .sub-menu a:hover { background: rgba(255,213,0,0.1); color: var(--brass); }
.nav .sub-menu em { font-style: normal; font-size: var(--fs-micro); color: var(--steel); font-family: var(--font-mono); }
.nav .sub-menu .is-all a { border-top: 1px solid var(--ink-line); margin-top: 6px; color: var(--brass); }

.mobile-nav .sub-menu { list-style: none; margin: 0 0 0 14px; padding: 0; }
.mobile-nav .sub-menu a { display: flex; justify-content: space-between; gap: 14px; font-size: 0.92rem; color: var(--steel); }
.mobile-nav .sub-menu em { font-style: normal; font-family: var(--font-mono); font-size: var(--fs-micro); opacity: 0.7; }
/* Accordion. The toggle button is added by the script, so the categories are
   only hidden once there is something on the page able to show them again. */
.mobile-nav .has-sub-toggle { display: flex; flex-wrap: wrap; align-items: stretch; }
.mobile-nav .has-sub-toggle > a { flex: 1 1 auto; }
.mobile-nav__sub {
	flex: 0 0 48px; display: flex; align-items: center; justify-content: center;
	background: none; border: 0; border-bottom: 1px solid var(--ink-line);
	color: inherit; cursor: pointer; padding: 0;
}
.mobile-nav__sub svg { transition: transform 0.2s ease; }
.mobile-nav .is-open > .mobile-nav__sub svg { transform: rotate(180deg); }
.mobile-nav .has-sub-toggle > .sub-menu { flex: 0 0 100%; display: none; }
.mobile-nav .has-sub-toggle.is-open > .sub-menu { display: block; }
.mobile-nav__contact { margin-top: 18px; font-size: var(--fs-small); color: var(--steel); }
.mobile-nav__contact a { text-decoration: none; }

/* --- WhatsApp action button ---------------------------------------------- */

.btn--wa { background: #1FAF54; color: #fff; }
.btn--wa svg { width: 18px; height: 18px; flex: none; }
.btn--wa:hover { background: #189343; }
/* --- Product image magnifier ---------------------------------------------
   A second copy of the image at 2.2x, positioned by pointer. Fine pointers
   only: on a phone, pinch-zoom already does this better.
   ------------------------------------------------------------------------ */

.product-gallery__main.has-magnifier { cursor: zoom-in; overflow: hidden; }
.magnifier-lens {
	position: absolute; inset: 0; pointer-events: none;
	background-repeat: no-repeat; background-color: #fff;
	opacity: 0; transition: opacity 160ms var(--ease);
	z-index: 2;
}
.product-gallery__main.is-zooming .magnifier-lens { opacity: 1; }
.product-gallery__main { position: relative; }
.magnifier-hint {
	position: absolute; right: 12px; bottom: 12px; z-index: 3;
	background: var(--ink); color: var(--paper);
	font-size: var(--fs-micro); padding: 5px 10px; border-radius: 2px;
	opacity: 0.72; pointer-events: none;
}
.product-gallery__main.is-zooming .magnifier-hint { opacity: 0; }
@media (hover: none), (pointer: coarse) { .magnifier-hint { display: none; } }

/* --- Catalogue page ------------------------------------------------------- */

.catalogue-block { display: grid; gap: clamp(24px, 4vw, 52px); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 860px) { .catalogue-block { grid-template-columns: 0.8fr 1.2fr; } }
.catalogue-cover img { width: 100%; border: 1px solid var(--paper-line); border-radius: var(--radius); }
.catalogue-cover__fallback {
	aspect-ratio: 1/1.414; display: grid; place-items: center;
	border: 1px solid var(--paper-line); border-radius: var(--radius);
	background: var(--paper-raised); color: var(--slate);
	font-family: var(--font-mono); font-size: 1.4rem;
}
.catalogue-meta { font-family: var(--font-mono); font-size: var(--fs-small); color: var(--slate); }
.catalogue-qr {
	display: flex; gap: 18px; align-items: center; margin-top: 28px; padding-top: 24px;
	border-top: 1px solid var(--paper-line);
}
.catalogue-qr__code {
	width: 116px; height: 116px; flex: none; display: grid; place-items: center;
	border: 1px solid var(--paper-line); border-radius: var(--radius); background: #fff; padding: 8px;
}
.catalogue-qr__code img, .catalogue-qr__code canvas { width: 100%; height: 100%; }
.catalogue-qr p { font-size: var(--fs-small); color: var(--slate); margin: 0; }
.catalogue-qr strong { display: block; color: var(--ink); }

.gate--wide { max-width: 960px; width: calc(100% - 32px); }
.pdf-viewer { aspect-ratio: 1/1.3; max-height: 72vh; border: 1px solid var(--paper-line); border-radius: var(--radius); overflow: hidden; }
.pdf-viewer iframe { width: 100%; height: 100%; border: 0; display: block; }


/* --- Flipbook ------------------------------------------------------------- */

dialog.gate--book { display: none; }
dialog.gate--book[open] {
	display: flex; flex-direction: column;
	position: fixed; inset: 0; margin: auto;
	max-width: 1480px; width: calc(100% - 32px); height: calc(100vh - 32px); max-height: 980px;
	background: var(--ink); color: var(--paper); border-color: var(--ink-line);
	padding: 40px clamp(16px, 2vw, 28px) clamp(14px, 2vw, 24px);
	z-index: 200;
}
dialog.gate--book .gate-close {
	top: 12px; right: 14px;
	width: 40px; height: 40px;
	display: grid; place-items: center;
	border-radius: 50%;
	background: var(--ink-raised);
	color: var(--paper);
	font-size: 1.8rem; line-height: 1;
	transition: background var(--fast) var(--ease), transform 180ms var(--ease);
}
dialog.gate--book .gate-close:hover { background: var(--brass); color: var(--ink); transform: rotate(90deg); }
dialog.gate--book[open]::backdrop { background: rgba(0,0,0,0.86); }
dialog.gate--book[open] .flipbook-stage { flex: 1; min-height: 0; display: flex; flex-direction: column; align-items: center; width: 100%; }
dialog.gate--book[open] .flipbook-frame { flex: 1; min-height: 0; width: 100%; max-width: 1300px; position: relative; }
dialog.gate--book[open] .flipbook { position: absolute; inset: 0; margin: auto; }
.gate--book .gate-close { color: var(--steel); }
.flipbook-stage { display: flex; flex-direction: column; align-items: center; }
.flipbook-controls { display: flex; align-items: center; gap: 16px; margin-bottom: 10px; }
.flip-btn { display: grid; place-items: center; width: 40px; height: 40px; border: 0; border-radius: 50%; cursor: pointer; background: var(--ink-raised); color: var(--paper); box-shadow: 0 4px 10px rgba(0,0,0,0.35); transition: background var(--fast) var(--ease), color var(--fast) var(--ease), transform 180ms var(--ease); text-decoration: none; }
.flip-btn svg { width: 20px; height: 20px; }
.flip-btn:hover { background: var(--brass); color: var(--ink); transform: translateY(-2px); }
.flip-btn:active { transform: translateY(0); }
.flip-btn--download { background: var(--brass); color: var(--ink); }
.flip-counter { font-family: var(--font-mono); font-size: var(--fs-small); color: var(--steel); min-width: 66px; text-align: center; }
.flipbook { width: 100%; max-width: 900px; margin-inline: auto; }
.flipbook__page { background-size: cover; background-position: center; background-color: #fff; box-shadow: inset 0 0 22px rgba(0,0,0,0.18); }
.flipbook__hint { margin: 8px 0 0; font-size: var(--fs-micro); color: var(--steel); }
@media (max-width: 620px) { .flipbook__hint { display: none; } .flip-btn { width: 42px; height: 42px; } }

/* --- Reviews -------------------------------------------------------------- */

.reviews__head { display: flex; justify-content: space-between; align-items: flex-end; gap: 24px; flex-wrap: wrap; margin-bottom: clamp(24px, 3vw, 42px); }
.reviews__score { text-align: right; }
.reviews__score strong {
	display: block; font-family: var(--font-display); font-variation-settings: "wdth" 118;
	font-size: 2.6rem; line-height: 1; color: var(--ink);
}
.reviews__score em { display: block; font-style: normal; font-size: var(--fs-micro); color: var(--slate); margin-top: 4px; }
@media (max-width: 620px) { .reviews__head { flex-direction: column; align-items: flex-start; } .reviews__score { text-align: left; } }

/* --- OTP input ------------------------------------------------------------ */

.otp-input {
	font-family: var(--font-mono) !important; font-size: 1.5rem !important;
	letter-spacing: 0.5em; text-align: center; text-indent: 0.5em;
}

/* --- Footer -------------------------------------------------------------- */

.site-footer { background: var(--ink); color: var(--steel); padding-block: clamp(44px, 6vw, 72px) 28px; font-size: var(--fs-small); }
.footer-grid { display: grid; gap: 34px; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.footer-brand { grid-column: span 1; }
@media (min-width: 900px) { .footer-grid { grid-template-columns: 1.5fr 1fr 1fr 1.2fr; } }
.site-footer h4 { color: var(--paper); font-size: 0.92rem; letter-spacing: 0.02em; margin-bottom: 14px; font-variation-settings: "wdth" 104; }
.site-footer a { color: var(--steel); text-decoration: none; }
.site-footer a:hover { color: var(--brass); }
.site-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.site-footer img.footer-logo { max-height: 60px; width: auto; margin-bottom: 16px; }
.footer-legal {
	margin-top: 38px; padding-top: 20px; border-top: 1px solid var(--ink-line);
	display: flex; flex-wrap: wrap; gap: 8px 24px; justify-content: space-between;
	font-size: var(--fs-micro);
}

/* --- Breadcrumbs & pagination ------------------------------------------- */

.crumbs { font-size: var(--fs-micro); color: var(--slate); margin-bottom: 16px; }
.crumbs a { text-decoration: none; }
.crumbs a:hover { text-decoration: underline; }
.dark .crumbs, .dark .crumbs a { color: var(--steel); }

/* Deep enough to separate the page from the header, shallow enough that it
   reads as a band rather than a masthead. The product page gets no dark block
   at all, so these two should not be competing with it for weight. */
.page-head { padding-block: clamp(24px, 3vw, 38px); border-bottom: 1px solid var(--ink-line); background: var(--ink); color: var(--paper); }
.page-head h1 { margin-bottom: 10px; }
.page-head .lead { font-size: 1.05rem; max-width: 70ch; }
.page-head p { color: var(--steel); }

.pagination { display: flex; gap: 8px; margin-top: 40px; flex-wrap: wrap; }
.pagination .page-numbers { padding: 9px 15px; border: 1px solid var(--paper-line); border-radius: var(--radius); text-decoration: none; font-size: var(--fs-small); }
.pagination .current { background: var(--ink); color: var(--brass); border-color: var(--ink); }

/* --- Editorial ----------------------------------------------------------- */

.prose { max-width: 68ch; }
.prose h2 { margin-top: 1.6em; }
.prose ul, .prose ol { padding-left: 1.3em; }
.prose li { margin-bottom: 0.5em; }
.prose img { border-radius: var(--radius); margin-block: 1.6em; }
.prose blockquote { margin: 1.8em 0; padding-left: 22px; border-left: 3px solid var(--brass); font-size: 1.1rem; }

/* --- The loader ---------------------------------------------------------
   The one deliberate piece of motion on the site: a shackle dropping into a
   padlock body. Runs once per browser session, capped at 1.6s, and skipped
   entirely for anyone who has asked for reduced motion.
   ------------------------------------------------------------------------ */

.loader {
	position: fixed; inset: 0; z-index: 999;
	display: grid; place-items: center;
	background: var(--ink);
	transition: opacity 380ms var(--ease), visibility 380ms;
}
.loader[hidden] { display: none; }
.loader.is-done { opacity: 0; visibility: hidden; pointer-events: none; }

.loader__lock { width: 96px; height: auto; overflow: visible; }
.loader__body { fill: none; stroke: var(--brass); stroke-width: 4; }
.loader__keyhole { fill: var(--brass); opacity: 0; animation: keyhole 420ms var(--ease) 640ms forwards; }
.loader__shackle {
	fill: none; stroke: #CFCBC5; stroke-width: 5; stroke-linecap: round;
	transform: translateY(-13px);
	animation: shackle 560ms var(--ease) 180ms forwards;
}
.loader__word {
	margin-top: 22px; text-align: center;
	font-family: var(--font-display); font-variation-settings: "wdth" 118;
	font-size: var(--fs-micro); letter-spacing: 0.36em; text-indent: 0.36em;
	color: var(--steel);
	opacity: 0; animation: fadeUp 420ms var(--ease) 760ms forwards;
}

@keyframes shackle {
	0%   { transform: translateY(-13px); }
	72%  { transform: translateY(2px); }
	86%  { transform: translateY(-1px); }
	100% { transform: translateY(0); }
}
@keyframes keyhole { to { opacity: 1; } }
@keyframes fadeUp { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
	html { scroll-behavior: auto; }
	.loader { display: none; }
	*, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
}


/* ===========================================================================
   MOTION LAYER
   ===========================================================================

   Three things live here: a shared scroll-reveal, the ring carousel and the
   spotlight carousel. They share one rule — the page must be complete and
   readable with the stylesheet applied and the script dead. Anything that
   hides content does so behind .js-reveal, a class written by an inline
   script in the head, so it can only ever apply where scripting is alive.
   ------------------------------------------------------------------------ */

/* --- Scroll reveal -------------------------------------------------------- */

/* No will-change here on purpose. These targets are whole page sections, and
   promoting a dozen of them on a 10,000px homepage costs more layer memory
   than the compositor will spend on it — the symptom is sections painting
   blank. opacity and transform are composited anyway, so the hint bought
   nothing and the sections animate just as smoothly without it. */
.js-reveal [data-reveal] {
	opacity: 0;
	transform: translateY(20px);
	transition: opacity 620ms var(--ease), transform 620ms var(--ease);
}
.js-reveal [data-reveal].is-revealed {
	opacity: 1;
	transform: none;
}

/* Children arrive in sequence rather than as one slab. The delay is set from
   the script as --d, because a CSS-only nth-child ladder cannot know how many
   items a category actually has. */
.js-reveal [data-reveal-stagger] > * {
	opacity: 0;
	transform: translateY(16px);
	transition: opacity 520ms var(--ease), transform 520ms var(--ease);
	transition-delay: calc(var(--d, 0) * 1ms);
}
.js-reveal [data-reveal-stagger].is-revealed > * {
	opacity: 1;
	transform: none;
}

/* --- Hero: film behind the headline --------------------------------------- */

.hero-media { position: absolute; inset: 0; overflow: hidden; }
.hero-media video {
	width: 100%; height: 100%;
	object-fit: cover;
	opacity: 0;
	transition: opacity 900ms var(--ease);
}
.hero-media video.is-playing { opacity: 0.3; }

/* Two scrims, not one: a flat wash would grey the footage evenly and leave the
   headline fighting whatever happens to be behind it. This keeps the left side
   solid enough to read against and lets the right side stay filmic. */
.hero-media__scrim {
	position: absolute; inset: 0;
	background:
		linear-gradient(100deg, var(--ink) 18%, rgba(18,16,15,0.72) 48%, rgba(18,16,15,0.45) 100%),
		radial-gradient(120% 80% at 80% 0%, transparent 40%, var(--ink) 100%);
}
@media (max-width: 860px) {
	/* On a phone the video is never fetched, so the scrim is all there is. */
	.hero-media__scrim { background: var(--ink); }
}

/* The headline arrives a word at a time, masked from below. Set up only once
   the script has split the words, so an unsplit headline is never hidden. */
.hero h1 .hw { display: inline-block; overflow: hidden; vertical-align: bottom; }
.hero h1 .hw > span {
	display: inline-block;
	transform: translateY(105%);
	transition: transform 720ms var(--ease);
	transition-delay: calc(var(--d, 0) * 1ms);
}
.hero h1.is-lit .hw > span { transform: none; }

/* --- Numbers that count up ------------------------------------------------ */

/* Tabular figures stop the strip reflowing as the digits change. */
.stat b[data-count-up] { font-variant-numeric: tabular-nums; }

/* ===========================================================================
   RING CAROUSEL
   ===========================================================================

   Cards sit around the inside of a cylinder. The ring is pushed back by its
   own radius so that whichever card faces the viewer sits at z = 0, which is
   what keeps the front card the same size no matter how many cards there are.

   --ring-r is written by the script after measuring a real card; every other
   number here is static. Without the script the whole thing collapses to a
   horizontal scroller, which is what the .ring-stage:not(.is-live) rules do.
   ------------------------------------------------------------------------ */

.ring-section { overflow: hidden; }

.ring-stage {
	--ring-r: 420;
	--rot: 0;
	/* One place to change the card size. The radius the script measures, the
	   negative margins that centre a card and the fallback scroller all read
	   from this, so they cannot drift apart. */
	--card-w: clamp(215px, 22vw, 300px);
	position: relative;
	margin-inline: calc(var(--gutter) * -1);
}

.ring-viewport {
	perspective: 1500px;
	perspective-origin: 50% 46%;
	height: clamp(340px, 36vw, 450px);
	outline: none;
}
.ring-viewport:focus-visible { outline: 2px solid var(--brass); outline-offset: 6px; border-radius: var(--radius); }

.ring {
	position: relative;
	width: 100%; height: 100%;
	transform-style: preserve-3d;
	transform: translateZ(calc(var(--ring-r) * -1px)) rotateY(calc(var(--rot) * 1deg));
}

.ring-card {
	--f: 1;               /* 1 dead ahead, 0 side on, negative round the back */
	position: absolute;
	top: 50%; left: 50%;
	width: var(--card-w);
	margin: calc(var(--card-w) * -0.62) 0 0 calc(var(--card-w) * -0.5);
	text-decoration: none;
	color: var(--paper);
	cursor: pointer;
	-webkit-tap-highlight-color: transparent;
	transform: rotateY(var(--a)) translateZ(calc(var(--ring-r) * 1px));
	opacity: calc(0.26 + 0.74 * max(var(--f), 0));
	filter: brightness(calc(0.62 + 0.38 * max(var(--f), 0)));
	transition: opacity 180ms linear, filter 180ms linear;
}

.ring-card__plate {
	display: block;
	aspect-ratio: 1;
	background: var(--paper-raised);
	border: 1px solid var(--ink-line);
	border-radius: var(--radius);
	overflow: hidden;
	box-shadow: 0 18px 34px rgba(0,0,0,0.45);
	transition: border-color 220ms var(--ease), box-shadow 220ms var(--ease);
}
.ring-card__plate img { width: 100%; height: 100%; object-fit: contain; display: block; }

.ring-card__meta { display: block; margin-top: 12px; text-align: center; }
.ring-card__meta strong {
	display: block;
	font-family: var(--font-display);
	font-size: 0.9rem;
	font-weight: 600;
	line-height: 1.25;
}
.ring-card__meta em {
	display: block;
	margin-top: 3px;
	font-family: var(--font-mono);
	font-style: normal;
	font-size: var(--fs-micro);
	color: var(--steel);
}

/* The card facing the viewer is the one being offered, so it says so. */
.ring-card.is-front .ring-card__plate { border-color: var(--brass); box-shadow: 0 22px 44px rgba(0,0,0,0.55); }
.ring-card.is-front .ring-card__meta em { color: var(--brass); }

/* Two different jobs share one gesture, so they get two different cursors:
   the front card opens the product, any other card turns the ring to it. */
.ring-card:not(.is-front) { cursor: grab; }
.ring-card:not(.is-front):hover .ring-card__plate { border-color: rgba(255, 213, 0, 0.5); }
.ring-card.is-front:hover .ring-card__plate { box-shadow: 0 26px 52px rgba(0,0,0,0.62); }
.ring-card:focus-visible { outline: none; }
.ring-card:focus-visible .ring-card__plate { outline: 2px solid var(--brass); outline-offset: 4px; }

/* Round the back the photograph would read as a smear of white through the
   gaps, so the card drops to a brass outline instead: the cylinder still
   reads as a cylinder, without muddying the front of it. */
.ring-card.is-back { pointer-events: none; }
.ring-card.is-back .ring-card__plate {
	background: transparent;
	border-color: rgba(255, 213, 0, 0.22);
	box-shadow: none;
}
.ring-card.is-back .ring-card__plate img { opacity: 0.05; filter: grayscale(1); }
.ring-card.is-back .ring-card__meta { opacity: 0; }

/* --- Ring controls -------------------------------------------------------- */

.ring-controls {
	display: flex; align-items: center; justify-content: center;
	gap: 18px;
	margin-top: clamp(18px, 2.4vw, 30px);
}

.ring-nav {
	display: grid; place-items: center;
	width: 44px; height: 44px;
	flex: none;
	border: 1px solid var(--ink-line);
	border-radius: 50%;
	background: transparent;
	color: var(--steel);
	cursor: pointer;
	transition: color var(--fast) var(--ease), border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}
.ring-nav:hover { color: var(--ink); border-color: var(--brass); background: var(--brass); }
.ring-nav:focus-visible { outline: 2px solid var(--brass); outline-offset: 3px; }

.ring-readout {
	min-width: 16ch;
	/* The global p rule caps paragraphs at 68ch, which here would centre the
	   text inside a box narrower than the rail it labels. */
	max-width: none;
	margin: 0;
	text-align: center;
	font-family: var(--font-mono);
	font-size: var(--fs-small);
	color: var(--paper);
}

.ring-hint {
	margin: 10px 0 0;
	max-width: none;   /* see .ring-readout */
	text-align: center;
	font-size: var(--fs-micro);
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--steel);
	transition: opacity 300ms var(--ease);
}
.ring-stage.has-turned .ring-hint { opacity: 0; }

.ring-foot {
	display: flex; flex-wrap: wrap; align-items: center;
	gap: 14px 20px;
	margin-top: clamp(26px, 3.4vw, 42px);
}
.ring-foot__cats { margin-bottom: 0; }
.ring-section .filter-chip { border-color: var(--ink-line); color: var(--steel); }
.ring-section .filter-chip:hover { border-color: var(--brass); color: var(--brass); }
.ring-section .filter-chip em { font-style: normal; color: var(--steel); opacity: 0.7; margin-left: 6px; }

/* --- Ring, without the script --------------------------------------------- */

/* The cards are real anchors in document order, so this stays a usable list. */
.ring-stage:not(.is-live) .ring-viewport { perspective: none; height: auto; overflow-x: auto; padding: 4px var(--gutter) 14px; }
.ring-stage:not(.is-live) .ring { display: flex; gap: 20px; transform: none; height: auto; }
.ring-stage:not(.is-live) .ring-card {
	position: static;
	margin: 0;
	flex: 0 0 var(--card-w);
	transform: none;
	opacity: 1;
	filter: none;
}
.ring-stage:not(.is-live) .ring-controls,
.ring-stage:not(.is-live) .ring-hint { display: none; }

@media (max-width: 720px) {
	.ring-hint { display: none; }
}

/* ===========================================================================
   SPOTLIGHT CAROUSEL
   ===========================================================================

   A row of shingled photographs. The open card is wider, and because every
   image is object-fit: cover the browser recomposes the crop against the new
   box rather than stretching the old one — so the card reads as having opened
   rather than zoomed. That recrop is the effect; the width change drives it.
   ------------------------------------------------------------------------ */

.spotlight { position: relative; }

/* The rail always fills its container exactly, whatever the open card and
   however many applications there are.
 *
 * Each closed card is (what is left over / how many are closed) plus one
 * overlap, and every card but the first pulls back by that same overlap. The
 * overlaps therefore cancel and the row comes to exactly 100% — so nothing
 * has to be measured in script, and adding a sixth application re-solves it
 * on its own. --n is written onto the rail by the template. */
.spotlight__rail {
	--n: 5;
	--ov: 30px;                        /* how far each card sits over its neighbour */
	--active-w: min(46%, 520px);
	display: flex;
	align-items: stretch;
	height: clamp(320px, 42vw, 440px);
}

.spot-card {
	--w: calc( (100% - var(--active-w)) / (var(--n) - 1) + var(--ov) );
	position: relative;
	flex: 0 0 var(--w);
	width: var(--w);
	border-radius: var(--radius-lg);
	overflow: hidden;
	background: var(--ink);
	cursor: pointer;
	transform-origin: 50% 100%;
	transition:
		flex-basis 520ms cubic-bezier(0.22, 1, 0.36, 1),
		width 520ms cubic-bezier(0.22, 1, 0.36, 1),
		transform 520ms cubic-bezier(0.22, 1, 0.36, 1),
		filter 520ms var(--ease),
		box-shadow 520ms var(--ease);
	filter: brightness(0.74) saturate(0.85);
	box-shadow: 0 10px 22px rgba(0,0,0,0.22);
}
.spot-card + .spot-card { margin-left: calc(var(--ov) * -1); }

.spot-card.is-active {
	--w: var(--active-w);
	z-index: 3;
	transform: translateY(-10px) scale(1.015);
	filter: none;
	box-shadow: 0 26px 54px rgba(0,0,0,0.38);
	cursor: default;
}

/* The hit area is a real button so the card is reachable by keyboard; the
   open card hands its clicks back to the link inside it. */
.spot-card__hit {
	position: absolute; inset: 0; z-index: 4;
	border: 0; padding: 0;
	background: transparent;
	cursor: pointer;
	appearance: none;
}
.spot-card.is-active .spot-card__hit { display: none; }
.spot-card__hit:focus-visible { outline: 2px solid var(--brass); outline-offset: -4px; border-radius: var(--radius-lg); }

.spot-card__img {
	width: 100%; height: 100%;
	object-fit: cover;
	object-position: 50% 42%;
	display: block;
	transform: scale(1.06);
	transition: transform 700ms cubic-bezier(0.22, 1, 0.36, 1), object-position 520ms var(--ease);
}
/* Settling back to 1 as it opens is the difference between "it moved" and
   "it arrived". */
.spot-card.is-active .spot-card__img { transform: none; object-position: 50% 50%; }

.spot-card__scrim {
	position: absolute; inset: 0;
	background: linear-gradient(to top, rgba(12,10,9,0.86) 4%, rgba(12,10,9,0.34) 46%, transparent 72%);
	opacity: 0;
	transition: opacity 420ms var(--ease);
}
.spot-card.is-active .spot-card__scrim { opacity: 1; }

/* Closed cards carry their name sideways up the sliver, so the rail is still
   legible as a set of choices rather than a row of anonymous crops. */
.spot-card__spine {
	position: absolute;
	left: 50%; bottom: 20px;
	transform: translateX(-50%) rotate(180deg);
	writing-mode: vertical-rl;
	max-height: calc(100% - 44px);
	overflow: hidden;
	font-family: var(--font-display);
	font-size: 0.82rem;
	font-weight: 600;
	letter-spacing: 0.06em;
	color: var(--paper);
	text-shadow: 0 1px 6px rgba(0,0,0,0.7);
	white-space: nowrap;
	opacity: 1;
	transition: opacity 260ms var(--ease);
	pointer-events: none;
}
.spot-card.is-active .spot-card__spine { opacity: 0; }

.spot-card__body {
	position: absolute;
	left: 0; right: 0; bottom: 0;
	z-index: 5;
	display: flex; flex-direction: column; align-items: flex-start;
	gap: 8px;
	padding: clamp(18px, 2.4vw, 28px);
	color: var(--paper);
	opacity: 0;
	transform: translateY(10px);
	transition: opacity 320ms var(--ease) 140ms, transform 320ms var(--ease) 140ms;
	pointer-events: none;
}
.spot-card.is-active .spot-card__body { opacity: 1; transform: none; pointer-events: auto; }

.spot-card__n {
	font-family: var(--font-mono);
	font-size: var(--fs-micro);
	color: var(--brass);
	letter-spacing: 0.1em;
}
.spot-card__body strong {
	font-family: var(--font-display);
	font-size: clamp(1.15rem, 2vw, 1.5rem);
	font-weight: 700;
	line-height: 1.15;
}
.spot-card__body em {
	font-style: normal;
	font-size: var(--fs-small);
	color: rgba(244, 242, 238, 0.76);
	max-width: 34ch;
}
.spot-card__body .btn { margin-top: 4px; }

/* --- Spotlight controls --------------------------------------------------- */

.spotlight__controls {
	display: flex; align-items: center; justify-content: center;
	gap: 18px;
	margin-top: clamp(18px, 2.4vw, 28px);
}
.spotlight-section .ring-nav { border-color: var(--paper-line); color: var(--slate); }
.spotlight-section .ring-nav:hover { color: var(--ink); border-color: var(--brass); background: var(--brass); }

.spotlight__dots { display: flex; align-items: center; gap: 8px; }
.spot-dot {
	width: 22px; height: 3px;
	padding: 0;
	border: 0;
	border-radius: 2px;
	background: var(--paper-line);
	cursor: pointer;
	transition: width 380ms var(--ease), background 380ms var(--ease);
}
.spot-dot.is-active { width: 40px; background: var(--brass-deep); }
.spot-dot:focus-visible { outline: 2px solid var(--brass); outline-offset: 3px; }

@media (max-width: 760px) {
	/* One peeking neighbour per side instead of three, so the open card still
	   has room to be worth opening. */
	.spotlight__rail {
		height: 360px;
		--ov: 16px;
		--active-w: 72%;
	}
	.spot-card__spine { font-size: 0.72rem; }
}

/* --- Spotlight, without the script ---------------------------------------- */

.spotlight:not(.is-live) .spotlight__rail {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(258px, 1fr));
	gap: clamp(20px, 2.6vw, 34px);
	height: auto;
	padding: 0;
}
.spotlight:not(.is-live) .spot-card {
	width: auto;
	flex: none;
	margin: 0;
	aspect-ratio: 3 / 4;
	filter: none;
	transform: none;
}
.spotlight:not(.is-live) .spot-card__hit { display: none; }
.spotlight:not(.is-live) .spot-card__spine { display: none; }
.spotlight:not(.is-live) .spot-card__scrim,
.spotlight:not(.is-live) .spot-card__body { opacity: 1; transform: none; pointer-events: auto; }
.spotlight:not(.is-live) .spot-card__img { transform: none; }
.spotlight:not(.is-live) .spotlight__controls { display: none; }

/* ===========================================================================
   Reduced motion.

   Not the same thing played faster — the ring stops being a ring and the rail
   stops being a rail, because a 3D carousel snapping through its positions in
   0.01ms is worse than no carousel at all for the people this setting exists
   to protect.
   ------------------------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
	.js-reveal [data-reveal],
	.js-reveal [data-reveal-stagger] > * { opacity: 1 !important; transform: none !important; }
	.hero h1 .hw > span { transform: none !important; }
	.hero-media { display: none; }

	.ring-stage .ring-viewport { perspective: none; height: auto; overflow-x: auto; padding: 4px var(--gutter) 14px; }
	.ring-stage .ring { display: flex; gap: 20px; transform: none !important; height: auto; }
	.ring-stage .ring-card {
		position: static; margin: 0;
		flex: 0 0 var(--card-w);
		transform: none !important;
		opacity: 1 !important;
		filter: none !important;
		pointer-events: auto;
	}
	.ring-stage .ring-card.is-back .ring-card__plate { background: var(--paper-raised); border-color: var(--ink-line); }
	.ring-stage .ring-card.is-back .ring-card__plate img { opacity: 1; filter: none; }
	.ring-stage .ring-card.is-back .ring-card__meta { opacity: 1; }
	.ring-hint, .ring-controls { display: none; }

	.spotlight .spotlight__rail {
		display: grid;
		grid-template-columns: repeat(auto-fill, minmax(258px, 1fr));
		gap: clamp(20px, 2.6vw, 34px);
		height: auto; padding: 0;
	}
	.spotlight .spot-card {
		width: auto; flex: none; margin: 0;
		aspect-ratio: 3 / 4;
		filter: none; transform: none !important;
	}
	.spotlight .spot-card__hit,
	.spotlight .spot-card__spine,
	.spotlight .spotlight__controls { display: none; }
	.spotlight .spot-card__scrim,
	.spotlight .spot-card__body { opacity: 1; transform: none; pointer-events: auto; }
	.spotlight .spot-card__img { transform: none; }
}

/* --- Utilities ----------------------------------------------------------- */

.stack > * + * { margin-top: 20px; }
.mt-0 { margin-top: 0; }
.mb-0 { margin-bottom: 0; }
.text-center { text-align: center; }
.screen-reader-text {
	position: absolute !important; width: 1px; height: 1px;
	overflow: hidden; clip: rect(1px, 1px, 1px, 1px); white-space: nowrap;
}

/* ===========================================================================
   Company pages: About us, Quality & testing
   Photographs of people and of the works, as opposed to products on white.
   A product is shot cut-out and shown whole; these are cropped without
   apology, because a phone screenshot of the floor should not be allowed to
   set the height of a section.
   =========================================================================== */

/* --- Portrait ------------------------------------------------------------- */

.portrait { position: relative; margin: 0; }
/* --portrait-focus is the horizontal point the crop keeps, set per photograph
   on the Site Settings screen. 50% is a straight centre crop; lower moves the
   window left, higher moves it right. */
.portrait__img {
	display: block; width: 100%;
	aspect-ratio: 4 / 5; object-fit: cover;
	object-position: var(--portrait-focus, 50%) 0%;
	border-radius: var(--radius-lg); background: var(--paper-raised);
}

/* The same plate as the dimension callout on the homepage hero, so a face and
   a padlock are captioned in one voice. */
.portrait__cap {
	position: absolute; left: 0; bottom: 8%;
	background: rgba(18, 16, 15, 0.88);
	border: 1px solid var(--ink-line); border-left: 3px solid var(--brass);
	padding: 12px 18px; max-width: 86%;
	font-size: var(--fs-micro); color: var(--steel); letter-spacing: 0.02em;
}
.portrait__cap strong {
	display: block; color: var(--paper);
	font-family: var(--font-display); font-variation-settings: "wdth" 108;
	font-size: 1rem; font-weight: 600; letter-spacing: 0; margin-bottom: 2px;
}

/* --- Pull quote ----------------------------------------------------------- */

.pullquote { margin: 4px 0 0; padding-left: 22px; border-left: 3px solid var(--brass); }
.pullquote p { margin: 0; font-size: 1.14rem; line-height: 1.5; color: var(--ink); }
.dark .pullquote p { color: var(--paper); }
.pullquote cite {
	display: block; margin-top: 12px; font-style: normal;
	font-size: var(--fs-micro); letter-spacing: 0.08em; text-transform: uppercase; color: var(--slate);
}

/* --- Timeline ------------------------------------------------------------- */

/* Ruled rows rather than a drawn track: the years are irregular, and a track
   with a dot every few pixels implies a steadiness that a real workshop
   history does not have. */
.timeline { list-style: none; margin: 0; padding: 0; }
.timeline__item {
	display: grid; grid-template-columns: 120px 1fr; gap: 0 clamp(16px, 2.4vw, 32px);
	padding: 20px 0; border-top: 1px solid var(--paper-line); align-items: baseline;
}
.timeline__item:last-child { border-bottom: 1px solid var(--paper-line); }
.timeline__year {
	position: relative; padding-left: 20px;
	font-family: var(--font-mono); font-size: var(--fs-small); color: var(--ink);
	font-variant-numeric: tabular-nums;
}
.timeline__year::before {
	content: ""; position: absolute; left: 0; top: 0.45em;
	width: 8px; height: 8px; border-radius: 50%; background: var(--brass);
}
.timeline__item p { margin: 0; color: var(--slate); max-width: 64ch; }
.dark .timeline__item { border-color: var(--ink-line); }
.dark .timeline__year { color: var(--paper); }
.dark .timeline__item p { color: var(--steel); }
@media (max-width: 640px) {
	.timeline__item { grid-template-columns: 1fr; gap: 6px; }
}

/* --- Wide photograph of the works ---------------------------------------- */

.photo-band {
	position: relative; margin: 0; overflow: hidden;
	border-radius: var(--radius-lg); background: var(--ink);
}
.photo-band__img { display: block; width: 100%; aspect-ratio: 2 / 1; object-fit: cover; }
.photo-band__cap {
	position: absolute; inset: auto 0 0 0;
	padding: clamp(28px, 5vw, 44px) clamp(16px, 3vw, 30px) 16px;
	font-size: var(--fs-small); color: var(--paper); line-height: 1.5;
	background: linear-gradient(to top, rgba(18, 16, 15, 0.92), rgba(18, 16, 15, 0));
}

/* On a narrow screen the gradient eats the half of the photograph worth
   looking at, so the caption steps off the image and sits under it. */
@media (max-width: 640px) {
	.photo-band__img { aspect-ratio: 4 / 3; }
	.photo-band__cap { position: static; background: var(--ink); padding: 14px 16px; }
}

/* --- Strip of works photographs ------------------------------------------ */

.photo-strip {
	display: grid; grid-template-columns: repeat(2, 1fr);
	gap: clamp(10px, 1.6vw, 16px); align-content: start;
}
.photo-strip__item {
	margin: 0; overflow: hidden;
	border: 1px solid var(--paper-line); border-radius: var(--radius);
}
.photo-strip__img {
	display: block; width: 100%; aspect-ratio: 1; object-fit: cover;
	transition: transform var(--slow) var(--ease);
}
@media (hover: hover) and (pointer: fine) {
	.photo-strip__item:hover .photo-strip__img { transform: scale(1.04); }
}
@media (prefers-reduced-motion: reduce) {
	.photo-strip__img { transition: none; }
	.photo-strip__item:hover .photo-strip__img { transform: none; }
}

/* --- Photograph beside the address --------------------------------------- */

/* Cropped square rather than left at its own shape: this sits next to a short
   block of address lines, and a full-height portrait would tower over them. */
.visit-figure { margin: 0; }
.visit-photo {
	display: block; width: 100%;
	aspect-ratio: 1; max-height: 520px; object-fit: cover;
	border-radius: var(--radius-lg); background: var(--ink-raised);
}

/* --- Photo band as a slideshow ------------------------------------------- */

/* The single-photograph band above is a <figure>. With several it becomes a
   stage of stacked slides that cross-fade, with every control laid over the
   photograph: arrows on the flanks, caption and dots on a bar along the foot.
   Nothing sits below the picture, because a band that is already the width of
   the page does not need a strip of furniture under it as well. */
.photo-band--show { border-radius: 0; background: none; overflow: visible; }
.photo-band--show:focus { outline: none; }
.photo-band--show:focus-visible { outline: 2px solid var(--brass); outline-offset: 6px; }

/* The height is set outright rather than left to an aspect-ratio with a
   max-height on top of it. Those two together do not mean "as wide as the
   container, but never taller than this": a binding max-height on a box with
   an aspect-ratio makes the browser shrink the WIDTH to keep the ratio, and
   the band shrivels to a panel in the middle of the page. Full width always,
   with a height that grows to a point and then stops; the photographs recrop
   against whatever box that leaves. */
.photo-band__stage {
	position: relative; overflow: hidden; width: 100%;
	border-radius: var(--radius-lg); background: var(--ink);
	height: clamp(300px, 40vw, 620px);
}

.band-slide {
	position: absolute; inset: 0; margin: 0;
	opacity: 0; transition: opacity var(--slow) var(--ease);
}
.band-slide.is-active { opacity: 1; }
.band-slide .photo-band__img { width: 100%; height: 100%; aspect-ratio: auto; object-fit: cover; }

/* --- Arrows, on the photograph ------------------------------------------- */

.band-arrow {
	position: absolute; top: 50%; transform: translateY(-50%); z-index: 3;
	display: grid; place-items: center;
	width: 46px; height: 46px; padding: 0;
	border: 1px solid rgba(244, 242, 238, 0.22); border-radius: 50%;
	background: rgba(18, 16, 15, 0.55);
	color: var(--paper); cursor: pointer;
	transition: background var(--fast) var(--ease), color var(--fast) var(--ease), border-color var(--fast) var(--ease);
}
.band-arrow:hover { background: var(--brass); border-color: var(--brass); color: var(--ink); }
.band-arrow:focus-visible { outline: 2px solid var(--brass); outline-offset: 3px; }
.band-arrow--prev { left: 14px; }
.band-arrow--next { right: 14px; }

/* --- The bar along the foot ---------------------------------------------- */

.photo-band__bar {
	position: absolute; inset: auto 0 0 0; z-index: 2;
	display: flex; align-items: flex-end; justify-content: space-between; gap: 20px;
	padding: clamp(36px, 7vw, 60px) clamp(16px, 2.4vw, 26px) 14px;
	background: linear-gradient(to top, rgba(18, 16, 15, 0.9), rgba(18, 16, 15, 0));
	pointer-events: none;   /* the gradient must not swallow a swipe */
}
.photo-band__bar > * { pointer-events: auto; }

.photo-band--show .photo-band__cap {
	position: static; margin: 0; padding: 0; background: none;
	font-size: var(--fs-small); color: var(--paper); line-height: 1.5;
	max-width: 62ch;
}

.photo-band__meta { display: flex; align-items: center; gap: 14px; flex: none; }
.photo-band__dots { display: flex; gap: 8px; align-items: center; }

.band-dot {
	width: 9px; height: 9px; padding: 0; border: 0; border-radius: 50%;
	background: rgba(244, 242, 238, 0.45); cursor: pointer;
	transition: background var(--fast) var(--ease), transform var(--fast) var(--ease);
}
.band-dot:hover { background: var(--paper); }
.band-dot.is-active { background: var(--brass); transform: scale(1.25); }

.photo-band__count {
	font-family: var(--font-mono); font-size: var(--fs-micro);
	color: var(--steel); font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* On a phone the arrows shrink and tuck in, and the counter goes: at this
   width the dots already say where you are, and the caption needs the room. */
@media (max-width: 640px) {
	.band-arrow { width: 38px; height: 38px; }
	.band-arrow--prev { left: 8px; }
	.band-arrow--next { right: 8px; }
	.photo-band__bar { flex-direction: column; align-items: stretch; gap: 10px; }
	.photo-band__count { display: none; }
}

@media (prefers-reduced-motion: reduce) {
	.band-slide { transition: none; }
}


/* --- Legal pages ---------------------------------------------------------
   The privacy policy and the terms. Long documents nobody reads end to end,
   so they are built to be scanned: a sticky contents list on the left, and
   numbered headings on the right that the list points straight at.
   ------------------------------------------------------------------------ */

.legal-meta {
	margin-top: 14px; font-family: var(--font-mono);
	font-size: var(--fs-micro); color: var(--steel);
}
.legal-layout { display: grid; gap: clamp(28px, 4vw, 56px); align-items: start; }
@media (min-width: 900px) { .legal-layout { grid-template-columns: 250px minmax(0, 1fr); } }

/* 96px clears the sticky site header, which is about 75px tall, and leaves a
   little air. It is the offset both the contents list and the headings it
   jumps to are measured against, so they stay in step. */
.legal-toc { font-size: var(--fs-small); }
@media (min-width: 900px) {
	.legal-toc { position: sticky; top: 96px; max-height: calc(100vh - 120px); overflow-y: auto; }
}
.legal-toc h2 {
	font-size: var(--fs-micro); letter-spacing: 0.08em; text-transform: uppercase;
	color: var(--slate); margin-bottom: 14px; font-variation-settings: "wdth" 104;
}
.legal-toc ol { list-style: none; margin: 0; padding: 0; counter-reset: toc; display: grid; gap: 2px; }
.legal-toc li { counter-increment: toc; margin: 0; }
.legal-toc a {
	display: grid; grid-template-columns: 26px 1fr; gap: 4px;
	padding: 6px 8px 6px 0; text-decoration: none; color: var(--slate);
	border-left: 2px solid transparent; padding-left: 12px;
	transition: color var(--fast) var(--ease), border-color var(--fast) var(--ease);
}
.legal-toc a::before {
	content: counter(toc); font-family: var(--font-mono);
	font-size: var(--fs-micro); color: var(--steel);
}
.legal-toc a:hover { color: var(--ink); border-left-color: var(--brass); }

.legal-doc { max-width: 72ch; }
.legal-doc .legal-intro {
	font-size: 1.1rem; line-height: 1.55; color: var(--ink);
	padding-left: 18px; border-left: 3px solid var(--brass); margin-bottom: 2em;
}
.legal-doc h2 {
	display: grid; grid-template-columns: auto 1fr; align-items: baseline; gap: 12px;
	font-size: 1.45rem; margin-top: 2.2em; scroll-margin-top: 96px;
	padding-top: 1em; border-top: 1px solid var(--paper-line);
}
.legal-doc h2:first-of-type { border-top: 0; padding-top: 0; }
.legal-doc h2 .legal-num {
	font-family: var(--font-mono); font-size: 0.82rem; font-weight: 500;
	color: var(--brass-deep);
}
.legal-doc h3 { font-size: 1rem; margin-top: 1.7em; color: var(--slate); }
.legal-doc h3 + p { margin-top: 0.4em; }

.legal-contact { margin-top: 2.6em; }
.legal-contact p { margin-bottom: 1em; }
.legal-contact p:last-child { margin-bottom: 0; }

.legal-foot {
	margin-top: 2em; padding-top: 1.2em; border-top: 1px solid var(--paper-line);
	font-size: var(--fs-small); color: var(--slate);
}

/* The legal row in the footer: three groups that wrap onto their own lines
   on a phone rather than being squeezed side by side. */
.footer-legal__links { display: flex; flex-wrap: wrap; gap: 6px 18px; }
.footer-legal__links a { text-decoration: none; }
.footer-legal__links a:hover { text-decoration: underline; }
@media (max-width: 720px) {
	.footer-legal { flex-direction: column; gap: 12px; }
}

/* --- Certificate tiles ---------------------------------------------------- */

/* Laid across the page rather than stacked into columns. Three narrow columns
   turned an issuing body's name and a paragraph of explanation into a ladder
   of two- and three-word lines; given the full width, the identifying details
   sit in a fixed column on the left and the explanation reads as prose on the
   right, at a sane measure. */
.cert-list { display: grid; gap: clamp(16px, 2vw, 24px); }

.cert-tile { display: grid; gap: clamp(18px, 3vw, 40px); align-items: start; }
@media (min-width: 860px) {
	.cert-tile { grid-template-columns: minmax(240px, 300px) minmax(0, 1fr); }
}

.cert-tile__id h3 { margin-bottom: 14px; }
.cert-tile__body { display: flex; flex-direction: column; height: 100%; }
.cert-tile__text { font-size: var(--fs-small); color: var(--slate); max-width: 68ch; }
.cert-tile__text p { margin-bottom: 0.8em; }
.cert-tile__text p:last-child { margin-bottom: 0; }
.cert-tile__action { margin-top: auto; padding-top: 20px; }

/* The label sits above its value: even with the width, an issuing body's full
   name does not want to share a row with a 38% label column. */
.cert-tile .spec-table th,
.cert-tile .spec-table td { display: block; width: auto; padding: 0; border: 0; }
.cert-tile .spec-table th {
	font-size: var(--fs-micro); letter-spacing: 0.06em; text-transform: uppercase;
	color: var(--slate); margin-bottom: 3px;
}
.cert-tile .spec-table td { margin-bottom: 12px; word-break: break-word; line-height: 1.45; }
.cert-tile .spec-table tr { display: block; }

/* --- Editorial content across the full width ------------------------------ */

/* A single 68ch column under a full-width photograph leaves half the page
   empty. Two columns keep the measure readable and use the room; headings and
   list items are kept whole so nothing is orphaned across the gutter. */
@media (min-width: 1000px) {
	.prose--wide { max-width: none; columns: 2; column-gap: clamp(36px, 4vw, 72px); }
	.prose--wide > * { break-inside: avoid; }
	.prose--wide h2, .prose--wide h3 { break-after: avoid; }
	.prose--wide > :first-child { margin-top: 0; }
}

/* An editorial block's first heading already has the section's padding above
   it; its own top margin on top of that opens a hole between the block and
   whatever precedes it. */
.prose > :first-child { margin-top: 0; }

/* --- Field-level validation ----------------------------------------------
   The browser's own bubble points at one field, vanishes on the next click
   and cannot be styled. These messages stay put until the field is right. */

.field-error:empty { display: none; }
.field-error {
	margin: 6px 0 0; font-size: var(--fs-micro); line-height: 1.4;
	color: #B3261E; font-weight: 500;
}
.dark .field-error { color: #FFB4AB; }

input.is-invalid,
textarea.is-invalid,
select.is-invalid {
	border-color: #B3261E;
	box-shadow: 0 0 0 3px rgba(179, 38, 30, 0.12);
}
input.is-invalid:focus,
textarea.is-invalid:focus { outline-color: #B3261E; }

/* --- The confirmation a template forgot ----------------------------------
   Anchored to the foot of the window so it cannot be missed on a page that
   renders no inline notice of its own. */

.form-flash {
	position: fixed; left: 50%; bottom: 20px; transform: translateX(-50%);
	z-index: 90; max-width: min(560px, calc(100vw - 32px));
	display: flex; align-items: flex-start; gap: 10px;
	padding: 4px 6px 4px 4px; border-radius: var(--radius);
	background: var(--paper); border: 1px solid var(--paper-line);
	box-shadow: 0 10px 30px rgba(0,0,0,0.18);
}
.form-flash .form-note { margin: 0; }
.form-flash__close {
	flex: 0 0 auto; border: 0; background: none; cursor: pointer;
	font-size: 20px; line-height: 1; padding: 8px 10px; color: var(--slate);
	min-width: 44px; min-height: 44px;
}
.form-flash__close:hover { color: var(--ink); }

@media (max-width: 620px) {
	.form-flash { left: 16px; right: 16px; bottom: 16px; transform: none; max-width: none; }
}

/* --- The download, once it is on its way ---------------------------------- */

.gate-starting { padding: 8px 0 4px; }
.gate-starting h3 { margin-top: 0; }

/* --- Flipbook, at any window size ----------------------------------------
   turn.js positions its pages absolutely from the size it was last given, so
   anything that changes the box has to be followed by a resize of the book
   itself (see sizeBook in app.js). These rules keep the frame honest in the
   meantime: a fixed aspect box the book is centred in, and no overflow while
   a drag is still in progress. */

dialog.gate--book[open] .flipbook-frame { overflow: hidden; }
.flipbook { max-width: 100%; }
.flipbook__page { max-width: 100%; }

@media (max-width: 900px) {
	dialog.gate--book[open] { padding-inline: 12px; }
	.flipbook-controls { gap: 10px; margin-bottom: 8px; }
	.flip-counter { min-width: 56px; font-size: var(--fs-micro); }
}

/* Landscape on a phone leaves almost no height; the controls have to stop
   taking a line of their own or there is nothing left for the pages. */
@media (max-height: 520px) {
	dialog.gate--book[open] .flipbook-controls { margin-bottom: 4px; }
	dialog.gate--book[open] .flipbook__hint { display: none; }
	.flip-btn { width: 34px; height: 34px; }
	.flip-btn svg { width: 16px; height: 16px; }
}
