/* ============================================================================
   Kanele Arms — Technical Retail
   ----------------------------------------------------------------------------
   A trade supplier's catalogue, not a lookbook.

   The palette is read out of the logo, not invented: Kanele_Arms_logo-02.svg
   contains #ED1C24 and black, and nothing else. The client pins black at
   #373737. Everything here derives from those two facts.

   White ground, because 295 products were photographed on white and belong
   there. Dark bands — utility bar, category strip, footer — frame the catalogue
   without competing with it. Red is the brand, so it carries the primary action,
   the active category, and availability. It is never decoration.

   Two registers again, but both tighter than before: grotesk for language,
   MONO FOR EVERY NUMBER. A calibre, a capacity, a magnification and a count are
   all measurements, and a buyer scans them before reading a word.

   No eyebrows. Impeccable's craft floor bans the kicker above a heading outright
   — "no brief earns it back" — and the previous design used one on every section.
   ========================================================================= */

:root {
	--kn-canvas: #FFFFFF;
	--kn-surface: #F5F5F5;
	--kn-surface-2: #EBEBEB;
	--kn-ink: #373737;
	--kn-ink-2: #5E5E5E;
	--kn-muted: #8C8C8C;
	--kn-red: #ED1C24;
	--kn-red-deep: #C4141B;
	--kn-red-wash: #FDECEC;
	--kn-chrome: #262626;
	--kn-chrome-deep: #1C1C1C;
	--kn-border: #DCDCDC;
	--kn-border-strong: #B8B8B8;

	/* Pinned by the client. Impeccable's detector flags both as overused faces;
	   its own first rule is that the brief wins over a saturated-pattern warning,
	   so this is a deliberate override, not an oversight. Jakarta carries the
	   headings, Inter the reading, mono the measurements. */
	--kn-display: "Plus Jakarta Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
	--kn-sans: "Inter", "Helvetica Neue", Helvetica, Arial, sans-serif;
	--kn-mono: "Roboto Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

	/* 9px, echoing the crosshair dot in the mark. One radius everywhere: forms,
	   buttons, tiles, panels, images. A design with three different corner
	   treatments has no corner treatment. */
	--kn-r: 9px;

	/* 84rem (1344px) was near-full-bleed on the screens this is read on: at
	   1440 it left barely 48px a side, so the page had no margin and every
	   section ran the full width of the display. 75rem is the standard content
	   measure — one token, so every section standardises together. */
	--kn-wrap: 75rem;
	--kn-gutter: clamp(1rem, 3vw, 2.5rem);

	--kn-s1: .375rem;
	--kn-s2: .75rem;
	--kn-s3: 1.25rem;
	--kn-s4: 2rem;
	--kn-s5: 3.25rem;
	--kn-s6: 5rem;
}

/* ---------------------------------------------------------------- ground */

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

body {
	background: var(--kn-canvas);
	color: var(--kn-ink);
	font-family: var(--kn-sans);
	font-size: .9375rem;
	line-height: 1.6;
	font-weight: 400;
	-webkit-font-smoothing: antialiased;
}

::selection { background: var(--kn-red); color: #fff; }

a { color: inherit; text-underline-offset: .18em; }
a:hover { text-decoration-color: var(--kn-red); }

img { max-inline-size: 100%; block-size: auto; }

h1, h2, h3, h4 {
	font-family: var(--kn-display);
	font-weight: 700;
	line-height: 1.1;
	letter-spacing: -0.02em;
	text-wrap: balance;
	margin: 0;
}

/* A real scale — a catalogue that sets every heading at 1.3× body reads as a
   spreadsheet, and the craft floor asks for obvious steps. */
h1 { font-size: clamp(2rem, 4.2vw, 3.5rem); }
h2 { font-size: clamp(1.5rem, 2.6vw, 2.25rem); }
h3 { font-size: 1.125rem; }

p { margin: 0 0 var(--kn-s2); max-inline-size: 70ch; }

/* One measure, used once.
 *
 * A page was rendering at three widths at the same time: the page header at
 * 1264, the theme's content container at 1200, and every section inside it at
 * 1120. Two separate causes, both invisible until measured.
 *
 * 1. There is no global `box-sizing`, so `.kn-pagehead`'s 2rem padding was
 *    ADDED to its 1200px width — 1264 outer.
 * 2. The theme constrains `.wp-block-post-content` to 1200px and gives it
 *    padding; every `.kn-wrap` inside then subtracted the page gutter a SECOND
 *    time off that already-reduced box, landing at 1120.
 *
 * The container gives up its constraint and `.kn-wrap` becomes the only thing
 * that sets width anywhere. */
.kn-wrap, .kn-pagehead { box-sizing: border-box; }
.kn-wrap { inline-size: min(var(--kn-wrap), 100% - (var(--kn-gutter) * 2)); margin-inline: auto; }
.wp-block-post-content { max-inline-size: none; padding-inline: 0; }

/* Every number on this site is set in mono and tabular. Prices, calibres,
   magnifications, counts, SKUs — a buyer compares them in columns. */
.kn-num, .kn-card-spec, .kn-specs td, .kn-stat__n, .gf-facets__count,
.woocommerce-result-count { font-family: var(--kn-mono); font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------ dark chrome */


/* Dark, because the mark is the light-on-dark variant: Kanele_Arms_logo-02.svg
   is white and red, so on a white bar its white half simply disappeared and only
   the red wordmark read. The logo decides the bar, not the other way round.
   Three bands, each a step lighter: utility #1C1C1C, header #262626, then the
   category strip in white — so the dark mass resolves into the catalogue rather
   than sitting on it. */
.kn-header {
	position: sticky;
	inset-block-start: 0;
	z-index: 40;
	background: var(--kn-chrome);
	border-block-end: 1px solid #000;
}
/* One row, tight. Two dark bands plus a full-width search field cost roughly
   160px of vertical before a visitor saw a single product; on a catalogue that
   is the most expensive space on the page. Utility contact moved into the row
   as icons, and search became a toggle. */
.kn-header__in { display: flex; align-items: center; gap: var(--kn-s3); padding-block: .6rem; }
.kn-header__logo { flex: 0 0 auto; text-decoration: none; display: inline-flex; align-items: center; }
.kn-header__logo img, .custom-logo { block-size: 2.1rem; inline-size: auto; }
.kn-logo-text { font-family: var(--kn-display); font-weight: 800; font-size: 1.25rem; letter-spacing: -0.03em; }

/* Tight. The bar now carries the mark, six departments and five actions on one
   line, so the actions give up the space — icons sit together as a cluster
   rather than as five separately-padded buttons. */
.kn-actions { display: flex; align-items: center; gap: .125rem; margin-inline-start: auto; flex: 0 0 auto; }

.kn-ico {
	display: inline-flex; align-items: center; gap: .4rem;
	color: #D8D8D8; text-decoration: none; background: none; border: 0;
	cursor: pointer; padding: .45rem; border-radius: var(--kn-r);
	font-size: .8125rem; font-family: var(--kn-mono);
	transition: color .15s ease, background .15s ease;
}
.kn-ico:hover { color: #fff; background: #333; }
.kn-ico svg { inline-size: 18px; block-size: 18px; flex: 0 0 auto; }
/* The phone number as text no longer fits alongside the departments. The icon
   dials it, the footer prints it, and the drawer carries it in full. */
.kn-ico__t { display: none; }

/* Search is a full-screen modal, not a strip. On a 295-product catalogue the
   search IS the primary act, and a strip under the header makes it look like a
   secondary filter. Opens focused, closes on Escape or on the backdrop. */
.kn-searchbar[hidden] { display: none !important; }
.kn-searchbar {
	position: fixed; inset: 0; z-index: 100;
	background: rgb(28 28 28 / .88);
	backdrop-filter: blur(10px) saturate(120%);
	display: grid; place-items: start center;
	padding: 18vh var(--kn-gutter) var(--kn-gutter);
	animation: kn-fade .16s ease-out;
}
@keyframes kn-fade { from { opacity: 0 } to { opacity: 1 } }
.kn-search { display: flex; gap: var(--kn-s2); inline-size: min(52rem, 100%); }
.kn-searchbar__hint { color: #8C8C8C; font-size: .8125rem; margin: var(--kn-s3) 0 0; text-align: center; }
.kn-searchbar__close {
	position: absolute; inset-block-start: var(--kn-s3); inset-inline-end: var(--kn-gutter);
	background: none; border: 0; color: #C8C8C8; cursor: pointer; padding: .5rem;
	border-radius: var(--kn-r); line-height: 0;
}
.kn-searchbar__close:hover { color: #fff; background: #333; }
.kn-search input {
	flex: 1 1 auto; font: inherit; font-size: 1.125rem;
	padding: 1rem 1.15rem;
	border: 1.5px solid transparent; border-radius: var(--kn-r);
	background: var(--kn-canvas); color: var(--kn-ink);
}
.kn-search input::placeholder { color: var(--kn-muted); }
.kn-search input:focus { outline: 0; border-color: var(--kn-red); }
.kn-search button {
	flex: 0 0 auto; border: 0; cursor: pointer; border-radius: var(--kn-r);
	background: var(--kn-red); color: #fff; padding: 1rem 1.75rem;
	font: inherit; font-size: .8125rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
}
.kn-search button:hover { background: var(--kn-red-deep); }

.kn-header__quote {
	flex: 0 0 auto; display: inline-flex; align-items: center; gap: .4rem;
	background: var(--kn-red); color: #fff; text-decoration: none;
	padding: .55rem 1rem; border-radius: var(--kn-r);
	font-size: .75rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
}
.kn-header__quote:hover { background: var(--kn-red-deep); }
.kn-quote-count {
	font-family: var(--kn-mono); font-size: .6875rem; line-height: 1;
	background: #fff; color: var(--kn-red); padding: .15rem .35rem; border-radius: 999px;
}

/* The departments live INSIDE the dark bar, between the mark and the actions.
   They used to sit in a separate white strip below it — two bands to say one
   thing, and the strip ruled a hard line across the page before the visitor
   reached a single product. One band now carries all three. */
.kn-cats { min-inline-size: 0; margin-inline-start: var(--kn-s3); }
.kn-cats__in { display: flex; align-items: center; gap: 0; overflow-x: auto; scrollbar-width: none; }
.kn-cats__in::-webkit-scrollbar { display: none; }
.kn-cats a {
	flex: 0 0 auto; color: #E4E4E4; text-decoration: none;
	padding: .55rem .7rem; font-size: .8125rem; font-weight: 600;
	letter-spacing: .01em; white-space: nowrap;
	border-radius: var(--kn-r);
	transition: color .15s ease, background .15s ease;
}
.kn-cats a:hover { color: #fff; background: #333; }
.kn-cats a[aria-current="page"] { color: var(--kn-red); }

.kn-burger { display: none; background: none; border: 0; cursor: pointer; inline-size: 2.5rem; block-size: 2.5rem; flex-direction: column; justify-content: center; gap: .3rem; padding: 0; }
.kn-burger span { display: block; block-size: 2px; inline-size: 1.35rem; background: #F5F5F5; transition: transform .18s ease; }
.kn-burger[aria-expanded="true"] span:first-child { transform: translateY(.16rem) rotate(45deg); }
.kn-burger[aria-expanded="true"] span:last-child { transform: translateY(-.16rem) rotate(-45deg); }

/* An element that ships with `hidden` must restate that state after whatever
   display property overrode it, or it renders permanently open. */
.kn-drawer[hidden] { display: none !important; }
.kn-drawer { display: grid; background: var(--kn-chrome); padding: var(--kn-s2) var(--kn-gutter) var(--kn-s3); }
.kn-drawer a { color: #D8D8D8; text-decoration: none; padding-block: .7rem; font-size: .875rem; border-block-end: 1px solid #383838; }
.kn-drawer a:last-child { border-block-end: 0; }
.kn-locked, .kn-locked body { overflow: hidden; }

@media (max-width: 60rem) {
	.kn-burger { display: flex; }
	.kn-cats { display: none; }
}

/* The header row does not fit a phone. Logo (130) + actions (272) + the gap
   between them needs 454px of viewport once the gutters are counted; an iPhone
   gives 375, so the burger was pushed 63px off the right edge and the whole
   document scrolled sideways. Nothing in the row is optional-looking, which is
   why it went unnoticed — the overflow is off-screen by definition.
   The call and WhatsApp icons go first: both are repeated in the drawer this
   burger opens and again in the footer, so nothing becomes unreachable. Search
   and Quote stay, because neither is anywhere else. */
@media (max-width: 30rem) {
	.kn-actions a.kn-ico { display: none; }
}
@media (min-width: 60.0625rem) { .kn-drawer { display: none !important; } }

/* ------------------------------------------------------------------- hero */

/* Not a photograph. On a trade catalogue the first viewport's job is to prove
   range and get the visitor into the stock, so it carries the makers.
   Two columns, because a single column of copy across a 1440px viewport leaves
   half the screen empty — the detector calls that "one column stretches the
   first viewport", and it reads as an unfinished page. The right column carries
   the numbers, which is the fastest proof of range a supplier has. */
.kn-lede { padding-block: var(--kn-s5) var(--kn-s4); }
.kn-lede__grid { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: var(--kn-s5); align-items: center; }
.kn-lede h1 { max-inline-size: 16ch; }
.kn-lede p { font-size: 1.0625rem; color: var(--kn-ink-2); max-inline-size: 52ch; margin-block-start: var(--kn-s3); }
.kn-lede__actions { display: flex; flex-wrap: wrap; gap: var(--kn-s2); margin-block-start: var(--kn-s4); }

@media (max-width: 62rem) {
	.kn-lede__grid { grid-template-columns: 1fr; gap: var(--kn-s4); }
	.kn-lede h1 { max-inline-size: none; }
}

.kn-btn {
	display: inline-flex; align-items: center; gap: .5rem;
	padding: .8rem 1.35rem; border-radius: var(--kn-r);
	font-size: .8125rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
	text-decoration: none; border: 1.5px solid var(--kn-ink); color: var(--kn-ink); background: transparent;
	transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.kn-btn:hover { background: var(--kn-ink); color: #fff; }
.kn-btn--red { background: var(--kn-red); border-color: var(--kn-red); color: #fff; }
.kn-btn--red:hover { background: var(--kn-red-deep); border-color: var(--kn-red-deep); color: #fff; }

/* ------------------------------------------------------------- brand wall */

.kn-brands {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(12.5rem, 1fr));
	gap: var(--kn-s2);
}
/* Rectangles, not near-squares. At 8rem tall with s4 padding each tile held a
   3rem mark and a count inside 128px of box — most of it empty. The wall is 13
   marks; making each one shorter puts them all in view without scrolling. */
.kn-brand {
	position: relative;
	background: var(--kn-surface);
	border-radius: var(--kn-r);
	display: grid; place-items: center;
	padding: var(--kn-s3) var(--kn-s3);
	text-decoration: none; min-block-size: 5.25rem;
	transition: background .15s ease;
}
.kn-brand:hover { background: #EFEFEF; }
/* Full colour at rest. Greyscaling them was a designer's tidiness instinct and
   it was wrong: these are the marks a buyer is looking for, and a wall of grey
   logos hides exactly the signal the section exists to send. One height and one
   optical box give the wall its order; the colour stays. */
/* Sized for the WIDEST mark, not the average one. Blaser's wordmark is 300x51 —
   a 5.9:1 ratio — so an 82% width cap inside a narrow tile rendered it at
   105x18px: present in the DOM, loaded, and far too small to read. Wordmarks
   need width; the height cap alone does the constraining. */
.kn-brand img {
	max-block-size: 3rem; inline-size: 88%; object-fit: contain;
	transition: transform .25s cubic-bezier(.2,.7,.3,1);
}
.kn-brand:hover img { transform: scale(1.05); }
/* Three makers block hotlinking or publish no usable mark. Their wordmark is
   set in the site's own type at the same optical weight, so the wall stays
   even rather than showing a hole. */
.kn-brand__word { font-family: var(--kn-display); font-weight: 700; font-size: 1.25rem; letter-spacing: -0.02em; color: var(--kn-ink-2); }
.kn-brand:hover .kn-brand__word { color: var(--kn-ink); }
/* The count is the reason to click — "Blaser, 56 of them" — and at 11px muted
   mono it read as a caption nobody was meant to notice. Display face, bold, and
   lifted into the corner so it stops competing with the mark for the centre
   line and stops adding height to the tile. */
.kn-brand__n {
	position: absolute; inset-block-start: .5rem; inset-inline-end: .65rem;
	font-family: var(--kn-display); font-weight: 700; font-size: 1rem;
	line-height: 1; color: var(--kn-ink-2); font-variant-numeric: tabular-nums;
	transition: color .15s ease;
}
.kn-brand:hover .kn-brand__n { color: var(--kn-red); }

/* ------------------------------------------------------------- statistics */

.kn-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: var(--kn-s2); }
.kn-lede .kn-stats { grid-template-columns: repeat(2, 1fr); }
.kn-stat { background: var(--kn-surface); border-radius: var(--kn-r); padding: var(--kn-s4) var(--kn-s3); }
.kn-stat__n { display: block; font-size: 2rem; font-weight: 500; color: var(--kn-ink); line-height: 1; }
.kn-stat__l { display: block; font-size: .8125rem; color: var(--kn-ink-2); margin-block-start: .5rem; }

/* --------------------------------------------------------------- sections */

.kn-section { padding-block: var(--kn-s6); }
.kn-section--tight { padding-block: var(--kn-s5); }
.kn-section--surface { background: var(--kn-surface); }
.kn-section__head { margin-block-end: var(--kn-s4); }
.kn-section__head p { color: var(--kn-ink-2); margin-block-start: .6rem; }

/* A section title that carries a rule to the right edge — the trade-catalogue
   device that separates without needing a box. */
/* A rule head: title, a rule across the gap, then the way out to the right.
 * The class was named for a rule it never drew, so the section link sat jammed
 * against a 2.5rem heading in 13px red — legible as an accident, not a control.
 * The rule is what makes it read as a deliberate pair. Order puts the pseudo
 * element between the heading text (an anonymous flex item, always order 0)
 * and the link. */
.kn-rulehead { display: flex; align-items: baseline; gap: var(--kn-s3); flex-wrap: wrap; }
.kn-rulehead::after {
	content: ""; order: 1; flex: 1 1 3rem; min-inline-size: 2rem;
	block-size: 1px; background: var(--kn-border); translate: 0 -.3em;
}
.kn-rulehead a {
	order: 2; white-space: nowrap;
	font-size: .8125rem; font-weight: 600; letter-spacing: .01em;
	color: var(--kn-red); text-decoration: none;
}
.kn-rulehead a:hover { text-decoration: underline; }

/* ------------------------------------------------------------ shop chrome */

.kn-shop-head { padding-block: var(--kn-s3) var(--kn-s2); margin-block-end: var(--kn-s4); }
.kn-shop-title { font-size: clamp(1.75rem, 3.2vw, 2.5rem); }
.kn-shop-desc { color: var(--kn-ink-2); margin-block-start: .6rem; max-inline-size: 68ch; }
.kn-shop-count { font-family: var(--kn-mono); font-size: .75rem; color: var(--kn-muted); margin: .5rem 0 0; }

.kn-crumbs { font-size: .75rem; color: var(--kn-muted); padding-block: var(--kn-s2); }
.kn-crumbs a { color: var(--kn-ink-2); text-decoration: none; }
.kn-crumbs a:hover { color: var(--kn-red); }

.kn-shop-body { display: grid; grid-template-columns: 14rem minmax(0, 1fr); gap: var(--kn-s5); align-items: start; }
.kn-facets { position: sticky; inset-block-start: 6rem; max-block-size: calc(100vh - 8rem); overflow-y: auto; padding-inline-end: .4rem; }
.kn-facets::-webkit-scrollbar { inline-size: 5px; }
.kn-facets::-webkit-scrollbar-thumb { background: var(--kn-border-strong); }

@media (max-width: 62rem) {
	.kn-shop-body { grid-template-columns: 1fr; gap: var(--kn-s3); }
	.kn-facets { position: static; max-block-size: none; background: var(--kn-surface); border-radius: var(--kn-r); padding: var(--kn-s3); }
}

.gf-facets__title { color: var(--kn-ink); font-family: var(--kn-sans); font-weight: 700; font-size: .75rem; }
.gf-facets__group { border: 0; padding-block-end: var(--kn-s3); }
.gf-facets__opt { color: var(--kn-ink-2); font-size: .8125rem; }
.gf-facets__opt:hover { background: transparent; color: var(--kn-red); }
.gf-facets__opt.is-selected { color: var(--kn-ink); font-weight: 600; }
.gf-facets__opt.is-selected .gf-facets__box { background: var(--kn-red); border-color: var(--kn-red); }
.gf-facets__box { border-color: var(--kn-border-strong); }
.gf-facets__count { color: var(--kn-muted); }
.gf-facets__clear { color: var(--kn-red); }

/* ------------------------------------------------------------ product grid */

ul.products {
	list-style: none; margin: 0; padding: 0;
	display: grid; grid-template-columns: repeat(auto-fill, minmax(13.5rem, 1fr));
	gap: var(--kn-s3);
}
ul.products::before, ul.products::after { content: none !important; }
ul.products li.product {
	margin: 0 !important; inline-size: auto !important; float: none !important;
	display: flex; flex-direction: column;
	background: transparent; padding: 0;
	border-radius: var(--kn-r);
}
li.product:hover .woocommerce-loop-product__title { color: var(--kn-red); }
li.product .woocommerce-loop-product__title { transition: color .15s ease; }
li.product a { text-decoration: none; }

/* Each product is a card.
 *
 * Two earlier notes here were both wrong. The first — "shot on white, page is
 * white, so no plate is needed" — gave 24 cells no edges and a catalogue that
 * read as items floating in a void. The second reached for a surface plate
 * plus `mix-blend-mode: multiply` to fold the photos' white backgrounds into
 * it; but the blend composites against the white PAGE behind the (transparent)
 * list item, not the plate on the image, so every white photo stayed a white
 * box on grey — the nested-box look Impeccable bans, 24 times over.
 *
 * A photograph on a white JPEG wants a white tile. The card is defined by a
 * hairline and a radius, and it lifts on hover. No blend mode — those composite
 * against the backdrop and break the moment anything behind them changes.
 *
 * Contain, not cover: a rifle must not be cropped square to fill a box. */
li.product a img {
	inline-size: 100%; aspect-ratio: 4 / 3; object-fit: contain;
	background: #fff; box-sizing: border-box;
	border: 1px solid var(--kn-border); border-radius: var(--kn-r);
	padding: var(--kn-s3);
	transition: border-color .15s ease, box-shadow .25s cubic-bezier(.2,.7,.3,1), transform .25s cubic-bezier(.2,.7,.3,1);
}
li.product:hover a img {
	border-color: var(--kn-border-strong);
	box-shadow: 0 10px 26px rgb(0 0 0 / .09);
	transform: translateY(-3px);
}

li.product .woocommerce-loop-product__title {
	font-size: .875rem !important; font-weight: 600; line-height: 1.3;
	color: var(--kn-ink); margin: var(--kn-s2) 0 0 !important; padding: 0 !important;
}
.kn-card-meta { display: flex; flex-wrap: wrap; gap: .5rem; align-items: baseline; margin: .35rem 0 0; font-size: .6875rem; }
.kn-card-brand { color: var(--kn-red); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
.kn-card-spec { color: var(--kn-muted); }

li.product .price, li.product .add_to_cart_button, li.product .button { display: none !important; }

.woocommerce-result-count { font-size: .75rem; color: var(--kn-muted); }
.woocommerce-ordering select {
	background: var(--kn-canvas); color: var(--kn-ink); font: inherit; font-size: .8125rem;
	border: 1px solid var(--kn-border-strong); border-radius: var(--kn-r); padding: .4rem .6rem;
}

/* --------------------------------------------------------- product single */

.gc-product .product { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--kn-s5); align-items: start; }
@media (max-width: 58rem) { .gc-product .product { grid-template-columns: 1fr; gap: var(--kn-s4); } }

/* Woo writes an inline width onto the gallery and floats both columns; with its
   general stylesheet dequeued the floats go but the inline width stays, so the
   gallery sat at a third of its column with dead space beneath and the summary
   wrapped at ~320px. Both columns are owned by the grid. */
.woocommerce-product-gallery,
.gc-product .summary.entry-summary {
	inline-size: 100% !important;
	float: none !important;
	margin: 0 !important;
	max-inline-size: none;
}
.woocommerce-product-gallery img { background: var(--kn-canvas); border-radius: var(--kn-r); mix-blend-mode: multiply; inline-size: 100%; }
.woocommerce-product-gallery__wrapper { margin: 0; inline-size: 100%; }
.woocommerce-product-gallery__image { inline-size: 100%; }
/* Woo's zoom affordance ships as a bare emoji anchor. An unstyled 🔍 floating
   over the image is the kind of detail that reads as unfinished. */
.woocommerce-product-gallery__trigger {
	position: absolute; inset-block-start: .5rem; inset-inline-end: .5rem; z-index: 2;
	inline-size: 2.25rem; block-size: 2.25rem; display: grid; place-items: center;
	background: var(--kn-canvas); border-radius: 999px; text-decoration: none;
	font-size: .95rem; box-shadow: 0 1px 4px rgb(0 0 0 / .12);
}
.woocommerce-product-gallery { position: relative; }

/* The short description carries the maker's own spec table. It arrives as raw
   markup and needs the same instrument treatment as the derived specs. */
.woocommerce-product-details__short-description table { inline-size: 100%; border-collapse: collapse; margin-block: var(--kn-s3); font-size: .8125rem; }
.woocommerce-product-details__short-description th,
.woocommerce-product-details__short-description td { text-align: start; padding: .45rem .6rem; }
.woocommerce-product-details__short-description thead td,
.woocommerce-product-details__short-description thead th { font-weight: 700; color: var(--kn-ink); border-block-end: 1.5px solid var(--kn-ink); }
.woocommerce-product-details__short-description tbody tr:nth-child(odd) { background: var(--kn-surface); }
.woocommerce-product-details__short-description tbody td { font-family: var(--kn-mono); font-variant-numeric: tabular-nums; }
.woocommerce-product-details__short-description ul { padding-inline-start: 1.1rem; }
.flex-control-thumbs { list-style: none; display: grid; grid-template-columns: repeat(5, 1fr); gap: .35rem; padding: .35rem 0 0; margin: 0; }
.flex-control-thumbs img { aspect-ratio: 1; object-fit: contain; cursor: pointer; border-radius: var(--kn-r); background: var(--kn-surface); }

.kn-brandline { font-size: .75rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--kn-red); margin: 0 0 .5rem; }
.product_title { font-size: clamp(1.5rem, 2.8vw, 2.125rem) !important; margin: 0 0 var(--kn-s3) !important; }
.woocommerce-product-details__short-description { color: var(--kn-ink-2); font-size: .9375rem; }

.kn-single-actions { margin-block: var(--kn-s4); padding: var(--kn-s3); background: var(--kn-surface); border-radius: var(--kn-r); }
.kn-poa { font-size: .8125rem; color: var(--kn-muted); margin: var(--kn-s2) 0 0; }

/* The instrument panel. Zebra rows because a buyer reads across, not down. */
/* The dealer's argument, full width beneath the gallery and buy box.
   Three columns on a surface band — the page's one marketing beat, carrying the
   licences, the workshop and the Registry.

   No red left-rule on each item, though the first draft had one. That is the
   side-tab tell, and worse, it made a liar of the footer comment that calls the
   legal notice "the one place red carries meaning". The columns are divided the
   way a table is — a hairline between them in the border grey, structure not
   decoration — and the red stays where it means something. */
.kn-assure {
	grid-column: 1 / -1;
	margin-block: var(--kn-s5) 0;
	background: var(--kn-surface); border-radius: var(--kn-r);
	padding: var(--kn-s4);
	display: grid; grid-template-columns: repeat(3, 1fr); gap: 0;
}
.kn-assure__i { padding-inline: var(--kn-s4); }
.kn-assure__i:first-child { padding-inline-start: 0; }
.kn-assure__i + .kn-assure__i { border-inline-start: 1px solid var(--kn-border); }
.kn-assure__t { margin: 0; font-size: .8125rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--kn-ink); }
.kn-assure__d { margin: .5rem 0 0; color: var(--kn-ink-2); font-size: .875rem; line-height: 1.55; }
@media (max-width: 48rem) {
	.kn-assure { grid-template-columns: 1fr; gap: 0; }
	.kn-assure__i { padding-inline: 0; }
	.kn-assure__i + .kn-assure__i { border-inline-start: 0; border-block-start: 1px solid var(--kn-border); margin-block-start: var(--kn-s3); padding-block-start: var(--kn-s3); }
}

/* The gallery follows you down.
 *
 * On a two-column product the picture is 512px tall and the summary 1160 — so
 * the left column ended at a third of the page and left ~650px of white beside
 * the specification. Sticky costs nothing and means the thing being described
 * is on screen while you read the description. */
@media (min-width: 62rem) {
	.woocommerce-product-gallery {
		position: sticky; inset-block-start: 5rem;
	}
}

/* WooCommerce's own attributes table — the "Additional information" panel —
   had no rules at all. It rendered as a right-aligned label column with
   underlined link values and no alignment to anything else on the page, which
   is what "broken CSS" looked like from the outside. Same treatment as the
   specification table above it, so the product has one table, used twice. */
.woocommerce-product-attributes {
	inline-size: 100%; border-collapse: collapse; font-size: .875rem;
	max-inline-size: 46rem;
}
.woocommerce-product-attributes th,
.woocommerce-product-attributes td {
	text-align: start; padding: .55rem .75rem; vertical-align: top;
}
.woocommerce-product-attributes th { font-weight: 600; color: var(--kn-ink); inline-size: 12rem; }
.woocommerce-product-attributes td { color: var(--kn-ink-2); }
.woocommerce-product-attributes td p { margin: 0; }
.woocommerce-product-attributes tr:nth-child(odd) { background: var(--kn-surface); }
.woocommerce-product-attributes a { color: var(--kn-ink-2); text-decoration: none; }
.woocommerce-product-attributes a:hover { color: var(--kn-red); }

.kn-specs { inline-size: 100%; border-collapse: collapse; margin-block-start: var(--kn-s4); font-size: .875rem; }
.kn-specs caption { text-align: start; font-size: .75rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--kn-ink); padding-block-end: var(--kn-s2); }
.kn-specs th, .kn-specs td { text-align: start; padding: .55rem .75rem; vertical-align: top; }
.kn-specs tr:nth-child(odd) { background: var(--kn-surface); }
.kn-specs th { font-weight: 500; color: var(--kn-ink-2); inline-size: 45%; }
.kn-specs td { color: var(--kn-ink); }

.woocommerce-tabs { margin-block-start: var(--kn-s4); grid-column: 1 / -1; }
.woocommerce-tabs ul.tabs { list-style: none; display: flex; gap: var(--kn-s4); padding: 0 0 var(--kn-s2); margin: 0 0 var(--kn-s4); }
.woocommerce-tabs ul.tabs a { text-decoration: none; font-size: .8125rem; font-weight: 600; color: var(--kn-muted); }
.woocommerce-tabs ul.tabs li.active a { color: var(--kn-ink); }
/* WooCommerce prints an <h2> inside each tab panel repeating the label already
   on the tab above it — "Description" under the Description tab. Unstyled it
   took the global h2 scale, 36px, against a product title of 34px: a section
   heading outranking the page it sits on, on all 295 product pages. The tab
   nav is the label and is properly associated, so the repeat is removed rather
   than merely shrunk. Scoped to the panel's own first child so headings inside
   a product's own copy keep their size. */
.woocommerce-Tabs-panel > h2:first-child { display: none; }
.related.products, .up-sells { grid-column: 1 / -1; margin-block-start: var(--kn-s6); }
.related.products > h2, .up-sells > h2 { font-size: 1.25rem; margin-block-end: var(--kn-s3); }

/* ------------------------------------------------------------- quote layer */

.gf-quote-btn__go { border-color: var(--kn-red); background: var(--kn-red); color: #fff; border-radius: var(--kn-r); font-weight: 600; }
.gf-quote-btn__go:hover { background: var(--kn-red-deep); }
.gf-quote-btn__go .gf-quote-btn__text { color: #fff; }
.gf-quote-btn.is-added .gf-quote-btn__go { background: var(--kn-ink); border-color: var(--kn-ink); }
.gf-quote-btn__qty { border-color: var(--kn-border-strong); border-radius: var(--kn-r); }
.gf-quote__submit { background: var(--kn-red); color: #fff; border-radius: var(--kn-r); }
.gf-quote__input { border-color: var(--kn-border-strong); border-radius: var(--kn-r); }
.gf-quote__input:focus { outline: 2px solid var(--kn-red); outline-offset: 1px; }
.gf-quote__item { border-block-end-color: var(--kn-border); }

/* --------------------------------------------------------------- services */

.kn-services { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: var(--kn-s2); }
.kn-service { background: var(--kn-surface); border-radius: var(--kn-r); padding: var(--kn-s4) var(--kn-s3); text-decoration: none; display: block; transition: background .15s ease; }
a.kn-service { transition: transform .2s cubic-bezier(.2,.7,.3,1), color .15s ease; }
a.kn-service:hover { transform: translateY(-2px); }
a.kn-service:hover h3 { color: var(--kn-red); }
.kn-service h3 { transition: color .15s ease; }
.kn-service h3 { margin-block-end: .5rem; }
.kn-service p { color: var(--kn-ink-2); font-size: .875rem; margin: 0; }

.kn-split { display: grid; grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr)); gap: var(--kn-s5); align-items: center; }
.kn-split img { inline-size: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--kn-r); }

/* ----------------------------------------------------------------- footer */

.kn-footer { background: var(--kn-chrome); color: #C8C8C8; margin-block-start: var(--kn-s6); }
.kn-footer__in { padding-block: var(--kn-s5); display: grid; grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); gap: var(--kn-s4); }
.kn-footer h4 { font-size: .75rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: #fff; margin-block-end: var(--kn-s2); }
.kn-footer a { color: #C8C8C8; text-decoration: none; display: block; padding-block: .2rem; font-size: .875rem; }
.kn-footer a:hover { color: #fff; }
.kn-footer address { font-style: normal; font-size: .875rem; line-height: 1.6; }
.kn-hours { font-size: .875rem; line-height: 1.6; margin: 0; }
.kn-footer__bar { border-block-start: 1px solid #383838; }
.kn-footer__bar-in { padding-block: var(--kn-s3); display: flex; flex-wrap: wrap; gap: var(--kn-s3); font-size: .75rem; color: #8C8C8C; }

/* The one place red carries meaning rather than action. */
.kn-legal { background: var(--kn-chrome-deep); }
.kn-legal__in {
	inline-size: min(var(--kn-wrap), 100% - (var(--kn-gutter) * 2)); margin-inline: auto;
	padding-block: var(--kn-s3); border-inline-start: 3px solid var(--kn-red); padding-inline-start: var(--kn-s2);
}
.kn-legal p { font-size: .75rem; color: #9A9A9A; max-inline-size: 96ch; margin: 0; line-height: 1.55; }
.kn-legal strong { color: #DCDCDC; font-weight: 600; }

/* ------------------------------------------------------------ page header */

/* Every page opened with one word set on white — `<h1>Services</h1>` and a
   400px void beneath it. The photographs were already on the box and nothing
   was rendering them.
   Contained rather than full-bleed, and rounded to match the archive head, so
   the site has one header shape rather than two. */
.kn-pagehead {
	position: relative; isolation: isolate; overflow: clip;
	border-radius: var(--kn-r);
	min-block-size: clamp(11rem, 24vw, 17rem);
	display: grid; align-items: end;
	margin-block: var(--kn-s3) var(--kn-s5);
	padding: var(--kn-s4);
}
.kn-pagehead__img {
	position: absolute; inset: 0; z-index: -2;
	inline-size: 100%; block-size: 100%; object-fit: cover;
}
/* Weighted to the foot, where the words are. A flat scrim over the whole frame
   would dim the picture everywhere to earn contrast in one band. */
.kn-pagehead::after {
	content: ""; position: absolute; inset: 0; z-index: -1;
	background: linear-gradient(to top, rgb(20 20 20 / .88) 0%, rgb(20 20 20 / .55) 45%, rgb(20 20 20 / .15) 100%);
}
.kn-pagehead__t {
	color: #fff; margin: 0;
	font-size: clamp(2rem, 4.4vw, 3.25rem); line-height: 1.02; letter-spacing: -0.03em;
}
.kn-pagehead__s {
	color: #E4E4E4; margin: .7rem 0 0; max-inline-size: 60ch; font-size: 1rem;
}

/* ------------------------------------------------------------------ a11y */

:where(a, button, input, select, textarea, summary):focus-visible {
	outline: 2px solid var(--kn-red);
	outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

@media print {
	body { font-size: 11pt; }
	.kn-specs tr:nth-child(odd) { background: none; }
	.kn-specs th, .kn-specs td { border-block-end: 1px solid #ccc; }
}

/* ============================================================ nav + imagery */

/* The primary menu is six items again. A flat strip of nine product categories
   read as a shelf list, not navigation, and it had pushed Services and About
   off the site entirely. The three that own children open a mega panel. */
/* `static`, not `relative`: the panel is now anchored to the sticky header
   rather than to the item that opens it. While each item was its own
   containing block the panel had to be dragged back to the viewport edge with
   `calc(50% - 50vw + gutter)` — a sum that only held while the departments
   began at the left edge of the wrap. They now start after the mark, so that
   calc would offset every panel by the width of the logo. */
.kn-navitem { position: static; display: flex; }
.kn-navitem > a {
	flex: 0 0 auto; color: #E4E4E4; text-decoration: none;
	padding: .55rem .7rem; font-size: .8125rem; font-weight: 600;
	white-space: nowrap; border-radius: var(--kn-r);
	transition: color .15s ease, background .15s ease;
}
.kn-navitem > a:hover, .kn-navitem:focus-within > a { color: #fff; background: #333; }
.kn-navitem > a[aria-current="page"] { color: var(--kn-red); }

/* Hover and focus-within, no JavaScript: a menu that needs a script to open is
   a menu that fails before the script loads. */
.kn-mega {
	position: absolute; inset-block-start: 100%; inset-inline: 0;
	background: var(--kn-canvas); border-block-end: 1px solid var(--kn-border);
	box-shadow: 0 12px 28px rgb(0 0 0 / .10);
	opacity: 0; visibility: hidden; transform: translateY(-4px);
	transition: opacity .14s ease, transform .14s ease, visibility .14s;
	z-index: 50;
}
.kn-navitem:hover .kn-mega, .kn-navitem:focus-within .kn-mega { opacity: 1; visibility: visible; transform: none; }
.kn-mega__in { display: grid; grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); gap: var(--kn-s3); padding-block: var(--kn-s4); }
.kn-mega__item { display: grid; gap: .4rem; text-decoration: none; color: var(--kn-ink); }
.kn-mega__item img, .kn-mega__noimg {
	inline-size: 100%; aspect-ratio: 4 / 3; object-fit: cover;
	border-radius: var(--kn-r); background: var(--kn-surface);
	transition: transform .25s cubic-bezier(.2,.7,.3,1);
}
.kn-mega__item:hover img { transform: scale(1.04); }
.kn-mega__t { font-size: .875rem; font-weight: 600; }
.kn-mega__item:hover .kn-mega__t { color: var(--kn-red); }
.kn-mega__n { font-family: var(--kn-mono); font-size: .6875rem; color: var(--kn-muted); }

/* Department tiles — the site was rendering these as text while WooCommerce
   held a real photograph for thirteen of them. */
.kn-depts { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: var(--kn-s3); }
.kn-dept {
	position: relative; display: block; text-decoration: none;
	border-radius: var(--kn-r); overflow: clip; min-block-size: 12rem;
	background: var(--kn-surface); isolation: isolate;
}
.kn-dept img {
	position: absolute; inset: 0; inline-size: 100%; block-size: 100%;
	object-fit: cover; z-index: -2; transition: transform .5s cubic-bezier(.2,.7,.3,1);
}
.kn-dept::after {
	content: ""; position: absolute; inset: 0; z-index: -1;
	background: linear-gradient(to top, rgb(28 28 28 / .88) 12%, rgb(28 28 28 / .35) 55%, rgb(28 28 28 / .08));
}
.kn-dept:hover img { transform: scale(1.05); }
.kn-dept__body { position: absolute; inset-block-end: 0; inset-inline: 0; padding: var(--kn-s3); display: grid; gap: .15rem; }
.kn-dept__t { color: #fff; font-family: var(--kn-display); font-weight: 700; font-size: 1.0625rem; }
.kn-dept__n { font-family: var(--kn-mono); font-size: .6875rem; color: #D8D8D8; }

/* The archive header carries the category photograph beside its title.
 *
 * It used to run the picture full-bleed behind the words under a dark scrim.
 * That design assumed the wide category banners this site was built on — and
 * every one of them is gone: 15 terms point at 2019/09 files that exist in the
 * database and nowhere on disk, the other 10 never had a thumbnail. So all 33
 * archives fall through to the borrowed fallback, the first product photograph
 * in the category, which is square and shot on white. Crop a square to 6.9:1
 * and you frame its empty background; put a 90%-black scrim over that and every
 * archive opens with a grey slab. Give the picture its own box at its own shape
 * and the same asset reads as a photograph again. */
.kn-shop-head.has-image {
	display: grid; grid-template-columns: auto minmax(0, 1fr);
	gap: var(--kn-s3); align-items: center;
	padding: 0 0 var(--kn-s3); margin-block: var(--kn-s3) var(--kn-s4);
	border-block-end: 1px solid var(--kn-border);
}
.kn-shop-head__img {
	inline-size: 6.5rem; block-size: 6.5rem; object-fit: cover;
	border-radius: var(--kn-r); background: var(--kn-surface);
}
@media (max-width: 40rem) {
	.kn-shop-head__img { inline-size: 4.5rem; block-size: 4.5rem; }
}

@media (max-width: 60rem) { .kn-mega { display: none; } }
