/* ==========================================================================
   Carbon Underfloor Heating - catalogue theme

   Loads after canvas.css and furniture.css. Two kinds of rule belong here:
     1. brand tokens that re-point the furniture demo's variables, and
     2. the catalogue components the demo has no equivalent for.

   Note on colour: the furniture demo drives everything - body text, headings,
   icons - from --cnvs-themecolor, which in the demo is a dark green. Our brand
   orange cannot serve as body text, so themecolor becomes a warm near-black
   and orange is applied deliberately, as an accent.
   ========================================================================== */

:root {
	/* Brand orange, sampled from the logo. */
	--cuh-orange:      #ff8f00;
	--cuh-orange-rgb:  255, 143, 0;
	--cuh-orange-dark: #d97600;
	/* Hover orange. --cuh-orange-deep is dark enough to read as brown against
	   body text; this keeps the brand hue and still passes on white. */
	--cuh-orange-hover: #d96b00;
	--cuh-orange-deep: #a85400;   /* passes AA at body size */
	/* Deeper again than --cuh-orange-deep, for type that has to read on a
	   translucent panel rather than on solid white. */
	--cuh-orange-darkest:    #6b3400;
	--cuh-orange-tint: #fff6e8;

	--cuh-ink:      #1c1a17;
	--cuh-ink-soft: #5c5750;
	--cuh-line:     #e7e4df;

	/* The demo's own variables, re-pointed. */
	--cnvs-themecolor:       var(--cuh-ink);
	--cnvs-themecolor-rgb:   28, 26, 23;
	--cnvs-themecolor-light: #faf7f2;

	--bs-link-color:       var(--cuh-orange-deep);
	--bs-link-hover-color: var(--cuh-ink);
}

body { background-color: #fff; }

/* Accent, applied on purpose rather than inherited. */
.svg-underline span::after { background-color: var(--cuh-orange) !important; }
.product-price, .hero-card-price, .category-card-count { color: var(--cuh-orange-deep); }

/* Buttons rest dark, like the demo's, and come up orange on hover. */
.button {
	background-color: var(--cuh-ink);
	color: #fff;
	border-color: var(--cuh-ink);
	text-transform: none;
	letter-spacing: 0;
	transition: background-color .18s ease, border-color .18s ease, color .18s ease;
}
.button:hover,
.button:focus-visible {
	background-color: var(--cuh-orange);
	border-color: var(--cuh-orange);
	color: #21160a;
}
.button-border {
	background-color: transparent;
	color: var(--cuh-ink);
	border-color: var(--cuh-line);
}
.button-border:hover,
.button-border:focus-visible {
	background-color: var(--cuh-orange);
	border-color: var(--cuh-orange);
	color: #21160a;
}

.lead-copy { color: var(--cuh-ink-soft); line-height: 1.75; }
.page-heading { line-height: 1.2; }

/* --------------------------------------------------------------- top bar */
#top-bar { border-bottom: 1px solid var(--cuh-line); }
#top-bar h2 { font-size: .8125rem; letter-spacing: .01em; }
#top-bar a.color { color: var(--cuh-orange-deep); }
#top-bar a.color:hover { color: var(--cuh-ink); }

/* ------------------------------------------------------------------ header */
#header-wrap #logo img { height: 76px; width: auto; max-height: none; display: block; }
#footer .footer-logo { height: 88px; width: auto; }

/* The logo hangs like a sign: its top edge sits flush against the top of the
   header, and the rest of it drops below the bar and over the slider. The
   negative bottom margin is what creates the overhang, so nothing in the
   chain may clip it. */
@media (min-width: 992px) {
	#header, #header-wrap, #header .container, #header .header-row { overflow: visible; }
	#logo {
		position: relative;
		z-index: 5;
		align-self: flex-start;
		margin-top: 0;
		padding-top: 0;
	}
	#logo a { display: block; margin-top: 0; }
	#header #header-wrap #logo img { height: 100px; max-height: none; margin-top: 0; margin-bottom: -44px; }

	/* Sticky shrinks the header, so the sign shortens with it and stays hung
	   from the same edge rather than jumping. */
	/* Canvas shrinks the logo to --cnvs-sticky-header-height (60px) through
	   .is-expanded-menu #header.sticky-header-shrink #header-wrap #logo img,
	   which carries one more class than a plain sticky-header selector and so
	   won. At 60px the wordmark stopped being readable at a glance; this keeps
	   it legible while still stepping down from the 100px at rest. */
	#header.sticky-header #header-wrap #logo img,
	.is-expanded-menu #header.sticky-header.sticky-header-shrink #header-wrap #logo img {
		height: 92px;
		margin-bottom: -36px;
	}
}

.header-phone { display: flex; align-items: center; margin-right: 1rem; }
.header-phone a { font-weight: 500; color: var(--cuh-ink); text-decoration: none; white-space: nowrap; }
.header-phone a:hover { color: var(--cuh-orange-deep); }
.header-phone i { color: var(--cuh-orange); margin-right: .35rem; }

/* ------------------------------------------------------------ menu arrows */
/* Canvas ships the indicator hidden and only reveals it for top-level items.
   Every item that actually opens something gets one here. */
.primary-menu .menu-link div > i.sub-menu-indicator {
	display: inline-block !important;
	margin-left: .35rem;
	font-size: .7em;
	vertical-align: middle;
	transition: transform .18s ease;
}
/* A top-level chevron flips to point up while its panel is open. Inside a
   dropdown the chevron already points right at the panel it opens, and
   flipping that one turned it upside down. */
.primary-menu .menu-container > .menu-item:hover > .menu-link div > i.sub-menu-indicator { transform: rotate(180deg); }
.primary-menu .sub-menu-container .menu-item:hover > .menu-link div > i.sub-menu-indicator { transform: translateY(-50%) rotate(-90deg); }

@media (min-width: 992px) {
	/* The visible edge of an open dropdown. */
	.is-expanded-menu #header .primary-menu:not(.on-click) .menu-item > .cuh-submenu {
		/* Canvas pins this to 1px with !important; answered in kind. */
		border-top: 2px solid var(--cuh-orange);
		border-top-width: 2px !important;
	}
}

.breadcrumb { font-size: .8125rem; margin-bottom: .75rem; }

/* -------------------------------------------------------------------- hero */
#slider .hero-copy { position: relative; z-index: 3; padding-top: 6rem; max-width: 620px; }
/* The label band.
   Worn by the slide eyebrow on the home page and by every .info-label - the
   small caps line above a heading - so the two are one thing defined once.

   The fill is the translucent orange the Browse the shop button rests on,
   between a solid rule above and below and no sides at all, so it reads as a
   band laid across the page rather than a boxed label. Both ends fade out.

   A mask does the fade rather than a gradient background, because the rules
   have to fade with the fill; a background gradient would leave two hard
   orange lines running out to nothing. The fade is set in pixels and the
   padding is wider than it, so it dissolves inside the padding and never
   touches the first or last letter. Each user sets its own --band-fade and
   --band-pad, because a 13px eyebrow and a 12px label want different runs. */
.hero-eyebrow,
.info-label {
	--band-fade: 34px;
	--band-pad: 2.75rem;
	display: inline-block;
	padding: .3rem var(--band-pad);
	border-top: 2px solid var(--cuh-orange);
	border-bottom: 2px solid var(--cuh-orange);
	border-left: 0;
	border-right: 0;
	background-color: rgba(255, 143, 0, .38);
	line-height: 1.5;
	-webkit-mask-image: linear-gradient(to right, transparent 0, #000 var(--band-fade), #000 calc(100% - var(--band-fade)), transparent 100%);
	mask-image: linear-gradient(to right, transparent 0, #000 var(--band-fade), #000 calc(100% - var(--band-fade)), transparent 100%);
}

.hero-eyebrow {
	margin-bottom: 1rem;
	color: #fff;
	font-size: .8125rem;
	font-weight: 500;
	letter-spacing: .12em;
	text-transform: uppercase;
}

/* The label is smaller than the eyebrow, so it runs out over a shorter
   distance and sits in narrower padding. */
.info-label {
	--band-fade: 26px;
	--band-pad: 2rem;
	margin-bottom: .9rem;
	font-size: .75rem;
	font-weight: 600;
	letter-spacing: .14em;
	text-transform: uppercase;
	/* Orange type on a translucent orange fill is unreadable on a light ground:
	   the brand orange measures 1.65:1 over the band and even --cuh-orange-deep
	   only reaches 3.86:1, under the 4.5 a 12px label needs. This burnt shade
	   measures 5.22:1 on white and 4.99:1 on the tinted bands and still reads
	   as orange. The hero keeps white, since it sits on a photograph. */
	color: #8a4400;
}
.info-hero .info-label { color: #fff; }

@media (max-width: 575.98px) {
	.hero-eyebrow { --band-fade: 22px; --band-pad: 1.75rem; }
	.info-label   { --band-fade: 18px; --band-pad: 1.4rem; }
}

.hero-heading { color: #fff; font-size: clamp(1.9rem, 4vw, 3rem); line-height: 1.15; font-weight: 500; }

.hero-cards .card {
	background: rgba(255, 255, 255, .1);
	backdrop-filter: blur(6px);
	border: 1px solid rgba(255, 255, 255, .18);
	border-radius: .5rem;
	overflow: hidden;
	text-decoration: none !important;
	transition: background .2s ease;
}
.hero-cards .card:hover { background: rgba(255, 255, 255, .2); }
.hero-card-image {
	flex: 0 0 84px;
	width: 84px;
	height: 84px;
	background: #fff;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: .4rem;
}
.hero-card-image img { width: auto; height: auto; max-width: 100%; max-height: 100%; object-fit: contain; }
.hero-card-title {
	display: block;
	color: #fff;
	font-weight: 500;
	font-size: .9375rem;
	line-height: 1.35;
	margin-bottom: .3rem;
}
.hero-card-price { display: flex; align-items: center; color: #fff; opacity: .9; font-size: .875rem; }
.hero-card-price .price-from { font-size: .75rem; opacity: .75; margin-right: .25rem; }

/* Buttons rest dark elsewhere, which would vanish against the hero image, so
   over the slider they rest white and still come up orange on hover. */
#slider .button {
	background-color: #fff;
	border-color: #fff;
	color: var(--cuh-ink);
}
#slider .button:hover,
#slider .button:focus-visible {
	background-color: var(--cuh-orange);
	border-color: var(--cuh-orange);
	color: #21160a;
}

@media (max-width: 767.98px) {
	#slider .hero-copy { padding-top: 3.5rem; }
	.hero-cards { display: none !important; }
}

/* ----------------------------------------------------------------- imagery */
/* No image is ever displayed larger than the file actually is. Several of the
   product masters are only 250px wide, and stretching one to fill its tile is
   exactly what makes it look zoomed in and soft. Canvas' own rule for
   .product .product-image img is width:100%, so this has to override it. */
.product .product-image img,
.category-card-image img,
.product-gallery img,
.category-intro-image img {
	width: auto !important;
	height: auto !important;
	max-width: 100%;
	max-height: 100%;
	object-fit: contain;
}

/* ------------------------------------------------------ one-row product sets */
/* A category holding three to five products should land on a single desktop
   row. Bootstrap has no five-column step, so the width is set explicitly and
   the fixed col-lg-* span is left off these cards in the markup. */
@media (min-width: 992px) {
	.products-fit > .product { flex: 0 0 auto; }
	.products-fit-2 > .product { width: 50%; }
	.products-fit-3 > .product { width: 33.3333%; }
	.products-fit-4 > .product { width: 25%; }
	.products-fit-5 > .product { width: 20%; }
}

/* ----------------------------------------------------------- product tiles */
.product .grid-inner {
	height: 100%;
	display: flex;
	flex-direction: column;
	background: #fff;
	border: 1px solid var(--cuh-line);
	border-radius: .5rem;
	overflow: hidden;
	transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}
.product .grid-inner:hover {
	border-color: var(--cuh-orange);
	box-shadow: 0 12px 28px rgba(28, 26, 23, .1);
	transform: translateY(-3px);
}
.product .product-image {
	display: flex;
	align-items: center;
	justify-content: center;
	height: 220px;
	background: var(--cnvs-themecolor-light);
	padding: 1rem;
	border-radius: 0;
}
.product .product-image > a {
	display: flex !important;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 100%;
}
.product-sizes-badge {
	position: absolute;
	top: .6rem;
	left: .6rem;
	z-index: 3;
	font-size: .6875rem;
	font-weight: 600;
	color: var(--cuh-orange-deep);
	background: #fff;
	border-radius: 100px;
	padding: .15rem .55rem;
}
.product .product-desc {
	display: flex;
	flex-direction: column;
	flex: 1;
	padding: 1.1rem 1.2rem 1.25rem;
	text-align: left;
}
.product .product-title a { color: var(--cuh-ink); text-decoration: none; }
.product .product-title a:hover { color: var(--cuh-orange-deep); }
.product-summary {
	font-size: .8125rem;
	line-height: 1.6;
	color: var(--cuh-ink-soft);
	flex: 1;
	margin: .5rem 0 1rem;
	display: -webkit-box;
	-webkit-line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
.product .product-price {
	margin: 0;
	padding-top: .8rem;
	border-top: 1px solid var(--cuh-line);
	font-size: 1.1rem;
	font-weight: 700;
}
.product .product-price .price-from { font-size: .75rem; font-weight: 400; color: var(--cuh-ink-soft); }

/* ---------------------------------------------------------- category tiles */
.category-card {
	display: flex;
	flex-direction: column;
	height: 100%;
	background: #fff;
	border: 1px solid var(--cuh-line);
	border-radius: .5rem;
	overflow: hidden;
	text-decoration: none !important;
	transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}
.category-card:hover {
	border-color: var(--cuh-orange);
	box-shadow: 0 12px 28px rgba(28, 26, 23, .1);
	transform: translateY(-3px);
}
.category-card-image {
	display: flex;
	align-items: center;
	justify-content: center;
	height: 200px;
	background: var(--cnvs-themecolor-light);
	padding: 1rem;
}
.category-card-body { display: flex; flex-direction: column; gap: .4rem; padding: 1.15rem 1.25rem 1.35rem; flex: 1; }
.category-card-title { font-family: var(--cnvs-primary-font); font-size: 1.05rem; font-weight: 500; color: var(--cuh-ink); line-height: 1.3; }
.category-card-strap { font-size: .8125rem; color: var(--cuh-ink-soft); line-height: 1.55; flex: 1; }
.category-card-count { font-size: .8125rem; font-weight: 600; margin-top: .35rem; }
.category-card-count i { display: inline-block; transition: transform .18s ease; }
.category-card:hover .category-card-count i { transform: translateX(4px); }

.category-intro-image { text-align: center; }
.category-intro-image img { border-radius: .5rem; }
.category-strap { font-size: 1.15rem; font-weight: 500; color: var(--cuh-ink); }

/* ------------------------------------------------------------ floor finish */
/* Floor-finish tiles now use the category card, so they only need the one
   difference: these are photographs that should fill their tile rather than
   product cut-outs that must sit at natural size. */
.category-card-image-cover { padding: 0; }
.category-card-image-cover img {
	width: 100% !important;
	height: 100% !important;
	max-width: none;
	max-height: none;
	object-fit: cover;
	transition: transform .3s ease;
}
.category-card:hover .category-card-image-cover img { transform: scale(1.04); }

/* ------------------------------------------------------------ brand strip */
/* The demo sets each logo about 100px wide and 30px tall inside a .col.op-05,
   in two centred rows under the features. Ours are wordmarks rather than
   artwork, sized and greyed to sit on the same optical line. */
.brand-strip { margin-top: 4.5rem; text-align: center; }

/* Set in the display face at the same weight as "Why Choose Us" above it,
   rather than as a small-caps label - a second type treatment in the same
   band was the thing making this row look bolted on. */
.brand-strip-heading {
	font-family: var(--cnvs-primary-font);
	font-size: clamp(1.25rem, 2vw, 1.6rem);
	font-weight: 400;
	line-height: 1.3;
	letter-spacing: 0;
	text-transform: none;
	color: var(--cuh-ink);
	margin-bottom: 2rem;
}
.brand-strip .row { row-gap: 1.5rem; }
.brand-strip .col { padding-inline: 18px; }

/* Every mark to one height, greyed so a row of competing brand colours does
   not pull the eye off the page, and back to full colour under the pointer. */
.brand-cell {
	display: flex;
	align-items: center;
	justify-content: center;
}
.brand-cell img,
.brand-cell .brand-wordmark {
	filter: grayscale(1);
	opacity: .5;
	transition: filter .3s ease, opacity .3s ease;
}
.brand-cell:hover img,
.brand-cell:hover .brand-wordmark { filter: grayscale(0); opacity: 1; }
.brand-strip .col img {
	height: 56px;
	width: auto;
	max-width: 100%;
	object-fit: contain;
}

/* The first row is the heating system on its own; a little more air under it
   separates it from the flooring houses without needing a caption. */
.brand-row + .brand-row { margin-top: 2.25rem !important; }
.brand-wordmark {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 56px;
	font-family: var(--cnvs-primary-font);
	font-size: 1.85rem;
	font-weight: 600;
	letter-spacing: .01em;
	line-height: 1;
	color: var(--cuh-ink);
	white-space: nowrap;
}

/* Six across is too tight for a phone, so each row of three keeps its three.
   A flex item will not shrink below its content width unless min-width is
   cleared, which is why nowrap wordmarks were forcing 2 + 1 instead. */
@media (max-width: 767.98px) {
	.brand-strip { margin-top: 3rem; }
	.brand-strip .row { flex-wrap: nowrap; }
	.brand-strip .col {
		flex: 1 1 0;
		width: auto;
		min-width: 0;
		padding-inline: 6px;
	}
	.brand-wordmark { font-size: 1rem; white-space: normal; }
}
@media (max-width: 400px) {
	.brand-wordmark { font-size: .9rem; }
}

/* --------------------------------------------------------- product gallery */
/* Full-width shots stacked down the column, scrolling past the sticky
   description - the demo's arrangement. */
.product-gallery-shot {
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--cnvs-themecolor-light);
	border-radius: .5rem;
	padding: 2rem;
	min-height: 420px;
	margin-bottom: 1.5rem;
}
.product-gallery-shot:last-child { margin-bottom: 0; }

@media (max-width: 767.98px) {
	.product-gallery-shot { min-height: 260px; padding: 1.25rem; }
}

/* --------------------------------------------------------- product toggles */
.single-product .qv-toogle + .qv-toogle { border-top: 1px solid var(--cuh-line); padding-top: 1.25rem; }
.single-product .qv-toogle a {
	color: var(--cuh-ink);
	text-decoration: none;
	padding-block: .25rem;
}
.single-product .qv-toogle a:hover { color: var(--cuh-orange-deep); }
.single-product .qv-toogle a i { font-size: .9rem; color: var(--cuh-orange-deep); }
.qv-toogle-body { color: var(--cuh-ink-soft); line-height: 1.8; padding-top: .5rem; }
.qv-toogle-body h3 { font-size: 1rem; color: var(--cuh-ink); margin: 1.4rem 0 .6rem; }
.qv-toogle-body p { margin-bottom: .9rem; font-size: .9375rem; }
.qv-toogle-body ul { margin: 0 0 1.1rem; padding-left: 1.15rem; font-size: .9375rem; }
.qv-toogle-body li { margin-bottom: .4rem; }
.qv-toogle-body strong { color: var(--cuh-ink); }
.qv-toogle-body .size-table { margin-bottom: 0; }
.guarantee-badge { display: block; width: 88px; height: auto; margin-top: 1rem; }

/* The "kit includes" callout: a thin orange rule around the whole panel
   rather than the heavy left bar it had. */
.qv-toogle-body blockquote.product-kit,
.product-copy blockquote.product-kit {
	margin: 1rem 0 1.5rem;
	padding: 1.15rem 1.35rem;
	background: var(--cuh-orange-tint);
	border: 1px solid var(--cuh-orange);
	border-radius: .35rem;
	font-size: .9375rem;
}
.qv-toogle-body blockquote.product-kit :last-child,
.product-copy blockquote.product-kit :last-child { margin-bottom: 0; }

/* ------------------------------------------------------------- product buy */
.product-lead { font-size: 1.0625rem; line-height: 1.7; color: var(--cuh-ink-soft); margin-bottom: 1.5rem; }

.product-buy {
	background: var(--cnvs-themecolor-light);
	border: 1px solid var(--cuh-line);
	border-radius: .5rem;
	padding: 1.25rem 1.35rem;
}
.product-price-row { display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap; }
.product-desc .product-price { font-size: 2rem; font-weight: 700; line-height: 1; border: 0; padding: 0; }
.product-price-note { font-size: .8125rem; color: var(--cuh-ink-soft); }

.product-size-label {
	display: block;
	margin: 1.15rem 0 .4rem;
	font-size: .75rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: .08em;
	color: var(--cuh-ink-soft);
}
.product-size-select {
	width: 100%;
	padding: .7rem .9rem;
	font-size: .9375rem;
	color: var(--cuh-ink);
	background-color: #fff;
	border: 1px solid var(--cuh-line);
	border-radius: .35rem;
	appearance: none;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%235c5750'%3E%3Cpath d='M8 11.5 3 6h10z'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right .8rem center;
	background-size: 15px;
	padding-right: 2.2rem;
}
.product-size-select:focus { outline: 2px solid var(--cuh-orange); outline-offset: 1px; border-color: var(--cuh-orange); }
.product-size-help { margin: .55rem 0 0; font-size: .8125rem; line-height: 1.55; color: var(--cuh-ink-soft); }

/* ----------------------------------------------------------------- enquiry */
.enquiry-panel { margin-top: 1.25rem; }
.enquiry-lead { font-size: .875rem; line-height: 1.6; color: var(--cuh-ink-soft); margin-bottom: .9rem; }
.enquiry-actions {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: .6rem;
}
/* The two written routes share a line; wrapping is theirs to do, and the
   telephone number is a sibling of the row rather than a third item in it,
   so it always starts a line of its own however wide the column gets. */
.enquiry-row {
	display: flex;
	flex-wrap: wrap;
	gap: .6rem;
}
.enquiry-actions .button,
.product-buy .product-add {
	display: inline-flex;
	align-items: center;
	justify-content: flex-start;
	flex: 0 0 auto;
	width: auto;
	min-height: 42px;
	padding: 0 1.15rem;
	font-size: .9375rem;
	line-height: 1.45;
	border-radius: .3rem;
	text-align: left;
	white-space: nowrap;
}
/* A bordered button carries its edge inside its box. Height comes from
   min-height on both, so the outlined pair and the filled one line up
   whatever the border does. */
.enquiry-actions .button-border { padding: 0 calc(1.15rem - 2px); }

@media (max-width: 420px) {
	/* Below this the two no longer sit side by side without their labels
	   wrapping mid-phrase, so each takes its own line. */
	.enquiry-row { flex-direction: column; align-items: flex-start; }
}

.product-meta-list {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: .55rem 1.25rem;
	margin: 1.5rem 0 0;
	padding-top: 1.25rem;
	border-top: 1px solid var(--cuh-line);
	font-size: .875rem;
}
.product-meta-list dt { font-weight: 600; color: var(--cuh-ink-soft); }
.product-meta-list dd { margin: 0; color: var(--cuh-ink); }

/* -------------------------------------------------------------- side panel */
#side-panel .top-cart-title { padding-bottom: 1rem; border-bottom: 1px solid var(--cuh-line); }
.side-panel-empty, .side-panel-note { font-size: .875rem; line-height: 1.6; color: var(--cuh-ink-soft); }
.side-panel-note { padding-top: 1rem; border-top: 1px solid var(--cuh-line); }
#side-panel .top-cart-item { padding: 1rem 0; border-bottom: 1px solid var(--cuh-line); }
#side-panel .top-cart-item-desc-title a { color: var(--cuh-ink); font-weight: 500; text-decoration: none; }
#side-panel .top-cart-item-price { color: var(--cuh-orange-deep); font-weight: 700; font-size: 1.1rem; margin-top: .25rem; }
#side-panel .top-cart-item-quantity { font-size: .8125rem; color: var(--cuh-ink-soft); }
.top-cart-number { background-color: var(--cuh-orange) !important; color: #21160a !important; }

/* -------------------------------------------------------- long-form content */
.product-section + .product-section { margin-top: 3rem; }
.product-copy { color: var(--cuh-ink-soft); line-height: 1.8; }
.product-copy h2 { font-size: 1.25rem; color: var(--cuh-ink); margin: 2rem 0 .85rem; }
.product-copy h3 { font-size: 1.05rem; color: var(--cuh-ink); margin: 1.6rem 0 .7rem; }
.product-copy p { margin-bottom: 1rem; }
.product-copy ul { margin: 0 0 1.25rem; padding-left: 1.15rem; }
.product-copy li { margin-bottom: .45rem; }
.product-copy strong { color: var(--cuh-ink); }

.size-table { font-size: .9375rem; }
.size-table thead th {
	font-size: .75rem;
	text-transform: uppercase;
	letter-spacing: .06em;
	color: var(--cuh-ink-soft);
	border-bottom: 1px solid var(--cuh-line);
}
.size-table tbody tr { cursor: pointer; }
.size-table tbody tr:hover { background: #fff; }
.size-table tbody tr.is-selected { background: var(--cuh-orange-tint); box-shadow: inset 3px 0 0 var(--cuh-orange); }
.size-table th[scope="row"] { font-weight: 600; color: var(--cuh-ink); }
.size-table td { color: var(--cuh-ink-soft); }

/* ------------------------------------------------------------ why choose us */
/* The demo's own treatment: a centred 64px line drawing in the ink colour,
   no chip, no brand-orange fill. */
.assurance .fbox-icon {
	width: auto;
	height: auto;
	background: none;
	border: 0;
	margin: 0 auto 1.25rem;
	display: flex;
	justify-content: center;
	align-items: center;
}
.assurance .fbox-icon svg { display: block; width: 64px; height: 64px; }
.assurance .fbox-content { text-align: center; }
.assurance .fbox-content h3 { color: var(--cuh-ink); }
.assurance p { font-size: .9375rem; line-height: 1.7; color: var(--cuh-ink-soft); margin-bottom: 0; }

/* Hovering one of the four takes the icon, its heading and its text over to
   the brand colour together. The drawings paint themselves in
   var(--cnvs-themecolor), so re-pointing that one variable on the box recolours
   the artwork without a second copy of the icon. */
.assurance {
	/* Decelerating rather than linear-ish, and long enough to read as a move
	   rather than a jump: it lifts, slows and settles. */
	transition: transform .42s cubic-bezier(.16, .84, .28, 1);
	cursor: default;
}
.assurance .fbox-icon,
.assurance .fbox-content h3,
.assurance p { transition: color .28s ease-out; }
.assurance:hover {
	--cnvs-themecolor: var(--cuh-orange);
	transform: translateY(-7px);
}
.assurance:hover .fbox-content h3,
.assurance:hover p { color: var(--cuh-orange-hover); }

@media (prefers-reduced-motion: reduce) {
	.assurance { transition: none; }
	.assurance:hover { transform: none; }
}

/* ------------------------------------------------------------------ footer */
#footer .footer-tips li {
	display: block;
	position: relative;
	padding-left: 1.1rem;
	font-size: .875rem;
	line-height: 1.6;
	color: var(--cuh-ink-soft);
	margin-bottom: .7rem;
}
#footer .footer-tips li::before {
	content: "";
	position: absolute;
	left: 0;
	top: .65em;
	width: 8px;
	height: 2px;
	background: var(--cuh-orange);
}
#footer .footer-tips strong { color: var(--cuh-ink); font-weight: 600; }

/* furniture.css sets the footer link list in uppercase with 1px of tracking.
   The dropdowns settled on Title Case, and the footer lists the same pages -
   two cases for one set of labels reads as an oversight. */
#footer .widget_links li {
	text-transform: none;
	letter-spacing: 0;
	font-size: .8125rem;
}

/* The same house as the main menu, on the same terms: the gutter is always
   reserved, only opacity moves, and the link goes orange with it.

   The gutter is one measurement - house plus the gap after it - so the column
   heading can be indented by the same amount and sit over the first letter of
   the links rather than out on its own to the left, which is what made the
   headings look adrift once the links moved across to make room. The gap is
   tight, so the house reads as belonging to the word beside it. */
#footer .widget_links {
	--foot-house: 11px;
	--foot-gap: 4px;
	--foot-indent: calc(var(--foot-house) + var(--foot-gap));
}
#footer .widget_links li a,
#copyrights a {
	position: relative;
	display: inline-block;
	padding-left: var(--foot-indent, 1.15rem);
	transition: color .18s ease;
}
#footer .widget_links h4 { padding-left: var(--foot-indent); }
#footer .widget_links li a::before,
#copyrights a::before {
	content: "";
	position: absolute;
	left: 0;
	top: 50%;
	width: var(--foot-house, 11px);
	height: var(--foot-house, 11px);
	margin-top: calc(var(--foot-house, 11px) / -2 - 1px);
	background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23ff8f00' d='M12 2.6L.8 11.8h3v9.6h16.4v-9.6h3z'/%3E%3C/svg%3E") no-repeat center center;
	background-size: contain;
	opacity: 0;
	transition: opacity .1s ease-out;
	pointer-events: none;
}
#footer .widget_links li a:hover,
#copyrights a:hover { color: var(--cuh-orange-hover); }
#footer .widget_links li a:hover::before,
#copyrights a:hover::before { opacity: 1; }

/* The page you are on, marked in the footer too. */
#footer .widget_links li a.is-current { color: var(--cuh-orange-hover); }
#footer .widget_links li a.is-current::before { opacity: 1; }
#footer .widget h4 { font-family: var(--cnvs-primary-font); }
#copyrights { font-size: .8125rem; color: var(--cuh-ink-soft); background: #fff; }
/* The message button is fixed over the bottom-right corner, which is exactly
   where the small print ends. Keep the last line clear of it. */
@media (min-width: 768px) {
	#copyrights .text-md-end { padding-right: 92px; }
}
@media (max-width: 767.98px) {
	/* Both circles are fixed over the bottom-right corner and the small print
	   is centred across the full width, so on a phone the go-to-top sat on top
	   of it. Smaller circles there, and enough room under the last line for
	   both of them once the page is scrolled right down. */
	#copyrights { padding-bottom: 9.5rem; }
}

@media (max-width: 991.98px) {
	.product .product-image { height: 190px; }
	.category-card-image { height: 170px; }
	.product-desc .product-price { font-size: 1.7rem; }
}

/* ====================================================================== */
/* Product page                                                           */
/* ====================================================================== */

/* The demo runs its product block on a tinted band rather than plain white.
   `--cuh-product-bg` is the demo's own value; change this one line to move
   the whole block to white, a warmer cream, or anything else. */
:root { --cuh-product-bg: #EBF1F0; }

.product-hero {
	background-color: var(--cuh-product-bg);
	padding-block: 2.5rem 4rem;
}

/* All the space above the breadcrumb belongs to the band.

   It used to be three lots stacked: 80px from .content-wrap, then the
   band's own padding on top of that, then the breadcrumb's margin - which
   is why nothing that was changed in one place ever moved the gap by the
   amount it was changed by. The wrapper and the section give up their top
   padding entirely, so the band's padding-top is the whole measurement and
   is the only thing to adjust. */
.page-product #content,
.page-product .content-wrap { padding-top: 0; }
.page-product .product-hero { padding-top: 60px; }

/* Narrower than a desktop, the band is nearer the top of the screen and
   60px of tinted nothing starts to read as a mistake. The breadcrumb takes
   the room instead, which it needs anyway: it wraps to two lines around
   here and was sitting tight under the heading. */
@media (max-width: 991.98px) {
	.page-product .product-hero { padding-top: 25px; }
	.page-product .breadcrumb { margin-bottom: 30px; }
}

/* On a phone the breadcrumb is gone altogether, so the heading is the first
   thing in the band - and being first is exactly why it needs clear air above
   it rather than sitting on the header rule. */
@media (max-width: 767.98px) {
	.page-product .product-hero { padding-top: 30px; }
}
.product-hero .product-gallery-shot,
.product-hero .product-buy {
	background: #fff;
	border-color: rgba(28, 26, 23, .08);
}
.product-hero .size-table tbody tr:hover { background: rgba(255, 255, 255, .6); }

/* ====================================================================== */
/* About page                                                             */
/* ====================================================================== */

.about-hero {
	background-position: center 65%;
	background-size: cover;
	display: flex;
	align-items: center;
}
.about-hero h1 { max-width: 18ch; }

.about-figure img {
	width: 100%;
	height: auto;
	border-radius: .5rem;
}

.process-step {
	height: 100%;
	background: #fff;
	border: 1px solid var(--cuh-line);
	border-radius: .5rem;
	padding: 1.75rem 1.5rem;
}
.process-step-number {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2.25rem;
	height: 2.25rem;
	margin-bottom: 1rem;
	border-radius: 50%;
	background: var(--cuh-orange);
	color: #21160a;
	font-weight: 700;
	font-family: var(--cnvs-primary-font);
}
.process-step p { font-size: .9375rem; line-height: 1.7; color: var(--cuh-ink-soft); }

.about-cta {
	background: var(--cnvs-themecolor-light);
	border: 1px solid var(--cuh-line);
	border-radius: .5rem;
	padding: 3rem 1.5rem;
}
.about-cta .lead-copy { max-width: 52ch; }

/* ====================================================================== */
/* Floating quick contact                                                 */
/* ====================================================================== */

.floating-contact-wrap {
	position: fixed;
	right: 50px;
	bottom: 60px;
	z-index: 299;
}
#gotoTop {
	--cnvs-gotoTop-size: 60px;
	--cnvs-gotoTop-icon-size: 22px;
	--cnvs-gotoTop-bg: var(--cuh-orange);
	--cnvs-gotoTop-icon-color: #fff;
	--cnvs-gotoTop-border-radius: 50%;
	--cnvs-gotoTop-hover-color: var(--cuh-ink);
	transition: background-color .3s ease, transform .3s ease, opacity .4s ease;
}
#gotoTop:hover {
	color: #fff;
	transform: scale(1.1);
}

/* The message button is centred on the wrap's origin at right:50px, so the
   arrow needs right:20px to sit on the same vertical line, and enough height
   between them that the two circles do not touch. */
.floating-contact-wrap + #gotoTop,
.stretched .floating-contact-wrap + #gotoTop {
	right: 20px;
	bottom: 108px;
}

@media (max-width: 767.98px) {
	.floating-contact-wrap + #gotoTop,
	.stretched .floating-contact-wrap + #gotoTop { right: 14px; bottom: 96px; }
}

/* Every offset around this button is half of it - the circle is centred on
   its anchor point - so the size is a variable and the rest is arithmetic. A
   phone overrides the one value at the foot of this file. */
.floating-contact-wrap { --fab: 60px; }
.floating-contact-btn {
	position: absolute;
	left: 0;
	top: 0;
	width: var(--fab);
	height: var(--fab);
	border-radius: var(--fab);
	background-color: var(--cuh-orange);
	color: #fff;
	cursor: pointer;
	z-index: 3;
	transform: translate(-50%, -50%);
	transition: transform .3s ease, background-color .3s ease;
}
.floating-contact-btn:hover,
.floating-contact-wrap.active .floating-contact-btn {
	transform: translate(-50%, -50%) scale(1.1);
	background-color: var(--cuh-ink);
	color: #fff;
}
.floating-contact-icon {
	position: absolute;
	top: 50%;
	left: 50%;
	font-size: 22px;
	transform: translate(-50%, -50%);
	transition: .3s cubic-bezier(.645, .045, .355, 1);
	transition-property: opacity, transform;
	backface-visibility: hidden;
}
.floating-contact-icon.btn-active,
.floating-contact-wrap.active .floating-contact-icon { opacity: 0; }
.floating-contact-wrap.active .floating-contact-icon.btn-active {
	opacity: 1;
	transform: translate(-50%, -50%) rotate(-45deg);
}

.floating-contact-box {
	opacity: 0;
	position: absolute;
	right: 0;
	bottom: 0;
	width: 380px;
	background-color: #fff;
	border-radius: 6px;
	z-index: 1;
	transform-origin: right bottom;
	transform: scale(.01);
	box-shadow: 0 0 13px 3px rgba(0, 0, 0, .07);
	transition: all .3s cubic-bezier(.645, .045, .355, 1);
	backface-visibility: hidden;
	pointer-events: none;
}
.floating-contact-wrap.active .floating-contact-box {
	opacity: 1;
	transform: scale(1);
	pointer-events: auto;
}
.floating-contact-heading {
	background: var(--cuh-ink);
	border-radius: 6px 6px 0 0;
	color: #fff;
}
.floating-contact-heading h2 { color: #fff; }
.floating-contact-heading p { color: rgba(255, 255, 255, .72); font-size: .875rem; }
.floating-contact-note { font-size: .8125rem; color: var(--cuh-ink-soft); text-align: center; margin-top: .85rem; }

@media (max-width: 767.98px) {
	.floating-contact-wrap { right: 34px; bottom: 44px; }
	.floating-contact-box { width: min(340px, calc(100vw - 48px)); }
}

/* ====================================================================== */
/* Services page                                                          */
/* ====================================================================== */

.services-columns { --services-col-2: #2f3a3d; --services-col-3: #8a4a12; }
.services-column { background-color: var(--cuh-ink); }
.services-column-2 { background-color: var(--services-col-2); }
.services-column-3 { background-color: var(--services-col-3); }
.services-column h3 { color: #fff; letter-spacing: .04em; }
.services-column p { color: rgba(255, 255, 255, .78); line-height: 1.8; }
.services-column .bg-icon { color: rgba(255, 255, 255, .07); }
.service-more { color: var(--cuh-orange-deep); text-decoration: none; }
.service-more i { transition: transform .18s ease; display: inline-block; }
.service-more:hover i { transform: translateX(4px); }

.pricing-extended { background: var(--cnvs-themecolor-light); border: 1px solid var(--cuh-line); border-radius: .5rem; }
.pricing-extended .pricing-features li { font-size: .9375rem; color: var(--cuh-ink-soft); }
.pricing-extended .pricing-features i { color: var(--cuh-orange); }
.pricing-extended .pricing-action-area { background: #fff; border-left: 1px solid var(--cuh-line); padding: 1.75rem; }
.pricing-extended .pricing-price { font-size: 1.75rem; font-weight: 700; color: var(--cuh-ink); margin-bottom: 1rem; }
.pricing-extended .pricing-meta { font-size: .75rem; text-transform: uppercase; letter-spacing: .1em; color: var(--cuh-ink-soft); }

.button-full { background-color: var(--cuh-ink); color: #fff; font-size: 1.15rem; }
.button-full:hover { background-color: var(--cuh-orange); color: #21160a; }

/* ====================================================================== */
/* Contact page                                                           */
/* ====================================================================== */

.contact-form-panel {
	background: var(--cnvs-themecolor-light);
	border: 1px solid var(--cuh-line);
	border-radius: .5rem;
	padding: 2rem;
	height: 100%;
}
.contact-form-panel label { font-size: .8125rem; font-weight: 600; color: var(--cuh-ink-soft); margin-bottom: .35rem; }
.contact-form-panel .form-control,
.contact-form-panel .form-select { border-color: var(--cuh-line); background-color: #fff; }
.contact-form-panel .form-control:focus,
.contact-form-panel .form-select:focus { border-color: var(--cuh-orange); box-shadow: 0 0 0 .2rem rgba(255, 143, 0, .18); }
.contact-form-panel .form-control.is-invalid { border-color: #b3261e; }
.form-note { font-size: .8125rem; color: var(--cuh-ink-soft); }

/* The result line every form writes into once Web3Forms has answered. */
/* A confirmation has to be unmissable, so it is a boxed, bold notice sitting
   directly above the button that was just pressed - not a quiet line under it. */
.form-status {
	font-size: .875rem;
	line-height: 1.5;
	font-weight: 700;
	padding: .75rem .9rem;
	border-radius: .4rem;
	border: 1px solid var(--cuh-orange);
	background: #fff;
}
.form-status.is-success { border-color: var(--cuh-orange); color: var(--cuh-ink); }
/* A failure stays red: orange is the house colour and would read as success. */
.form-status.is-error { border-color: #b3261e; color: #7f2018; }
.info-close-status { background: rgba(255, 255, 255, .9); text-align: left; }

/* Turnstile renders a fixed 300px widget; keep it from pushing the panel wide
   on a narrow phone. */
.cf-turnstile { max-width: 100%; overflow: hidden; }

.contact-map {
	border-radius: .5rem;
	overflow: hidden;
	border: 1px solid var(--cuh-line);
	min-height: 420px;
}
/* The iframe is a replaced element, so neither a percentage height nor
   flex-grow filled the box reliably - it stopped 73px short of the form panel
   beside it. Absolute positioning against the container always fills it. */
/* Canvas runs fitVids over the page and wraps every iframe in a 16:9 ratio
   box at runtime. That caught the Google Maps embed, which is not a video,
   and pinned it to 625px - 73px short of the form panel beside it. The
   wrapper is neutralised here so the iframe fills the container instead. */
.contact-map { position: relative; }
.contact-map .fluid-width-video-wrapper,
.contact-map .ratio {
	position: static !important;
	padding: 0 !important;
	height: 100%;
	width: 100%;
}
.contact-map .ratio::before { display: none; }
.contact-map iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block; }

.contact-info-box { background: var(--cnvs-themecolor-light); border-radius: .5rem; height: 100%; }

/* Canvas hangs the icon 2rem above an .fbox-bg.fbox-center card and gives it a
   body-coloured chip so it reads as punching through the top edge. .fbox-plain
   removes that chip, which left the icon floating in the gap above the card
   with nothing tying it to the box. Brought inside instead. */
.contact-info-box.fbox-bg.fbox-center {
	margin-top: 0;
	padding: 1.75rem 1.25rem;
	border-color: var(--cuh-line);
}
.contact-info-box.fbox-bg.fbox-center .fbox-icon {
	margin-top: 0;
	margin-bottom: .9rem;
	background-color: transparent;
}
.contact-info-box .fbox-icon i { font-size: 1.5rem; color: var(--cuh-orange); }
.contact-info-box h3 { font-size: 1rem; font-weight: 600; color: var(--cuh-ink); }
.contact-info-box .subtitle { display: block; margin-top: .35rem; font-size: .875rem; font-weight: 400; color: var(--cuh-ink-soft); }
.contact-info-box .subtitle a { color: var(--cuh-orange-deep); text-decoration: none; }

/* ====================================================================== */
/* Mobile menu                                                            */
/* ====================================================================== */

/* The trigger is one fixed-size element, so toggling it cannot nudge the
   logo. Canvas animates the bars into an X via .primary-menu-trigger-active. */
.primary-menu-trigger .cnvs-hamburger {
	--cnvs-hamburger-size: 22px;
	--cnvs-hamburger-width: 2px;
	width: 22px;
	height: 22px;
	padding: 0;
	border: 0;
	background: none;
}
.primary-menu-trigger .cnvs-hamburger-inner,
.primary-menu-trigger .cnvs-hamburger-inner::before,
.primary-menu-trigger .cnvs-hamburger-inner::after {
	background-color: var(--cuh-ink);
	border-radius: 2px;
}

/* Balance: browse links left, About/Contact right, logo dead centre between
   them. The two navs are given the same basis so the logo cannot drift. */
@media (min-width: 992px) {
	.primary-menu { flex: 1 1 0; }
	.secondary-menu { flex: 0 1 auto; }
	.secondary-menu .menu-container { justify-content: flex-end; }
	#header .header-row { position: relative; }
	#logo { flex: 0 0 auto; }
}

@media (max-width: 991.98px) {
	#header-wrap { position: relative; }

	/* Full width of the screen, overlaying the page, sliding open.

	   Anchored to #header-wrap, not to .container. Canvas makes .container
	   position:relative, so left/right would otherwise resolve against the
	   padded container and the panel would start inset - and 100vw on top of
	   that pushed it past the right edge, which is the gap that appeared
	   below 400px. Neutralising the container's positioning lets left/right
	   do the work, with no viewport units involved. */
	#header .container,
	#header .header-row { position: static; }
	body:not(.is-expanded-menu) .primary-menu {
		position: absolute;
		top: 100%;
		left: 0;
		right: 0;
		width: auto;
		z-index: 399;
		background: #fff;
		border-top: 2px solid var(--cuh-orange);
		box-shadow: 0 18px 32px rgba(28, 26, 23, .16);
		max-height: calc(100vh - 100%);
		overflow-y: auto;
		overflow-x: hidden;

		opacity: 0;
		transform: translateY(-8px);
		transition: opacity .22s ease, transform .22s ease;
	}
	body.primary-menu-open:not(.is-expanded-menu) .primary-menu {
		opacity: 1;
		transform: translateY(0);
	}

	.primary-menu .menu-container { display: block; padding: .5rem 0 1rem; }
	.cuh-mobile { display: block; }
	#header-wrap #logo img { height: 62px; }
}

/* -------------------------------------------------------------- accordion */
/* Three levels, each set further in than the last. Nothing is bold and
   nothing is uppercased - mixing the two was what made the levels read as a
   jumble rather than a hierarchy. Weight and indent carry the structure
   instead, and the product group sits on its own tinted panel so it is
   obvious where one category ends and the next parent begins. */
.cuh-mobile-nav { display: block; padding: .25rem 1.25rem 0; }
/* The foot of the open menu.
   Canvas animates the list open by putting an inline max-height on it, sized
   from the content it measured - so any padding added inside the list is
   simply clipped off and never seen. The gap under the last row has to come
   from the list's margin, which sits outside that clamp. It was 16px of margin
   on top of 16px of clipped-then-not padding, which read as 35px of blank
   under the number. One 10px margin instead. */
@media (max-width: 991.98px) {
	#header .primary-menu > .menu-container {
		padding-bottom: 0;
		margin-bottom: 10px;
	}
}
.cuh-acc-link, .cuh-acc-head { min-width: 0; overflow-wrap: anywhere; }
.cuh-acc-head > span { min-width: 0; }

.cuh-acc-link,
.cuh-acc-head {
	font-family: var(--cnvs-body-font);
	font-weight: 400;
	letter-spacing: 0;
	text-transform: none;
}

/* Level 1 - top-level destinations. */
.cuh-acc-link-top,
.cuh-mobile-nav > .cuh-acc > .cuh-acc-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	width: 100%;
	padding: .95rem .25rem;
	font-size: 1rem;
	color: var(--cuh-ink);
	text-decoration: none;
	background: none;
	border: 0;
	border-bottom: 1px solid var(--cuh-line);
	text-align: left;
	cursor: pointer;
}
.cuh-acc-link-top:hover,
.cuh-mobile-nav > .cuh-acc > .cuh-acc-head:hover { color: var(--cuh-orange-deep); }
/* The last row in the menu. Every row here is space-between, which on this
   one left the icon marooned at the far left with the number at the far
   right and a hand-span of nothing between them. Naming what the icon
   means fills that space with the reason to use it, and the number itself
   goes up a size, because it is the thing being offered rather than a
   label. */
.cuh-acc-link-phone { color: var(--cuh-orange-deep); }
.cuh-acc-phone-label {
	display: inline-flex;
	align-items: center;
	gap: .45rem;
}
.cuh-acc-phone-number {
	font-size: 1.125rem;
	font-weight: 600;
	letter-spacing: -.01em;
}

.cuh-acc-head i { font-size: .75rem; color: var(--cuh-ink-soft); transition: transform .28s ease; }
.cuh-acc.is-open > .cuh-acc-head i { transform: rotate(180deg); }

/* Level 2 - categories, indented and marked with a rule down the left so the
   whole group reads as belonging to Shop. */
.cuh-acc-categories {
	padding: .25rem 0 .5rem .9rem;
	border-left: 2px solid var(--cuh-line);
	margin-left: .25rem;
}
.cuh-acc-head-cat,
.cuh-acc-link-cat {
	display: flex;
	align-items: center;
	justify-content: space-between;
	width: 100%;
	padding: .7rem .25rem;
	font-size: .9375rem;
	color: var(--cuh-ink);
	text-decoration: none;
	background: none;
	border: 0;
	border-bottom: 1px solid var(--cuh-line);
	text-align: left;
	cursor: pointer;
}
.cuh-acc-cat:last-child > .cuh-acc-head-cat { border-bottom: 0; }
.cuh-acc-head-cat:hover, .cuh-acc-link-cat:hover { color: var(--cuh-orange-deep); }

/* Level 3 - the products, on their own tinted panel. */
.cuh-acc-products {
	margin: .1rem 0 .75rem .5rem;
	padding: .35rem .9rem;
	background: var(--cnvs-themecolor-light);
	border-radius: .35rem;
}
.cuh-acc-products .cuh-acc-link {
	display: block;
	padding: .6rem .1rem;
	font-size: .875rem;
	color: var(--cuh-ink-soft);
	text-decoration: none;
	border-bottom: 1px solid rgba(28, 26, 23, .07);
}
.cuh-acc-products .cuh-acc-link:last-child { border-bottom: 0; }
.cuh-acc-products .cuh-acc-link:hover { color: var(--cuh-orange-deep); }

/* Height is animated from JS, which measures the panel and then releases it
   to auto so nested panels can grow without being clipped. */
.cuh-acc-panel {
	height: 0;
	overflow: hidden;
	transition: height .3s cubic-bezier(.4, 0, .2, 1);
}
.cuh-acc-panel.is-static { height: auto; }

@media (prefers-reduced-motion: reduce) {
	.cuh-acc-panel, .cuh-acc-head i,
	body:not(.is-expanded-menu) .primary-menu { transition: none; }
}

/* ====================================================================== */
/* Small-screen gutters                                                   */
/* ====================================================================== */

/* Canvas' gutter-* classes pull a row outwards by half the gutter: gutter-30
   gives -15px a side, gutter-40 gives -20px. Below 576px the container only
   has 12px of padding to absorb that, so every grid row hangs a few pixels
   past the edge and the page gains a horizontal scroll - the "gap on the
   right". Clamping the gutter so the negative margin matches the container
   padding removes it at the source, rather than hiding it with overflow. */
@media (max-width: 575.98px) {
	[class*="gutter-"] { --cnvs-custom-gutter: 24px; }
}

/* ====================================================================== */
/* Navigation casing                                                      */
/* ====================================================================== */

/* The furniture demo uppercases the primary menu with a 1px letter-spacing.
   The mobile menu reads as Title Case, so the desktop bar matches it rather
   than shouting a different way on the same site. */
#header {
	--cnvs-primary-menu-tt: none;
	--cnvs-primary-menu-ls: 0;
	--cnvs-primary-menu-font-size: 0.875rem;
	--cnvs-primary-menu-font-weight: 500;

	/* Canvas drives submenu weight from these, defaulting to 600 with a 700
	   hover - that is the bold in the Shop dropdown. Weight is not what should
	   separate a category from its products. */
	--cnvs-primary-menu-submenu-font-weight: 400;
	--cnvs-primary-menu-submenu-hover-font-weight: 400;
	--cnvs-primary-menu-submenu-tt: none;

	/* Every menu colour comes from these variables, and their hover values
	   default to --cnvs-themecolor. Since that is now our ink - the same shade
	   the links already are - hovering changed nothing visible. Pointing them
	   at the orange is what actually gives the links a hover state. */
	--cnvs-primary-menu-color: var(--cuh-ink);
	--cnvs-primary-menu-hover-color: var(--cuh-orange-deep);
	--cnvs-primary-menu-active-color: var(--cuh-orange-deep);
	--cnvs-primary-menu-submenu-color: var(--cuh-ink-soft);
	--cnvs-primary-menu-submenu-hover-color: var(--cuh-orange-deep);
	--cnvs-primary-menu-submenu-hover-bg: transparent;
}
.primary-menu .menu-link { text-transform: none; letter-spacing: 0; }
.cuh-submenu .menu-link { text-transform: none; letter-spacing: 0; }

/* col-mb-* puts padding under every column so that wrapped rows clear each
   other. Canvas never cancels the last row's, so a grid that is the final thing
   in its band leaves that padding hanging below it - 50px under the Why Choose
   Us icons, on top of the band's own 64px and the container's 48px. Pulling the
   row up by the same amount removes the trailing space and leaves the gap
   between wrapped rows untouched. Absolutely positioned rows are exempt: the
   hero cards are one, and their offset from the pagination dots is deliberate. */
.row[class*="col-mb-"]:last-child:not(.position-absolute) {
	margin-bottom: calc(var(--cnvs-col-mb, 0px) * -1);
}

/* Long unbroken strings - the email address is 260px of it - must wrap rather
   than widen their column and take the whole page with them. */
#footer a[href^="mailto:"],
#footer .footer-tips li,
.contact-info-box .subtitle,
.floating-contact-note { overflow-wrap: anywhere; }

/* ====================================================================== */
/* Hero slider arrows                                                     */
/* ====================================================================== */

/* Matching the Sabai Cruise hero: a 50px white disc inset from each edge,
   dark chevron, filling with brand colour on hover. */
/* ----------------------------------------------------------------------
   Hero slider arrows - taken from the slider on sabaicruise.com/new/.

   Measured off that page: a 54px button with no background and no CSS
   border. The whole control is drawn inside the SVG - a Phosphor duotone
   caret-circle, where the soft disc is a circle filled with currentColor at
   0.2 opacity, the ring is the same circle stroked at 12, and the chevron is
   a polyline. Everything uses currentColor, so the colour property is the
   only thing to set: theirs is the brand amber, ours is the orange. Inset
   30px, vertically centred, transition transform .3s / color .2s.
   ---------------------------------------------------------------------- */
#slider .slider-arrow-left,
#slider .slider-arrow-right {
	position: absolute;
	top: 50%;
	margin: 0;
	padding: 0;
	width: 70px;
	height: 70px;
	border: 0;
	border-radius: 0;
	/* furniture.css forces slider arrows transparent, which suits these. */
	background: none !important;
	color: var(--cuh-orange);
	cursor: pointer;
	z-index: 10;
	display: block;
	transition: transform .3s ease, color .2s ease;
}
#slider .slider-arrow-left  { left: 30px;  right: auto; transform: translateY(-50%); }
#slider .slider-arrow-right { right: 30px; left: auto;  transform: translateY(-50%); }

#slider .slider-arrow-left svg,
#slider .slider-arrow-right svg { display: block; width: 100%; height: 100%; }

#slider .slider-arrow-left:hover,
#slider .slider-arrow-right:hover,
#slider .slider-arrow-left:focus-visible,
#slider .slider-arrow-right:focus-visible { color: #fff; }
#slider .slider-arrow-left:hover  { transform: translateY(-50%) scale(1.08); }
#slider .slider-arrow-right:hover { transform: translateY(-50%) scale(1.08); }

#slider .slider-arrow-left::after,
#slider .slider-arrow-right::after { content: none; }

@media (max-width: 767.98px) {
	#slider .slider-arrow-left,
	#slider .slider-arrow-right { width: 55px; height: 55px; }
	#slider .slider-arrow-left  { left: 14px; }
	#slider .slider-arrow-right { right: 14px; }
}

/* Three equal cards on one row. Bootstrap's row negative margins plus
   col-mb-30 were pushing the first card off the left edge and the third past
   the right, which is what dropped one onto its own line. A plain flex row
   with a gap removes all of that arithmetic. */
/* The cards sit above the pagination dots, not on top of them.
   Swiper puts .swiper-pagination 20px off the slider base and it is 16px
   tall, so clearing it needs 20 + 16 + 10 = 46px of bottom offset for a 10px
   gap. The selector carries #slider so it beats the mb-3 utility class on the
   element, which was holding it at 16px and causing the overlap. */
#slider .hero-cards {
	display: flex;
	flex-wrap: nowrap;
	gap: 1rem;
	width: 100%;
	margin: 0 0 46px;
}
.hero-cards > [class*="col-"] {
	flex: 1 1 0;
	width: auto;
	max-width: none;
	min-width: 0;
	padding: 0;
	margin: 0;
}

/* ====================================================================== */
/* Main menu dropdowns                                                    */
/* ====================================================================== */

/* Every dropdown in the main menu is the same narrow panel. Shop used to be a
   full-width mega-menu, which is the right shape for a catalogue of several
   categories and looked absurd once it was down to one: a 1400px sheet holding
   a single column. The category is now a heading inside the panel with its
   products beneath it, so a second category adds a second group rather than
   changing the shape of the menu. */
@media (min-width: 992px) {
	.cuh-submenu { --cnvs-primary-menu-submenu-width: 264px; }
	/* Canvas zeroes submenu padding at .is-expanded-menu .sub-menu-container,
	   which outranks a bare class. Equal above and below, inside the edge. */
	.is-expanded-menu #header .primary-menu .cuh-submenu { padding: .5rem 0; }
	/* The logo overhangs the header on z-index 5. An open panel has to sit
	   over it, or the second level slides underneath the logo card. */
	.is-expanded-menu #header .primary-menu .menu-item > .cuh-submenu { z-index: 600; }
	.is-expanded-menu .cuh-submenu .menu-link { white-space: normal; line-height: 1.45; }

	/* Canvas puts 10px above and below every submenu link. On the first item
	   that opened a 29px trough between All Products and the group heading
	   under it. One value for every row instead, so the list reads evenly and
	   the panel's own padding measures the same at the top as at the bottom. */
	.is-expanded-menu #header .primary-menu .cuh-submenu .menu-item > .menu-link {
		padding-top: .3rem;
		padding-bottom: .3rem;
	}

	/* The group label. Weight stays at 500 - the size, the letter-spacing and
	   the rule above it carry the hierarchy, not the weight. */
	.cuh-submenu .cuh-menu-group { margin-top: .35rem; border-top: 1px solid var(--cuh-line); padding-top: .35rem; }
	.is-expanded-menu .primary-menu .cuh-submenu .cuh-menu-group > .menu-link {
		--cnvs-primary-menu-submenu-font-weight: 500;
		--cnvs-primary-menu-submenu-hover-font-weight: 500;
		font-weight: 500 !important;
		font-size: .75rem;
		letter-spacing: .07em;
		text-transform: uppercase;
		color: var(--cuh-ink);
	}
	.is-expanded-menu .primary-menu .cuh-submenu .cuh-menu-group > .menu-link:hover { color: var(--cuh-orange-deep); }

	/* Products under the label, set in so the grouping reads at a glance
	   without a second flyout the visitor has to go looking for. */
	.is-expanded-menu #header .primary-menu .cuh-submenu .cuh-menu-child > .menu-link {
		padding-left: 1.85rem;
		font-size: .8125rem;
		color: var(--cuh-ink-soft);
	}
	.is-expanded-menu #header .primary-menu .cuh-submenu .cuh-menu-child > .menu-link:hover { color: var(--cuh-orange-deep); }

	/* A chevron beside the category heading would promise a flyout that is not
	   there. Items that really do open one - .cuh-has-children - keep theirs,
	   and Canvas rotates it to point right at the panel it opens. */
	.cuh-submenu .cuh-menu-group > .menu-link div > i.sub-menu-indicator,
	.cuh-submenu .cuh-menu-child > .menu-link div > i.sub-menu-indicator { display: none !important; }
}

/* ====================================================================== */
/* Information pages                                                      */
/* ====================================================================== */

/* Treatment from demo-fashion-store-about.html: a full-bleed hero with the
   title over a darkened photograph, a small-caps label above it and a rule
   under it. The demo's camel-and-sand palette and its Cormorant display face
   are not carried over - this uses our own colours and type. */
.info-hero {
	position: relative;
	min-height: 52vh;
	display: flex;
	align-items: flex-end;
	overflow: hidden;
}
.info-hero-image {
	position: absolute;
	inset: 0;
	background-size: cover;
	background-position: center;
}
.info-hero-overlay {
	position: absolute;
	inset: 0;
	background: linear-gradient(to top, rgba(28, 26, 23, .82) 0%, rgba(28, 26, 23, .25) 55%, rgba(28, 26, 23, .1) 100%);
}
.info-hero-content { position: relative; z-index: 2; color: #fff; padding: 3.5rem 0; }
.info-hero-content h1 {
	color: #fff;
	margin: 0;
	font-size: clamp(1.9rem, 4vw, 3.2rem);
	line-height: 1.15;
	font-weight: 500;
	max-width: 20ch;
}


/* Measured off the demo: 40 x 2, 1rem above and below. */
.info-divider {
	width: 40px;
	height: 2px;
	background: var(--cuh-orange);
	margin: 1rem 0;
}
.info-divider.mx-auto { margin-left: auto; margin-right: auto; }

/* The body is the WordPress copy dropped straight in, so the rules here have
   to cover whatever headings and lists it happens to contain. */
.info-body { color: var(--cuh-ink-soft); line-height: 1.85; font-size: 1rem; }
.info-body h2 { font-size: 1.5rem; color: var(--cuh-ink); margin: 2.5rem 0 1rem; line-height: 1.3; }
.info-body h3 { font-size: 1.15rem; color: var(--cuh-ink); margin: 2rem 0 .75rem; }
.info-body h4 { font-size: 1rem; color: var(--cuh-ink); margin: 1.5rem 0 .5rem; }
.info-body p { margin-bottom: 1.25rem; }
.info-body ul, .info-body ol { margin: 0 0 1.5rem; padding-left: 1.25rem; }
.info-body li { margin-bottom: .5rem; }
.info-body strong { color: var(--cuh-ink); }
.info-body a { color: var(--cuh-orange-deep); }
.info-body a:hover { color: var(--cuh-ink); }
.info-body img { max-width: 100%; height: auto; border-radius: .5rem; }
.info-body blockquote {
	margin: 2rem 0;
	padding-left: 1.75rem;
	border-left: 3px solid var(--cuh-orange);
	font-size: 1.05rem;
	color: var(--cuh-ink);
}

/* Cards to the sibling pages - the demo's value-card treatment. */
.info-card {
	display: flex;
	flex-direction: column;
	height: 100%;
	padding-top: 1.25rem;
	border-top: 2px solid var(--cuh-orange);
	text-decoration: none !important;
	transition: border-color .18s ease;
}
.info-card:hover { border-top-color: var(--cuh-ink); }
.info-card-label {
	font-size: .6875rem;
	font-weight: 600;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--cuh-ink-soft);
	margin-bottom: .4rem;
}
.info-card-title { font-size: 1.05rem; font-weight: 500; color: var(--cuh-ink); line-height: 1.35; flex: 1; }
.info-card-more { margin-top: .75rem; font-size: .8125rem; font-weight: 600; color: var(--cuh-orange-deep); }
.info-card-more i { transition: transform .18s ease; display: inline-block; }
.info-card:hover .info-card-more i { transform: translateX(4px); }

@media (max-width: 767.98px) {
	.info-hero { min-height: 38vh; }
	.info-hero-content { padding: 2.5rem 0; }
}

/* ====================================================================== */
/* Information page sections                                              */
/* ====================================================================== */

.info-band-heading { font-size: clamp(1.6rem, 3vw, 2.4rem); font-weight: 500; line-height: 1.2; margin: 0; }
.info-band-intro {
	color: var(--cuh-ink-soft);
	max-width: 620px;
	margin: 0 auto;
	font-size: .9375rem;
	line-height: 1.85;
}

/* Pullquote from the demo's brand story. */
.info-pullquote {
	font-family: var(--cnvs-primary-font);
	font-size: clamp(1.2rem, 2.2vw, 1.7rem);
	font-weight: 500;
	font-style: italic;
	line-height: 1.5;
	color: var(--cuh-ink);
	border-left: 3px solid var(--cuh-orange);
	padding-left: 1.75rem;
	margin: 2.5rem 0 .75rem;
}
.info-pullquote-by { font-size: .8rem; color: var(--cuh-ink-soft); margin: 0; padding-left: 1.75rem; }

/* Story band.
   The text column carries the page’s opening and its first section now, so on
   most of these pages it runs taller than the pictures beside it - by 963px on
   the laminate page. Centring the row floated the stack in a lake of white, so
   the row is top-aligned: the pictures start level with the heading and the
   column simply ends where they do. There is no background on it, so a short
   column reads as the text running on beside the last picture, not as a gap. */

/* Story column: clamped, with a Read more.

   The page's opening and its first section together run to 1473px on the
   laminate page against a 510px stack of photographs. Printed in full that is
   a wall of text with pictures stranded at the top of it; hidden at the foot
   of the page it is a dump. So the column is cut to the height of the pictures
   beside it and opens from there.

   The height is set by script from the art column's real height rather than
   guessed here, because the stack is a different height on different pages.
   This value only applies before the script runs and if it never does. */
.info-story-prose {
	position: relative;
	overflow: hidden;
	transition: height .45s cubic-bezier(.22, .77, .3, 1);
}

/* Released to auto once open, so a long column is never clipped by a height
   measured before the images finished loading. */
.info-story-prose.is-open { height: auto; overflow: visible; }

/* The last line fades out rather than being guillotined mid-word.
   A mask rather than a gradient overlay: an overlay has to be painted in the
   band’s own colour, and the moment the band is not the colour the gradient
   ends in - tinted, or a body background that is not pure white - it shows as
   a pale rectangle across the text. A mask fades the words themselves and is
   right against any ground. */
.info-story-prose.is-clamped {
	-webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 5.5rem), transparent 100%);
	mask-image: linear-gradient(to bottom, #000 calc(100% - 5.5rem), transparent 100%);
}

.info-read-more {
	display: inline-flex;
	align-items: center;
	gap: .45rem;
	margin-top: 1.1rem;
	padding: 0;
	border: 0;
	background: none;
	font-family: inherit;
	font-size: .9375rem;
	font-weight: 600;
	color: var(--cuh-orange-hover);
	cursor: pointer;
	transition: color .18s ease;
}
.info-read-more:hover { color: var(--cuh-ink); }
.info-read-more i {
	font-size: .8em;
	transition: transform .3s ease;
}
.info-read-more[aria-expanded="true"] i { transform: rotate(180deg); }

@media (prefers-reduced-motion: reduce) {
	.info-story-prose { transition: none; }
	.info-read-more i { transition: none; }
}

/* Story image stack. */
.info-figure img { width: 100%; height: auto; display: block; border-radius: .5rem; object-fit: cover; }
.info-figure-square img { aspect-ratio: 1; }
.info-figure-wide img { aspect-ratio: 16 / 9; }

/* Values grid - each card takes its own accent on the top rule, which is what
   gives the row the colour the demo has without tinting whole columns. */
.info-values-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
	gap: 2rem;
}
.info-value-card { border-top: 2px solid var(--cuh-orange); padding-top: 1.5rem; }
/* The card body carries the section’s own paragraphs now, not one line of
   summary, so it needs paragraph spacing and a last-child that does not push
   the card taller than its neighbours. */
.info-value-body p { margin-bottom: .85rem; }
.info-value-body p:last-child { margin-bottom: 0; }
.info-value-card h3 { font-size: 1.15rem; font-weight: 500; color: var(--cuh-ink); margin-bottom: .75rem; }
.info-value-card p { font-size: .875rem; line-height: 1.8; color: var(--cuh-ink-soft); margin: 0; }

/* Ticked bullet list. */
.info-checklist { list-style: none; padding: 0; margin: 0 0 1.75rem; }
.info-checklist li {
	display: flex;
	gap: .75rem;
	padding: .6rem 0;
	border-bottom: 1px solid var(--cuh-line);
	font-size: .875rem;
	line-height: 1.7;
	color: var(--cuh-ink-soft);
}
.info-checklist li:last-child { border-bottom: 0; }
.info-checklist i { color: var(--cuh-orange); flex-shrink: 0; margin-top: .25rem; }

/* Stat tiles. */
.info-stat { text-align: center; padding: 1.75rem 1rem; background: var(--cnvs-themecolor-light); height: 100%; border-radius: .5rem; }
.info-stat-num {
	display: block;
	font-family: var(--cnvs-primary-font);
	font-size: clamp(1.6rem, 3vw, 2.2rem);
	font-weight: 600;
	line-height: 1;
	color: var(--cuh-orange-deep);
	margin-bottom: .5rem;
}
.info-stat p { font-size: .8125rem; line-height: 1.6; color: var(--cuh-ink-soft); margin: 0; }

/* Manufacturing partners. */
.info-partner { background: #fff; padding: 2rem; height: 100%; border-radius: .5rem; }
.info-partner h3 { font-size: 1.1rem; font-weight: 500; color: var(--cuh-ink); margin-bottom: .4rem; }
.info-partner-place {
	display: block;
	margin-bottom: .85rem;
	font-size: .7rem;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--cuh-orange-deep);
}
.info-partner p { font-size: .875rem; line-height: 1.8; color: var(--cuh-ink-soft); margin: 0; }

@media (max-width: 767.98px) {
	.info-pullquote { padding-left: 1.25rem; margin-top: 2rem; }
	.info-pullquote-by { padding-left: 1.25rem; }
	.info-values-grid { gap: 1.5rem; }
}

/* Band rhythm, matching the demo: white and tinted bands alternate, each with
   its own vertical padding rather than relying on utility margins. */
/* Canvas gives .section a 4rem margin of its own. Left in place it stacks on
   top of this padding, so every band boundary came to 208px of dead white
   (72 bottom + 64 margin + 72 top). The demo runs margin:0 with 4rem padding
   and no gap between bands at all - this matches it exactly. */
.info-section { margin: 0; padding: 4rem 0; }
/* Canvas wraps page content in .content-wrap with 80px of its own top and
   bottom padding. Every band here brings its own, so that 80px only showed
   as extra white under the hero and again above the footer. The demo runs
   the wrapper flush. */
/* A page that opens on a banner has nothing to sit below the header - the
   photograph is the top of the page. The services page grew a banner of its
   own, so it needs the same treatment the information pages have. */
.page-info .content-wrap { padding-top: 0; padding-bottom: 0; }
.page-services .content-wrap { padding-top: 0; }
.info-section.pt-0 { padding-top: 0; }
.info-section-tinted { background: var(--cnvs-themecolor-light); }
.info-detail-intro { color: var(--cuh-ink-soft); line-height: 1.85; margin-bottom: 1.25rem; font-size: .9375rem; }

/* Band 6 - the demo's press slot, carrying approvals instead. */
.info-mark {
	font-family: var(--cnvs-primary-font);
	font-size: 1.15rem;
	font-weight: 600;
	color: var(--cuh-ink-soft);
	margin: 0;
}
.info-note {
	border-left: 3px solid var(--cuh-orange);
	padding: 1.25rem 1.5rem;
	background: var(--cnvs-themecolor-light);
	height: 100%;
}
.info-note p {
	font-family: var(--cnvs-primary-font);
	font-size: 1.05rem;
	font-style: italic;
	color: var(--cuh-ink);
	margin-bottom: .75rem;
	line-height: 1.6;
}
.info-note small {
	font-size: .75rem;
	color: var(--cuh-ink-soft);
	font-weight: 600;
	letter-spacing: .06em;
	text-transform: uppercase;
}

/* Band 7 - the demo's newsletter slot, carrying the contact call. */
.info-close {
	margin: 0;
	background: var(--cnvs-themecolor-light);
	padding: 5rem 0;
	text-align: center;
}
.info-close h2 { margin-bottom: .75rem; }
.info-close p {
	color: var(--cuh-ink-soft);
	margin: 0 auto 2rem;
	max-width: 520px;
	line-height: 1.8;
}
/* The demo's inline newsletter form: field and button joined as one control. */
.info-close-form {
	max-width: 520px;
	margin: 0 auto;
	text-align: left;
}
.info-close-form button {
	display: block;
	width: 100%;
	margin-top: 1.25rem;
	padding: .95rem 1.6rem;
	border: 0;
	border-radius: .35rem;
	background: var(--cuh-ink);
	color: #fff;
	font-weight: 500;
	font-size: .9375rem;
	cursor: pointer;
	transition: background-color .18s ease, color .18s ease;
}
.info-close-form button:hover { background: var(--cuh-orange); color: #21160a; }
/* The phone line under the form: the fallback for anyone who would rather
   talk, so it is set to be read rather than tucked away in small print. */
.info-close-alt {
	/* .info-close p centres itself with auto side margins; keep them. */
	margin: 1.75rem auto 0 !important;
	max-width: none;
	text-align: center;
	font-size: 1.0625rem;
	color: var(--cuh-ink);
}
.info-close-alt a {
	color: var(--cuh-orange-deep);
	font-weight: 600;
	font-size: 1.25rem;
	white-space: nowrap;
}
.info-close-alt a:hover { color: var(--cuh-ink); }

/* The quote fields. Two across on a desktop, stacked on a phone, inside the
   same 520px measure the single field used to occupy. */
.info-close-grid {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 1rem;
	text-align: left;
}
.info-close-field label {
	display: block;
	margin-bottom: .3rem;
	font-size: .78125rem;
	font-weight: 600;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: var(--cuh-ink-soft);
}
.info-close-field label span { color: var(--cuh-orange-deep); }
.info-close-field input,
.info-close-field select {
	width: 100%;
	padding: .8rem .95rem;
	border: 1px solid var(--cuh-line);
	border-radius: .35rem;
	background: #fff;
	font-size: .9375rem;
	color: var(--cuh-ink);
}
.info-close-field input:focus,
.info-close-field select:focus { outline: 2px solid var(--cuh-orange); outline-offset: -2px; }
.info-close-field input.is-invalid,
.info-close-field select.is-invalid { border-color: #b3261e; }

@media (max-width: 575.98px) {
	.info-close-grid { grid-template-columns: minmax(0, 1fr); }
}

/* The page's spare copy, set apart from the band above it. */
.info-section-extra { border-top: 1px solid var(--cuh-line); }

@media (max-width: 767.98px) {
	.info-section { padding: 2.75rem 0; }
	.info-close { padding: 3.5rem 0; }
}

/* Related pages sit inside the closing band, so the white / tinted alternation
   the demo keeps runs unbroken to the foot of the page. */
.info-related-wrap { margin-bottom: 3.5rem; padding-bottom: 3.5rem; border-bottom: 1px solid var(--cuh-line); }
.info-related-wrap .info-card { text-align: left; }

/* The page you are on, marked in the menus it appears in. */
.primary-menu .menu-item.is-current > .menu-link,
.primary-menu .menu-item.is-current > .menu-link > div {
	color: var(--cuh-orange-deep) !important;
}
.cuh-acc-link.is-current {
	color: var(--cuh-orange-deep) !important;
	font-weight: 500;
}

/* ====================================================================== */
/* Menu hover marker                                                      */
/* ====================================================================== */

/*
 * A small orange house - the logo's, without its windows or doorway - fades in
 * beside whichever menu link the pointer is on, at every level: the top row,
 * the dropdown beneath it and the second-level flyout beneath that.
 *
 * Three measurements, kept apart because they do different jobs:
 *
 *   --cuh-house         the glyph itself
 *   --cuh-house-gap     between the house and the word it belongs to; small,
 *                       so the house reads as part of that link
 *   --cuh-house-clear   clear space to the left of the house, so it is not
 *                       butted against whatever sits before it
 *
 * The gutter is the three added together and is reserved on every link whether
 * or not the house is showing. Only opacity animates, so nothing moves as the
 * pointer travels along the menu.
 */
@media (min-width: 992px) {
	.primary-menu {
		--cuh-house: 13px;
		--cuh-house-gap: 3px;
		--cuh-house-clear: 9px;
		/* Optically centred rather than box-centred: the glyph's weight is in
		   its body with the roof above, so dead-centre reads as low. */
		--cuh-house-rise: 1px;
		--cuh-house-gutter: calc(var(--cuh-house) + var(--cuh-house-gap) + var(--cuh-house-clear));
	}

	.primary-menu .menu-link > div {
		position: relative;
		padding-left: var(--cuh-house-gutter);
	}
	.primary-menu .menu-link > div::before {
		content: "";
		position: absolute;
		left: var(--cuh-house-clear);
		top: 50%;
		width: var(--cuh-house);
		height: var(--cuh-house);
		margin-top: calc((var(--cuh-house) / -2) - var(--cuh-house-rise));
		background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23ff8f00' d='M12 2.6L.8 11.8h3v9.6h16.4v-9.6h3z'/%3E%3C/svg%3E") no-repeat center center;
		background-size: contain;
		opacity: 0;
		transition: opacity .1s ease-out;
		pointer-events: none;
	}

	/* The link actually under the pointer. */
	.primary-menu .menu-link:hover > div::before { opacity: 1; }

	/* And the page you are actually on, which keeps its house without being
	   hovered at all. Only the page itself - its section stays in the normal
	   colour, so the mark says "you are here" rather than "this branch is
	   open", which is what the hover already says. */
	.primary-menu .menu-item.is-current > .menu-link > div::before { opacity: 1; }

	/* And the top-level item whose panel is open, so the branch you came in
	   through stays marked while you move down it. Deliberately only the top
	   one: an :hover on every ancestor would light the whole chain, so a row
	   that opens a second level goes dark once the pointer moves into it. */
	.primary-menu .menu-container > .menu-item:hover > .menu-link > div::before { opacity: 1; }

	/* Top row: the gutter opens the space on the left of each item, and this
	   keeps the item before it from running into that space. */
	.primary-menu .menu-container > .menu-item > .menu-link {
		padding-left: 0;
		padding-right: .6rem;
	}

	/* Dropdown rows sit a little further along than they did, with the house
	   tucked in against the text rather than floating between the two. */
	.is-expanded-menu #header .primary-menu .cuh-submenu .menu-item > .menu-link { padding-left: .35rem; }
	.primary-menu .cuh-submenu { --cuh-house-rise: 2px; }
	.is-expanded-menu #header .primary-menu .cuh-submenu .cuh-menu-child > .menu-link { padding-left: 1.25rem; }

	/* The indicator on a nested parent is positioned against the link, so it
	   stays clear of the text now that the text has moved right. */
	.primary-menu .cuh-has-children > .menu-link > div { padding-right: .9rem; }
}

/* ====================================================================== */
/* Hero slide call to action                                              */
/* ====================================================================== */

/*
 * "Browse the shop" on each slide, and its inverse on hover.
 *
 * At rest: a translucent orange panel over the photograph, a solid 2px orange
 * edge, white label. On hover the same shape in the other colour - translucent
 * white, solid white edge, orange label.
 *
 * Both states carry the same 2px border and the same fill opacity, so the
 * button neither moves nor changes weight as it flips; only the three colours
 * cross-fade. The background needs !important because Canvas paints .button
 * from --cnvs-btn-color at a specificity this cannot otherwise reach.
 */
#slider .hero-cta {
	background-color: rgba(255, 143, 0, .38) !important;
	border: 2px solid var(--cuh-orange);
	color: #fff;
	transition: background-color .32s ease, border-color .32s ease, color .32s ease;
}
#slider .hero-cta i { color: #fff; transition: color .32s ease; }

/* The hover panel: white, but thin enough to keep the photograph underneath.

   The two settings are tied together and cannot be chosen separately. Measured
   on all four slides, a #a85400 label needs the panel at .92 to clear 4.5:1 -
   at .86 it is 3.93 and at .78 it is 3.25 - so the panel could not be thinned
   at all while the label stayed that colour. Taking the label two steps deeper
   buys the transparency: at .72 the darkest orange measures about 5:1 on the
   worst of the four slides, where the deep orange would have been 2.8.

   So the panel now sits at .72 and the photograph reads through it, which is
   the point of it being white over a picture rather than a white box. */
#slider .hero-cta:hover,
#slider .hero-cta:focus-visible {
	background-color: rgba(255, 255, 255, .72) !important;
	border-color: #fff;
	color: var(--cuh-orange-darkest);
}
#slider .hero-cta:hover i,
#slider .hero-cta:focus-visible i { color: var(--cuh-orange-darkest); }

@media (prefers-reduced-motion: reduce) {
	#slider .hero-cta,
	#slider .hero-cta i { transition: none; }
}

/* ====================================================================== */
/* Scroll-in sweep                                                        */
/* ====================================================================== */

/*
 * When a row of Why Choose Us points, or the row of brand logos, scrolls into
 * view, each item lights in turn from left to right and then fades back.
 *
 * The lit state is the same one the pointer produces, so the sweep is a
 * demonstration of the hover rather than a second, unrelated effect. It runs
 * once per row per page load - a thing that re-fires every time it scrolls past
 * stops reading as a flourish and starts reading as a fault.
 *
 * The stagger is set per item as an inline --lit-delay by catalogue.js, because
 * the number of items differs between the two rows.
 */
.assurance,
.brand-cell {
	transition-delay: 0s;
}

.assurance.is-lit {
	--cnvs-themecolor: var(--cuh-orange);
	transform: translateY(-7px);
}
.assurance.is-lit .fbox-content h3,
.assurance.is-lit p { color: var(--cuh-orange-hover); }

.brand-cell.is-lit img,
.brand-cell.is-lit .brand-wordmark { filter: grayscale(0); opacity: 1; }
.brand-cell.is-lit .brand-wordmark { color: var(--cuh-orange); }

/* Nothing sweeps for anyone who has asked the system to stop moving things;
   the rows simply sit in their resting state. */
@media (prefers-reduced-motion: reduce) {
	.assurance.is-lit { transform: none; }
}

/* ====================================================================== */
/* Order basket and order form                                            */
/* ====================================================================== */

/*
 * Both live in the side panel: the basket, and the form that slides over it
 * when Send Order is pressed. One overlay, two views, so composing an order
 * never takes the visitor off the page they were reading.
 */

/* ------------------------------------------------- minimising the basket */
/* Canvas ships a close control but hides it above 768px, so on a desktop the
   only way out of the panel was to click the page behind it - which is not a
   thing anyone thinks to try. A square minus in the corner, drawn in the same
   black-and-white as the rest of the panel furniture: white face, black rule
   round it, black bar through the middle. Hovering fills it orange and keeps
   the bar black, so it lights up without the glyph disappearing into it. */
#side-panel #side-panel-trigger-close a.cart-minimise {
	display: flex;
	align-items: center;
	justify-content: center;
	position: absolute;
	z-index: 12;
	top: .75rem;
	right: 1rem;
	width: 24px;
	height: 24px;
	border: 2px solid var(--cuh-ink);
	border-radius: 3px;
	background-color: #fff;
	color: var(--cuh-ink);
	line-height: 1;
	transition: background-color .18s ease;
}
/* The bar is drawn rather than set in the icon font: at this size the font
   renders a hairline that reads grey no matter what colour it is given. Two
   solid pixels of black read as black. */
/* Two bars crossed rather than one flat one. The anchor is already positioned,
   so both sit against it and rotate about the same centre. */
#side-panel #side-panel-trigger-close a.cart-minimise::before,
#side-panel #side-panel-trigger-close a.cart-minimise::after {
	content: "";
	position: absolute;
	width: 12px;
	height: 2px;
	background-color: #000;
}
#side-panel #side-panel-trigger-close a.cart-minimise::before { transform: rotate(45deg); }
#side-panel #side-panel-trigger-close a.cart-minimise::after { transform: rotate(-45deg); }
#side-panel #side-panel-trigger-close a.cart-minimise:hover,
#side-panel #side-panel-trigger-close a.cart-minimise:focus-visible {
	background-color: var(--cuh-orange);
	border-color: var(--cuh-ink);
	color: var(--cuh-ink);
}
/* Keep the heading clear of it. */
#side-panel .top-cart-title h4,
#side-panel .order-form-head h4 { padding-right: 2.5rem; }

/* The trolley in the header warms to the brand orange on the way to the
   basket. Both the outline and the tinted body are painted from
   --cnvs-themecolor, so re-pointing that one variable moves the whole glyph
   and the transition on fill and stroke carries it. */
#top-cart a svg path,
#top-cart a svg circle {
	transition: fill .2s ease, stroke .2s ease;
}
#top-cart a:hover svg,
#top-cart a:focus-visible svg { --cnvs-themecolor: var(--cuh-orange); }

/* ---------------------------------------------------------- the basket */
/* Two rows per line: the product name runs the full width, with the remove
   control at its right, and the quantity and price sit beneath it. Squeezing
   name, stepper, price and remove into one row left the name in a column
   barely wide enough for two words. */
.cart-line {
	display: grid;
	/* The name row runs the full width bar the cross. Sharing one auto column
	   with the price meant a long price - "Priced on free quotation" - set the
	   column width and squeezed the line beneath the name into two. */
	grid-template-columns: auto minmax(0, 1fr) auto;
	grid-template-areas:
		"name   name    remove"
		"qty    price   price";
	gap: .55rem .75rem;
	align-items: center;
	padding: 1rem 0;
	border-bottom: 1px solid var(--cuh-line);
}
.cart-line:first-child { padding-top: .35rem; }
.cart-line:last-child { border-bottom: 0; }

.cart-line-main { grid-area: name; min-width: 0; }
.cart-line-name {
	display: block;
	font-size: .875rem;
	font-weight: 600;
	line-height: 1.35;
	color: var(--cuh-ink);
}
.cart-line-name:hover { color: var(--cuh-orange-hover); }
.cart-line-size {
	display: block;
	margin-top: .2rem;
	font-size: .75rem;
	line-height: 1.4;
	color: var(--cuh-ink-soft);
}

/* The stepper: one control, not two buttons and a number that happen to be
   next to each other. */
.cart-line-qty {
	grid-area: qty;
	display: inline-flex;
	align-items: stretch;
	justify-self: start;
	border: 1px solid var(--cuh-line);
	border-radius: .35rem;
	overflow: hidden;
	background: #fff;
}
.cart-line-qty button {
	width: 30px;
	border: 0;
	background: none;
	color: var(--cuh-ink-soft);
	font-size: 1rem;
	font-weight: 600;
	line-height: 1;
	cursor: pointer;
	transition: background-color .15s ease, color .15s ease;
}
.cart-line-qty button:hover {
	background: var(--cuh-orange);
	color: #21160a;
}
.cart-line-qty button:active { background: var(--cuh-orange-hover); color: #fff; }
.cart-line-qty span {
	min-width: 34px;
	padding: .35rem 0;
	text-align: center;
	font-size: .875rem;
	font-weight: 600;
	color: var(--cuh-ink);
	border-inline: 1px solid var(--cuh-line);
}

.cart-line-price {
	grid-area: price;
	justify-self: end;
	font-size: 1.0625rem;
	font-weight: 600;
	letter-spacing: -.01em;
	color: var(--cuh-ink);
	white-space: nowrap;
}

/* A line with no price still has to hold the same column, but it is a
   sentence rather than a figure - set smaller and lighter so it reads as an
   explanation and does not shout over the prices beside it. */
.cart-line-quoted {
	max-width: 8.5rem;
	font-size: .75rem;
	font-weight: 500;
	line-height: 1.35;
	text-align: right;
	white-space: normal;
	color: var(--cuh-ink-soft);
}

.cart-line-remove {
	grid-area: remove;
	justify-self: end;
	align-self: start;
	width: 26px;
	height: 26px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: none;
	font-size: 1.35rem;
	line-height: 1;
	color: var(--cuh-ink-soft);
	cursor: pointer;
	transition: color .15s ease;
}
.cart-line-remove:hover,
.cart-line-remove:focus-visible { color: var(--cuh-orange); }

.cart-total {
	display: flex;
	justify-content: space-between;
	align-items: baseline;
	/* 1rem each side is the panel's own inset, carried on the margin rather
	   than the padding so the rule above the total starts and ends with the
	   text instead of running out to the panel edges. */
	margin: 1.1rem 1rem 0;
	padding: 1.1rem 0 1.25rem;
	border-top: 2px solid var(--cuh-ink);
	font-size: .9375rem;
}
.cart-total strong { font-size: 1.35rem; letter-spacing: -.01em; }
/* Same 1rem inset as the total it qualifies. When there is no total above it
   the rule comes back, so the note is still separated from the lines. */
.cart-total-note {
	margin: 0 1rem 1.25rem;
	font-size: .75rem;
	line-height: 1.5;
	color: var(--cuh-ink-soft);
}
.cart-total.d-none + .cart-total-note {
	margin-top: 1.1rem;
	padding-top: 1.1rem;
	border-top: 2px solid var(--cuh-ink);
}

/* Send Order: the panel's one committing action, so it fills with brand
   colour rather than the default dark hover. */
[data-cart-send]:hover:not(:disabled),
[data-cart-send]:focus-visible:not(:disabled) {
	background-color: var(--cuh-orange) !important;
	border-color: var(--cuh-orange) !important;
	color: #21160a !important;
}
[data-cart-send]:disabled { opacity: .45; cursor: not-allowed; }

/* ------------------------------------------------------ the order form */
.order-form {
	display: flex;
	flex-direction: column;
	height: 100%;
	overflow-y: auto;
}
/* The panel insets every block by 1rem. The form was the exception - it sat
   against both edges, button included - because the padding lived on the
   blocks around it rather than on the overlay. */
#order-form {
	padding: 1rem 1rem 1.5rem;
}
.order-grid + .order-summary { margin-top: 0; }
.order-form-head { display: flex; align-items: center; gap: .6rem; }
.order-back {
	border: 0;
	background: none;
	padding: 0;
	font-size: 1.05rem;
	line-height: 1;
	color: var(--cuh-ink-soft);
	cursor: pointer;
}
.order-back:hover { color: var(--cuh-orange-hover); }

.order-summary {
	margin-bottom: 1.25rem;
	padding: .9rem 1rem;
	border-radius: .4rem;
	background: var(--cnvs-themecolor-light);
}
.order-summary h5 {
	margin: 0 0 .6rem;
	font-size: .6875rem;
	font-weight: 600;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--cuh-ink-soft);
}
.order-summary-line {
	display: flex;
	justify-content: space-between;
	gap: .75rem;
	font-size: .8125rem;
	line-height: 1.45;
	padding: .2rem 0;
}
.order-summary-line small { display: block; color: var(--cuh-ink-soft); }
.order-summary-line em {
	flex: none;
	font-style: normal;
	font-size: .75rem;
	color: var(--cuh-ink-soft);
}
.order-summary-note {
	margin: .55rem 0 0;
	padding-top: .55rem;
	border-top: 1px solid var(--cuh-line);
	font-size: .75rem;
	line-height: 1.5;
	color: var(--cuh-ink-soft);
}
.order-summary-total {
	display: flex;
	justify-content: space-between;
	margin-top: .55rem;
	padding-top: .55rem;
	border-top: 1px solid var(--cuh-line);
	font-size: .875rem;
}

.order-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .85rem; margin-bottom: 1.25rem; }
.order-field-wide { grid-column: 1 / -1; }
.order-field label {
	display: block;
	margin-bottom: .3rem;
	font-size: .75rem;
	font-weight: 600;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: var(--cuh-ink-soft);
}
.order-field label span { color: var(--cuh-orange-deep); }
.order-field input,
.order-field textarea {
	width: 100%;
	padding: .65rem .8rem;
	border: 1px solid var(--cuh-line);
	border-radius: .35rem;
	background: #fff;
	font-size: .9375rem;
	font-family: inherit;
	color: var(--cuh-ink);
}
.order-field input:focus,
.order-field textarea:focus { outline: 2px solid var(--cuh-orange); outline-offset: -2px; }
.order-field input.is-invalid,
.order-field textarea.is-invalid { border-color: #b3261e; }

.order-foot { margin: .9rem 0 0; font-size: .78125rem; line-height: 1.5; color: var(--cuh-ink-soft); }

@media (max-width: 400px) {
	.order-grid { grid-template-columns: minmax(0, 1fr); }
}

/* The two panel views are switched with the hidden attribute, but the cart
   carries Bootstrap's .d-flex, which sets display:flex !important and wins.
   Inside the panel, hidden means hidden. */
#side-panel [hidden] { display: none !important; }

/* The quick-question subject. Sits between the fields above and the message
   box below, so it borrows their border and spacing rather than looking
   like a control from somewhere else. */
.quick-topic {
	border: 1px solid var(--cuh-line);
	border-radius: .3rem;
	padding: .6rem .75rem .7rem;
}
.quick-topic legend {
	float: none;
	width: auto;
	margin: 0 0 .45rem;
	padding: 0;
	font-size: .6875rem;
	font-weight: 600;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--cuh-ink-soft);
}
.quick-topic label {
	display: flex;
	align-items: center;
	gap: .5rem;
	margin: 0;
	/* The whole row is the target, not just the box - 44px is the smallest
	   thing a thumb hits reliably. */
	min-height: 44px;
	padding: .2rem 0;
	font-size: .875rem;
	line-height: 1.3;
	color: var(--cuh-ink);
	cursor: pointer;
}
.quick-topic input {
	flex: 0 0 auto;
	width: 20px;
	height: 20px;
	accent-color: var(--cuh-orange);
	cursor: pointer;
}

/* ====================================================================== */
/* Phones                                                                 */
/* ====================================================================== */

/* The menu that was there all along.
   Below the expanded-menu breakpoint the primary menu is taken out of the
   flow and faded to nothing, but Canvas leaves it visible and clickable - so
   a closed menu was still an invisible 524px sheet lying over the top of the
   page, catching taps and reading out to screen readers. Take it out of the
   accessibility tree and out of the way of the pointer when it is closed.
   The visibility change is held back until the fade has finished, so opening
   and closing still animate. */
@media (max-width: 991.98px) {
	body:not(.primary-menu-open) #header .primary-menu {
		visibility: hidden;
		pointer-events: none;
		transition: opacity .22s, transform .22s, visibility 0s linear .22s;
	}
	body.primary-menu-open #header .primary-menu {
		visibility: visible;
		transition: opacity .22s, transform .22s, visibility 0s;
	}

	/* The clone reserves the height the header will need once it sticks. It is
	   sized from --cnvs-header-height, which is the desktop figure, so on a
	   phone it was holding 100px open for a 62px header - 38px of blank page
	   above everything, at every scroll position. Tell it the real number. */
	#header { --cnvs-header-height: 62px; }
	/* And hold nothing at all until the header has actually stuck. */
	#header[data-mobile-sticky="true"]:not(.sticky-header) .header-wrap-clone { display: none; }
}

/* -------------------------------------------- the product page on a phone */
/* Wide, the page is two columns: photographs down the left, and a sticky
   column on the right carrying the heading, the price, the ways of ordering
   and the detail. Stacking that as-is put every photograph above the heading,
   so a phone opened on a wall of pictures with the name of the product some
   way below them.

   The order a phone wants is the order someone reads in: what is this, what
   does it look like, what does it cost, how do I order it - and only then the
   rest of the pictures and the small print. Both columns are dissolved with
   display:contents so their children become items of one column, which can
   then be put in that order. Nothing is duplicated and the wide layout is
   untouched. */
@media (max-width: 767.98px) {
	.single-product .product > .row {
		display: flex;
		flex-direction: column;
		row-gap: 1.75rem;
		margin-left: 0;
		margin-right: 0;
	}
	.single-product .product-media,
	.single-product .product-media > .product-gallery,
	.single-product .product-desc { display: contents; }

	.single-product .product-head         { order: 1; }
	.single-product .product-gallery-lead { order: 2; }
	.single-product .product-buy          { order: 3; }
	.single-product .enquiry-panel        { order: 4; }
	.single-product .product-gallery-rest { order: 5; }
	.single-product .product-detail       { order: 6; }

	/* The gap between blocks is the row gap now, so the margins that used to
	   do that job would double it. */
	.single-product .product-head > *:last-child,
	.single-product .enquiry-panel,
	.single-product .product-detail { margin-top: 0; margin-bottom: 0; }
	.single-product .product-gallery-lead .product-gallery-shot { margin-bottom: 0; }

	/* The top of the band is set with the rest of its spacing further up.
	   Only the foot of it is a phone measurement. */
	.page-product .product-hero { padding-bottom: 2.5rem; }
	/* Bootstrap gives .row a negative top margin to cancel the gutter its
	   children add back. With the columns dissolved to display:contents
	   there are no such children, so the negative margin was left pulling
	   the heading 4px above the top of the band. */
	.single-product .product > .row { margin-top: 0; }
}

/* On a wide screen the two halves of the gallery are one run again, so the
   join between them needs the same gap as the shots inside them. */
@media (min-width: 768px) {
	.product-gallery-lead { margin-bottom: 1.5rem; }
}

/* ------------------------------------------------ the two fixed circles */
/* The message button is centred on its wrapper's bottom-right origin, so its
   centre sits at (viewport - right). The arrow is positioned by its own box,
   so its centre is at (viewport - right - half its width). Matching those two
   sums is what keeps the circles on one vertical line: 44 = 14 + 30.

   The arrow takes the bottom corner and the message sits above it - it is the
   one you would reach for, and the thumb gets there first. */
@media (max-width: 767.98px) {
	/* With no arrow on screen there is no reason for the message button to
	   hover above an empty corner, so it sits in the corner itself and
	   steps up when the arrow arrives to take the spot. Canvas puts
	   .gototop-active on the body the moment the arrow appears, which is
	   the same moment the move should happen. 44 = 14 from the floor plus
	   half the button, because the button is centred on this point. */
	.floating-contact-wrap {
		right: calc(14px + var(--fab) / 2);
		bottom: calc(14px + var(--fab) / 2);
		transition: bottom .35s cubic-bezier(.4, 0, .2, 1);
	}
	/* Cleared of the arrow by the same 14px that holds it off the floor. The
	   arrow's own size is a variable on #gotoTop, which is a sibling and so
	   out of reach from here - 42px is that value, and the two move together. */
	.gototop-active .floating-contact-wrap {
		bottom: calc(14px + 42px + 14px + var(--fab) / 2);
	}
	@media (prefers-reduced-motion: reduce) {
		.floating-contact-wrap { transition: none; }
	}
	.floating-contact-wrap + #gotoTop,
	.stretched .floating-contact-wrap + #gotoTop { right: 14px; bottom: 14px; }

	/* The box opens from the button, which is now half its own width to the
	   right of the wrapper, and it must not run off the screen. */
	.floating-contact-box { right: calc(var(--fab) / -2); width: calc(100vw - 28px); }
}

/* -------------------------------------------- product pages on a phone */
/* The trail is four levels deep and the last of them is the name of the page
   you are already on, so on a phone it wrapped to three lines of grey text
   above the heading. It earns nothing there - the back button and the menu
   both do the job - so the heading takes the top of the page instead. It stays
   in the markup for wider screens, and the BreadcrumbList in the page's
   structured data is untouched either way. */
@media (max-width: 767.98px) {
	.page-product .breadcrumb { display: none; }

	/* One way of ordering is enough on a phone, and the basket is the one
	   that knows what you picked. The mailto also put the address in the
	   markup for anything scraping the page. */
	.enquiry-panel .js-enquiry-email { display: none; }
}

/* ------------------------------------------------------------ the ticker */
/* The aside is a subordinate clause, so it takes an italic. On a phone the
   two halves stack and centre instead of running together across a wrap,
   which is what made the line look ragged rather than centred. */
.top-bar-aside { font-style: italic; }
@media (max-width: 767.98px) {
	#top-bar .top-bar-line { text-align: center; }
	.top-bar-lead,
	.top-bar-aside { display: block; }
	.top-bar-sep { display: none; }
}

/* --------------------------------------------------- narrow phones only */
/* Below 500px a line of heading rarely fills its measure, so a left-aligned
   heading leaves a ragged block of white to its right. Centre the heading
   cluster - label, heading, rule, and the Read more that closes it - and
   leave the body copy ranged left, because centred paragraphs are hard to
   read once they run past a line or two. */
@media (max-width: 499.98px) {
	.page-heading,
	.info-hero .info-hero-content,
	.product-head { text-align: center; }

	/* .info-label is an inline-block band, so it centres from its parent
	   rather than from itself. */
	.info-story [class*="col-"] { text-align: center; }
	.info-story .info-story-prose { text-align: left; }
	.info-story .info-divider { margin-left: auto; margin-right: auto; }
}

/* ----------------------------------------------- the free-quote opening */
/* Once per session, on the first scroll, the message button stretches open
   and says what it is for. The circle grows leftwards - the transform holds
   its right edge on the same point it was centred on - so nothing runs off
   the screen and it returns to exactly where it started. The pill radius is
   kept, so the ends stay round through the whole move.

   The label waits for the width before fading in; the envelope leaves first.
   Only the button animates, so the arrow beside it never moves. */
.floating-contact-label {
	position: absolute;
	top: 50%;
	/* Clear of the envelope, which keeps the right-hand end of the pill. */
	right: calc(var(--fab) / 2 + 26px);
	transform: translateY(-50%);
	white-space: nowrap;
	font-size: .9375rem;
	font-weight: 600;
	line-height: 1;
	color: #fff;
	opacity: 0;
	pointer-events: none;
	transition: opacity .3s ease;
}
.floating-contact-btn { transition: transform .9s cubic-bezier(.4, 0, .2, 1), width .9s cubic-bezier(.4, 0, .2, 1), background-color .3s ease; }

.floating-contact-wrap.is-teasing .floating-contact-btn {
	width: 196px;
	/* -100% + half the circle keeps the right edge exactly where the circle's
	   right edge was, so it opens to the left. */
	transform: translate(calc(-100% + var(--fab) / 2), -50%);
}
.floating-contact-wrap.is-teasing .floating-contact-icon.btn-unactive {
	left: auto;
	right: calc(var(--fab) / 2);
	transform: translate(50%, -50%);
}
.floating-contact-wrap.is-teasing .floating-contact-label {
	opacity: 1;
	transition: opacity .35s ease .45s;
}
@media (max-width: 767.98px) {
	.floating-contact-wrap.is-teasing .floating-contact-btn { width: 186px; }
	.floating-contact-wrap.is-teasing .floating-contact-label { font-size: .875rem; }
}
@media (prefers-reduced-motion: reduce) {
	.floating-contact-btn,
	.floating-contact-label { transition: none; }
}

/* ---------------------------------------------------------- the quote */
.quote-aside {
	padding: 1.75rem;
	border-radius: .5rem;
	background: var(--cnvs-themecolor-light);
}
.quote-steps li {
	display: flex;
	gap: .9rem;
	padding: .9rem 0;
	border-bottom: 1px solid var(--cuh-line);
}
.quote-steps li:last-child { border-bottom: 0; padding-bottom: 0; }
.quote-steps li:first-child { padding-top: 0; }
.quote-step-no {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 26px;
	height: 26px;
	border-radius: 50%;
	background: var(--cuh-orange);
	color: #21160a;
	font-size: .8125rem;
	font-weight: 700;
	line-height: 1;
}
.quote-steps strong { display: block; font-size: .9375rem; color: var(--cuh-ink); }
.quote-steps span:not(.quote-step-no) {
	display: block;
	margin-top: .2rem;
	font-size: .8125rem;
	line-height: 1.6;
	color: var(--cuh-ink-soft);
}

/* The needs list: same treatment as the quick-question subject, so the two
   forms do not each invent their own kind of checkbox. */
/* The floor carried in from the catalogue. Tinted, because it is the one
   field on the form the visitor did not type - it wants to read as something
   already answered on their behalf, and still be editable if it is wrong. */
.quote-floor input {
	background: var(--cnvs-themecolor-light);
	border-color: var(--cuh-ink);
}
.quote-floor-note {
	margin: .4rem 0 0;
	font-size: .75rem;
	color: var(--cuh-ink-soft);
}

.quote-topic { border: 0; padding: 0; margin: 0; }
.quote-topic legend {
	float: none;
	width: auto;
	margin: 0 0 .5rem;
	padding: 0;
	font-size: .8125rem;
	font-weight: 500;
	color: var(--cuh-ink);
}
.quote-topic-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
	gap: .1rem .9rem;
}
.quote-topic label {
	display: flex;
	align-items: center;
	gap: .55rem;
	min-height: 44px;
	margin: 0;
	font-size: .875rem;
	color: var(--cuh-ink);
	cursor: pointer;
}
.quote-topic input {
	flex: 0 0 auto;
	width: 20px;
	height: 20px;
	accent-color: var(--cuh-orange);
	cursor: pointer;
}

/* -------------------------------------------------- manufacturer tiles */
/* Where one of these rows is about a manufacturer, the tile carries their
   mark rather than a glyph.

   Each mark comes on its own coloured field, so the tile is filled exactly
   as the glyph tiles are filled - same 64px square, same rounding, same
   place in the row. Nothing is added round it, because a border on a filled
   tile would be an edge the glyph tiles do not have. The ring that grows on
   hover is Canvas's own and applies untouched, so both kinds of tile answer
   a pointer identically. */
.fbox-icon .fbox-logo {
	display: block;
	overflow: hidden;
	border-radius: var(--cnvs-featured-box-rounded, 4px);
	background-color: #fff;
}
/* Canvas rounds and fills every img inside .fbox-icon, which is right for a
   photograph standing in for an icon and wrong for a mark filling a tile. */
.fbox-icon .fbox-logo .fbox-logo-img {
	display: block;
	width: 100%;
	height: 100%;
	border-radius: 0;
	background: none;
	object-fit: cover;
}

/* ------------------------------------------------ where the work is done */
/* A second line inside the H1, naming the place the service covers. Being
   inside the heading rather than under it means the location is part of what
   the page is called - "Laminate floor fitting, Edinburgh, Scotland" - which
   is what a local search is looking for, without a second heading competing
   with the first.

   Sized in em, so it stays in proportion as the heading shrinks down the
   breakpoints rather than needing a value at each one. The colour is the
   deep orange: the brighter one measures 2.3:1 on white and the mid tones
   3.5 to 4.4, all under the 4.5 this size of text needs. This one is 5.3. */
.page-heading-place {
	display: block;
	margin-top: .55rem;
	/* In em so it keeps its proportion as the heading shrinks, with a floor so
	   it never drops below readable on a phone: .45 of a 28px heading would be
	   12.6px. The class carries Canvas's `nocolor`, which is the escape hatch
	   its own `h1 > span:not(.nocolor)` rule leaves for exactly this. */
	font-size: max(1rem, .45em);
	font-style: italic;
	font-weight: 400;
	letter-spacing: .01em;
	line-height: 1.3;
	color: var(--cuh-orange-deep);
}

/* "(optional)" after a tile title. Same line, lighter weight and colour, so
   it reads as a qualifier on the heading rather than part of the name. */
.fbox-content h3 .tile-opt {
	font-weight: 400;
	font-size: .8125rem;
	font-style: italic;
	color: var(--cuh-ink-soft);
	white-space: nowrap;
}

/* ----------------------------------------------- marks on partner cards */
/* The same square tiles the fitting rows use, at the size a supporting
   detail wants rather than the size an icon wants. They sit between the
   name and the location, so the card reads as who, what they look like,
   where they are. */
.info-partner-logos {
	display: flex;
	flex-wrap: wrap;
	gap: .5rem;
	margin: .1rem 0 .6rem;
}
.info-partner-logo {
	display: block;
	width: 46px;
	height: 46px;
	border-radius: 4px;
	overflow: hidden;
	background: #fff;
}
.info-partner-logo .info-partner-logo-img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* The line under a slide heading. Between the heading and the button, at a
   size that reads as a sentence rather than a second title, and held to a
   measure so it breaks where a line of prose should. */
.hero-sub {
	max-width: 34rem;
	margin: .9rem 0 0;
	font-size: 1.0625rem;
	line-height: 1.6;
	color: rgba(255, 255, 255, .93);
	text-shadow: 0 1px 12px rgba(0, 0, 0, .5);
}
@media (max-width: 767.98px) {
	.hero-sub { font-size: .9375rem; margin-top: .7rem; }
}

/* ------------------------------------------ steps on an information page */
/* Something above each step in "How the job goes". Three blocks of prose in
   a row read as a wall; a mark at the top of each gives the eye somewhere to
   start and makes the three legible as three. Same square tile as the
   fitting rows, so the site has one idea of what an icon looks like. */
.info-value-icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 46px;
	height: 46px;
	margin-bottom: 1rem;
	border-radius: 4px;
	background: var(--cuh-ink);
	color: #fff;
	font-size: 20px;
	line-height: 1;
}
.info-value-card:hover .info-value-icon { background: var(--cuh-orange); color: #21160a; }
.info-value-icon i { transition: none; }

/* Why Choose Us, when it sits in the run of bands, takes the run's tint.
   It and the partners band are deliberately the same cream: the two belong
   together as the part of the page that is about us rather than the job. */
.info-section.info-section-tinted .assurance-row { margin-bottom: 0; }

/* ------------------------------------------------- the brands, on white */
/* A row of manufacturers' marks wants nothing behind it. On a tint the
   greyed logos sit in a wash of colour and the white in the artwork shows
   as a patch; on white they read as marks on a page. */
.brand-band {
	background: #fff;
	padding-block: 3.5rem 4rem;
}
@media (max-width: 767.98px) {
	.brand-band { padding-block: 2.5rem 3rem; }
}

/* ====================================================================== */
/* Flooring catalogue                                                     */
/* ====================================================================== */

/* Filters down the left, results to the right of them. The column sticks, so
   the choice stays reachable however far the grid runs on. Below the tablet
   breakpoint it goes back to a block above the results - a sidebar on a phone
   is just a screenful between you and the floors.

   The gutter between the two columns is a real rule, not just space - with a
   grid this dense the eye needs telling where the filters end. */

/* The page itself is wider than the rest of the site. A prose column is set at
   a width you can read a sentence across; a wall of floor samples is not prose,
   and the wider it runs the more of them you can compare at once. It is the
   whole column that widens - heading included - rather than the grid alone
   breaking out of it, so the H1, the filters and the first card still share one
   left edge and the block stays centred with even air either side. Bounded, so
   on a very wide screen it stops rather than sprawling. */
@media (min-width: 1200px) {
	/* The air either side is a share of the screen rather than a fixed inset:
	   a flat 3rem gutter is generous at 1200 and invisible at 1920, and taking
	   it as a percentage keeps the cards the same size at 1200 as they were
	   before the page widened. */
	.page-catalogue #content .container { max-width: min(1560px, 94vw); }
}
.floor-catalogue {
	--floor-gutter: 2.75rem;
	display: grid;
	grid-template-columns: 320px minmax(0, 1fr);
	gap: var(--floor-gutter);
	align-items: start;
	margin-top: 2.5rem;
}
.floor-side {
	position: sticky;
	top: 96px;
	padding-right: var(--floor-gutter);
	border-right: 1px solid var(--cuh-line);
}
.floor-results { min-width: 0; }

@media (max-width: 991.98px) {
	.floor-catalogue {
		grid-template-columns: minmax(0, 1fr);
		gap: 1.75rem;
	}
	.floor-side { position: static; padding-right: 0; border-right: 0; }
}

/* The filters. Chips rather than dropdowns: with six manufacturers and
   five types the whole choice fits on the page, and seeing the counts is
   half of deciding what to click. */
.floor-filters { padding: 0; }


.floor-filters-groups {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: 1.35rem;
}
@media (max-width: 991.98px) {
	.floor-filters-groups { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1.25rem 2rem; }
}
.floor-facet { border: 0; padding: 0; margin: 0; min-width: 0; }
.floor-facet legend {
	float: none;
	width: auto;
	margin: 0 0 .55rem;
	padding: 0;
	font-size: .6875rem;
	font-weight: 600;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--cuh-ink-soft);
}
.floor-facet-options { display: flex; flex-wrap: wrap; gap: .4rem; }

.floor-chip {
	display: inline-flex;
	align-items: center;
	gap: .35rem;
	min-height: 34px;
	padding: 0 .7rem;
	border: 1px solid var(--cuh-line);
	border-radius: .3rem;
	background: #fff;
	font-family: inherit;
	font-size: .8125rem;
	line-height: 1;
	color: var(--cuh-ink);
	cursor: pointer;
	transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.floor-chip span {
	font-size: .6875rem;
	color: var(--cuh-ink-soft);
	font-variant-numeric: tabular-nums;
}
.floor-chip:hover { border-color: var(--cuh-ink); }
.floor-chip.is-on {
	background: var(--cuh-ink);
	border-color: var(--cuh-ink);
	color: #fff;
}
.floor-chip.is-on span { color: rgba(255, 255, 255, .7); }

/* The count leads. It is the answer to what the filters were for, so it
   belongs where the eye lands first rather than at the foot of a long
   column where it has to be gone looking for. */
.floor-filters-head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 1rem;
	margin-bottom: 1.35rem;
	padding-bottom: 1rem;
	border-bottom: 1px solid var(--cuh-line);
}
.floor-count { margin: 0; font-size: 1.0625rem; font-weight: 600; color: var(--cuh-ink); font-variant-numeric: tabular-nums; }
.floor-clear {
	border: 0;
	background: none;
	padding: 0;
	font-family: inherit;
	font-size: .8125rem;
	color: var(--cuh-orange-deep);
	text-decoration: underline;
	cursor: pointer;
}

/* The grid. A floor is judged on its face, so the photograph is most of the
   card and the words underneath are only there to name what you are
   looking at. */
.floor-grid {
	display: grid;
	/* Four across, five rows down: exactly the twenty a page holds, so a page
	   is a complete rectangle rather than three and a half rows and a gap.
	   Stated rather than left to auto-fill, which was picking its own number
	   depending on where the minimum happened to land. */
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 1.4rem;
	margin-top: 0;
}
.floor-card {
	display: flex;
	text-align: left;
	font: inherit;
	padding: 0;
	cursor: pointer;
	flex-direction: column;
	border: 1px solid var(--cuh-line);
	border-radius: .5rem;
	overflow: hidden;
	background: #fff;
	transition: border-color .2s ease, transform .2s ease;
}
.floor-card:hover { border-color: var(--cuh-ink); transform: translateY(-3px); }
/* Every card is the same height, whatever it is holding. A grid row takes the
   height of its tallest card, so one card that will not behave drags a whole
   row of well-behaved ones with it.

   Two things used to do that. The frames: most of the catalogue photography is
   square, but a handful of shots are not (827x964 among the Kahrs), and
   aspect-ratio only states a preference - an image asking for more height than
   the square got it, and the frame grew to 303px in a 260px row. Clamped here
   so the ratio is enforced rather than requested, and the odd shot is cropped
   to it. */
.floor-card-image {
	display: block;
	aspect-ratio: 1 / 1;
	overflow: hidden;
	background: var(--cnvs-themecolor-light);
}
.floor-card-image img {
	display: block;
	width: 100%;
	height: 100%;
	aspect-ratio: 1 / 1;
	object-fit: cover;
}
.floor-card-body { display: block; padding: .85rem 1rem 1rem; }

/* And the names: most are two or three words, but the Parador ranges run to
   "Oak Chianti Natural Character Classic 3025 Wide plank (1748900)". The block
   is held at exactly two lines - reserved when the name is short, cut when it
   is long - so no card is taller or shorter than its neighbours. The full name
   is on the card's tooltip and in the dialog. */
.floor-card-name {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	overflow: hidden;
	min-height: calc(2 * 1.35em);
	font-size: .9375rem;
	font-weight: 600;
	line-height: 1.35;
	color: var(--cuh-ink);
}
.floor-card-meta {
	display: block;
	margin-top: .2rem;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
	font-size: .75rem;
	color: var(--cuh-ink-soft);
}

.floor-empty {
	margin: 3rem 0 0;
	text-align: center;
	font-size: .9375rem;
	color: var(--cuh-ink-soft);
}
.floor-more { margin-top: 2.5rem; text-align: center; }
.floor-shown {
	margin: .9rem 0 0;
	font-size: .8125rem;
	color: var(--cuh-ink-soft);
}

@media (max-width: 1199.98px) { .floor-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 991.98px)  { .floor-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
/* Four across a tablet held upright leaves each floor about 160px, which is not
   enough of a sample to judge one by. Ordered after the rule above so it wins
   the overlap between them. */
@media (max-width: 849.98px)  { .floor-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 767.98px)  { .floor-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* A phone opens this page on 104px of nothing: 80px of the shell's own top
   padding plus the breadcrumb's 24px. The 80px goes, which puts the trail
   24px under the header - close, but not jammed against it. Only here; the
   pages with a hero above the fold still want their room. */
@media (max-width: 991.98px) {
	.page-catalogue #content .content-wrap { padding-top: 1.5rem; }
	/* Stated on the padding above rather than left to this, which collapsed
	   through the parent at some widths and put the trail flush against the
	   header. */
	.page-catalogue #content .breadcrumb { margin-top: 0; }
}

/* The toggle and its badge, and the way out of the panel. Both are phone
   furniture: above the breakpoint the chips are simply on the page. */
.floor-filters-toggle {
	display: none;
	align-items: center;
	gap: .45rem;
	min-height: 44px;
	padding: 0 1.05rem;
	border: 1px solid var(--cuh-ink);
	border-radius: 2rem;
	background: #fff;
	font-size: .875rem;
	font-weight: 600;
	color: var(--cuh-ink);
	cursor: pointer;
}
.floor-filters-toggle i { font-size: 1rem; }
.floor-filters.is-open .floor-filters-toggle {
	background: var(--cuh-ink);
	border-color: var(--cuh-ink);
	color: #fff;
}
.floor-filters-badge {
	display: inline-grid;
	place-items: center;
	min-width: 20px;
	height: 20px;
	padding: 0 .3rem;
	border-radius: 10px;
	background: var(--cuh-orange);
	font-size: .6875rem;
	font-weight: 700;
	color: #21160a;
}
.floor-filters-done {
	display: none;
	width: 100%;
	min-height: 46px;
	margin-top: .35rem;
	border: 0;
	border-radius: .4rem;
	background: var(--cuh-ink);
	font-size: .9375rem;
	font-weight: 600;
	color: #fff;
	cursor: pointer;
}
.floor-filters-done:hover { background: var(--cuh-orange); color: #21160a; }

@media (max-width: 991.98px) {
	/* Stacked above the grid it needs an edge of its own again. */
	.floor-filters {
		padding: 1.35rem 1.5rem 1.15rem;
		border: 1px solid var(--cuh-line);
		border-radius: .5rem;
		background: var(--cnvs-themecolor-light);
	}

	/* Folded away by default. Left open, the chips ran to three quarters of a
	   phone screen - the page opened on a wall of filters and you had to scroll
	   past all of them to reach the first floor. The count stays out, so the
	   size of the catalogue is still the first thing read. */
	.floor-filters { padding-bottom: 1.35rem; }
	/* Height rather than display, so it can be animated. The gap above the
	   chips is padding rather than margin, so it is inside the box being
	   measured and does not sit there holding 20px open while closed. */
	.floor-filters-groups {
		max-height: 0;
		padding-top: 0;
		overflow: hidden;
		/* Only the height animates. Transitioning the padding as well would mean
		   measuring the panel while the padding was still on its way in, and
		   opening it 20px short of its own content. */
		transition: max-height .4s cubic-bezier(.22, .61, .36, 1);
	}
	.floor-filters.is-open .floor-filters-groups { padding-top: 1.25rem; }
	.floor-filters-toggle { display: inline-flex; }
	.floor-filters-done { display: block; }

	.floor-filters-head {
		align-items: center;
		flex-wrap: wrap;
		gap: .75rem;
		margin-bottom: 0;
		padding-bottom: 0;
		border-bottom: 0;
	}
	.floor-count { flex: 1 1 auto; }

	/* Thumbs, not cursors: everything tappable clears the 44px the hand
	   actually needs, where a mouse was happy with 34. */
	.floor-chip { min-height: 44px; padding: 0 .9rem; font-size: .875rem; }
	.floor-page { min-width: 44px; height: 44px; }
	.floor-page-step { padding: 0 1rem; }
	.floor-clear { min-height: 44px; }
}

@media (max-width: 575.98px) {
	.floor-filters { padding: 1.15rem 1.15rem 1rem; }
	.floor-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; }
	.floor-card-body { padding: .7rem .8rem .8rem; }
}

/* ------------------------------------------------------------ the pager */
/* Sixty-six pages of floors. Previous and Next for stepping, the two ends
   always reachable, and a window around wherever you are - a row of sixty-six
   numbers would be a worse way to reach page thirty than a gap and a jump. */
.floor-pager {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	margin-top: 2.5rem;
	padding-top: 1.5rem;
	border-top: 1px solid var(--cuh-line);
}
.floor-pages { display: flex; flex-wrap: wrap; gap: .3rem; }
.floor-page {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 38px;
	min-height: 38px;
	padding: 0 .55rem;
	border: 1px solid var(--cuh-line);
	border-radius: .3rem;
	background: #fff;
	font-family: inherit;
	font-size: .875rem;
	font-variant-numeric: tabular-nums;
	color: var(--cuh-ink);
	cursor: pointer;
	transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.floor-page:hover:not(:disabled) { border-color: var(--cuh-ink); }
.floor-page.is-on {
	background: var(--cuh-ink);
	border-color: var(--cuh-ink);
	color: #fff;
}
.floor-page:disabled { opacity: .4; cursor: not-allowed; }
.floor-page-step { padding: 0 .9rem; }
.floor-page-gap { padding: 0 .2rem; color: var(--cuh-ink-soft); align-self: center; }

@media (max-width: 575.98px) {
	.floor-pager { justify-content: center; text-align: center; }
	.floor-page-step { padding: 0 .7rem; }
}

/* --------------------------------------------------- floors arriving in */
/* Each card comes in from the left, one after the next. The delay is tied to
   the card's own position, so a page of twenty resolves left to right across
   each row in about a second - enough to read as a sequence rather than a
   flicker, and short enough that the last one is not still arriving when you
   reach for it. */
@keyframes floor-in {
	from { opacity: 0; transform: translateX(-18px); }
	to   { opacity: 1; transform: none; }
}
.floor-card {
	animation: floor-in .42s cubic-bezier(.22, .61, .36, 1) both;
	animation-delay: calc(var(--i, 0) * 45ms);
}
@media (prefers-reduced-motion: reduce) {
	.floor-card { animation: none; }
}

/* --------------------------------------------------------- one floor, up */
/* A floor opened over the grid rather than on a page of its own. There are
   1,312 of these and none of them is a search destination, so a dialog is
   the honest shape: you came here to compare, and closing it puts you back
   where you were rather than in the browser history.

   The panel is a photograph and a specification side by side - the picture
   is what a floor is judged on, and the numbers are what settles it. The
   copywriting is trimmed to a couple of sentences on the way in. */
.floor-modal {
	position: fixed;
	inset: 0;
	z-index: 700;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 2rem 1.5rem;
}
.floor-modal[hidden] { display: none; }
body.floor-modal-open { overflow: hidden; }
/* Canvas puts the side panel at 699, one below this dialog, so a floor added
   from the dialog slid the basket in behind it. While a floor is open the
   basket goes over the top - and stays there when the floor is closed, until
   it is closed itself. */
body.floor-modal-open #side-panel { z-index: 701; }
/* Arriving with ?add=1 opens the floor and the basket together, and the basket
   is 380px of opaque panel over the right of the screen. The dialog centres in
   what is left rather than behind it, so the specification column and both
   buttons stay readable. */
@media (min-width: 992px) {
	body.side-panel-open .floor-modal { padding-right: calc(var(--cnvs-side-panel-size, 380px) + 1.5rem); }
}

.floor-modal-veil {
	position: absolute;
	inset: 0;
	background: rgba(23, 24, 26, .62);
	backdrop-filter: blur(3px);
	animation: floor-veil .2s ease both;
}
@keyframes floor-veil { from { opacity: 0; } to { opacity: 1; } }

.floor-modal-panel {
	position: relative;
	display: grid;
	grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
	/* The row is capped at the panel rather than at its tallest column. Left to
	   itself the grid row took the height of the specifications, which can run
	   past the panel's own maximum - the panel clipped the overspill, but the
	   picture column had already stretched to the taller row and taken the
	   thumbs sitting at its foot down past the visible edge with it. */
	grid-template-rows: minmax(0, 1fr);
	width: min(1040px, 100%);
	max-height: min(660px, calc(100vh - 4rem));
	border-radius: .6rem;
	overflow: hidden;
	background: #fff;
	box-shadow: 0 30px 80px rgba(23, 24, 26, .35);
	animation: floor-rise .28s cubic-bezier(.22, .61, .36, 1) both;
}
@keyframes floor-rise {
	from { opacity: 0; transform: translateY(14px) scale(.985); }
	to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
	.floor-modal-veil, .floor-modal-panel { animation: none; }
}

.floor-modal-x {
	position: absolute;
	top: .75rem;
	right: .85rem;
	z-index: 2;
	width: 34px;
	height: 34px;
	border: 0;
	border-radius: 50%;
	background: rgba(255, 255, 255, .9);
	font-size: 1.5rem;
	line-height: 1;
	color: var(--cuh-ink);
	cursor: pointer;
	transition: background-color .15s ease;
}
.floor-modal-x:hover { background: var(--cuh-orange); color: #21160a; }

/* The gallery. A floor is a surface, and a surface wants to be seen big, so
   the photograph takes the full height of the panel and the shots sit on top
   of it rather than taking a strip of it away. */
.floor-modal-gallery {
	position: relative;
	display: flex;
	flex-direction: column;
	background: var(--cnvs-themecolor-light);
	min-width: 0;
	min-height: 0;
	overflow: hidden;
}
/* The frame decides its own size and the photograph fills it, never the other
   way round. `height: 100%` on an image inside a flex parent of indefinite
   height falls back to auto, so a portrait shot - Kahrs run some at 1496x2000 -
   laid out at its own ratio and pushed the frame taller than the panel. The
   panel clips, so the growth was invisible, but the thumbs are positioned
   against this column and went down with it, well below the visible edge.
   Taking the image out of the flow settles it: the frame is measured without
   it, and it fills whatever the frame turns out to be. */
.floor-modal-stage {
	position: relative;
	flex: 1;
	min-height: 0;
	overflow: hidden;
}
.floor-modal-stage img {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Enough shadow under the thumbs to hold them against whatever is behind -
   these photographs run from near-black walnut to near-white ash - and none
   at all when there is only one shot and no strip to carry. */
.floor-modal-gallery::after {
	content: '';
	position: absolute;
	inset: auto 0 0;
	height: 110px;
	background: linear-gradient(to top, rgba(18, 16, 14, .55), rgba(18, 16, 14, 0));
	opacity: 0;
	pointer-events: none;
	transition: opacity .2s ease;
}
.floor-modal-gallery.has-thumbs::after { opacity: 1; }

/* The peel. A small black disc straddling the foot of the picture - half on
   the photograph, half on the white below it - so it reads as the handle
   between the two rather than as something sitting on either. Phone only: on a
   desktop the frame is already as tall as the panel. */
.floor-modal-peel {
	display: none;
	position: absolute;
	z-index: 3;
	right: 16px;
	bottom: -18px;
	place-items: center;
	width: 36px;
	height: 36px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: #12100e;
	line-height: 0;
	color: #fff;
	box-shadow: 0 2px 8px rgba(18, 16, 14, .3);
	cursor: pointer;
	transition: background-color .15s ease;
}
.floor-modal-peel svg {
	display: block;
	transition: transform .45s cubic-bezier(.22, .61, .36, 1);
}
.floor-modal-gallery.is-peeled .floor-modal-peel svg { transform: rotate(180deg); }
.floor-modal-peel:active { background: #2b251e; }

.floor-modal-thumbs {
	position: absolute;
	z-index: 1;
	left: 0;
	right: 0;
	bottom: 20px;
	display: flex;
	justify-content: center;
	gap: .4rem;
	padding: 0 .6rem;
}
.floor-modal-thumbs:empty { display: none; }
.floor-modal-thumbs button {
	flex: 0 0 auto;
	width: 54px;
	height: 54px;
	padding: 0;
	border: 2px solid rgba(255, 255, 255, .55);
	border-radius: .3rem;
	overflow: hidden;
	background: none;
	cursor: pointer;
	opacity: .8;
	box-shadow: 0 2px 10px rgba(18, 16, 14, .35);
	transition: opacity .15s ease, border-color .15s ease, transform .15s ease;
}
.floor-modal-thumbs button img { display: block; width: 100%; height: 100%; object-fit: cover; }
.floor-modal-thumbs button:hover { opacity: 1; transform: translateY(-2px); }
.floor-modal-thumbs button.is-on { opacity: 1; border-color: #fff; }

.floor-modal-body {
	/* 10px off the top so the name and the specification below it both sit
	   further up the panel, which is 10px more room for the description
	   between them. */
	padding: 1.6rem 2.25rem 2rem;
	overflow-y: auto;
}
.floor-modal-brand {
	margin: 0 0 .3rem;
	font-size: .6875rem;
	font-weight: 600;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--cuh-orange-deep);
}
.floor-modal-name { margin: 0 0 .8rem; font-size: 1.65rem; line-height: 1.2; }
.floor-modal-desc {
	margin: 0 0 .775rem;
	font-size: .9375rem;
	line-height: 1.7;
	color: var(--cuh-ink-soft);
	/* Cut to whatever is left after everything else has had its room. The
	   height is set in pixels rather than by line-clamp alone, because a clamp
	   cannot be animated and this has to open and close softly. */
	overflow: hidden;
	transition: max-height .38s cubic-bezier(.22, .61, .36, 1);
}
.floor-modal-desc.is-clamped {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	/* The button below takes over the gap, so keeping this as well would spend
	   most of the line the clamp just saved. */
	margin-bottom: 0;
}
.floor-modal-desc:empty { display: none; }
@media (prefers-reduced-motion: reduce) {
	.floor-modal-desc { transition: none; }
}

/* Sits with the copy, not apart from it - it is the end of the paragraph
   rather than a control of its own. */
.floor-modal-more {
	display: none;
	margin: .35rem 0 1rem;
	padding: 0;
	border: 0;
	background: none;
	font-size: .8125rem;
	font-weight: 600;
	color: var(--cuh-ink);
	text-decoration: underline;
	text-underline-offset: 3px;
	cursor: pointer;
}
.floor-modal-more.is-shown { display: inline-block; }
.floor-modal-more:hover { color: var(--cuh-orange-hover); }

/* The specification as rows of label and value, not a table - it is a short
   list of facts, and a table would give it a grid it does not need. */
/* A floor with ten facts to list was spending 406px on them and running the
   panel 43px past its own height. The rows are tightened rather than dropped -
   the wear layer and the fitting method are why somebody opened this - which
   buys back more than the overflow and leaves the copy its lines. */
.floor-modal-specs { margin: 0 0 1.25rem; }
.floor-modal-specs > div {
	display: flex;
	justify-content: space-between;
	gap: 1.5rem;
	padding: .3rem 0;
	border-bottom: 1px solid var(--cuh-line);
}
.floor-modal-specs > div:last-child { border-bottom: 0; }
.floor-modal-specs dt { font-size: .8125rem; color: var(--cuh-ink-soft); }
.floor-modal-specs dd {
	margin: 0;
	font-size: .8125rem;
	font-weight: 600;
	text-align: right;
	color: var(--cuh-ink);
}
/* Two actions, equal width. Adding it to the order and asking about it are
   the same size of decision, so neither is made to look like the other one's
   afterthought. The telephone number goes below as a line of text rather than
   a third button - three buttons in a 400px column is a wall. */
.floor-modal-actions { display: flex; flex-wrap: wrap; gap: .6rem; }
.floor-modal-actions > * { flex: 1 1 12rem; text-align: center; }
.floor-modal-call {
	margin: .85rem 0 0;
	font-size: .8125rem;
	color: var(--cuh-ink-soft);
}
.floor-modal-call a { color: var(--cuh-ink); font-weight: 600; }
.floor-modal-call a:hover { color: var(--cuh-orange); }

@media (max-width: 767.98px) {
	.floor-modal { padding: 0; }
	.floor-modal-panel {
		grid-template-columns: minmax(0, 1fr);
		/* The row cap that keeps the two desktop columns inside the panel has to
		   come off here: stacked, it made the picture share one capped row with
		   the copy and squashed a 493px frame into 199. Down here the panel is
		   the whole screen and scrolls, so both rows take what they need. */
		grid-template-rows: auto;
		width: 100%;
		max-height: 100vh;
		border-radius: 0;
		overflow-y: auto;
	}
	/* A band across the top: a little deeper than the 4:3 crop it was, and
	   deliberately not the whole floor - the peel is what opens it to 85% of
	   the screen. Height rather than aspect-ratio, because a ratio and a fixed
	   addition cannot be transitioned between. */
	.floor-modal-stage {
		flex: 0 0 auto;
		aspect-ratio: auto;
		height: calc(75vw + 50px);
		transition: height .45s cubic-bezier(.22, .61, .36, 1);
	}
	.floor-modal-gallery.is-peeled .floor-modal-stage { height: 85vh; }
	.floor-modal-peel { display: grid; }
	/* Half the button hangs below the picture, so the frame cannot clip to
	   itself here. The stage keeps its own clip, which is the one that
	   mattered. */
	.floor-modal-gallery { overflow: visible; }
	@media (prefers-reduced-motion: reduce) {
		.floor-modal-stage { transition: none; }
	}
	.floor-modal-body { padding: 1.5rem 1.35rem 2rem; }
	.floor-modal-name { font-size: 1.35rem; }
}


@media (prefers-reduced-motion: reduce) {
	.floor-filters-groups { transition: none; }
}

/* On the narrowest screens the thumb strip reaches under the peel. The two
   clear each other vertically by 2px, which is a gap rather than an overlap
   but not one worth trusting - the strip stops short of it instead. Last in
   the file because the strip's own padding is a shorthand set further up. */
@media (max-width: 575.98px) {
	.floor-modal-thumbs { padding-right: 52px; }
}

/* Both circles on a phone.

   These were written once already, higher up, where the base rules that set
   60px came after them and won - so a phone has been carrying two full-size
   60px circles over the corner of every page. At the end of the file they
   actually apply.

   42px is 30% off that. The offsets are all measured from the button's centre,
   because the button is translated by half itself: 14px of floor plus half the
   circle to rest in the corner, and enough above the arrow to leave the same
   14px between them once it appears. */
@media (max-width: 767.98px) {
	#gotoTop {
		--cnvs-gotoTop-size: 42px;
		--cnvs-gotoTop-icon-size: 15px;
	}
	.floating-contact-wrap { --fab: 42px; }
	.floating-contact-icon { font-size: 15px; }
}

/* The story band's own heading. It is the first heading after the H1 and so an
   H2, but it is a section heading inside prose - it should read at the size the
   H3 did rather than at band size. */
.info-story-prose .info-story-heading {
	margin: 1.6rem 0 .6rem;
	font-size: 1.2rem;
	font-weight: 600;
	line-height: 1.35;
	color: var(--cuh-ink);
}

/* The product accordion's label is a major section of the page and is now an
   H2, but it is still drawn by the link inside it - so the heading itself
   carries no size or spacing of its own. */
.qv-toogle-heading {
	margin: 0;
	font-size: inherit;
	font-weight: inherit;
	line-height: inherit;
	letter-spacing: inherit;
	text-transform: none;
}

/* ====================================================================== */
/* The range strip on a fitting page                                      */
/* ====================================================================== */
/* Canvas's shop grid, in this site's colours. The markup is the demo's
   unchanged - two stacked images that cross-fade on hover, an overlay with the
   basket and the eye - so every behaviour Canvas hangs off .product-image
   still applies. Only the colour and a little of the spacing is ours. */
.floor-range {
	padding: 4.5rem 0;
	background: var(--cnvs-themecolor-light);
}
.floor-range .shop { align-items: stretch; }

/* The title column reads as the section's own heading, not a card. */
.floor-range h2 { line-height: 1.15; }
.floor-range p { max-width: 34ch; }

/* Both buttons take the brand outline, and fill on hover rather than going
   the default dark. */
.floor-range .button {
	margin: 0 .5rem .5rem 0;
	border-color: var(--cuh-ink);
	color: var(--cuh-ink);
}
.floor-range .button:hover,
.floor-range .button:focus-visible {
	background-color: var(--cuh-orange) !important;
	border-color: var(--cuh-orange) !important;
	color: #21160a !important;
}

/* The frame owns its own layout rather than inheriting Canvas's, which is a
   flex box here and left the photograph floating small in the middle of the
   card. The furniture demo stacks its two images with CSS that ships with that
   demo and not with this build, so the cross-fade is stated here too. */
.floor-range .product-image {
	display: block;
	position: relative;
	/* .grid-inner is a flex column, and a flex item is shrunk before its
	   aspect-ratio is honoured - which is what squashed a 300px square frame
	   into 300x220. */
	flex: 0 0 auto;
	padding: 0;
	/* The shop-grid rule above pins every .product-image to 220px, which an
	   aspect-ratio cannot argue with. Released here so the square applies. */
	height: auto;
	aspect-ratio: 1 / 1;
	border-radius: .5rem;
	overflow: hidden;
	background: var(--cnvs-themecolor-light);
}
.floor-range .product-image > a {
	position: absolute;
	inset: 0;
	/* The shop-grid rule centres this as a flex box with !important, so the
	   image inside sizes to its content instead of filling the frame. Matched
	   in kind rather than by piling on specificity. */
	display: block !important;
	width: 100%;
	height: 100%;
}
/* Pinned to the frame rather than sized by it: a percentage height inside an
   absolutely positioned anchor was resolving against the image's own ratio and
   leaving a band of background under some floors. */
.floor-range .product-image img {
	position: absolute;
	inset: 0;
	display: block;
	/* The shop's photographs are cut-outs on white and are deliberately
	   contained, with !important, so nothing crops a product. A floor is a
	   surface: it should fill its card and crop. Matched in kind. */
	width: 100% !important;
	height: 100% !important;
	max-width: none;
	max-height: none;
	object-fit: cover;
	transition: transform .5s cubic-bezier(.22, .61, .36, 1);
}
/* The second photograph sits over the first and fades in on hover. Where a
   floor only has one - every cork floor in the catalogue - there is no second
   anchor and the card simply does not swap. */
.floor-range .product-image > a:nth-of-type(2) {
	opacity: 0;
	transition: opacity .45s ease;
}
.floor-range .product:hover .product-image > a:nth-of-type(2) { opacity: 1; }
.floor-range .product:hover .product-image img { transform: scale(1.04); }
@media (prefers-reduced-motion: reduce) {
	.floor-range .product-image > a:nth-of-type(2),
	.floor-range .product-image img { transition: none; }
	.floor-range .product:hover .product-image img { transform: none; }
}

/* The overlay is only drawn over the picture, and only when the card is
   hovered or something inside it has keyboard focus. */
.floor-range .bg-overlay {
	position: absolute;
	inset: 0;
	z-index: 2;
	opacity: 0;
	transition: opacity .25s ease;
	pointer-events: none;
}
.floor-range .product:hover .bg-overlay,
.floor-range .product:focus-within .bg-overlay { opacity: 1; pointer-events: auto; }
.floor-range .bg-overlay-content {
	display: flex;
	height: 100%;
}

/* The two round controls that appear over the photograph. White discs with
   the brand colour on hover, matching the basket controls elsewhere. */
.floor-range .bg-overlay-content { padding: .9rem; }
.floor-range .btn-light {
	display: inline-grid;
	place-items: center;
	width: 42px;
	height: 42px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: #fff;
	font-size: 1.05rem;
	color: var(--cuh-ink);
	box-shadow: 0 2px 10px rgba(18, 16, 14, .25);
	transition: background-color .15s ease, color .15s ease, transform .15s ease;
}
.floor-range .btn-light:hover,
.floor-range .btn-light:focus-visible {
	background: var(--cuh-orange);
	color: #21160a;
	transform: translateY(-2px);
}

.floor-range .product-desc { padding-top: .85rem; text-align: left; }
.floor-range .product-title a { color: var(--cuh-ink); }
.floor-range .product-title a:hover { color: var(--cuh-orange-hover); }

/* Where a price sits in the demo, this carries the manufacturer - so it is set
   as a label rather than as a figure. */
.floor-range .product-price {
	margin-top: .15rem;
	font-size: .8125rem;
	font-weight: 600;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--cuh-orange-deep);
}

/* The demo's column maths puts the title beside two cards at this width and
   leaves a row of one at the bottom. Full width for the title instead, so the
   seven cards break cleanly as four and three. */
@media (min-width: 992px) and (max-width: 1199.98px) {
	.floor-range .shop > .col-xl-3 { flex: 0 0 100%; max-width: 100%; }
	.floor-range p { max-width: 60ch; }
}

@media (max-width: 991.98px) {
	.floor-range { padding: 3rem 0; }
	.floor-range p { max-width: none; }
}

/* Two to a row on a phone. Seven square photographs stacked one per screen is
   a long scroll through a section that is meant to be a glance. */
@media (max-width: 575.98px) {
	.floor-range .shop > .product { flex: 0 0 50%; max-width: 50%; }
	.floor-range .btn-light { width: 38px; height: 38px; }
	.floor-range .product-title a { font-size: .9375rem; }
	.floor-range .product-price { font-size: .6875rem; }
}

/* ====================================================================== */
/* The action bar on a phone, and fitting the quick form on a short screen */
/* ====================================================================== */
/* Two things a visitor on a phone wants on every page within thumb reach: the
   number and a price. The bar carries both across the foot of the screen and
   pushes the floating button and the go-to-top arrow up above itself. */
.mobile-bar { display: none; }

@media (max-width: 767.98px) {
	.mobile-bar {
		display: flex;
		position: fixed;
		z-index: 698;
		left: 0;
		right: 0;
		bottom: 0;
		align-items: center;
		gap: .6rem;
		padding: .45rem .7rem calc(.45rem + env(safe-area-inset-bottom, 0px));
		background: #fff;
		border-top: 1px solid var(--cuh-line);
		box-shadow: 0 -2px 14px rgba(18, 16, 14, .09);
	}

	.mobile-bar-call {
		display: flex;
		align-items: center;
		gap: .5rem;
		flex: 1 1 auto;
		min-width: 0;
		padding: .3rem .2rem;
		font-size: .9375rem;
		font-weight: 600;
		line-height: 1.15;
		color: var(--cuh-ink);
	}
	.mobile-bar-call i { font-size: 1.05rem; color: var(--cuh-orange); }
	.mobile-bar-call span { display: flex; flex-direction: column; min-width: 0; }
	.mobile-bar-call small {
		font-size: .625rem;
		font-weight: 600;
		letter-spacing: .1em;
		text-transform: uppercase;
		color: var(--cuh-ink-soft);
	}

	.mobile-bar-quote {
		flex: 0 0 auto;
		min-height: 42px;
		padding: 0 1.05rem;
		border: 0;
		border-radius: 2rem;
		background: var(--cuh-orange);
		font-size: .9375rem;
		font-weight: 600;
		line-height: 1;
		color: #fff;
		cursor: pointer;
	}
	.mobile-bar-quote:active { background: var(--cuh-orange-hover); }

	/* The message button is retired on a phone: the bar says the same thing in
	   words, in the same place, and two floating call-to-actions over one
	   corner was one too many. The wrapper stays - it holds the form. */
	.floating-contact-btn,
	.floating-contact-label { display: none !important; }
	.floating-contact-wrap { pointer-events: none; }
	.floating-contact-wrap .floating-contact-box { pointer-events: auto; }

	/* Room under the small print, and the two circles lifted clear of the bar. */
	#copyrights { padding-bottom: 12rem; }
	.floating-contact-wrap { bottom: calc(14px + var(--fab) / 2 + 58px); }
	.gototop-active .floating-contact-wrap { bottom: calc(14px + 42px + 14px + var(--fab) / 2 + 58px); }
	.floating-contact-wrap + #gotoTop,
	.stretched .floating-contact-wrap + #gotoTop { bottom: calc(14px + 58px); }
}

/* The quick-question form, on a screen too short to hold it.

   At 698px tall it overflowed an iPhone SE by 66px, and what fell off the top
   was the heading - so the form arrived with no explanation of what it was.
   Every rule below buys height back: a one-line intro, the two topics side by
   side, a shorter message box, tighter gaps, and the send button sharing its
   row with the phone number, which had width going spare. */
.fc-short { display: none; }

.floating-contact-actions {
	display: flex;
	align-items: center;
	gap: .75rem;
}
.floating-contact-actions .button { flex: 0 0 auto; }
.floating-contact-note { flex: 1 1 auto; margin: 0; font-size: .8125rem; }

/* On a phone the form rises from the foot of the screen rather than floating
   above the button. Anchored to the button it moved with it, and once the bar
   pushed the button up the heading went off the top - which is the one part of
   the form that says what it is. From the bottom it uses the whole screen and
   sits over the arrow, which is what the arrow is there for. */
@media (max-width: 767.98px) {
	.floating-contact-box {
		position: fixed;
		left: 10px;
		right: 10px;
		bottom: 68px;
		width: auto;
		max-height: calc(100vh - 82px);
		max-height: calc(100dvh - 82px);
		overflow-y: auto;
		overscroll-behavior: contain;
	}
	/* Above the bar and the arrow both. */
	.floating-contact-wrap.active .floating-contact-box { z-index: 699; }
}

@media (max-height: 720px) {
	.fc-long { display: none; }
	.fc-short { display: inline; }

	/* Both topics on one row. Two stacked checkboxes spend a whole row saying
	   very little, and this is the cheapest 40px on the form. */
	.quick-topic { display: flex; flex-wrap: wrap; align-items: center; gap: 0 .9rem; }
	.quick-topic legend { flex: 0 0 100%; }
	.quick-topic label { min-height: 34px; font-size: .78125rem; }

	/* The compact form left about 120px of screen unused on an iPhone SE. All
	   of it goes to the message box, which is the field people actually need
	   room in - the other four are one line each by nature. */
	#floating-contact textarea.form-control { height: 7.5rem; }

	.floating-contact-heading { padding: .9rem 1.25rem !important; }
	.floating-contact-heading h2 { font-size: 1.0625rem; }
	.floating-contact-heading p { font-size: .8125rem; }

	#floating-contact { padding: 1rem 1.25rem 1.15rem !important; }
	#floating-contact .input-group { margin-bottom: .6rem !important; }
	#floating-contact .form-control,
	#floating-contact .input-group-text { padding-top: .45rem; padding-bottom: .45rem; }
	#floating-contact textarea.form-control { min-height: 0; }

	/* Both topics on one line: two stacked checkboxes cost a row for nothing. */
	.quick-topic { margin-bottom: .6rem !important; }
	.quick-topic legend { margin-bottom: .3rem; font-size: .6875rem; }
	.quick-topic label { font-size: .8125rem; }

	.floating-contact-actions .button { padding-top: .55rem; padding-bottom: .55rem; }
	.floating-contact-note { font-size: .75rem; line-height: 1.3; }
}

/* The quick-question form's close control. Sits in the corner of the dark
   heading, so it reads against it without a border of its own. */
.floating-contact-heading { position: relative; }
.floating-contact-close {
	position: absolute;
	top: .5rem;
	right: .5rem;
	display: grid;
	place-items: center;
	width: 34px;
	height: 34px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: rgba(255, 255, 255, .12);
	font-size: 1.4rem;
	line-height: 1;
	color: #fff;
	cursor: pointer;
	transition: background-color .15s ease, color .15s ease;
}
.floating-contact-close:hover,
.floating-contact-close:focus-visible {
	background: var(--cuh-orange);
	color: #21160a;
}
.floating-contact-heading h2,
.floating-contact-heading p { padding-right: 2.4rem; }

/* Below about 600px of screen there is no spare height to give away, so the
   message box goes back to the smaller size rather than pushing the form into
   a scroll it does not need. */
@media (max-height: 600px) {
	#floating-contact textarea.form-control { height: 4.2rem; }
}

/* Asking about a floor: the dialog sinks away and the quick-question form
   takes its place, so the reader never leaves the catalogue. */
.floor-modal.is-leaving .floor-modal-panel {
	animation: floor-sink .3s cubic-bezier(.4, 0, .2, 1) both;
}
.floor-modal.is-leaving .floor-modal-veil {
	animation: floor-veil-out .3s ease both;
}
@keyframes floor-sink {
	from { opacity: 1; transform: none; }
	to   { opacity: 0; transform: translateY(24px) scale(.97); }
}
@keyframes floor-veil-out { from { opacity: 1; } to { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
	.floor-modal.is-leaving .floor-modal-panel,
	.floor-modal.is-leaving .floor-modal-veil { animation: none; opacity: 0; }
}

/* The quick-question form, given room. It was 380px wide in the corner of the
   screen and read as an afterthought; a form somebody is asked to write a
   paragraph into deserves more than that. Desktop only - on a phone it already
   uses the full width. */
@media (min-width: 768px) {
	.floating-contact-box { width: 480px; }
	.floating-contact-heading { padding: 1.6rem 1.75rem !important; }
	#floating-contact { padding: 1.6rem 1.75rem 1.75rem !important; }
	#floating-contact textarea.form-control { height: 8.5rem; }
}

/* The floor carried in from the catalogue: tinted, so it reads as something
   already filled in on the reader's behalf, and still editable if it is wrong. */
.quick-floor .form-control {
	background: var(--cnvs-themecolor-light);
	border-color: var(--cuh-ink);
	font-weight: 600;
}

/* A chip with nothing behind it is removed from the flow rather than dimmed:
   a greyed-out option still asks to be read and considered. */
.floor-chip[hidden],
.floor-facet[hidden] { display: none !important; }

/* A group down to one option cannot be narrowed further. It is still worth
   reading - it says every cork floor comes from Granorte - so it is quieted
   rather than hidden. */
.floor-facet.is-single legend { opacity: .6; }

/* The catalogue's search box. Sits under the count and above the chips, and
   stays put when the chips fold away on a phone - it is the one control worth
   having in reach at every width. */
.floor-search {
	position: relative;
	display: flex;
	align-items: center;
	margin: 0 0 1.35rem;
}
.floor-search i {
	position: absolute;
	left: .8rem;
	font-size: .9375rem;
	color: var(--cuh-ink-soft);
	pointer-events: none;
}
.floor-search input {
	width: 100%;
	min-height: 44px;
	padding: 0 2.4rem 0 2.3rem;
	border: 1px solid var(--cuh-line);
	border-radius: .4rem;
	background: #fff;
	font-size: .875rem;
	color: var(--cuh-ink);
}
.floor-search input::placeholder { color: var(--cuh-ink-soft); }
.floor-search input:focus {
	outline: none;
	border-color: var(--cuh-ink);
	box-shadow: 0 0 0 3px rgba(255, 143, 0, .18);
}
/* The browser's own clear button would sit on top of ours. */
.floor-search input::-webkit-search-cancel-button { display: none; }

.floor-search-clear {
	position: absolute;
	right: .35rem;
	display: grid;
	place-items: center;
	width: 32px;
	height: 32px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: none;
	font-size: 1.25rem;
	line-height: 1;
	color: var(--cuh-ink-soft);
	cursor: pointer;
}
.floor-search-clear:hover { color: var(--cuh-orange); }
.floor-search-clear[hidden] { display: none; }

/* The search box on a phone: clear of the count and the Filter button above
   it, and 10px back underneath - with the chips folded away it was sitting in
   more space than it needs. Last in the file because the box's own margin is a
   shorthand set further up. */
@media (max-width: 991.98px) {
	.floor-search {
		margin-top: 10px;
		margin-bottom: calc(1.35rem - 10px);
	}
}

/* Hero slide buttons, pinned relative to the slider arrows.
   Each slide carries a different amount of copy above its button, so in normal
   flow the four buttons landed at four different heights - 442px on one slide
   and 469px on the next. The arrows are the fixed thing on that slider: they sit
   dead centre of it at every width. So the button hangs off the same centre line,
   half an arrow down plus 30px, and every slide agrees.
   Horizontal position is untouched - left:0 keeps it against the copy column. */
.hero-copy { height: 100%; }
.hero-copy .hero-cta {
	position: absolute;
	left: 0;
	top: calc(50% + 60px);   /* half a 70px arrow, plus a measured 30px clear */
}
@media (max-width: 767.98px) {
	/* The arrows shrink to 55px below this, so the half-arrow does too. */
	.hero-copy .hero-cta { top: calc(50% + 52.5px); }
}

/* Catalogue page, phone. Everything above the first floor is overhead, and there
   was 825px of it. */
.catalogue-intro-more {
	border: 0;
	background: none;
	padding: 0;
	margin-left: .35rem;
	font: inherit;
	font-weight: 500;
	color: var(--cuh-accent, #d97706);
	text-decoration: underline;
	cursor: pointer;
	display: none;                 /* desktop has the room; only phones need it */
}
@media (max-width: 767.98px) {
	/* The delivery promise is on every other page and in the footer. Here it costs
	   100px before the visitor has seen a single floor. */
	.page-catalogue #top-bar { display: none; }

	.catalogue-intro-more { display: inline; }
	.catalogue-intro-rest {
		display: block;
		max-height: 0;
		opacity: 0;
		overflow: hidden;
		transition: max-height .35s ease, opacity .25s ease, margin-top .35s ease;
		margin-top: 0;
	}
	.catalogue-intro.is-open .catalogue-intro-rest {
		max-height: 22em;
		opacity: 1;
		margin-top: .5rem;
	}

	/* The grid sat 58px below the filter box, from three separate rules stacking:
	   the filter box's own 30px bottom margin, the grid's 10px row gap and a
	   10px top margin on the results. One 10px gap is enough, so the row gap
	   carries it and the other two stand down. */
	.floor-filters { margin-bottom: 0; }
	.floor-results { margin-top: 0; }
	.floor-catalogue { row-gap: 10px; }
}

/* The order panel slides in from the right onto a white page, with no border and
   no shadow, so its left edge simply vanished. One black line gives it an edge. */
#side-panel {
	border-left: 1px solid var(--cuh-ink);
}

/* Links inside body copy. They were the same colour as the text around them with
   nothing to mark them, which in a paragraph of prose is indistinguishable from
   not being a link at all.

   Canvas strips underlines site-wide with
     a:not(.btn-link):not(.text-decoration-underline):not(.more-link) { ... !important }
   which is (0,3,1) and !important, so a plain ".info-body a" never stood a chance.
   These carry one more :not() to outrank it, and !important to match it. */
.info-body a:not(.button):not(.btn-link):not(.more-link),
.info-value-body a:not(.button):not(.btn-link):not(.more-link),
.lead-copy a:not(.button):not(.btn-link):not(.more-link),
.info-section-extra a:not(.button):not(.btn-link):not(.more-link),
.product-copy a:not(.button):not(.btn-link):not(.more-link),
.info-story-prose a:not(.button):not(.btn-link):not(.more-link) {
	text-decoration: underline !important;
	text-underline-offset: 2px;
}

/* Standard house orange on hover and on keyboard focus. */
.info-body a:not(.button):hover,
.info-value-body a:not(.button):hover,
.lead-copy a:not(.button):hover,
.info-section-extra a:not(.button):hover,
.product-copy a:not(.button):hover,
.info-story-prose a:not(.button):hover,
.info-body a:not(.button):focus-visible,
.lead-copy a:not(.button):focus-visible,
.info-story-prose a:not(.button):focus-visible {
	color: var(--cuh-orange) !important;
	text-decoration-color: var(--cuh-orange) !important;
}

/* The region on its own line under the page title, quieter than the phrase above
   it: "Underfloor Heating Fitting" is the service, "in East Lothian" is where. */
.page-region {
	display: block;
	font-size: .62em;
	font-weight: 400;
	line-height: 1.3;
	margin-top: .45rem;
	/* The hero art behind it is dark, so the region reads white like the title. */
	color: #fff;
}
