/*
Theme Name: Tiny Wood Stove Base
Theme URI: https://www.tinywoodstove.com
Author: CampMW
Author URI: https://campmw.com
Description: Standalone block (FSE) theme for tinywoodstove.com. Built from scratch to replace Astra + Beaver Builder. Not a child theme — fully independent, owns its full theme.json, templates, and template parts.
Requires at least: 6.5
Tested up to: 6.7
Requires PHP: 7.4
Version: 0.44.4
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: tws-base
Tags: full-site-editing, block-patterns, e-commerce, custom-colors, custom-menu

Global design tokens live in theme.json. This stylesheet covers the things
theme.json can't express, plus legacy compatibility shims for content that
was authored while Astra was active.
*/

/* ===============================================================
   LEGACY ASTRA COMPATIBILITY SHIM

   Existing page content (built while Astra was active) carries
   classes like .has-ast-global-color-5-background-color and inline
   styles referencing var(--ast-global-color-N). Astra generated
   both; with Astra gone they resolve to nothing and blocks lose
   their backgrounds and text colours.

   These slugs are deliberately NOT registered in theme.json's
   palette — that would put nine duplicate greys in the editor's
   colour picker and invite editors to keep using them. Defining
   them here keeps legacy content rendering correctly while the
   picker only offers the real brand palette.

   MIGRATION: this whole block can be deleted once every page has
   been re-saved onto the new palette. To find what still depends
   on it:
     wp db query "SELECT ID, post_title FROM wp_posts \
       WHERE post_content LIKE '%ast-global-color%' \
       AND post_status = 'publish';"
   =============================================================== */
:root {
	--ast-global-color-0: #0170b9;
	--ast-global-color-1: #3a3a3a;
	--ast-global-color-2: #3a3a3a;
	--ast-global-color-3: #4b4f58;
	--ast-global-color-4: #f5f5f5;
	--ast-global-color-5: #ffffff;
	--ast-global-color-6: #e5e5e5;
	--ast-global-color-7: #424242;
	--ast-global-color-8: #000000;

	/* Astra content-width vars referenced by some legacy blocks. */
	--wp--custom--ast-content-width-size: 1240px;
	--wp--custom--ast-wide-width-size: 1400px;
}

.has-ast-global-color-0-color { color: var(--ast-global-color-0) !important; }
.has-ast-global-color-1-color { color: var(--ast-global-color-1) !important; }
.has-ast-global-color-2-color { color: var(--ast-global-color-2) !important; }
.has-ast-global-color-3-color { color: var(--ast-global-color-3) !important; }
.has-ast-global-color-4-color { color: var(--ast-global-color-4) !important; }
.has-ast-global-color-5-color { color: var(--ast-global-color-5) !important; }
.has-ast-global-color-6-color { color: var(--ast-global-color-6) !important; }
.has-ast-global-color-7-color { color: var(--ast-global-color-7) !important; }
.has-ast-global-color-8-color { color: var(--ast-global-color-8) !important; }

.has-ast-global-color-0-background-color { background-color: var(--ast-global-color-0) !important; }
.has-ast-global-color-1-background-color { background-color: var(--ast-global-color-1) !important; }
.has-ast-global-color-2-background-color { background-color: var(--ast-global-color-2) !important; }
.has-ast-global-color-3-background-color { background-color: var(--ast-global-color-3) !important; }
.has-ast-global-color-4-background-color { background-color: var(--ast-global-color-4) !important; }
.has-ast-global-color-5-background-color { background-color: var(--ast-global-color-5) !important; }
.has-ast-global-color-6-background-color { background-color: var(--ast-global-color-6) !important; }
.has-ast-global-color-7-background-color { background-color: var(--ast-global-color-7) !important; }
.has-ast-global-color-8-background-color { background-color: var(--ast-global-color-8) !important; }

.has-ast-global-color-0-border-color { border-color: var(--ast-global-color-0) !important; }
.has-ast-global-color-1-border-color { border-color: var(--ast-global-color-1) !important; }
.has-ast-global-color-2-border-color { border-color: var(--ast-global-color-2) !important; }
.has-ast-global-color-3-border-color { border-color: var(--ast-global-color-3) !important; }
.has-ast-global-color-4-border-color { border-color: var(--ast-global-color-4) !important; }
.has-ast-global-color-5-border-color { border-color: var(--ast-global-color-5) !important; }
.has-ast-global-color-6-border-color { border-color: var(--ast-global-color-6) !important; }
.has-ast-global-color-7-border-color { border-color: var(--ast-global-color-7) !important; }
.has-ast-global-color-8-border-color { border-color: var(--ast-global-color-8) !important; }

/* ===============================================================
   COLOUR TOKENS

   Contrast-checked against WCAG 2.0 AA:
     --tws-ink          #3A3A3A on white        11.37:1  (AA text)
     --tws-muted        #757575 on white         4.61:1  (AA text)
     --tws-accent       #DD9933 + --tws-ink      4.70:1  (AA text)
     --tws-accent-deep  #C57F1A on white         3.27:1  (AA non-text only)
     --tws-accent-text  #8C5A18 on white         5.85:1  (AA text)

   Three oranges, because one can't satisfy every requirement:

     accent       brand orange. Only usable as a BACKGROUND, and only with
                  dark text — white on it is 2.42:1, which fails badly.
     accent-deep  icons, borders, focus rings. Non-text UI needs 3:1, and
                  this is the closest to brand that clears it.
     accent-text  orange TEXT on a light background, which needs the full
                  4.5:1. Used for toast links and CTA hover.

   Product pricing:
     --tws-sale       #1E7A3C  5.38:1 white / 4.85:1 grey  (AA text)
     --tws-price-was  #666666  5.74:1 white / 5.17:1 grey  (AA text)
     --tws-accent-border #B8791F 3.63:1 white / 3.27:1 grey (AA non-text)

   Interaction:
     --tws-hover      #32373C  white label 12.02:1  (AA/AAA text)
                      Single shared hover for every button on the site.
   =============================================================== */
:root {
	--tws-ink: #3a3a3a;
	--tws-body: #4b4f58;
	--tws-muted: #757575;
	--tws-accent: #dd9933;
	--tws-accent-deep: #c57f1a;
	--tws-accent-text: #8c5a18;
	--tws-accent-border: #b8791f;
	/* Shared button hover: charcoal + white, 12.02:1. One hover colour for
	   every button on the site so the interaction reads consistently. */
	--tws-hover: #32373c;
	--tws-sale: #1e7a3c;
	--tws-price-was: #666666;
	--tws-border: #e5e5e5;
	--tws-header-h: 80px;
}

/* ===============================================================
   HEADER
   =============================================================== */
.wp-site-blocks > header {
	position: sticky;
	top: 0;
	z-index: 100;
	border-bottom: 1px solid var(--tws-border);
	box-shadow: 0 1px 6px rgba(0, 0, 0, 0.06);
}

/*
 * Desktop order, left to right:
 *   logo | (space) | menu | Find My Stove | search | account | cart
 * The logo pushes everything else right via margin-right:auto rather than
 * space-between, so the nav and actions stay grouped together on the right.
 */
/* Outer wrapper now holds two rows (banner + bar), so the flex rules that
   used to live here moved to .tws-header__bar. */
.tws-header {
	gap: 0;
}

.tws-header__bar {
	min-height: 80px;
	flex-wrap: nowrap !important;
}

.tws-header__right {
	flex: 0 1 auto;
	min-width: 0;
}

.tws-header__logo {
	flex: 0 0 auto;
}

.tws-header__logo img {
	display: block;
	height: auto;
	max-width: 250px;
}

.tws-header__actions {
	display: flex;
	align-items: center;
	gap: 4px;
	flex: 0 0 auto;
}

/* --- Find My Stove CTA ------------------------------------------------- */
.tws-header__cta {
	margin-right: 8px;
}

/*
 * Every box-affecting property is repeated on :hover/:focus so the button
 * cannot change size between states. WordPress' own button styles apply a
 * border on hover, which was widening the element by 2px and shoving the
 * whole header row sideways.
 */
.tws-cta-button .wp-block-button__link,
.tws-cta-button .wp-block-button__link:hover,
.tws-cta-button .wp-block-button__link:focus,
.tws-cta-button .wp-block-button__link:focus-visible,
.tws-cta-button .wp-block-button__link:active {
	font-size: 15px;
	font-weight: 500;
	line-height: 1.2;
	padding: 11px 22px;
	border: 1px solid transparent;
	border-radius: 3px;
	white-space: nowrap;
	box-sizing: border-box;
	text-decoration: none;
}

.tws-cta-button .wp-block-button__link {
	background-color: var(--tws-accent);
	color: var(--tws-ink);
}

.tws-cta-button .wp-block-button__link:hover,
.tws-cta-button .wp-block-button__link:focus-visible {
	background-color: var(--tws-hover);
	color: #ffffff;
}

/* --- Icon buttons (search, account) ------------------------------------ */
.tws-icon-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	/* 44x44 minimum touch target (WCAG 2.5.5). */
	width: 44px;
	height: 44px;
	padding: 0;
	background: none;
	border: none;
	border-radius: 3px;
	color: var(--tws-body);
	cursor: pointer;
	text-decoration: none;
}

.tws-icon-btn:hover {
	color: var(--tws-accent-deep);
}

/* Visible keyboard focus everywhere (WCAG 2.4.7). */
.tws-icon-btn:focus-visible,
.tws-search-overlay__close:focus-visible,
.tws-search-overlay__field:focus-visible,
.tws-search-overlay__submit:focus-visible,
.tws-toast__close:focus-visible,
.tws-toast__link:focus-visible,
.wp-block-button__link:focus-visible,
.wp-block-navigation-item__content:focus-visible {
	outline: 2px solid var(--tws-accent-deep);
	outline-offset: 2px;
}

/* --- Cart -------------------------------------------------------------- */
.tws-header__cart .wc-block-mini-cart__button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	color: var(--tws-accent-deep);
}

.tws-header__cart .wc-block-mini-cart__icon {
	stroke: currentColor;
	stroke-width: 2.25;
}

.tws-header__cart .wc-block-mini-cart__badge {
	background: transparent;
	color: var(--tws-accent-deep);
	font-weight: 700;
	font-size: 12px;
}

/* --- Mobile ------------------------------------------------------------
 * Single row: logo | (space) | search | menu | cart
 * The CTA and account move into the mobile menu overlay — see README note
 * about adding them as menu items with .tws-menu-cta / .tws-menu-account.
 * ---------------------------------------------------------------------- */
@media (max-width: 900px) {
	.tws-header__bar {
		padding-left: 16px !important;
		padding-right: 16px !important;
		min-height: 64px;
	}

	.tws-header__logo img {
		max-width: 170px;
	}

	.tws-header__actions {
		order: 2;
		gap: 0;
	}

	/* CTA + account are not shown twice — they live in the menu on mobile. */
	.tws-header__cta,
	.tws-account-link {
		display: none;
	}

	/* Cart sits after the hamburger. */
	.tws-header__cart {
		order: 4;
	}
}

@media (max-width: 380px) {
	.tws-header__logo img {
		max-width: 130px;
	}
}

/* The core Navigation block was removed from the header in 0.23.0: the
   mobile drawer replaced it. Its styles, and the shims that hid the legacy
   Astra menu items Astra used to inject into it, went with it. Those menu
   items can now simply be deleted in Appearance > Menus, or left alone: the
   theme no longer renders a WP menu anywhere.
   ----------------------------------------------------------------------- */


/* ===============================================================
   SEARCH OVERLAY
   =============================================================== */
.tws-no-scroll,
.tws-no-scroll body {
	overflow: hidden;
}

.tws-search-overlay {
	position: fixed;
	inset: 0;
	z-index: 999;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgba(255, 255, 255, 0.96);
	opacity: 0;
	transition: opacity 0.2s ease;
}

.tws-search-overlay[hidden] {
	display: none;
}

.tws-search-overlay.is-open {
	opacity: 1;
}

.tws-search-overlay__inner {
	position: relative;
	width: min(680px, calc(100vw - 40px));
}

.tws-search-overlay__close {
	position: absolute;
	top: -52px;
	left: 50%;
	transform: translateX(-50%);
	display: inline-flex;
	align-items: center;
	gap: 8px;
	min-height: 44px;
	padding: 8px 14px;
	background: none;
	border: none;
	color: var(--tws-ink);
	font-family: inherit;
	font-size: 16px;
	cursor: pointer;
}

.tws-search-overlay__close:hover {
	color: var(--tws-accent-deep);
}

.tws-search-overlay__form {
	display: flex;
	align-items: center;
	background: #ffffff;
	/* #949494 is the lightest grey that clears 3:1 on white for a form
	   boundary (WCAG 1.4.11 non-text contrast). */
	border: 1px solid #949494;
	border-radius: 2px;
}

.tws-search-overlay__field {
	flex: 1 1 auto;
	min-width: 0;
	padding: 16px 18px;
	border: none;
	background: transparent;
	font-family: inherit;
	font-size: 18px;
	color: var(--tws-ink);
}

.tws-search-overlay__field:focus {
	outline: none;
}

.tws-search-overlay__form:focus-within {
	border-color: var(--tws-accent-deep);
	box-shadow: 0 0 0 2px rgba(197, 127, 26, 0.35);
}

.tws-search-overlay__submit {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 52px;
	height: 52px;
	background: none;
	border: none;
	color: var(--tws-body);
	cursor: pointer;
}

.tws-search-overlay__submit:hover {
	color: var(--tws-accent-deep);
}

/* ===============================================================
   ADD-TO-CART TOAST
   =============================================================== */
.tws-toast-region {
	position: fixed;
	top: calc(var(--tws-header-h) + 12px);
	right: 16px;
	z-index: 1000;
	display: flex;
	flex-direction: column;
	gap: 10px;
	width: min(340px, calc(100vw - 32px));
	pointer-events: none;
}

.admin-bar .tws-toast-region {
	top: calc(var(--tws-header-h) + 44px);
}

.tws-toast {
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 12px;
	background: #ffffff;
	border: 1px solid var(--tws-border);
	border-left: 4px solid var(--tws-accent-deep);
	border-radius: 4px;
	box-shadow: 0 8px 24px rgba(0, 0, 0, 0.14);
	pointer-events: auto;
	opacity: 0;
	transform: translateY(-8px);
	transition: opacity 0.25s ease, transform 0.25s ease;
}

.tws-toast.is-visible {
	opacity: 1;
	transform: translateY(0);
}

.tws-toast__img {
	flex: 0 0 auto;
	width: 48px;
	height: 48px;
	object-fit: cover;
	border-radius: 3px;
}

.tws-toast__body {
	flex: 1 1 auto;
	min-width: 0;
}

.tws-toast__text {
	margin: 0 0 2px;
	font-size: 14px;
	line-height: 1.4;
	color: var(--tws-ink);
}

.tws-toast__link {
	font-size: 13px;
	font-weight: 500;
	/* Orange text on white needs the full 4.5:1 — accent-deep is only 3.27. */
	color: var(--tws-accent-text);
	text-decoration: underline;
}

.tws-toast__close {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
	padding: 0;
	background: none;
	border: none;
	border-radius: 3px;
	color: var(--tws-muted);
	cursor: pointer;
}

.tws-toast__close:hover {
	color: var(--tws-ink);
}

/* Respect reduced-motion preferences (WCAG 2.3.3). */
@media (prefers-reduced-motion: reduce) {
	.tws-search-overlay,
	.tws-toast {
		transition: none;
	}
}

/* Admin bar must not sit on top of the sticky header. */
.admin-bar .wp-site-blocks > header {
	top: 32px;
}

@media screen and (max-width: 782px) {
	.admin-bar .wp-site-blocks > header {
		top: 46px;
	}
}

.wp-site-blocks > header .wp-block-site-logo img {
	display: block;
	height: auto;
}

/* Header right cluster — search + mini cart on a shared baseline. */
.wp-site-blocks > header .wp-block-group {
	align-items: center;
}

.wp-site-blocks > header .wp-block-search__inside-wrapper {
	border: none;
}

.wp-site-blocks > header .wp-block-search__button {
	background: transparent;
	border: none;
	padding: 6px;
	color: #4b4f58;
	min-height: 0;
}

.wp-site-blocks > header .wp-block-search__button:hover {
	background: transparent;
	color: #dd9933;
}

.wp-site-blocks > header .wc-block-mini-cart__button {
	padding: 6px;
	color: #4b4f58;
}

/* Navigation submenus — light, low-contrast, matching current site. */
.wp-block-navigation .wp-block-navigation__submenu-container {
	background-color: #ffffff;
	border: 1px solid #e5e5e5;
	box-shadow: 0 6px 18px rgba(0, 0, 0, 0.08);
	padding: 6px 0;
}

.wp-block-navigation .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
	padding: 8px 18px;
}

/* (Old footer rules removed — superseded by the FOOTER section below.) */

/* ===============================================================
   LAYOUT — /store/ and other left-sidebar pages
   =============================================================== */
.tws-sidebar-layout {
	display: grid;
	grid-template-columns: 360px minmax(0, 1fr);
	gap: 0;
	align-items: start;
}

/* Hairline between the two columns, as production has it. The border lives
   on the CONTENT column because that one is always the taller of the two, so
   the line runs the full height of the page instead of stopping where the
   sidebar ends. Each side carries half the gutter, which puts the line in
   the middle of the space rather than hard up against the products. */
/* WordPress's flow layout puts margin-block-start on every child after the
   first. In this grid that dropped the content column 24px below the
   sidebar, so the search field and the breadcrumb never lined up. */
.tws-sidebar-layout > * {
	margin-block-start: 0;
}

/* A template part renders inside its own .wp-block-template-part wrapper,
   so the grid item is that div rather than the <aside> itself. */
.tws-sidebar-layout > .wp-block-template-part {
	display: contents;
}

.tws-sidebar {
	padding-right: 30px;
}

.tws-sidebar-content {
	padding-left: 30px;
	border-left: 1px solid var(--tws-border);
}

@media (max-width: 921px) {
	.tws-sidebar-layout {
		grid-template-columns: 1fr;
		gap: 40px;
	}

	/* Stacked: the divider and its gutter would read as a stray rule across
	   the page, so both come off. */
	.tws-sidebar { padding-right: 0; }

	.tws-sidebar-content {
		padding-left: 0;
		border-left: 0;
	}

	/* Products first. A phone visitor shouldn't have to scroll past a search
	   box, the whole category tree and a promo image before the first stove.
	   Swap these two to put the sidebar back on top. */
	.tws-sidebar { order: 2; }
	.tws-sidebar-content { order: 1; }
}

.tws-sidebar .wp-block-heading {
	font-size: 18px;
	font-weight: 500;
	color: #3a3a3a;
	margin-bottom: 12px;
}

.tws-sidebar ul {
	list-style: none;
	margin: 0 0 28px;
	padding: 0;
}

.tws-sidebar li {
	line-height: 2;
}

.tws-sidebar a {
	color: #666666;
	font-size: 15px;
	text-decoration: none;
}

.tws-sidebar a:hover {
	color: #dd9933;
}

/* --- Knowledgebase / stories sidebar -----------------------------------
   Rendered by patterns/sidebar-nav.php. Shares .tws-sidebar's link and
   list styling; these rules add the group headings, the nesting and the
   "you are here" marker. */
.tws-kb-sidebar__intro {
	margin: 0 0 16px;
	font-size: 14px;
	line-height: 1.6;
	color: var(--tws-price-was);
}

.tws-kb-sidebar__root {
	margin: 0 0 24px;
	padding-bottom: 16px;
	border-bottom: 1px solid var(--tws-border);
	font-size: 15px;
}

.tws-kb-sidebar__root a {
	color: var(--tws-ink);
	font-weight: 500;
	text-decoration: none;
}

.tws-kb-sidebar__root a:hover { color: var(--tws-accent-text); }

.tws-kb-sidebar__group {
	margin: 22px 0 8px;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--tws-muted);
}

.tws-kb-sidebar__group a { color: inherit; text-decoration: none; }
.tws-kb-sidebar__group a:hover { color: var(--tws-accent-text); }

/* --- Sidebar tree -------------------------------------------------------
   One tree, used by the shop sidebar and the knowledgebase/stories
   sidebar. Each section is a white card; the rows inside it are
   <details>, so a branch opens in place with no JavaScript.

   In a row the LABEL IS A LINK and the triangle is the toggle. Clicking
   the label navigates because the link handles the click before the
   summary's own toggle behaviour; clicking the triangle, the count or the
   empty part of the row expands it instead. */
.tws-tree__root {
	margin: 0 0 14px;
	font-size: 15px;
}

.tws-tree__root a {
	color: var(--tws-ink);
	font-weight: 500;
	text-decoration: none;
}

.tws-tree__root a:hover,
.tws-tree__root.is-current a { color: var(--tws-accent-text); }

.tws-tree__group {
	margin-bottom: 10px;
	padding: 12px;
	background: #ffffff;
	border: 1px solid var(--tws-border);
	border-radius: 8px;
}

.tws-tree__heading {
	margin: 0 0 6px;
	padding: 0 4px;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	/* Brand colour on the section label: it is the one place in the tree
	   where a warm accent reads as structure rather than as a link. */
	color: var(--tws-accent-text);
}

.tws-tree__heading a { color: inherit; text-decoration: none; }
.tws-tree__heading a:hover { color: var(--tws-accent-text); }

.tws-tree__branches,
.tws-tree__leaves {
	list-style: none;
	margin: 0;
	padding: 0;
}

.tws-tree__item + .tws-tree__item { margin-top: 1px; }

/* --- The row ----------------------------------------------------------- */
/* align-items:flex-start, not center: once a label wraps to two lines a
   centred twisty floats halfway down the row. Both the twisty and the
   count get a small top offset instead so they sit on the first line. */
.tws-tree__row {
	display: flex;
	align-items: flex-start;
	gap: 8px;
	padding: 7px 8px;
	border-radius: 5px;
	cursor: pointer;
	list-style: none;
	transition: background-color .12s ease;
}

.tws-tree__row::-webkit-details-marker { display: none; }
.tws-tree__row:hover { background: var(--tws-border-light, #f3f3f3); }

.tws-tree__row:focus-visible,
.tws-tree__link:focus-visible {
	outline: 2px solid var(--tws-accent-deep);
	outline-offset: 1px;
}

/* A real target rather than a 5px arrowhead: 18px square, chevron drawn
   inside it, so it is easy to hit and obvious that it is the control. */
.tws-tree__twisty {
	flex: none;
	position: relative;
	width: 20px;
	height: 20px;
	margin-top: 0;
	border-radius: 4px;
	background: var(--tws-border-light, #f3f3f3);
}

.tws-tree__twisty::before {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	width: 5px;
	height: 5px;
	margin: -3px 0 0 -3px;
	border-right: 1.5px solid var(--tws-body);
	border-bottom: 1.5px solid var(--tws-body);
	transform: rotate(-45deg);
	transition: transform .14s ease;
}

details[open] > .tws-tree__row .tws-tree__twisty {
	background: var(--tws-accent);
}

details[open] > .tws-tree__row .tws-tree__twisty::before {
	transform: rotate(45deg);
	margin-top: -4px;
	border-color: var(--tws-ink);
}

.tws-tree__row:hover .tws-tree__twisty { background: #e8e5e0; }

.tws-tree__link {
	flex: 1;
	min-width: 0;
	font-size: 14.5px;
	line-height: 1.35;
	color: var(--tws-ink);
	text-decoration: none;
}

.tws-tree__link:hover { color: var(--tws-accent-text); }

/* A pill rather than a bare number: on its own at the end of a wrapping
   row it read as a stray digit. */
.tws-tree__count {
	flex: none;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 22px;
	height: 20px;
	padding: 0 6px;
	border-radius: 10px;
	background: var(--tws-border-light, #f3f3f3);
	color: var(--tws-muted);
	font-size: 11px;
	font-weight: 600;
	font-variant-numeric: tabular-nums;
}

/* A section with no sub-categories uses its heading row as the toggle. */
.tws-tree__row--heading .tws-tree__link {
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--tws-muted);
}

.tws-tree__row--heading .tws-tree__link:hover { color: var(--tws-accent-text); }

/* --- Open branch -------------------------------------------------------
   No rule down the left: the indent and the quieter type carry the
   nesting on their own, and a hairline here fought the card border. */
/* Indented to line up under the label above, so the posts visibly hang off
   their category. Written with .tws-sidebar in front because the widget
   rule `.tws-sidebar ul { margin: 0 0 28px; padding: 0 }` is a class plus
   an element and outranks a lone class — that rule was flattening this
   indent and adding the extra space at the bottom of every card. */
.tws-sidebar .tws-tree__leaves,
.tws-tree__leaves {
	margin: 2px 0 8px;
	padding: 0 0 0 36px;
}

.tws-sidebar .tws-tree__branches,
.tws-tree__branches {
	margin: 0;
	padding: 0;
}

.tws-tree__leaves li { margin-bottom: 3px; }

/* Fifteen two-line titles in a row turn into a block of grey text with
   nothing to separate one from the next. A small marker in the gutter
   gives each entry a start, and the wrapped second line hangs under the
   first rather than under the marker, so the column still reads cleanly.

   Every leaf carries the 10px inset the current one needs for its bar, so
   all the text lines up with the label above and only the bar sits
   outside; the marker lives in that same gutter and steps aside on the
   current item, where the bar takes its place. */
.tws-tree__leaves li {
	position: relative;
}

/* A short vertical tick rather than a dot: it scales with the row, so a
   two-line title gets a taller mark, and it sits exactly where the
   current item's accent bar goes, which keeps the left edge consistent
   whichever state a row is in. */
.tws-tree__leaves li::before {
	content: "";
	position: absolute;
	left: -10px;
	top: 15%;
	width: 1px;
	height: 70%;
	background: #dedede;
}

.tws-tree__leaves li:hover::before { background: var(--tws-accent); }
.tws-tree__leaves li.is-current::before,
.tws-tree__leaves li.tws-tree__more::before { display: none; }

.tws-tree__leaves a {
	display: block;
	padding: 6px 8px 6px 10px;
	margin-left: -10px;
	border-radius: 3px;
	font-size: 13.5px;
	line-height: 1.45;
	color: var(--tws-price-was);
	text-decoration: none;
}

.tws-tree__leaves a:hover { color: var(--tws-accent-text); }

.tws-tree__more {
	margin-top: 6px;
	padding-top: 6px;
	border-top: 1px solid var(--tws-border);
}

.tws-tree__more a { color: var(--tws-accent-text); font-weight: 500; }

/* --- You are here ------------------------------------------------------
   A bar down the left edge of the row, which reads at a glance without
   needing colour alone to carry it. */
.tws-tree__item.is-current > details > .tws-tree__row,
.tws-tree__group.is-current > details > .tws-tree__row--heading {
	background: #faf6ef;
	box-shadow: inset 3px 0 0 var(--tws-accent);
}

.tws-tree__item.is-current > details > .tws-tree__row .tws-tree__link,
.tws-tree__group.is-current > details > .tws-tree__row--heading .tws-tree__link {
	color: var(--tws-accent-text);
	font-weight: 500;
}

.tws-tree__item.is-current > details > .tws-tree__row .tws-tree__count {
	background: var(--tws-accent);
	color: var(--tws-ink);
}

.tws-tree__group.is-current { border-color: var(--tws-accent-border); }

.tws-tree__leaves li.is-current > a {
	color: var(--tws-ink);
	font-weight: 500;
	background: #faf6ef;
	box-shadow: inset 3px 0 0 var(--tws-accent);
}

@media (prefers-reduced-motion: reduce) {
	.tws-tree__twisty::before,
	.tws-tree__row { transition: none; }
}

/* Shop tree: shared .tws-tree design above, only the outer spacing differs. */
.tws-shop-tree { margin-bottom: 28px; }

/* --- WooCommerce sale badge --------------------------------------------
   Woo ships a large green disc that belongs to no palette on this site and
   lands on top of the product photo. Charcoal pill instead: it reads as a
   label rather than a button, so it does not compete with the accent-
   coloured Add to cart beneath it, and it matches the charcoal discs the
   mega menu uses for the same "small marker" job. */
.woocommerce span.onsale,
.woocommerce ul.products li.product .onsale {
	position: absolute;
	top: 10px;
	left: 10px;
	right: auto;
	min-width: 0;
	min-height: 0;
	width: auto;
	height: auto;
	margin: 0;
	padding: 5px 10px;
	border-radius: 3px;
	background: var(--tws-hover);
	color: #ffffff;
	font-size: 11.5px;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	line-height: 1.1;
	text-align: center;
}

.tws-kb-sidebar__help {
	margin: 28px 0 0;
	padding-top: 16px;
	border-top: 1px solid var(--tws-border);
	font-size: 14px;
	line-height: 1.6;
	color: var(--tws-price-was);
}

/* The link inside this line was inheriting the muted body colour, so it
   read as plain text. Accent plus an underline on hover, like every other
   inline link in a sidebar. */
.tws-kb-sidebar__help a,
.tws-sidebar__note a {
	color: var(--tws-accent-text);
	font-weight: 500;
	text-decoration: none;
}

.tws-kb-sidebar__help a:hover,
.tws-sidebar__note a:hover {
	color: var(--tws-hover);
	text-decoration: underline;
}

/* --- Search results -----------------------------------------------------
   Results on the right, help on the left. The sidebar is two filled cards
   and nothing else: someone on this page has already failed to find
   something, so the page owes them a second search and a short list of
   the places people usually turn out to have wanted. */
.tws-search-card {
	margin-bottom: 14px;
	padding: 18px;
	background: #ffffff;
	border: 1px solid var(--tws-border);
	border-radius: 8px;
}

.tws-search-card--help {
	background: #faf9f7;
}

.tws-search-card__title {
	margin: 0 0 6px;
	font-size: 16px;
	font-weight: 500;
	color: var(--tws-ink);
}

.tws-search-card__text {
	margin: 0 0 14px;
	font-size: 13.5px;
	line-height: 1.55;
	color: var(--tws-price-was);
}

.tws-search-card__form { margin: 0; }

.tws-search-card__form .wp-block-search__inside-wrapper {
	border: 1px solid var(--tws-border);
	border-radius: 3px;
	background: #ffffff;
	overflow: hidden;
}

.tws-search-card__form .wp-block-search__input {
	border: 0;
	background: transparent;
	padding: 10px 12px;
	font-size: 14.5px;
	color: var(--tws-ink);
}

.tws-search-card__form .wp-block-search__input:focus { outline: 0; }

.tws-search-card__form .wp-block-search__button {
	border: 0;
	background: var(--tws-accent);
	color: var(--tws-ink);
	padding: 0 14px;
	margin: 0;
}

.tws-search-card__form .wp-block-search__button:hover {
	background: var(--tws-hover);
	color: #ffffff;
}

/* Each link carries one line saying what is behind it, so the list is
   scannable without being a wall of nav. */
.tws-sidebar .tws-search-links {
	list-style: none;
	margin: 0;
	padding: 0;
}

.tws-search-links li {
	padding: 9px 0;
	border-bottom: 1px solid var(--tws-border);
	line-height: 1.4;
}

.tws-search-links li:first-child { padding-top: 0; }
.tws-search-links li:last-child { border-bottom: 0; padding-bottom: 0; }

.tws-search-links a {
	display: block;
	font-size: 14.5px;
	font-weight: 500;
	color: var(--tws-ink);
	text-decoration: none;
}

.tws-search-links a:hover { color: var(--tws-accent-text); }

.tws-search-links span {
	display: block;
	margin-top: 2px;
	font-size: 12.5px;
	color: var(--tws-muted);
}

.tws-search-card__ask {
	margin: 16px 0 0;
	padding-top: 14px;
	border-top: 1px solid var(--tws-border);
	font-size: 13.5px;
	line-height: 1.55;
	color: var(--tws-price-was);
}

.tws-search-card__ask a { color: var(--tws-accent-text); font-weight: 500; }

/* --- Results list ------------------------------------------------------ */
.tws-search-title {
	font-size: clamp(24px, 3.2vw, 32px);
	font-weight: 400;
	color: var(--tws-ink);
}

.tws-result {
	display: flex;
	gap: 16px;
	align-items: flex-start;
	padding: 16px 0;
	border-bottom: 1px solid var(--tws-border);
}

.tws-result:last-child { border-bottom: 0; }

.tws-result__thumb {
	flex: none;
	margin: 0;
	width: 96px;
}

.tws-result__thumb img {
	display: block;
	width: 96px;
	height: 96px;
	object-fit: cover;
	border-radius: 5px;
}

.tws-result__body { flex: 1; min-width: 0; }

.tws-result__title {
	margin: 0 0 4px;
	font-size: 18px;
	font-weight: 500;
	line-height: 1.3;
}

.tws-result__title a { color: var(--tws-ink); text-decoration: none; }
.tws-result__title a:hover { color: var(--tws-accent-text); }

.tws-result__text {
	margin: 0;
	font-size: 14px;
	line-height: 1.55;
	color: var(--tws-price-was);
}

/* --- Nothing found ----------------------------------------------------- */
.tws-search-empty {
	padding: 28px;
	background: var(--tws-border-light, #f3f3f3);
	border-radius: 8px;
}

.tws-search-empty__title {
	margin: 0 0 8px;
	font-size: 22px;
	font-weight: 400;
}

.tws-search-empty p {
	margin: 0;
	max-width: 520px;
	font-size: 15px;
	color: var(--tws-price-was);
}

.tws-search-empty__ctas { margin-top: 20px; gap: 10px; }

@media (max-width: 620px) {
	.tws-result__thumb,
	.tws-result__thumb img { width: 72px; }
	.tws-result__thumb img { height: 72px; }
	.tws-result { gap: 12px; }
}

/* --- Article column ----------------------------------------------------
   The sidebar takes 360 of the 1240, so the article is ~820 wide. Prose
   is held to a readable measure inside it rather than by narrowing the
   whole column, which would leave images and galleries cramped too. */
.tws-sidebar-content .wp-block-post-content > :where(p, h2, h3, h4, ul, ol, blockquote) {
	max-width: 680px;
}

.tws-post-meta { color: var(--tws-muted); }

.tws-archive-title { font-size: clamp(26px, 3.4vw, 36px); font-weight: 400; }

.tws-archive-desc {
	max-width: 680px;
	font-size: 15px;
	color: var(--tws-price-was);
}

.tws-archive-card__title { font-size: 19px; font-weight: 500; line-height: 1.3; margin: 12px 0 6px; }
.tws-archive-card__title a { color: var(--tws-ink); text-decoration: none; }
.tws-archive-card__title a:hover { color: var(--tws-accent-text); }
.tws-archive-card__text { font-size: 14px; line-height: 1.55; color: var(--tws-price-was); }
.tws-archive-pagination { margin-top: 40px; }

@media (max-width: 620px) {
	.tws-archive-grid { grid-template-columns: minmax(0, 1fr) !important; }
}

/* --- Previous / next post ----------------------------------------------
   Two cards rather than two bare links, so the pair reads as navigation
   and not as stray body text. Next is pinned to the second column: when a
   post has no previous, the single card should still sit on the right
   where it belongs rather than sliding under the article. */
.tws-post-nav {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 16px;
	margin-bottom: 8px;
}

/* WP's flow layout puts margin-block-start on every child but the first,
   and does it with a selector that outranks a single class. Matching its
   specificity and landing later in the file is what actually wins. */
.tws-post-nav.wp-block-group > * { margin-block-start: 0; margin-block-end: 0; }

.tws-post-nav .wp-block-post-navigation-link {
	padding: 14px 16px;
	font-size: 15px;
	line-height: 1.45;
	background: #fff;
	border: 1px solid var(--tws-border);
	border-radius: 6px;
}

.tws-post-nav .post-navigation-link-next {
	grid-column: 2;
	text-align: right;
}

.tws-post-nav .wp-block-post-navigation-link a { color: var(--tws-ink); text-decoration: none; }
.tws-post-nav .wp-block-post-navigation-link a:hover { color: var(--tws-accent-text); }

.tws-post-nav .post-navigation-link__label {
	display: block;
	margin-bottom: 2px;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--tws-muted);
}

@media (max-width: 620px) {
	.tws-post-nav { grid-template-columns: minmax(0, 1fr); }
	.tws-post-nav .post-navigation-link-next { grid-column: 1; text-align: left; }
}

/* --- Comments -----------------------------------------------------------
   The thread was invisible because the comment loop in templates/single.html
   had no inner blocks: WordPress walked the comments and emitted an empty
   list item for each one, so the heading could count "2 responses" above a
   blank space. The loop prints a comment now, and this is its dressing.

   Full width of the content column rather than held to the prose measure:
   a comment card is a card, and leaving it short made the thread look like
   it belonged to something narrower than the article above it. The text
   inside still gets a measure of its own, below. */
.tws-comments {
	margin-top: 48px;
	padding-top: 32px;
	border-top: 1px solid var(--tws-border);
}

.tws-comments__title {
	margin: 0 0 24px;
	font-size: 22px;
	font-weight: 500;
	line-height: 1.3;
}

/* The loop emits <ol>, and replies nest another <ol> inside the parent
   item. Browser list styling has no business here; the indent on the
   nested list is what shows a reply is a reply. */
.wp-block-comment-template,
.wp-block-comment-template ol {
	list-style: none;
	margin: 0;
	padding: 0;
}

.wp-block-comment-template > li + li,
.wp-block-comment-template ol > li + li { margin-top: 16px; }

.wp-block-comment-template ol {
	margin-top: 16px;
	padding-left: 28px;
}

/* One comment ----------------------------------------------------------- */
.tws-comment {
	gap: 14px;
	padding: 18px 20px;
	background: #fff;
	border: 1px solid var(--tws-border);
	border-radius: 6px;
}

/* Flex groups default to centring their children, which would float a
   small avatar against the middle of a long comment. */
.tws-comment.wp-block-group { align-items: flex-start; }

.tws-comment__avatar { flex: 0 0 auto; line-height: 0; }
.tws-comment__avatar img { display: block; border-radius: 50%; }

/* min-width:0 so a long unbroken URL in a comment shrinks the column
   instead of pushing the card wider than its grid cell. */
.tws-comment__body { flex: 1 1 auto; min-width: 0; }

/* The body is a flow group, so WP would put its 24px block gap between the
   name row and the comment text — far too much inside a card this size.
   Spacing here is set by the meta row and the reply link instead. */
.tws-comment__body.wp-block-group > * { margin-block-start: 0; margin-block-end: 0; }

.tws-comment__meta.wp-block-group {
	align-items: baseline;
	gap: 4px 10px;
	margin-bottom: 6px;
}

.tws-comment__author { font-size: 15px; font-weight: 500; }
.tws-comment__author a { color: var(--tws-ink); text-decoration: none; }
.tws-comment__author a:hover { color: var(--tws-accent-text); }

.tws-comment__date,
.tws-comment__edit { font-size: 13px; }
.tws-comment__date a,
.tws-comment__edit a { color: var(--tws-muted); text-decoration: none; }
.tws-comment__date a:hover,
.tws-comment__edit a:hover { color: var(--tws-accent-text); }

/* The card spans the column, but the sentences inside it do not: a comment
   is prose, and an 800px line is tiring. The measure sits on the text alone
   so the card, its border and the avatar row still use the full width. */
.tws-comment__text {
	max-width: 680px;
	font-size: 15px;
	line-height: 1.6;
	overflow-wrap: break-word;
}
.tws-comment__text p { margin: 0 0 10px; }
.tws-comment__text > :last-child { margin-bottom: 0; }
.tws-comment__text a { color: var(--tws-accent-text); }

.tws-comment__reply { margin-top: 10px; font-size: 14px; }
.tws-comment__reply a {
	color: var(--tws-accent-text);
	font-weight: 500;
	text-decoration: none;
}
.tws-comment__reply a:hover { text-decoration: underline; }

/* A comment held for moderation. Says so quietly rather than looking like
   the comment failed to post. */
.tws-comment .comment-awaiting-moderation {
	display: block;
	margin-bottom: 8px;
	font-size: 13px;
	color: var(--tws-muted);
}

.tws-comments__pagination { margin-top: 24px; }

/* --- Comment form ------------------------------------------------------- */
.tws-comment-form { margin-top: 40px; }

.tws-comment-form .comment-reply-title {
	margin: 0 0 8px;
	font-size: 20px;
	font-weight: 500;
}

.tws-comment-form .comment-notes,
.tws-comment-form .akismet_comment_form_privacy_notice,
.tws-comment-form .form-submit + p {
	font-size: 13px;
	color: var(--tws-muted);
}

.tws-comment-form p { margin: 0 0 16px; }
.tws-comment-form .form-submit { margin-bottom: 0; }

.tws-comment-form label {
	display: block;
	margin-bottom: 6px;
	font-size: 14px;
}

.tws-comment-form input[type="text"],
.tws-comment-form input[type="email"],
.tws-comment-form input[type="url"],
.tws-comment-form textarea {
	width: 100%;
	padding: 10px 12px;
	font-family: inherit;
	font-size: 15px;
	color: var(--tws-ink);
	background: #fff;
	border: 1px solid var(--tws-border);
	border-radius: 5px;
}

.tws-comment-form textarea { min-height: 150px; resize: vertical; }

.tws-comment-form input[type="text"]:focus,
.tws-comment-form input[type="email"]:focus,
.tws-comment-form input[type="url"]:focus,
.tws-comment-form textarea:focus {
	border-color: var(--tws-accent-border);
	outline: 2px solid var(--tws-accent);
	outline-offset: 1px;
}

/* Replying to someone: WordPress drops a "Cancel reply" link beside the
   form heading, which is easy to miss when it inherits body colour. */
.tws-comment-form #cancel-comment-reply-link {
	margin-left: 10px;
	font-size: 14px;
	font-weight: 500;
	color: var(--tws-accent-text);
}

@media (max-width: 620px) {
	.tws-comment { padding: 16px; gap: 12px; }
	.tws-comment__avatar img { width: 36px; height: 36px; }
	.wp-block-comment-template ol { padding-left: 16px; }
}

/* --- Sidebar widgets ----------------------------------------------------
   Ported from the four Astra widgets on production: search, the WooCommerce
   category list, the ebook promo and the Idaho note. The category list is
   the dynamic Woo block, so it tracks the real category tree and counts
   instead of a hardcoded list that would rot. */

.tws-sidebar .wp-block-search { margin-bottom: 28px; }

.tws-sidebar .wp-block-search__inside-wrapper {
	border: 1px solid var(--tws-border);
	border-radius: 3px;
	background: #ffffff;
}

.tws-sidebar .wp-block-search__inside-wrapper:focus-within {
	border-color: var(--tws-accent-border);
}

.tws-sidebar .wp-block-search__input {
	border: 0;
	background: transparent;
	padding: 9px 12px;
	font-size: 15px;
	color: var(--tws-ink);
}

.tws-sidebar .wp-block-search__input:focus { outline: 0; }

.tws-sidebar .wp-block-search__button {
	border: 0;
	background: transparent;
	color: var(--tws-muted);
	padding: 0 10px;
}

.tws-sidebar .wp-block-search__button:hover { color: var(--tws-accent-text); }

/* The generic .tws-sidebar ul rules above handle the top level; these are
   for the nested tree and the counts the Woo block prints. */
.tws-sidebar .wc-block-product-categories-list ul,
.tws-sidebar__cats ul {
	margin: 2px 0 0 14px;
}

/* Top-level categories read as the headings of the list; the children sit
   under them in the regular link colour. */
.tws-sidebar__cats > li > a {
	color: var(--tws-ink);
	font-weight: 500;
}

.tws-sidebar__cats > li {
	margin-bottom: 6px;
}

.tws-sidebar__cats > li > a:hover { color: var(--tws-accent-text); }

.tws-sidebar .wc-block-product-categories-list-item-count {
	color: #999999;
	font-size: 13px;
}

/* The promo keeps its own 225px artwork width rather than stretching across
   the 360px column and going soft. */
.tws-sidebar__promo { margin: 0 0 24px; }

.tws-sidebar__promo img {
	display: block;
	width: 100%;
	max-width: 225px;
	height: auto;
}

.tws-sidebar__note {
	margin: 0;
	font-size: 15px;
	color: var(--tws-price-was);
	line-height: 1.6;
}

/* ===============================================================
   PRODUCT CARDS

   Applies to both the classic WooCommerce loop (ul.products > li.product)
   and the block-based grids (Product Collection / Products / All Products),
   because the store runs a mix of the two during the migration.
   =============================================================== */

.woocommerce ul.products li.product,
.wc-block-grid__product,
.wc-block-product-template .wc-block-product,
.wp-block-post.product {
	display: flex;
	flex-direction: column;
	text-align: left;
}

/* Push the button to the bottom so every card in a row lines up, however
   long the product titles run. */
.woocommerce ul.products li.product .button,
.wc-block-grid__product .wp-block-button,
.wc-block-product-template .wp-block-button,
.wp-block-post.product .wp-block-button {
	margin-top: auto;
}

.woocommerce ul.products li.product .woocommerce-loop-product__title,
.wc-block-grid__product-title,
.wc-block-components-product-name {
	font-size: 18px;
	font-weight: 400;
	line-height: 1.35;
	color: var(--tws-ink);
	margin: 14px 0 8px;
}

/* --- Prices -------------------------------------------------------------
 * The regular price reads as ordinary text in the heading colour — it is
 * not a call to action and shouldn't compete with the button.
 *
 * On sale, the old price is struck through in grey and the new price is
 * green. Green rather than orange for two reasons: orange is already the
 * button colour, so a second orange element dilutes the actual CTA; and
 * green reads as "saving" rather than "warning" (red) in most Western
 * retail contexts.
 * ---------------------------------------------------------------------- */
.woocommerce ul.products li.product .price,
.wc-block-grid__product-price,
.wc-block-components-product-price {
	font-size: 17px;
	font-weight: 500;
	color: var(--tws-ink);
	margin: 0 0 16px;
}

/* Struck-through original price. */
.woocommerce ul.products li.product .price del,
.wc-block-grid__product-price del,
.wc-block-components-product-price del,
.woocommerce div.product p.price del,
.wc-block-components-product-price__regular {
	color: var(--tws-price-was);
	font-weight: 400;
	text-decoration: line-through;
	margin-right: 6px;
}

/* The active sale price. */
.woocommerce ul.products li.product .price ins,
.wc-block-grid__product-price ins,
.wc-block-components-product-price ins,
.woocommerce div.product p.price ins,
.wc-block-components-product-price__value.is-discounted {
	color: var(--tws-sale);
	font-weight: 700;
	text-decoration: none;
	background: none;
}

/* --- Buttons ------------------------------------------------------------
 * Outline rather than solid. Across a grid of 8-12 products, solid orange
 * buttons dominate the page, compete with the product photography, and
 * dilute the single Find My Stove CTA in the header. Outline keeps them
 * clearly actionable while letting the products lead; the solid fill is
 * kept for hover/focus so the affordance stays obvious.
 * ---------------------------------------------------------------------- */
.woocommerce ul.products li.product .button,
.woocommerce ul.products li.product a.add_to_cart_button,
.wc-block-grid__product .wp-block-button__link,
.wc-block-product-template .wp-block-button__link,
.wp-block-post.product .wp-block-button__link {
	display: block;
	width: 100%;
	text-align: center;
	padding: 12px 18px;
	background: transparent;
	color: var(--tws-accent-text);
	border: 1px solid var(--tws-accent-border);
	border-radius: 3px;
	font-size: 14px;
	font-weight: 500;
	line-height: 1.3;
	letter-spacing: 0.01em;
	text-decoration: none;
	box-sizing: border-box;
	transition: background-color 0.15s ease, color 0.15s ease;
}

.woocommerce ul.products li.product .button:hover,
.woocommerce ul.products li.product .button:focus-visible,
.woocommerce ul.products li.product a.add_to_cart_button:hover,
.wc-block-grid__product .wp-block-button__link:hover,
.wc-block-grid__product .wp-block-button__link:focus-visible,
.wc-block-product-template .wp-block-button__link:hover,
.wc-block-product-template .wp-block-button__link:focus-visible,
.wp-block-post.product .wp-block-button__link:hover,
.wp-block-post.product .wp-block-button__link:focus-visible {
	background: var(--tws-hover);
	color: #ffffff;
	border-color: var(--tws-hover);
}

/* "View cart" link after adding — present but quiet. */
.woocommerce ul.products li.product .added_to_cart {
	display: inline-block;
	margin-left: 10px;
	font-size: 14px;
	color: var(--tws-accent-text);
	text-decoration: underline;
}

/* --- Star ratings ------------------------------------------------------ */
.woocommerce ul.products li.product .star-rating,
.wc-block-grid__product-rating .star-rating,
.wc-block-components-product-rating {
	color: var(--tws-accent-border);
	margin: 0 0 10px;
	font-size: 14px;
}

/* --- Grid ---------------------------------------------------------------
 * WooCommerce's classic loop still uses FLOATED list items, which is why the
 * buttons wouldn't line up: floats produce no equal-height rows, so the
 * `margin-top:auto` that should push a button to the bottom of its card has
 * nothing to push against.
 *
 * Converting the list to CSS Grid makes every card in a row stretch to the
 * same height, which is what actually enables the alignment below. The
 * float/width/margin resets undo WooCommerce's inline column maths.
 * ---------------------------------------------------------------------- */
.woocommerce ul.products {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
	gap: 44px 30px;
	margin: 0 0 0 !important;
	padding: 0;
	list-style: none;
}

.woocommerce ul.products::before,
.woocommerce ul.products::after {
	content: none !important;
}

.woocommerce ul.products.columns-1 { grid-template-columns: 1fr; }
.woocommerce ul.products.columns-2 { grid-template-columns: repeat(2, 1fr); }
.woocommerce ul.products.columns-3 { grid-template-columns: repeat(3, 1fr); }
.woocommerce ul.products.columns-4 { grid-template-columns: repeat(4, 1fr); }
.woocommerce ul.products.columns-5 { grid-template-columns: repeat(5, 1fr); }
.woocommerce ul.products.columns-6 { grid-template-columns: repeat(6, 1fr); }

@media (max-width: 1024px) {
	.woocommerce ul.products.columns-5,
	.woocommerce ul.products.columns-6,
	.woocommerce ul.products.columns-4 {
		grid-template-columns: repeat(3, 1fr);
	}
}

@media (max-width: 780px) {
	.woocommerce ul.products,
	.woocommerce ul.products.columns-3,
	.woocommerce ul.products.columns-4,
	.woocommerce ul.products.columns-5,
	.woocommerce ul.products.columns-6 {
		grid-template-columns: repeat(2, 1fr);
		gap: 32px 18px;
	}
}

@media (max-width: 420px) {
	.woocommerce ul.products,
	.woocommerce ul.products.columns-2,
	.woocommerce ul.products.columns-3,
	.woocommerce ul.products.columns-4 {
		grid-template-columns: 1fr;
	}
}

/* Undo WooCommerce's float-based column layout. */
.woocommerce ul.products li.product {
	float: none !important;
	clear: none !important;
	width: auto !important;
	margin: 0 !important;
	height: 100%;
	/* The sale badge is positioned against this card. */
	position: relative;
}

/* Pushing the PRICE (not the button) to the bottom aligns both the price row
   and the button row across a whole grid row, however many lines the titles
   above them wrap to. */
.woocommerce ul.products li.product .price {
	margin-top: auto;
}

/* The image box keeps a consistent aspect so cards start from a common
   baseline even when source images differ. */
.woocommerce ul.products li.product img {
	width: 100%;
	height: auto;
	aspect-ratio: 1 / 1;
	object-fit: contain;
	background: #ffffff;
	margin-bottom: 0;
}

/* --- Single product page ----------------------------------------------- */
.woocommerce div.product p.price {
	font-size: 24px;
	font-weight: 500;
	color: var(--tws-ink);
}

.woocommerce div.product p.price ins {
	color: var(--tws-sale);
	font-weight: 700;
}

/* The single product page keeps a solid button — there is only one, it is
   the primary action on the page, and it isn't competing with siblings. */
.woocommerce div.product .single_add_to_cart_button {
	background: var(--tws-accent);
	color: var(--tws-ink);
	border: 1px solid var(--tws-accent);
	border-radius: 3px;
	padding: 13px 28px;
	font-size: 15px;
	font-weight: 500;
}

.woocommerce div.product .single_add_to_cart_button:hover,
.woocommerce div.product .single_add_to_cart_button:focus-visible {
	background: var(--tws-hover);
	border-color: var(--tws-hover);
	color: #ffffff;
}

/* --- Programmatic focus must not draw a ring -----------------------------
   The kit builder moves focus to each step's heading so screen readers
   announce the new step (the 8.3.7 accessibility work). That heading carries
   tabindex="-1", and the browser then paints this theme's focus ring around
   it — which reads as a stray orange box around "Build My Kit". Astra styled
   no focus ring, so it never showed before.

   A tabindex="-1" element cannot be reached with Tab, so hiding its ring
   costs nothing for keyboard users; every real focus target keeps its ring
   through the :focus-visible rules elsewhere in this file. */
[tabindex="-1"]:focus,
[tabindex="-1"]:focus-visible {
	outline: none;
	box-shadow: none;
}

/* ===============================================================
   KNOWLEDGEBASE HUB  (/learn/ and pages like it)

   The page content is plain core blocks — headings, columns, groups,
   buttons — carrying only tws-kb-* class names. All of the styling lives
   here rather than in block attributes, so the markup stays short, stays
   valid in the editor, and can be restyled without touching the page.
   =============================================================== */

.tws-kb-hero__title { margin-bottom: 6px; }

.tws-kb-hero__sub {
	margin: 0 0 32px;
	font-size: clamp(17px, 2vw, 20px);
	line-height: 1.45;
	color: var(--tws-price-was);
}

/* --- Intro row ---------------------------------------------------------- */
.tws-kb-intro { margin-bottom: 40px; }
.tws-kb-intro__title { margin-top: 0; font-size: clamp(20px, 2.2vw, 24px); }
.tws-kb-intro__image img { border-radius: 6px; display: block; }

/* --- Jump links ---------------------------------------------------------- */
.tws-kb-jump__label {
	margin: 0 0 10px;
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--tws-muted);
}

.tws-kb-jump { margin-bottom: 8px; gap: 10px; }

.tws-kb-jump .wp-block-button__link {
	padding: 9px 16px;
	font-size: 14px;
	font-weight: 500;
	border-radius: 3px;
}

/* --- Section headings ----------------------------------------------------
   scroll-margin-top so a jump link doesn't park the heading underneath the
   sticky header. */
.tws-kb-section,
.tws-about-section {
	margin: 56px 0 20px;
	padding-bottom: 12px;
	border-bottom: 1px solid var(--tws-border);
	font-size: clamp(22px, 2.6vw, 28px);
	font-weight: 500;
	scroll-margin-top: calc(var(--tws-header-h) + 20px);
}

/* --- Card grid -----------------------------------------------------------
   Core columns stack on their own below 782px, so the two-up grid needs no
   media query of its own. The row gap is set here because columns only
   space themselves horizontally. */
.tws-kb-grid { margin-bottom: 24px; }

.tws-kb-card,
.tws-about-card {
	height: 100%;
	padding: 22px 24px;
	background: #ffffff;
	border: 1px solid var(--tws-border);
	border-radius: 6px;
	box-sizing: border-box;
}

.tws-kb-card__title,
.tws-about-card__title {
	margin: 0 0 8px;
	font-size: 18px;
	font-weight: 500;
	line-height: 1.35;
}

.tws-kb-card__title a { color: var(--tws-ink); text-decoration: none; }
.tws-kb-card__title a:hover,
.tws-kb-card__title a:focus-visible { color: var(--tws-accent-text); }

.tws-kb-card__text,
.tws-about-card__text {
	margin: 0;
	font-size: 15px;
	line-height: 1.6;
	color: var(--tws-price-was);
}

.tws-kb-card__text a { color: var(--tws-accent-text); font-weight: 500; }

.tws-kb-card__list { margin: 10px 0 0; padding-left: 20px; font-size: 15px; line-height: 1.7; }
.tws-kb-card__list a { color: var(--tws-accent-text); }

/* An empty column pads an odd-numbered row; it must not draw a card. */
.tws-kb-grid .wp-block-column:empty { padding: 0; border: 0; background: none; }

/* --- Card with a pinned action -------------------------------------------
   /manuals-and-downloads/ ends every card with a download button, and the
   descriptions run from four words to four lines, so without this the
   buttons sit at a different height in every card of a row. The card
   becomes a column and the button row takes up the slack.

   The cards that use this are flow-layout groups rather than constrained
   ones on purpose: a constrained group gives its children automatic left
   and right margins, and in a flex column those centre each child at its
   content width instead of stretching it to the card.

   padding-top is the floor: margin-top:auto collapses to nothing in the
   tallest card of a row, which would leave its button touching the text. */
.tws-kb-card--stack {
	display: flex;
	flex-direction: column;
}

.tws-kb-card--stack .wp-block-buttons {
	margin-top: auto;
	padding-top: 18px;
}

/* --- Customer story cards ------------------------------------------------ */
.tws-kb-stories { margin-top: 8px; }

.tws-kb-story {
	height: 100%;
	background: #ffffff;
	border: 1px solid var(--tws-border);
	border-radius: 6px;
	overflow: hidden;
}

.tws-kb-story__thumb { margin: 0; }
.tws-kb-story__thumb img { display: block; width: 100%; }

.tws-kb-story__title {
	margin: 0;
	padding: 16px 18px;
	font-size: 17px;
	font-weight: 500;
	line-height: 1.35;
}

.tws-kb-story__title a { color: var(--tws-ink); text-decoration: none; }
.tws-kb-story__title a:hover,
.tws-kb-story__title a:focus-visible { color: var(--tws-accent-text); }

/* --- Narrow screens ------------------------------------------------------
   Core stacks the columns itself; these just tidy the gaps that are left. */
@media (max-width: 781px) {
	.tws-kb-intro { margin-bottom: 28px; }
	.tws-kb-intro__image { margin-top: 18px; }
	.tws-kb-section,
	.tws-about-section { margin-top: 40px; }
	.tws-kb-grid .wp-block-column:empty { display: none; }
}

/* ===============================================================
   CART

   The store uses WooCommerce's CLASSIC (shortcode) cart:

     .woocommerce
       .woocommerce-notices-wrapper
       form.woocommerce-cart-form
         table.shop_table.cart            items, then a td.actions row
       .cart-collaterals
         .cross-sells                     "You may be interested in…"
         .cart_totals                     totals + Proceed to checkout

   THE PAGE HAD NO CART CSS AT ALL before this block. Three things were
   stacked on top of each other, measured on staging:

   1. /cart/ holds [woocommerce_cart], a shortcode, so has_blocks() is false
      and the Beaver Builder legacy shim flagged the page and clamped it to
      an 860px reading measure meant for prose. Fixed at source — the shim
      now steps aside on the WooCommerce pages (see functions.php).

   2. WooCommerce caps .woocommerce at 1000px in block themes, and floats
      .cross-sells left at 48% and .cart_totals right at 48%. That float pair
      is what left a wide empty strip beside the totals.

   3. Nothing kept the actions row's three controls apart, so "Update cart"
      printed on top of "Empty Cart".

   WHY .cart-collaterals IS display:contents
      The totals belong beside the items table and the cross-sells belong
      underneath it, full width — but WooCommerce wraps both in one div, so
      as a single grid item they would have to share a cell. display:contents
      dissolves the wrapper and lets each child take its own grid position.

   WHY td.actions IS NOT A FLEXBOX
      It is the obvious fix and it does not work: a <td> set to display:flex
      leaves the table's sizing algorithm, and the cell collapsed from 800px
      to 215px, taking the table's width with it. Measured, not guessed. The
      cell stays a table-cell and its three controls are floated instead.
   =============================================================== */

/* Both pages run at the site's 1240px content width. Without this they take
   the 1400px wide-size, because WooCommerce's output lands in an alignwide
   content block. */
.woocommerce-cart .wp-block-post-content,
.woocommerce-checkout .wp-block-post-content {
	max-width: 1240px;
}

.woocommerce-cart .entry-content > .woocommerce,
.woocommerce-checkout .entry-content > .woocommerce {
	max-width: none;
}

.woocommerce-cart .cart-collaterals::before,
.woocommerce-cart .cart-collaterals::after {
	content: none !important;
}

/* The floats have to go at every width, or they escape the grid cells. */
.woocommerce-cart .cart-collaterals .cart_totals,
.woocommerce-cart .cart-collaterals .cross-sells {
	float: none !important;
	width: auto !important;
}

@media (min-width: 900px) {
	.woocommerce-cart .entry-content > .woocommerce {
		display: grid;
		grid-template-columns: minmax(0, 1fr) minmax(320px, 400px);
		column-gap: 40px;
		row-gap: 0;
		align-items: start;
	}

	/* Notices speak for the whole page, not for one column. */
	.woocommerce-cart .entry-content > .woocommerce > .woocommerce-notices-wrapper {
		grid-column: 1 / -1;
		grid-row: 1;
	}

	.woocommerce-cart .woocommerce-cart-form {
		grid-column: 1;
		grid-row: 2;
	}

	.woocommerce-cart .cart-collaterals { display: contents; }

	.woocommerce-cart .cart-collaterals .cart_totals {
		grid-column: 2;
		grid-row: 2;
		/* Keeps the total and the checkout button in view while quantities
		   are being edited. */
		position: sticky;
		top: calc(var(--tws-header-h) + 20px);
	}

	.woocommerce-cart .cart-collaterals .cross-sells {
		grid-column: 1;
		grid-row: 3;
		margin: 40px 0 0 !important;
	}
}

/* --- Items table -------------------------------------------------------- */
.woocommerce-cart table.shop_table.cart {
	width: 100%;
	margin: 0;
	border: 1px solid var(--tws-border);
	border-radius: 4px;
	border-collapse: separate;
	border-spacing: 0;
	background: #ffffff;
	font-size: 15px;
}

.woocommerce-cart table.shop_table.cart thead th {
	padding: 14px 12px;
	background: #fafafa;
	border-bottom: 1px solid var(--tws-border);
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--tws-muted);
	text-align: left;
}

.woocommerce-cart table.shop_table.cart td {
	padding: 18px 12px;
	border-top: 1px solid var(--tws-border);
	vertical-align: middle;
	line-height: 1.35;
}

.woocommerce-cart table.shop_table.cart tbody tr:first-child td {
	border-top: none;
}

.woocommerce-cart td.product-remove,
.woocommerce-cart th.product-remove { width: 44px; text-align: center; }

.woocommerce-cart td.product-thumbnail,
.woocommerce-cart th.product-thumbnail { width: 92px; }

.woocommerce-cart td.product-thumbnail img {
	display: block;
	width: 72px;
	height: 72px;
	object-fit: contain;
	background: #ffffff;
	border: 1px solid var(--tws-border);
	border-radius: 4px;
}

/* The product name gets the slack. Without a width it lost out to the two
   money columns and wrapped to four lines. */
.woocommerce-cart td.product-name,
.woocommerce-cart th.product-name { width: 40%; }

.woocommerce-cart td.product-name a {
	color: var(--tws-ink);
	font-weight: 500;
	text-decoration: none;
}

.woocommerce-cart td.product-name a:hover { color: var(--tws-accent-text); }

/* Variation and bundle detail printed under the title. */
.woocommerce-cart td.product-name .variation,
.woocommerce-cart td.product-name dl.variation {
	margin: 6px 0 0;
	font-size: 13px;
	line-height: 1.5;
	color: var(--tws-muted);
}

.woocommerce-cart td.product-price,
.woocommerce-cart td.product-subtotal,
.woocommerce-cart th.product-price,
.woocommerce-cart th.product-subtotal { text-align: right; }

.woocommerce-cart td.product-subtotal { font-weight: 500; }

/* The remove "x" is a destructive control — quiet until it is aimed at. */
.woocommerce-cart td.product-remove a.remove {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 26px;
	height: 26px;
	border-radius: 50%;
	font-size: 18px;
	line-height: 1;
	color: var(--tws-muted) !important;
	text-decoration: none;
	background: transparent;
}

.woocommerce-cart td.product-remove a.remove:hover,
.woocommerce-cart td.product-remove a.remove:focus-visible {
	background: #fdeaea;
	color: #b3261e !important;
}

/* --- Quantity ----------------------------------------------------------- */
.woocommerce-cart td.product-quantity,
.woocommerce-cart th.product-quantity { width: 110px; }

.woocommerce-cart .quantity input.qty {
	width: 74px;
	padding: 9px 6px 9px 10px;
	border: 1px solid #949494;
	border-radius: 3px;
	font-family: inherit;
	font-size: 15px;
	color: var(--tws-ink);
	background: #ffffff;
	text-align: left;
}

.woocommerce-cart .quantity input.qty:focus {
	outline: 2px solid var(--tws-accent-deep);
	outline-offset: 1px;
	border-color: var(--tws-accent-deep);
}

/* --- Actions row --------------------------------------------------------
   Coupon group floated left, the two secondary actions floated right. In
   source order Update cart comes first, so it lands furthest right with
   Empty Cart beside it. overflow:hidden on the cell contains both floats so
   the row keeps its height. */
.woocommerce-cart table.shop_table.cart td.actions {
	padding: 18px 12px;
	background: #fafafa;
	border-top: 1px solid var(--tws-border);
	overflow: hidden;
	text-align: left;
}

.woocommerce-cart td.actions::before,
.woocommerce-cart td.actions::after { content: none !important; }

.woocommerce-cart td.actions .coupon {
	float: left;
	display: flex;
	gap: 10px;
	width: min(430px, 56%);
	padding: 0 !important;
	margin: 0;
}

.woocommerce-cart td.actions .coupon input#coupon_code {
	flex: 1 1 auto;
	min-width: 0;
	width: auto !important;
	margin: 0;
	padding: 11px 12px;
	border: 1px solid #949494;
	border-radius: 3px;
	font-family: inherit;
	font-size: 15px;
	color: var(--tws-ink);
	background: #ffffff;
	box-sizing: border-box;
}

.woocommerce-cart td.actions .coupon input#coupon_code:focus {
	outline: 2px solid var(--tws-accent-deep);
	outline-offset: 1px;
	border-color: var(--tws-accent-deep);
}

/* Every button in this row is secondary: the primary action on the cart is
   Proceed to checkout, and three solid orange buttons would bury it. */
.woocommerce-cart td.actions .button,
.woocommerce-cart td.actions button.button,
.woocommerce-cart td.actions a.button {
	width: auto;
	margin: 0;
	padding: 11px 20px;
	background: transparent;
	color: var(--tws-accent-text);
	border: 1px solid var(--tws-accent-border);
	border-radius: 3px;
	font-family: inherit;
	font-size: 14px;
	font-weight: 500;
	line-height: 1.3;
	white-space: nowrap;
	cursor: pointer;
	text-decoration: none;
	box-sizing: border-box;
	transition: background-color 0.15s ease, color 0.15s ease;
}

.woocommerce-cart td.actions .coupon button { float: none; }

.woocommerce-cart td.actions > button[name="update_cart"],
.woocommerce-cart td.actions > input[name="update_cart"] {
	float: right;
	margin-left: 10px;
}

.woocommerce-cart td.actions > a.button.empty_cart { float: right; }

.woocommerce-cart td.actions .button:hover,
.woocommerce-cart td.actions .button:focus-visible {
	background: var(--tws-hover);
	border-color: var(--tws-hover);
	color: #ffffff;
}

/* "Update cart" is disabled until a quantity actually changes. It has to
   look disabled, or it reads as a broken button. */
.woocommerce-cart td.actions .button[disabled],
.woocommerce-cart td.actions .button:disabled { opacity: 0.45; cursor: not-allowed; }

.woocommerce-cart td.actions .button[disabled]:hover {
	background: transparent;
	color: var(--tws-accent-text);
	border-color: var(--tws-accent-border);
}

/* Emptying the cart throws work away — rendered as a link rather than a
   button so it is hard to hit by accident. */
.woocommerce-cart td.actions a.button.empty_cart {
	border-color: transparent;
	padding-left: 8px;
	padding-right: 8px;
	color: var(--tws-muted);
}

.woocommerce-cart td.actions a.button.empty_cart:hover,
.woocommerce-cart td.actions a.button.empty_cart:focus-visible {
	background: transparent;
	border-color: transparent;
	color: #b3261e;
	text-decoration: underline;
}

/* --- Totals card --------------------------------------------------------- */
.woocommerce-cart .cart_totals {
	background: #ffffff;
	border: 1px solid var(--tws-border);
	border-radius: 4px;
	padding: 22px 24px;
	box-sizing: border-box;
}

.woocommerce-cart .cart_totals h2 {
	margin: 0 0 14px;
	padding-bottom: 12px;
	border-bottom: 1px solid var(--tws-border);
	font-size: 20px;
	font-weight: 500;
	color: var(--tws-ink);
}

.woocommerce-cart .cart_totals table.shop_table {
	width: 100%;
	margin: 0;
	border: none;
	border-collapse: collapse;
	font-size: 15px;
}

.woocommerce-cart .cart_totals table.shop_table th,
.woocommerce-cart .cart_totals table.shop_table td {
	padding: 11px 0;
	border: none;
	border-bottom: 1px solid var(--tws-border);
	vertical-align: top;
	box-sizing: border-box;
}

.woocommerce-cart .cart_totals table.shop_table th {
	width: 45%;
	font-weight: 500;
	color: var(--tws-ink);
	text-align: left;
}

.woocommerce-cart .cart_totals table.shop_table td { text-align: right; }

.woocommerce-cart .cart_totals tr.order-total th,
.woocommerce-cart .cart_totals tr.order-total td {
	border-bottom: none;
	padding-top: 14px;
}

.woocommerce-cart .cart_totals tr.order-total td .amount {
	font-size: 20px;
	font-weight: 700;
	color: var(--tws-ink);
}

/* Shipping options stack inside their cell rather than running off it. */
.woocommerce-cart .cart_totals #shipping_method {
	margin: 0;
	padding: 0;
	list-style: none;
	text-align: right;
}

.woocommerce-cart .cart_totals #shipping_method li { margin: 0 0 6px; }
.woocommerce-cart .cart_totals #shipping_method li:last-child { margin-bottom: 0; }

.woocommerce-cart .cart_totals .woocommerce-shipping-destination,
.woocommerce-cart .cart_totals .shipping-calculator-button { font-size: 13px; }

.woocommerce-cart .cart_totals .woocommerce-shipping-destination { color: var(--tws-muted); }

/* Proceed to checkout — the one solid button on the page. border-box or the
   padding pushes it 25px past the edge of the card. */
.woocommerce-cart .wc-proceed-to-checkout { padding: 20px 0 0; }

.woocommerce-cart .wc-proceed-to-checkout a.checkout-button {
	display: block;
	width: 100%;
	margin: 0;
	padding: 15px 24px;
	background: var(--tws-accent);
	color: var(--tws-ink);
	border: 1px solid var(--tws-accent);
	border-radius: 3px;
	font-size: 16px;
	font-weight: 600;
	text-align: center;
	text-decoration: none;
	box-sizing: border-box;
}

.woocommerce-cart .wc-proceed-to-checkout a.checkout-button:hover,
.woocommerce-cart .wc-proceed-to-checkout a.checkout-button:focus-visible {
	background: var(--tws-hover);
	border-color: var(--tws-hover);
	color: #ffffff;
}

.woocommerce-cart .cross-sells h2 { font-size: 18px; font-weight: 500; margin: 0 0 14px; }

/* --- The sale, where the decision is made --------------------------------
   functions.php puts <del>/<ins> back into the Price and Subtotal cells, the
   checkout's order review and the mini cart. The product page's own del/ins
   rules are scoped to .price selectors that cannot reach a table cell, so the
   treatment is repeated here: struck grey for the old figure, green for what
   is actually being charged.

   Stacked rather than side by side. Two figures on one line made both money
   columns wide enough to squeeze the product name to four lines. */
.woocommerce-cart td.product-price del,
.woocommerce-cart td.product-subtotal del,
.woocommerce-checkout td.product-total del,
.woocommerce-mini-cart del,
.widget_shopping_cart del {
	color: var(--tws-price-was);
	font-weight: 400;
	text-decoration: line-through;
	opacity: 1;
}

.woocommerce-cart td.product-price del,
.woocommerce-cart td.product-subtotal del,
.woocommerce-checkout td.product-total del {
	display: block;
	font-size: 13px;
}

.woocommerce-cart td.product-price ins,
.woocommerce-cart td.product-subtotal ins,
.woocommerce-checkout td.product-total ins,
.woocommerce-mini-cart ins,
.widget_shopping_cart ins {
	display: inline;
	color: var(--tws-sale);
	font-weight: 700;
	text-decoration: none;
	background: none;
}

.woocommerce-mini-cart del,
.widget_shopping_cart del { margin-right: 5px; }

/* --- The savings block ---------------------------------------------------
   WooCommerce prints one totals row per coupon, and this theme adds its own
   sale-savings row on top. A cart with a sale and two coupons therefore ran
   four rows of discount before reaching the total, and none of them answered
   the question being asked, which is "how much am I saving". functions.php
   collapses them into one headline figure with the detail underneath.

   The rows this replaces are hidden rather than removed: cart-totals.php and
   review-order.php emit the coupon rows inline with no filter to suppress
   them, and overriding both templates to delete four lines would mean owning
   two copies that go stale on every WooCommerce update. The block only ever
   renders when there is something to show, and a coupon always produces a
   line in it, so there is no state in which this hides a row without
   replacing it. */
.woocommerce-cart .cart_totals tr.cart-discount,
.woocommerce-checkout .woocommerce-checkout-review-order-table tr.cart-discount {
	display: none;
}

/* The headline. The only row in the table that is good news, so it is the
   only one with colour. */
.woocommerce-cart .cart_totals tr.tws-savings th,
.woocommerce-cart .cart_totals tr.tws-savings td,
.woocommerce-checkout tr.tws-savings th,
.woocommerce-checkout tr.tws-savings td {
	color: var(--tws-sale);
	font-weight: 700;
	border-bottom: none;
	padding-bottom: 2px;
}

.tws-savings__total { font-size: 17px; white-space: nowrap; }

/* The amount-less variant carries a coupon name and a [Remove] link instead
   of a figure, so it has to be allowed to wrap. */
.woocommerce-cart .cart_totals tr.tws-savings--single td,
.woocommerce-checkout tr.tws-savings--single td { white-space: normal; }

/* A single saving with a figure of its own needs no breakdown; the row keeps
   the table's normal rule under it. */
.woocommerce-cart .cart_totals tr.tws-savings--single th,
.woocommerce-cart .cart_totals tr.tws-savings--single td,
.woocommerce-checkout tr.tws-savings--single th,
.woocommerce-checkout tr.tws-savings--single td {
	border-bottom: 1px solid var(--tws-border);
	padding-bottom: 11px;
}

/* The itemisation. Deliberately quiet: it is there so the customer can see
   where the number came from and pull a coupon back out, not to compete with
   the number itself. */
.woocommerce-cart .cart_totals tr.tws-savings-detail td,
.woocommerce-checkout tr.tws-savings-detail td {
	padding-top: 0;
	padding-bottom: 11px;
	border-bottom: 1px solid var(--tws-border);
	text-align: left;
}

.tws-savings__list {
	list-style: none;
	margin: 0;
	padding: 0;
}

.tws-savings__list li {
	display: flex;
	justify-content: space-between;
	align-items: baseline;
	gap: 14px;
	padding: 2px 0;
	font-size: 13px;
	line-height: 1.45;
	color: var(--tws-muted);
}

.tws-savings__value {
	text-align: right;
	color: var(--tws-price-was);
}

/* WooCommerce's [Remove] link, carried through from its own coupon cell so
   the customer keeps the control the hidden row used to give them. */
.tws-savings a.woocommerce-remove-coupon,
.tws-savings__list a.woocommerce-remove-coupon {
	margin-left: 6px;
	color: var(--tws-accent-text);
	font-weight: 500;
	text-decoration: none;
	white-space: nowrap;
}

.tws-savings a.woocommerce-remove-coupon:hover,
.tws-savings a.woocommerce-remove-coupon:focus-visible,
.tws-savings__list a.woocommerce-remove-coupon:hover,
.tws-savings__list a.woocommerce-remove-coupon:focus-visible {
	text-decoration: underline;
}

/* --- Empty cart ---------------------------------------------------------- */
.woocommerce-cart .cart-empty { font-size: 18px; margin-bottom: 20px; }

.woocommerce-cart .return-to-shop a.button {
	display: inline-block;
	padding: 13px 26px;
	background: var(--tws-accent);
	color: var(--tws-ink);
	border: 1px solid var(--tws-accent);
	border-radius: 3px;
	font-size: 15px;
	font-weight: 500;
	text-decoration: none;
}

/* --- Narrow screens ------------------------------------------------------
   WooCommerce's shop_table_responsive collapses each row into label/value
   lines below 768px, so the columns are kept down to the tablet range where
   they still fit. */
@media (max-width: 899px) {
	.woocommerce-cart .cart-collaterals { margin-top: 32px; }
	.woocommerce-cart .cross-sells { margin-bottom: 32px; }
}

@media (max-width: 768px) {
	.woocommerce-cart table.shop_table.cart thead { display: none; }

	.woocommerce-cart table.shop_table.cart tbody tr.cart_item {
		display: grid;
		grid-template-columns: 72px minmax(0, 1fr) auto;
		gap: 4px 14px;
		padding: 16px 14px;
		border-top: 1px solid var(--tws-border);
	}

	.woocommerce-cart table.shop_table.cart tbody tr.cart_item:first-child { border-top: none; }

	.woocommerce-cart table.shop_table.cart tbody tr.cart_item td {
		display: block;
		width: auto;
		padding: 0;
		border: none;
		text-align: left !important;
	}

	.woocommerce-cart td.product-thumbnail { grid-row: 1 / span 3; grid-column: 1; }
	.woocommerce-cart td.product-name      { grid-column: 2; }
	.woocommerce-cart td.product-remove    { grid-column: 3; grid-row: 1; }
	.woocommerce-cart td.product-price     { grid-column: 2; }
	.woocommerce-cart td.product-quantity  { grid-column: 2; margin-top: 8px; }
	.woocommerce-cart td.product-subtotal  { grid-column: 3; align-self: end; }

	.woocommerce-cart td.product-price del,
	.woocommerce-cart td.product-subtotal del { display: inline; margin-right: 5px; }

	/* Price and Subtotal both print a bare figure; without their headings
	   they need their own labels or the row reads as two random numbers. */
	.woocommerce-cart td.product-price::before,
	.woocommerce-cart td.product-subtotal::before {
		content: attr(data-title) ": ";
		font-size: 12px;
		text-transform: uppercase;
		letter-spacing: 0.04em;
		color: var(--tws-muted);
	}

	.woocommerce-cart td.actions .coupon {
		float: none;
		width: auto;
		margin-bottom: 12px;
	}

	.woocommerce-cart td.actions > button[name="update_cart"],
	.woocommerce-cart td.actions > a.button.empty_cart {
		float: none;
		display: block;
		width: 100%;
		margin: 0 0 10px;
		text-align: center;
	}
}

/* ===============================================================
   CHECKOUT

   The store uses WooCommerce's CLASSIC (shortcode) checkout, whose markup is:

     form.checkout
       #customer_details.col2-set
         .col-1   Billing details
         .col-2   Ship to a different address?
       h3#order_review_heading   "Your order"
       #order_review             order table + payment methods

   By default WooCommerce floats .col-1 and .col-2 side by side and drops
   the order review full-width underneath. The layout below instead stacks
   billing and shipping in a left column and moves the order review into a
   sticky right-hand column, so the summary and payment stay in view while
   the customer works down the form.
   =============================================================== */

/* --- Minimal checkout header ------------------------------------------- */
.tws-header--checkout {
	min-height: 80px;
}

.tws-back-button .wp-block-button__link,
.tws-back-button .wp-block-button__link:hover,
.tws-back-button .wp-block-button__link:focus-visible {
	padding: 10px 20px;
	font-size: 15px;
	font-weight: 500;
	line-height: 1.2;
	border: 1px solid var(--tws-accent-border);
	border-radius: 3px;
	box-sizing: border-box;
	white-space: nowrap;
	text-decoration: none;
}

.tws-back-button .wp-block-button__link {
	background: transparent;
	color: var(--tws-accent-text);
}

.tws-back-button .wp-block-button__link:hover,
.tws-back-button .wp-block-button__link:focus-visible {
	background: var(--tws-hover);
	color: #ffffff;
	border-color: var(--tws-hover);
}

/* --- Two-column form ---------------------------------------------------- */
@media (min-width: 900px) {
	.woocommerce-checkout form.checkout.woocommerce-checkout {
		display: grid;
		grid-template-columns: minmax(0, 1fr) minmax(330px, 420px);
		grid-template-rows: auto 1fr;
		column-gap: 48px;
		align-items: start;
	}

	.woocommerce-checkout form.checkout #customer_details {
		grid-column: 1;
		grid-row: 1 / span 2;
	}

	.woocommerce-checkout form.checkout #order_review_heading {
		grid-column: 2;
		grid-row: 1;
		margin-top: 0;
	}

	.woocommerce-checkout form.checkout #order_review {
		grid-column: 2;
		grid-row: 2;
		/* Keeps the total and payment buttons visible while filling the form. */
		position: sticky;
		top: calc(var(--tws-header-h) + 20px);
	}
}

/* Billing and "Ship to a different address?" stack in the left column —
   WooCommerce floats them side by side by default. */
.woocommerce-checkout form.checkout #customer_details .col-1,
.woocommerce-checkout form.checkout #customer_details .col-2 {
	float: none !important;
	width: 100% !important;
	max-width: none;
}

.woocommerce-checkout form.checkout #customer_details .col-2 {
	margin-top: 36px;
}

.woocommerce-checkout form.checkout .col2-set::before,
.woocommerce-checkout form.checkout .col2-set::after {
	content: none !important;
}

/* --- Headings ----------------------------------------------------------- */
.woocommerce-checkout form.checkout h3,
.woocommerce-checkout #order_review_heading {
	font-size: 22px;
	font-weight: 500;
	color: var(--tws-ink);
	margin: 0 0 18px;
	padding-bottom: 12px;
	border-bottom: 1px solid var(--tws-border);
}

#ship-to-different-address {
	font-size: 22px;
	font-weight: 500;
}

#ship-to-different-address label {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	cursor: pointer;
}

/* --- Order review panel -------------------------------------------------- */
.woocommerce-checkout #order_review {
	background: #ffffff;
	border: 1px solid var(--tws-border);
	border-radius: 4px;
	padding: 24px;
}

.woocommerce-checkout #order_review table.shop_table {
	border: none;
	margin: 0 0 18px;
	font-size: 15px;
}

.woocommerce-checkout #order_review table.shop_table th,
.woocommerce-checkout #order_review table.shop_table td {
	padding: 10px 0;
	border-top: 1px solid var(--tws-border);
}

.woocommerce-checkout #order_review table.shop_table thead th {
	border-top: none;
	font-weight: 500;
	color: var(--tws-ink);
}

.woocommerce-checkout #order_review .order-total .amount {
	font-size: 20px;
	font-weight: 700;
	color: var(--tws-ink);
}

.woocommerce-checkout #payment {
	background: transparent;
	border-radius: 0;
}

.woocommerce-checkout #payment ul.payment_methods {
	padding: 0;
	border-bottom: 1px solid var(--tws-border);
}

.woocommerce-checkout #payment div.form-row {
	padding: 18px 0 0;
}

/* Place order — solid, primary, full width of the panel. */
.woocommerce-checkout #payment #place_order {
	display: block;
	width: 100%;
	padding: 15px 24px;
	background: var(--tws-accent);
	color: var(--tws-ink);
	border: 1px solid var(--tws-accent);
	border-radius: 3px;
	font-size: 16px;
	font-weight: 600;
	float: none;
}

.woocommerce-checkout #payment #place_order:hover,
.woocommerce-checkout #payment #place_order:focus-visible {
	background: var(--tws-hover);
	border-color: var(--tws-hover);
	color: #ffffff;
}

/* --- Form fields --------------------------------------------------------- */
.woocommerce form .form-row label {
	font-size: 14px;
	font-weight: 500;
	color: var(--tws-ink);
	margin-bottom: 6px;
}

.woocommerce form .form-row input.input-text,
.woocommerce form .form-row textarea,
.woocommerce form .form-row select,
.woocommerce form .form-row .select2-container .select2-selection {
	padding: 11px 12px;
	border: 1px solid #949494;
	border-radius: 3px;
	font-family: inherit;
	font-size: 15px;
	color: var(--tws-ink);
	background: #ffffff;
}

.woocommerce form .form-row input.input-text:focus,
.woocommerce form .form-row textarea:focus,
.woocommerce form .form-row select:focus {
	outline: 2px solid var(--tws-accent-deep);
	outline-offset: 1px;
	border-color: var(--tws-accent-deep);
}

/* Required-field marker needs to be distinguishable without relying on
   colour alone (WCAG 1.4.1) — WooCommerce already prints an asterisk. */
.woocommerce form .form-row .required {
	color: #b3261e;
	text-decoration: none;
}

@media (max-width: 899px) {
	.woocommerce-checkout #order_review {
		margin-top: 32px;
	}
}

/* ===============================================================
   GIFT CARD REDEEM FORM  (WooCommerce Gift Cards plugin)

   The plugin ships no layout of its own — the input and button are plain
   block-level siblings, so they stack full width and the Apply button ends
   up as a giant orange slab. Lay them out as one input group.
   =============================================================== */
.add_gift_card_form {
	margin: 28px 0 0;
}

.add_gift_card_form h4 {
	font-size: 18px;
	font-weight: 500;
	color: var(--tws-ink);
	margin: 0 0 12px;
}

#wc_gc_cart_redeem_form {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	align-items: stretch;
}

/* Notices span the full width above the field. */
.wc_gc_add_gift_card_form__notices {
	flex: 1 0 100%;
}

.wc_gc_add_gift_card_form__notices:empty {
	display: none;
}

#wc_gc_cart_redeem_form #wc_gc_cart_code {
	flex: 1 1 200px;
	min-width: 0;
	margin: 0;
	padding: 11px 12px;
	border: 1px solid #949494;
	border-radius: 3px;
	font-family: inherit;
	font-size: 15px;
	color: var(--tws-ink);
	background: #ffffff;
}

#wc_gc_cart_redeem_form #wc_gc_cart_code:focus {
	outline: 2px solid var(--tws-accent-deep);
	outline-offset: 1px;
	border-color: var(--tws-accent-deep);
}

/* Secondary action next to the field — outline, auto width, matching the
   field height rather than filling the row. */
#wc_gc_cart_redeem_form #wc_gc_cart_redeem_send {
	flex: 0 0 auto;
	width: auto;
	margin: 0;
	padding: 11px 22px;
	background: transparent;
	color: var(--tws-accent-text);
	border: 1px solid var(--tws-accent-border);
	border-radius: 3px;
	font-family: inherit;
	font-size: 15px;
	font-weight: 500;
	line-height: 1.3;
	cursor: pointer;
	white-space: nowrap;
}

#wc_gc_cart_redeem_form #wc_gc_cart_redeem_send:hover,
#wc_gc_cart_redeem_form #wc_gc_cart_redeem_send:focus-visible {
	background: var(--tws-hover);
	color: #ffffff;
	border-color: var(--tws-hover);
}

/* Coupon form gets the same treatment — same shape of problem. */
.woocommerce form.checkout_coupon .form-row {
	display: flex;
	gap: 10px;
	align-items: stretch;
	width: 100%;
	padding: 0;
	margin: 0 0 10px;
	float: none;
}

/* ===============================================================
   CONTENT HEADING RHYTHM

   Section headings inside page content need clear separation from the
   block above them. Scoped to post content and explicitly excluding
   product-card titles, which are H2s inside a tight grid card and must
   NOT inherit this spacing.
   =============================================================== */
/*
 * CARD HEADINGS OPT OUT BY NAME.
 *
 * This rule is specific enough (0,3,1) to beat a plain .some-card__title
 * class rule, so every card component whose heading is an H2 or H3 was
 * getting 3.5rem of air above it inside its own box: measured 56px between
 * the photo and the name in a team card, and the same above every
 * knowledgebase card title on /learn/. A card sets its own rhythm, so the
 * ones we ship are excluded here. A new card component with a heading has
 * to be added to both lists.
 */
.wp-block-post-content h2:not(.woocommerce-loop-product__title):not(.wc-block-grid__product-title):not(.tws-kb-card__title):not(.tws-kb-story__title):not(.tws-about-card__title):not(.tws-team-card__name),
.wp-block-post-content h3:not(.woocommerce-loop-product__title):not(.wc-block-grid__product-title):not(.tws-kb-card__title):not(.tws-kb-story__title):not(.tws-about-card__title):not(.tws-team-card__name) {
	margin-top: 3.5rem;
}

.wp-block-post-content h4,
.wp-block-post-content h5 {
	margin-top: 2.5rem;
}

/* No leading gap at the very top of the content. */
.wp-block-post-content > *:first-child {
	margin-top: 0;
}

/* Anchored headings must not hide beneath the sticky header when a
   #fragment link jumps to them. */
:target,
.wp-block-post-content h2[id],
.wp-block-post-content h3[id] {
	scroll-margin-top: calc(var(--tws-header-h) + 24px);
}

/* ===============================================================
   SCROLL TO TOP
   =============================================================== */
.tws-to-top {
	position: fixed;
	right: 24px;
	bottom: 24px;
	z-index: 90;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	/* 40px on desktop where a mouse is the likely input; the mobile rule
	   below restores 44px for touch (WCAG 2.5.5). */
	width: 40px;
	height: 40px;
	padding: 0;
	background: var(--tws-accent);
	/* Dark glyph, not white: white on #DD9933 is 2.42:1 and fails the 3:1
	   non-text contrast minimum. #3A3A3A on it is 4.70:1. */
	color: var(--tws-ink);
	border: 1px solid var(--tws-accent);
	border-radius: 4px;
	box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
	cursor: pointer;
	opacity: 0;
	transform: translateY(8px);
	transition: opacity 0.2s ease, transform 0.2s ease, background-color 0.15s ease;
}

.tws-to-top[hidden] {
	display: none;
}

.tws-to-top.is-visible {
	opacity: 1;
	transform: translateY(0);
}

.tws-to-top:hover,
.tws-to-top:focus-visible {
	background: var(--tws-hover);
	border-color: var(--tws-hover);
	color: #ffffff;
}

.tws-to-top:focus-visible {
	outline: 2px solid var(--tws-ink);
	outline-offset: 2px;
}

@media (max-width: 600px) {
	.tws-to-top {
		right: 16px;
		bottom: 16px;
		width: 44px;
		height: 44px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.tws-to-top {
		transition: none;
		transform: none;
	}
}

@media print {
	.tws-to-top {
		display: none !important;
	}
}

/* ===============================================================
   CUSTOMER STORIES LISTING  (tws-base/customer-stories pattern)
   =============================================================== */
.tws-story {
	padding-bottom: 36px;
	border-bottom: 1px solid var(--tws-border);
}

.tws-story__meta {
	color: var(--tws-muted);
}

.tws-story__meta a {
	color: var(--tws-muted);
}

.tws-story__meta a:hover {
	color: var(--tws-accent-text);
}

.tws-story .wp-block-post-featured-image img {
	width: 100%;
	height: auto;
	border-radius: 4px;
}

.tws-story__more,
.wp-block-read-more.tws-story__more {
	display: inline-block;
	margin-top: 12px;
	font-size: 15px;
	font-weight: 500;
	color: var(--tws-accent-text);
	text-decoration: underline;
}

.tws-story__more:hover,
.wp-block-read-more.tws-story__more:hover {
	color: var(--tws-hover);
}

@media (max-width: 780px) {
	.tws-story .wp-block-column {
		flex-basis: 100% !important;
	}
}

/* ===============================================================
   BUTTON HOVER — !important, and why

   WordPress prints preset colour utility classes with !important:

       .has-accent-background-color { background-color: ... !important; }

   Any block whose colour was picked in the editor therefore carries an
   !important background, and a normal :hover rule — whatever its
   specificity — can never win against it. The result is buttons that
   simply don't respond to hover.

   The theme's own buttons avoid the problem by not carrying preset colour
   classes at all (see parts/header.html). But buttons authored by an editor
   in page content WILL carry them, and those still need to hover. The only
   way to beat !important is !important, so this block is a deliberate
   exception to the usual rule against it — scoped tightly to hover/focus
   states so it never affects a resting button.
   =============================================================== */
.wp-block-button__link:hover,
.wp-block-button__link:focus-visible,
.wp-element-button:hover,
.wp-element-button:focus-visible,
.woocommerce a.button:hover,
.woocommerce a.button:focus-visible,
.woocommerce button.button:hover,
.woocommerce button.button:focus-visible,
.woocommerce input.button:hover,
.woocommerce input.button:focus-visible {
	background-color: var(--tws-hover) !important;
	border-color: var(--tws-hover) !important;
	color: #ffffff !important;
}

/* Outline-style buttons start transparent; on hover they fill like the rest. */
.wp-block-button.is-style-outline .wp-block-button__link:hover,
.wp-block-button.is-style-outline .wp-block-button__link:focus-visible {
	background-color: var(--tws-hover) !important;
	border-color: var(--tws-hover) !important;
	color: #ffffff !important;
}

/* The scroll-to-top control is not a .button, so it keeps its own rule and
   is listed here only so the hover palette stays in one place. */

/* ===============================================================
   PRODUCT GRIDS INSIDE THE SIDEBAR LAYOUT

   On /store/ the content column is ~840px, not the full 1240px. The
   columns-N classes WooCommerce prints are based on the shortcode
   attribute, not the space actually available, so a columns-4 grid inside
   the sidebar layout gives ~190px cards — too tight for the image, title,
   price and full-width button.

   These rules step the column count down inside .tws-sidebar-content only,
   leaving full-width pages untouched. (Container queries would express this
   more directly, but this keeps support simple and the intent is the same.)
   =============================================================== */
.tws-sidebar-content .woocommerce ul.products.columns-4,
.tws-sidebar-content .woocommerce ul.products.columns-5,
.tws-sidebar-content .woocommerce ul.products.columns-6 {
	grid-template-columns: repeat(3, 1fr);
}

@media (max-width: 1200px) {
	.tws-sidebar-content .woocommerce ul.products.columns-3,
	.tws-sidebar-content .woocommerce ul.products.columns-4,
	.tws-sidebar-content .woocommerce ul.products.columns-5,
	.tws-sidebar-content .woocommerce ul.products.columns-6 {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (max-width: 921px) {
	/* Sidebar has stacked above the content by now, so the full width is
	   available again. */
	.tws-sidebar-content .woocommerce ul.products.columns-3,
	.tws-sidebar-content .woocommerce ul.products.columns-4 {
		grid-template-columns: repeat(3, 1fr);
	}
}

@media (max-width: 780px) {
	.tws-sidebar-content .woocommerce ul.products,
	.tws-sidebar-content .woocommerce ul.products.columns-3,
	.tws-sidebar-content .woocommerce ul.products.columns-4 {
		grid-template-columns: repeat(2, 1fr);
	}
}

/* Category tiles from [product_categories] use the same list markup. */
.woocommerce ul.products li.product-category a {
	text-decoration: none;
}

.woocommerce ul.products li.product-category h2,
.woocommerce ul.products li.product-category h3 {
	font-size: 17px;
	font-weight: 500;
	color: var(--tws-ink);
	margin: 12px 0 0;
}

.woocommerce ul.products li.product-category mark.count {
	background: transparent;
	color: var(--tws-muted);
	font-size: 14px;
	font-weight: 400;
}

/* ===============================================================
   PROMO BANNER

   Sits above the header bar inside the header template part, so it is
   part of the sticky header. Contrast: white on #B4482B is 5.38:1 (AA).
   =============================================================== */
/* The promo bar is its own template part now, so WordPress wraps it in a
   <div class="wp-block-template-part">. That wrapper becomes the child the
   header's constrained layout sizes, which caps the bar at content width and
   loses its full-bleed. display:contents takes the wrapper out of the layout
   so the bar itself spans the header again — the same trick the sidebar
   layout uses on its own template part. */
.tws-header > .wp-block-template-part { display: contents; }

.tws-promo-bar {
	font-size: 15px;
	font-weight: 600;
	line-height: 1.4;
	text-align: center;
}

.tws-promo-bar__text {
	margin: 0;
	font-size: inherit;
	font-weight: inherit;
	color: inherit;
}

/* The whole line is the link; underline only on hover so the bar stays clean
   but the affordance is still discoverable. */
.tws-promo-bar__text a {
	color: inherit;
	text-decoration: none;
}

.tws-promo-bar__text a:hover,
.tws-promo-bar__text a:focus-visible {
	text-decoration: underline;
}

.tws-promo-bar__text a:focus-visible {
	outline: 2px solid #ffffff;
	outline-offset: 3px;
}

.tws-promo-bar__icon {
	display: inline-flex;
	align-items: center;
	line-height: 0;
	color: inherit;
}

@media (max-width: 600px) {
	.tws-promo-bar {
		font-size: 13px;
	}

	/* One flame is plenty at phone width; the text is the message. */
	.tws-promo-bar__icon:last-child {
		display: none;
	}
}

/* ===============================================================
   HEADER ROWS (two-row structure)
   =============================================================== */

/* core/icon blocks inside the banner follow the group's text colour. */
.tws-promo-bar .wp-block-icon svg {
	fill: currentColor;
	display: block;
}

.tws-promo-bar .wp-block-icon {
	line-height: 0;
}

/* The nav + actions cluster sits hard right; the logo holds the left. */
.tws-header__bar > .tws-header__logo {
	margin-right: auto;
}

/* ===============================================================
   MEGA MENU

   Structure (see parts/header.html and parts/mega-*.html):
     nav.tws-mega
       .tws-mega__item
         button.tws-mega__trigger[aria-expanded][aria-controls]
         .tws-mega__panel#id   ->  template part with the content

   Accessibility notes:
   - Disclosure pattern, not a modal: focus is NOT trapped, because the
     panel is part of the page rather than a dialog over it.
   - Closed panels use visibility:hidden, which removes their links from
     the tab order and the accessibility tree. Using only opacity would
     leave invisible-but-focusable links behind.
   - Each card carries exactly ONE link (on its heading); CSS stretches it
     over the whole card. Linking the icon and title separately would give
     screen reader users duplicate links to the same destination.
   =============================================================== */
:root {
	--mega-pad: 30px;
	--mega-gap: 30px;
	--mega-card-gap: 20px;
	--mega-feature-w: 300px;
	/* Green tick for the reassurance line, drawn as a mask so it inherits
	   --tws-sale rather than hard-coding the colour into the data URI. */
	--tws-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 0a8 8 0 1 0 0 16A8 8 0 0 0 8 0Zm4 5.3-5.2 5.9-2.9-2.8 1.1-1.1 1.7 1.7 4.1-4.6 1.2.9Z'/%3E%3C/svg%3E");
}

.tws-mega {
	display: flex;
	align-items: center;
	gap: 30px;
}

/* Panels are positioned against the header, not the item, so they can span
   the full width regardless of where the trigger sits. */
.tws-mega__item {
	position: static;
	margin: 0;
}

.tws-mega__trigger {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 10px 0;
	background: none;
	border: 0;
	border-bottom: 2px solid transparent;
	font-family: inherit;
	font-size: 15px;
	font-weight: 400;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	color: var(--tws-muted);
	cursor: pointer;
}

.tws-mega__trigger svg {
	width: 14px;
	height: 14px;
	fill: none;
	stroke: currentColor;
	stroke-width: 2.5;
	transition: transform 0.18s ease;
}

.tws-mega__trigger:hover,
.tws-mega__trigger[aria-expanded="true"] {
	color: var(--tws-accent-text);
	/* accent-border, not accent: the underline is a state indicator and
	   #DD9933 on white is only 2.42:1, under the 3:1 non-text minimum. */
	border-bottom-color: var(--tws-accent-border);
}

.tws-mega__trigger[aria-expanded="true"] svg {
	transform: rotate(180deg);
}

.tws-mega__trigger:focus-visible,
.tws-mega__plain a:focus-visible {
	outline: 2px solid var(--tws-accent-deep);
	outline-offset: 3px;
}

.tws-mega__plain {
	margin: 0;
	font-size: 15px;
	text-transform: uppercase;
	letter-spacing: 0.02em;
}

.tws-mega__plain a {
	color: var(--tws-muted);
	text-decoration: none;
}

.tws-mega__plain a:hover {
	color: var(--tws-accent-text);
}

/* --- The dropdown ------------------------------------------------------- */
.tws-mega__panel {
	position: absolute;
	left: 0;
	right: 0;
	top: 100%;
	opacity: 0;
	visibility: hidden;
	transform: translateY(-6px);
	transition: opacity 0.18s ease, transform 0.18s ease, visibility 0.18s;
	/* Transparent gutter so the card's shadow isn't clipped; click-through so
	   it doesn't swallow the outside-click that should close the menu. */
	pointer-events: none;
	padding-bottom: 44px;
	z-index: 90;
}

.tws-mega__item.is-open .tws-mega__panel {
	opacity: 1;
	visibility: visible;
	transform: none;
}

.tws-mega-panel {
	max-width: 1240px;
	margin: 0 auto;
	background: #ffffff;
	border: 1px solid var(--tws-border);
	border-top: 0;
	border-radius: 0 0 6px 6px;
	box-shadow: 0 14px 34px rgba(0, 0, 0, 0.13);
	padding: var(--mega-pad);
	display: grid;
	gap: var(--mega-gap);
	pointer-events: auto;
	/* Cap to the space under the header and scroll internally on short
	   windows. --tws-header-h is measured live in header.js. */
	max-height: calc(100vh - var(--tws-header-h, 130px) - 24px);
	overflow-y: auto;
	overscroll-behavior: contain;
}

.tws-mega-panel--split { grid-template-columns: var(--mega-feature-w) minmax(0, 1fr); }
.tws-mega-panel--reverse { grid-template-columns: minmax(0, 1fr) var(--mega-feature-w); }
.tws-mega-panel--even { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: center; }

/* --- Feature column ----------------------------------------------------- */
.tws-mega-feature-col {
	display: flex;
	flex-direction: column;
	gap: 10px;
	height: 100%;
}

.tws-mega-feature {
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 10px;
	background: var(--tws-border-light, #f3f3f3);
	border: 1px solid var(--tws-border);
	border-left: 4px solid var(--tws-accent);
	border-radius: 5px;
	padding: 26px;
}

.tws-mega-feature__title {
	font-size: 23px;
	font-weight: 500;
	margin: 0;
}

.tws-mega-feature__title a {
	color: var(--tws-ink);
	text-decoration: none;
}

.tws-mega-feature__text {
	margin: 0;
	font-size: 14px;
	/* #666 not #757575: on the grey card #757575 is 4.15:1, under AA. */
	color: var(--tws-price-was);
	line-height: 1.55;
}

.tws-mega-feature__cta { margin-top: 6px; }

.tws-mega-alt {
	margin: 0;
	font-size: 14px;
	color: var(--tws-muted);
	line-height: 1.6;
}

.tws-mega-alt a {
	color: var(--tws-accent-text);
	font-weight: 500;
	text-decoration: none;
}

.tws-mega-alt a:hover { color: var(--tws-hover); text-decoration: underline; }

/* The header section sets `.wp-site-blocks > header .wp-block-group {
   align-items: center }` for the header bar's own rows. A mega panel is
   inside that header, so every card in it inherited the rule: its children
   were shrink-wrapped and centred, which is why panel buttons were never
   full width however often width:100% was set on them. Reset it for the
   panels only, at higher specificity than the rule it is undoing. */
.wp-site-blocks > header .tws-mega-panel .wp-block-group,
.wp-site-blocks > header .tws-mega-panel .wp-block-buttons {
	align-items: stretch;
}

/* --- Shop panel: two-step funnel ---------------------------------------
   Step 1 narrows to a model, step 2 turns that into a cart. The numbers are
   CSS counters on the column, so adding, removing or reordering a
   .tws-mega-step in the editor renumbers the rest with no markup to touch.
   Both steps share one card treatment on purpose: the ONLY thing separating
   them is the filled button on step 2, which is where the conversion is. */
.tws-mega-feature-col { counter-reset: tws-step; }

.tws-mega-step {
	counter-increment: tws-step;
	display: flex;
	flex-direction: column;
	gap: 7px;
	background: var(--tws-border-light, #f3f3f3);
	border: 1px solid var(--tws-border);
	border-left: 4px solid var(--tws-accent);
	border-radius: 5px;
	padding: 15px 17px;
}

.tws-mega-step__title {
	display: flex;
	align-items: center;
	gap: 9px;
	margin: 0;
	font-size: 17px;
	font-weight: 500;
	line-height: 1.2;
}

/* Charcoal disc + white numeral is 12.02:1 (AAA), and keeps the accent
   reserved for the left border and the one button that converts. The numeral
   is decorative repetition of the reading order, so it lives in CSS rather
   than in the markup. */
.tws-mega-step__title::before {
	content: counter(tws-step);
	flex: none;
	display: grid;
	place-items: center;
	width: 21px;
	height: 21px;
	border-radius: 50%;
	background: var(--tws-hover);
	color: #ffffff;
	font-size: 12px;
	font-weight: 600;
	line-height: 1;
}

/* Learn panel: same card, but these are two ways in rather than a
   sequence, so the numbers come off. */
.tws-mega-step--plain .tws-mega-step__title::before { content: none; }

.tws-mega-step__title a { color: var(--tws-ink); text-decoration: none; }
.tws-mega-step__title a:hover { color: var(--tws-accent-text); }

.tws-mega-step__text {
	margin: 0;
	font-size: 13.5px;
	/* #666 not #757575: on the grey card #757575 is 4.15:1, under AA. */
	color: var(--tws-price-was);
	line-height: 1.5;
}

/* Step 1's CTA: outlined, but the same footprint as the filled button in
   step 2, so the two cards line up and weight alone tells them apart. */
.tws-mega-step__cta { margin-top: 6px; }

.tws-mega-step__cta .wp-block-button__link {
	display: block;
	text-align: center;
	padding: 10px 16px;
	font-size: 14px;
	font-weight: 500;
	border: 1px solid var(--tws-accent-border);
	border-radius: 3px;
	background: transparent;
	color: var(--tws-accent-text);
}

.tws-mega-step__cta .wp-block-button__link:hover {
	background: var(--tws-hover);
	border-color: var(--tws-hover);
	color: #ffffff;
}

/* "Shop all products" is the escape hatch rather than somewhere we push
   people, so it sits at the foot of the column as a plain link. */
.tws-mega-shopall { margin: auto 0 0; font-size: 13.5px; }
.tws-mega-shopall a { color: var(--tws-accent-text); font-weight: 500; text-decoration: none; }
.tws-mega-shopall a:hover { color: var(--tws-hover); text-decoration: underline; }

/* Secondary CTA inside a step card: outlined, full width like the filled
   one above it so the two cards' buttons line up down the column. */
.tws-mega-step__cta-outline .wp-block-button__link {
	background: transparent;
	border: 1px solid var(--tws-accent-border);
	color: var(--tws-accent-text);
}

.tws-mega-step__cta-outline .wp-block-button__link:hover,
.tws-mega-step__cta-outline .wp-block-button__link:focus-visible {
	background: var(--tws-hover);
	border-color: var(--tws-hover);
	color: #ffffff;
}

/* Reassurance line under the Kit Builder button: answers the expensive fear
   with a stove kit - ordering parts that turn out not to fit each other. */
.tws-mega-step__note {
	position: relative;
	margin: 3px 0 0;
	padding-left: 21px;
	font-size: 12.5px;
	color: var(--tws-price-was);
	line-height: 1.45;
}

.tws-mega-step__note::before {
	content: "";
	position: absolute;
	left: 0;
	top: 2px;
	width: 14px;
	height: 14px;
	background: var(--tws-sale);
	-webkit-mask: var(--tws-check) center / 14px no-repeat;
	mask: var(--tws-check) center / 14px no-repeat;
}

/* --- Feature column alignment -------------------------------------------
   Everything in the column reads left-aligned, and every button fills the
   width of its card so the CTAs line up down the column rather than
   floating at their own label widths. Both are written out explicitly:
   block layout and the Astra-era shims otherwise centre the heading row
   and shrink-wrap the button. */
.tws-mega-feature-col :is(h3, h4, p, .wp-block-heading) { text-align: left; }
.tws-mega-feature-col .tws-mega-step__title,
.tws-mega-feature-col .tws-mega-feature__title { text-align: left; }
.tws-mega-step__title { justify-content: flex-start; }

.tws-mega-feature-col .wp-block-buttons { justify-content: flex-start; }
.tws-mega-feature-col .wp-block-button { width: 100%; }

.tws-mega-feature-col .wp-block-button__link {
	display: block;
	width: 100%;
	text-align: center;
}

/* Ghost button sits at the bottom of the column, level with the last row
   of cards. */
.tws-mega-ghost { margin-top: auto; }

.tws-mega-ghost .wp-block-button__link {
	display: block;
	text-align: center;
	padding: 11px 18px;
	font-size: 14px;
	font-weight: 500;
	border: 1px solid var(--tws-accent-border);
	border-radius: 3px;
	background: transparent;
	color: var(--tws-accent-text);
}

/* --- Category cards ----------------------------------------------------- */
.tws-mega-cards { gap: var(--mega-card-gap); }

.tws-card {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: 0;
}

.tws-card__title {
	margin: 0 0 2px;
	/* One step up from the stacked card: the title now has a whole column to
	   itself instead of sharing the width with a full-bleed picture. */
	font-size: 16px;
	font-weight: 500;
	line-height: 1.3;
}

.tws-card__title a {
	color: var(--tws-ink);
	text-decoration: none;
}

/* Stretched link: the whole card is clickable, but only one link exists in
   the accessibility tree and tab order. */
.tws-card__title a::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: 5px;
}

.tws-card__text {
	margin: 0;
	font-size: 13.5px;
	/* #666 not #757575: #757575 fails AA (4.15:1) the moment this sits on the
	   hover tint rather than pure white. */
	color: var(--tws-price-was);
	line-height: 1.45;
}

.tws-card:hover .tws-card__title a { color: var(--tws-accent-text); }
.tws-card__title a:focus-visible::after { outline: 2px solid var(--tws-accent-deep); outline-offset: 2px; }

/* --- Support: link columns + guarantee ---------------------------------- */
.tws-mega-linkcols { gap: 26px; }

.tws-linkcol__title {
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--tws-muted);
	margin: 0 0 12px;
}

.tws-linkcol__list { list-style: none; margin: 0; padding: 0; }
.tws-linkcol__list li { margin-bottom: 9px; line-height: 1.5; }
.tws-linkcol__list a { font-size: 15px; color: var(--tws-ink); text-decoration: none; }
.tws-linkcol__list a:hover { color: var(--tws-accent-text); text-decoration: underline; }

.tws-guarantee {
	display: grid;
	grid-template-columns: 96px minmax(0, 1fr);
	gap: 24px;
	align-items: center;
	background: #f3f3f3;
	border: 1px solid var(--tws-border);
	border-radius: 5px;
	padding: 24px;
}

/* The badge artwork is black line work on a WHITE ground (that's what the
   "_white" in the filename means - it's the variant built for dark
   backgrounds). Dropped straight onto this grey card it would read as a
   white sticker, so multiply blends the white away and leaves only the
   line art. Remove that one line to get the white badge back. */
.tws-guarantee__badge {
	margin: 0;
	width: 96px;
	justify-self: start;
	mix-blend-mode: multiply;
}

.tws-guarantee__badge img {
	display: block;
	width: 100%;
	height: auto;
}

.tws-guarantee__title { margin: 0 0 6px; font-size: 20px; font-weight: 500; }
.tws-guarantee__text { margin: 0; font-size: 14px; color: var(--tws-price-was); line-height: 1.55; }
.tws-guarantee__text strong { color: var(--tws-ink); font-weight: 600; }
.tws-guarantee__more { margin: 10px 0 0; font-size: 14px; }
.tws-guarantee__more a { color: var(--tws-accent-text); font-weight: 500; text-decoration: underline; }
.tws-guarantee__more a:hover { color: var(--tws-hover); }

/* --- Desktop / mobile handover ------------------------------------------ */
/* The Navigation block is the mobile menu; hide it while the mega menu is up. */


@media (max-width: 1180px) {
	:root { --mega-feature-w: 270px; --mega-gap: 26px; --mega-card-gap: 18px; }
}

@media (max-width: 1024px) {
	:root { --mega-pad: 26px; }
	.tws-mega-panel--split,
	.tws-mega-panel--reverse { grid-template-columns: minmax(0, 1fr); }
	/* TWO EQUAL COLUMNS, not 1fr + auto.
	   `auto` sizes column 2 to its content, and the Build My Kit card's
	   paragraph is long, so it took 786 of the 806px available and squeezed
	   the Find My Stove card into a 39px-wide, 660px-tall orange sliver.
	   Measured at 860px on the live site. The Learn panel failed the same
	   way with 131px, which wrapped "The Knowledgebase" to one word a line
	   and clipped its button.

	   Equal columns can't collapse: at 800px each card gets 363px, at 1024px
	   it is 468px. Verified at 800, 860 and 1010.

	   align-items:start because the cards are different heights and centring
	   them left the shorter one floating; the margin reset kills the editor's
	   24px block gap, which a grid turns into a 24px drop on the second card
	   rather than a gap between rows. */
	.tws-mega-feature-col {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 16px 20px;
		height: auto;
		align-items: start;
	}

	.tws-mega-feature-col > * {
		margin-block-start: 0;
		margin-block-end: 0;
	}
	.tws-mega-feature { grid-column: 1 / -1; }
	.tws-mega-alt { grid-column: 1; }
	.tws-mega-ghost { grid-column: 2; margin-top: 0; min-width: 220px; }
	.tws-card { grid-template-columns: 96px minmax(0, 1fr); gap: 12px; }
	.tws-card__thumb { width: 96px; height: 72px; }
	/* Shop panel: the two steps sit side by side rather than stacking, and
	   the ghost button spans beneath them. */
	.tws-mega-step { grid-column: auto; }
	.tws-mega-shopall { grid-column: 1 / -1; margin: 0; }
	/* Reverse panel: put the feature first now that it's stacked. */
	.tws-mega-panel--reverse .tws-mega-feature-col { order: -1; }
}

@media (max-width: 900px) {
	.tws-mega { gap: 18px; }
	.tws-mega__trigger, .tws-mega__plain { font-size: 14px; }
	.tws-mega-panel--even { grid-template-columns: minmax(0, 1fr); }
	.tws-guarantee { grid-template-columns: 72px minmax(0, 1fr); }
	.tws-guarantee__badge { width: 72px; }
}

@media (max-width: 794px) {
	:root { --mega-pad: 22px; --mega-gap: 22px; --mega-card-gap: 16px; }
	.tws-mega { display: none; }
	.tws-mega-feature-col { grid-template-columns: minmax(0, 1fr); }
	.tws-mega-alt, .tws-mega-ghost { grid-column: 1; }
	.tws-mega-linkcols { grid-template-columns: minmax(0, 1fr) !important; }
	.tws-guarantee { grid-template-columns: minmax(0, 1fr); }
}

@media (max-height: 720px) {
	:root { --mega-pad: 22px; --mega-gap: 22px; }
	.tws-card { grid-template-columns: 88px minmax(0, 1fr); }
	.tws-card__thumb { width: 88px; height: 66px; }
	.tws-mega-feature__title { font-size: 20px; }
}

@media (prefers-reduced-motion: reduce) {
	.tws-mega__panel, .tws-mega__trigger svg { transition: none; }
}

/* ===============================================================
   FOOTER BAR / SCROLL-TO-TOP CLEARANCE

   The scroll-to-top button is fixed bottom-right, so at the very bottom of
   the page it lands on top of the footer bar's right-hand text. Reserve
   room for it rather than moving the button — the button's position is the
   conventional one and users expect it there.

   Width reserved = button (40px) + its right offset (24px) + breathing room.
   =============================================================== */
.tws-footer-bar {
	padding-right: 88px !important;
}

@media (max-width: 781px) {
	/* Stacked bar: the button sits over the last line, so pad the bottom
	   instead of the side. */
	.tws-footer-bar {
		padding-right: 30px !important;
		padding-bottom: 76px !important;
	}
}

/* ===============================================================
   FOOTER (Option C — trust-led)

   Link count is down from 25 to 13; the deep /store/#… anchors live in the
   mega menu instead. The reclaimed space carries reassurance rather than a
   second copy of the navigation.
   =============================================================== */
.tws-footer-title {
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 0.09em;
	text-transform: uppercase;
	/* #666 not #757575: on the grey footer #757575 is only 4.15:1, under AA. */
	color: var(--tws-price-was);
	margin: 0 0 14px;
}

.tws-footer-list {
	list-style: none;
	margin: 0;
	padding: 0;
}

.tws-footer-list li {
	margin-bottom: 9px;
	line-height: 1.5;
}

.tws-footer-list a {
	font-size: 15px;
	color: var(--tws-ink);
	text-decoration: none;
}

.tws-footer-list a:hover,
.tws-footer-list a:focus-visible {
	color: var(--tws-accent-text);
	text-decoration: underline;
}

.tws-footer-tagline {
	margin: 0 0 18px;
	font-size: 14px;
	color: var(--tws-price-was);
	line-height: 1.6;
	max-width: 34ch;
}

/* --- Trust points ------------------------------------------------------- */
.tws-trust {
	display: grid;
	gap: 10px;
}

.tws-trust__item {
	display: flex;
	align-items: flex-start;
	gap: 9px;
}

.tws-trust__icon {
	flex: 0 0 17px;
	margin-top: 3px;
	line-height: 0;
	color: var(--tws-accent-border);
}

.tws-trust__icon svg { fill: currentColor; display: block; }

.tws-trust__text {
	margin: 0;
	font-size: 13.5px;
	line-height: 1.45;
	color: var(--tws-price-was);
}

.tws-trust__text strong { color: var(--tws-ink); font-weight: 600; }

/* --- Bottom bar --------------------------------------------------------- */
.tws-footer-bar__inner {
	gap: 14px 24px;
	font-size: 14px;
}

.tws-footer-bar__copy,
.tws-footer-bar__legal {
	margin: 0;
	font-size: 14px;
}

.tws-footer-bar__legal a {
	color: #ffffff;
	text-decoration: underline;
}

.tws-footer-bar__legal a:hover { color: var(--tws-accent); }

/* Powered by — quiet, with a flame. */
.tws-powered {
	display: flex;
	align-items: center;
	gap: 7px;
}

.tws-powered__icon {
	line-height: 0;
	color: var(--tws-accent);
}

.tws-powered__icon svg { fill: currentColor; display: block; }

.tws-powered__text {
	margin: 0;
	font-size: 14px;
	/* #C9C9C9 on #3A3A3A is 7.4:1 — quiet but comfortably AA. */
	color: #c9c9c9;
}

@media (max-width: 781px) {
	.tws-footer-bar__inner { justify-content: flex-start; }
}

/* ===============================================================
   FIXES PASS
   =============================================================== */

/* --- 1. Gap between the header and the open panel -----------------------
   The panel Group sits after the trigger inside .tws-mega__item, so WP's
   blockGap gave it a top margin. Because the panel is absolutely positioned,
   that margin became a visible gap under the header instead of collapsing. */
.tws-mega__panel {
	margin-top: 0 !important;
	margin-block-start: 0 !important;
}

/* --- 2. Header content constrained, backgrounds still full-bleed ---------
   max-width on these rows would shrink the ELEMENT, so the promo bar's red
   stopped short of the viewport edges. Symmetric padding keeps each row full
   width (background included) while pushing its content into the 1240px
   column: max() falls back to the 30px gutter on narrow screens. */
.tws-header__bar {
	padding-left: max(30px, calc((100% - 1240px) / 2)) !important;
	padding-right: max(30px, calc((100% - 1240px) / 2)) !important;
}

/* Rows must not inherit blockGap margins, or a white strip appears above the
   promo banner: in Safari that strip is what shows through behind the
   browser chrome instead of the banner colour. */
.tws-header > *,
.tws-promo-bar,
.tws-header__bar {
	margin-top: 0 !important;
	margin-bottom: 0 !important;
	margin-block-start: 0 !important;
	margin-block-end: 0 !important;
}

.tws-promo-bar {
	width: 100%;
	max-width: none;
}

/* The white/red backgrounds still need to span the full viewport, so they
   live on the row wrappers rather than on the constrained inner content. */
.tws-header {
	background: #ffffff;
}

/* --- 3. WooCommerce injects a customer-account link into the nav ---------
   It duplicates the account icon already in the header actions. Hidden here;
   the block itself is also listed in the Navigation block's
   ignoredHookedBlocks so it isn't re-inserted on save. */
.wc-block-customer-account,
.wp-block-woocommerce-customer-account,
.wc-block-customer-account__link,
.tws-header .wc-block-customer-account {
	display: none !important;
}

/* --- 4. Card: image beside text, 2 columns x 3 rows ----------------------
   Image-on-top made the tile as wide as its column, so at 1240px every
   picture stretched to ~280px and the panel needed two tall rows. A fixed
   112x84 image beside the text keeps a normal picture shape at any panel
   width, gives the description somewhere to sit, and fits six cards in
   roughly half the height. */
.tws-card {
	position: relative;
	display: grid;
	grid-template-columns: 112px minmax(0, 1fr);
	gap: 14px;
	align-items: center;
	align-self: start;
	padding: 10px;
	border: 1px solid transparent;
	border-radius: 6px;
	transition: border-color 0.15s ease, background 0.15s ease;
}

.tws-card:hover {
	border-color: var(--tws-border);
	background: #fcfcfc;
}

/* The stretched link means the real focus ring lands on an invisible box, so
   the card itself has to show the focus state. */
.tws-card:focus-within {
	border-color: var(--tws-accent-border);
}

.tws-card__thumb {
	width: 112px;
	height: 84px;
	margin: 0 !important;
	border-radius: 5px;
	overflow: hidden;
	border: 1px solid var(--tws-border);
	background: #ffffff;
}

.tws-card__thumb,
.tws-card__thumb img {
	/* The Image block writes aspect-ratio inline; the fixed box above governs. */
	aspect-ratio: auto !important;
}

.tws-card__thumb img {
	display: block;
	width: 100% !important;
	height: 100% !important;
	max-width: none !important;
	object-fit: cover !important;
	object-position: center;
}

.tws-card:hover .tws-card__thumb {
	border-color: var(--tws-accent-border);
}

.tws-card__body > * { margin-block: 0; }

/* Grid rows would otherwise stretch to fill the panel when the feature
   column is taller, pushing the first row down and making the top padding
   look different on the two sides. */
.tws-mega-cards {
	grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
	align-self: start !important;
	align-content: start !important;
	align-items: start !important;
}

/* --- 5. Ghost / outline buttons must not resize on hover -----------------
   Same trap as the header CTA: WordPress' outline button style swaps border
   width on hover, which nudged the whole header. Pin every box property
   across all states. */
.tws-mega-ghost .wp-block-button__link,
.tws-mega-ghost .wp-block-button__link:hover,
.tws-mega-ghost .wp-block-button__link:focus,
.tws-mega-ghost .wp-block-button__link:focus-visible,
.tws-mega-ghost .wp-block-button__link:active,
.wp-block-button.is-style-outline .wp-block-button__link,
.wp-block-button.is-style-outline .wp-block-button__link:hover,
.wp-block-button.is-style-outline .wp-block-button__link:focus-visible {
	border-width: 1px !important;
	border-style: solid !important;
	padding: 11px 18px !important;
	font-size: 14px;
	line-height: 1.3;
	box-sizing: border-box;
}

/* --- 6. Footer brand name gets its own size ------------------------------ */
.tws-footer-brandname {
	font-size: 19px;
	font-weight: 500;
	letter-spacing: 0;
	text-transform: none;
	color: var(--tws-ink);
	margin: 0 0 8px;
}

.tws-footer-address {
	margin: 0;
	font-size: 14px;
	color: var(--tws-price-was);
	line-height: 1.7;
}

.tws-footer-address a {
	color: var(--tws-price-was);
	text-decoration: underline;
}

.tws-footer-address a:hover { color: var(--tws-accent-text); }

/* --- 7. Footer lists are left aligned ------------------------------------
   The previous footer design centred them; that rule has been deleted, this
   is belt and braces against the old DB-saved copy. */
.tws-footer-list,
.tws-footer-list li {
	text-align: left;
}

/* --- 8. Trust points, now a full-width row under the columns ------------- */
.tws-trust {
	gap: 22px 30px;
	margin-top: 34px;
	padding-top: 26px;
	border-top: 1px solid #dedede;
}

/* --- 9. Bottom bar: legal links not underlined until hovered ------------- */
.tws-footer-bar__legal a {
	text-decoration: none;
}

.tws-footer-bar__legal a:hover,
.tws-footer-bar__legal a:focus-visible {
	text-decoration: underline;
	color: var(--tws-accent);
}

/* The Image block writes aspect-ratio inline. A fixed height plus contain is
   used instead of a ratio + crop: the product shots are tall objects on white,
   so "cover" sliced the top and bottom off the stoves. contain guarantees the
   whole product is visible whatever the source ratio, which is the behaviour
   asked for, and every tile is still exactly the same size. */
.tws-card__thumb {
	aspect-ratio: auto !important;
	width: 100%;
	height: 92px;
	max-height: none;
}

.tws-card__thumb img {
	aspect-ratio: auto !important;
	width: 100%;
	height: 100%;
	object-fit: contain !important;
	padding: 6px;
	background: #ffffff;
}

/* Grid rows stretch to fill the panel when the feature column is taller,
   which pushed the first row of cards down and made the top padding look
   different on the two sides. Pin content to the top instead. */
.tws-mega-cards {
	align-content: start;
}

.tws-card {
	justify-content: flex-start;
}


/* =========================================================================
   MOBILE MENU (below 795px)

   Replaces the core Navigation block entirely. The drawer's CONTENT is the
   "Mobile Menu" template part, so it is curated in the Site Editor with
   ordinary Heading, List, Search and Buttons blocks.

   Structure is three pieces:
     .tws-mmenu          fixed full-viewport panel, flex column
     .tws-mmenu__bar     sticky, holds the close button
     .tws-mmenu__scroll  the only thing that scrolls
   Keeping the scroll on the body rather than the panel is what stops the
   close button disappearing when the list is long.
   ========================================================================= */

.tws-mmenu-toggle {
	display: none;
	align-items: center;
	justify-content: center;
	width: 42px;
	height: 42px;
	padding: 0;
	border: 0;
	border-radius: 4px;
	background: none;
	color: var(--tws-ink);
	cursor: pointer;
}

.tws-mmenu-toggle:hover {
	color: var(--tws-accent-text);
	background: var(--tws-page-gray, #f3f3f3);
}

.tws-mmenu-toggle:focus-visible,
.tws-mmenu-close:focus-visible {
	outline: 2px solid var(--tws-accent-deep);
	outline-offset: 2px;
}

.tws-mmenu {
	position: fixed;
	inset: 0;
	z-index: 200;
	display: none;
	flex-direction: column;
	background: #ffffff;
	transform: translateX(100%);
	transition: transform 0.22s ease;
	visibility: hidden;
}

.tws-mmenu.is-open {
	transform: none;
	visibility: visible;
}

/* Sticky rather than fixed: it participates in the flex column, so the body
   below it gets exactly the remaining height and no overlap is possible. */
.tws-mmenu__bar {
	position: sticky;
	top: 0;
	z-index: 2;
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	padding: 12px 16px;
	background: #ffffff;
	border-bottom: 1px solid var(--tws-border);
}

.tws-mmenu__label {
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--tws-muted);
}

.tws-mmenu-close {
	width: 42px;
	height: 42px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	border: 0;
	border-radius: 4px;
	background: none;
	color: var(--tws-ink);
	cursor: pointer;
}

.tws-mmenu-close:hover {
	color: var(--tws-accent-text);
	background: var(--tws-page-gray, #f3f3f3);
}

.tws-mmenu__scroll {
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
	overscroll-behavior: contain;
	-webkit-overflow-scrolling: touch;
	/* safe-area keeps the last link clear of the iOS home indicator. */
	padding: 18px 16px calc(28px + env(safe-area-inset-bottom, 0px));
}

.tws-mmenu__content > * { margin-block: 0; }

.tws-mmenu__search { margin-bottom: 14px; }

.tws-mmenu__search .wp-block-search__input {
	/* 16px exactly: anything smaller makes iOS Safari zoom the page on focus. */
	font-size: 16px;
	padding: 11px 14px;
	border: 1px solid var(--tws-border);
	border-radius: 4px;
	color: var(--tws-ink);
}

.tws-mmenu__search .wp-block-search__input:focus {
	outline: 2px solid var(--tws-accent-deep);
	outline-offset: 1px;
	border-color: var(--tws-accent-border);
}

.tws-mmenu__ctas {
	display: grid;
	gap: 8px;
}

.tws-mmenu__ctas .wp-block-button { width: 100%; }

.tws-mmenu__ctas .wp-block-button__link {
	display: block;
	width: 100%;
	text-align: center;
	font-size: 16px;
	padding: 13px 20px;
}

.tws-mmenu__section { margin-top: 26px; }

.tws-mmenu__title {
	margin: 0 0 2px;
	padding-bottom: 8px;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	/* #666 not #757575: #757575 on white is fine, but this matches the footer
	   headings and stays AA if the drawer is ever given a tinted background. */
	color: var(--tws-price-was);
	border-bottom: 1px solid var(--tws-border);
}

.tws-mmenu__list {
	list-style: none;
	margin: 0;
	padding: 0;
}

.tws-mmenu__list li { border-bottom: 1px solid #f0f0f0; }
.tws-mmenu__list li:last-child { border-bottom: 0; }

.tws-mmenu__list a {
	display: block;
	/* 44px effective touch target. */
	padding: 12px 2px;
	font-size: 16px;
	color: var(--tws-ink);
	text-decoration: none;
}

.tws-mmenu__list a:hover,
.tws-mmenu__list a:focus-visible { color: var(--tws-accent-text); }

.tws-mmenu__contact {
	margin: 28px 0 0;
	padding-top: 18px;
	border-top: 1px solid var(--tws-border);
	font-size: 14px;
	line-height: 1.8;
	color: var(--tws-price-was);
}

.tws-mmenu__contact a {
	color: var(--tws-accent-text);
	text-decoration: underline;
}

/* --- The handover ------------------------------------------------------- */
@media (max-width: 794px) {
	.tws-mmenu-toggle { display: inline-flex; }
	.tws-mmenu { display: flex; }

	/* Desktop-only controls. Search and account both live inside the drawer
	   now, and Find My Stove is its primary button, so keeping them in the
	   bar would only duplicate them. */
	.tws-header .tws-mega,
	.tws-header__cta,
	.tws-header .tws-search-toggle,
	.tws-header .tws-account-link { display: none !important; }

	/* Promo banner: text only. The two flame icons ate a third of the line
	   on a phone and pushed the message onto three lines. */
	.tws-promo-bar > *:not(.tws-promo-bar__text) { display: none !important; }
	.tws-promo-bar { padding: 8px 16px !important; }
	.tws-promo-bar__text { font-size: 13.5px; }

	.tws-header__bar { padding-top: 12px !important; padding-bottom: 12px !important; }
	.tws-header__right { gap: 4px !important; }
}

@media (min-width: 795px) {
	.tws-mmenu,
	.tws-mmenu-toggle { display: none !important; }
}

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

/* --- What the drawer must sit above, and what must get out of its way ----
   Inventory of the other fixed layers, so the stacking is deliberate rather
   than accidental:
     .tws-header        100   sticky header
     .tws-mmenu         200   the drawer
     .tws-search-overlay 999  desktop only, its toggle is hidden below 795px
     .tws-toast-region  1000  must stay on top: it confirms a cart change
   .tws-to-top is 90, so it is painted under the drawer, but it is still a
   fixed control sitting over the panel's shadow area on some browsers and
   it has no purpose while a modal menu is open. Hide it outright. */
body.tws-mmenu-open .tws-to-top {
	display: none !important;
}

@media (max-width: 794px) {
	/* Touch targets. WCAG 2.5.5 asks for 44px; the mini-cart button ships
	   smaller than that. */
	.tws-header__actions .tws-icon-btn,
	.tws-header__cart button,
	.tws-header__cart .wc-block-mini-cart__button {
		min-width: 44px;
		min-height: 44px;
	}

	/* The checkout header is its own part with no __bar wrapper, so the
	   gutter rule above does not reach it. */
	.tws-header--checkout {
		padding-left: 16px !important;
		padding-right: 16px !important;
	}

	.tws-header--checkout .tws-header__logo img { max-width: 170px; }
	.tws-header--checkout .tws-back-button .wp-block-button__link { font-size: 14px; }
}

/* Single column of cards once the panel itself has stacked. */
@media (max-width: 620px) {
	.tws-mega-cards { grid-template-columns: minmax(0, 1fr) !important; }
	.tws-card { grid-template-columns: 84px minmax(0, 1fr); gap: 12px; }
	.tws-card__thumb { width: 84px; height: 63px; }
}

/* --- Drawer must escape the header's layout constraints -----------------
   The drawer is authored inside the header, so it inherits whatever the
   block layout system puts on nested groups: the constrained layout's
   content-size cap, root-padding-aware alignment padding, and flow layout's
   auto inline margins. Any one of those makes the sticky bar sit in a narrow
   centred column instead of spanning the screen. Being position:fixed does
   not exempt it: a max-width still applies.

   These are !important because the rules being beaten are generated by
   WordPress at runtime, so their specificity is not fixed and cannot be
   reliably out-specified. */
.tws-mmenu {
	position: fixed !important;
	inset: 0 !important;
	width: 100% !important;
	max-width: none !important;
	margin: 0 !important;
	padding: 0 !important;
}

.tws-mmenu > *,
.tws-mmenu__bar,
.tws-mmenu__scroll,
.tws-mmenu__scroll > .wp-block-template-part,
.tws-mmenu__content {
	width: 100% !important;
	max-width: none !important;
	margin-left: 0 !important;
	margin-right: 0 !important;
}

/* The scroll area keeps its own gutter; nothing else adds one. */
.tws-mmenu__scroll > .wp-block-template-part,
.tws-mmenu__content {
	padding-left: 0 !important;
	padding-right: 0 !important;
}

/* Template parts render inside a wrapper div that must not become a second
   flex item, or the sticky bar and the body stop sharing the height. */
.tws-mmenu__scroll > .wp-block-template-part { display: block; }

/* =========================================================================
   MEGA CARD + DRAWER CORRECTIONS
   ========================================================================= */

/* --- 1. Drawer bar gutter must match the list below it ------------------
   The earlier full-width override zeroed this bar's own padding along with
   the layout margins it was meant to strip, so "Menu" sat on the edge while
   the section headings underneath were indented. One shared value now. */
:root { --tws-mmenu-gutter: 16px; }

.tws-mmenu__bar {
	padding: 12px var(--tws-mmenu-gutter) !important;
}

.tws-mmenu__scroll {
	padding-left: var(--tws-mmenu-gutter) !important;
	padding-right: var(--tws-mmenu-gutter) !important;
}

/* --- 2. Cards must start level with the feature box ---------------------
   Root cause: .tws-mega-panel is a Group with flow layout, so WordPress
   emits `> * + * { margin-block-start: <blockGap> }`. The panel is CSS grid,
   and a top margin on a grid item pushes it down inside its own cell rather
   than collapsing. That margin, not alignment, is what dropped the card
   column below "Build My Kit". Same trap as the mega panel's own top gap. */
.tws-mega-panel > *,
.tws-mega-cards > *,
.tws-card > *,
.tws-card__body > * {
	margin-block-start: 0 !important;
	margin-block-end: 0 !important;
}

.tws-mega-cards > * { margin-top: 0 !important; }

/* --- 3. Image fills the frame, cropping if it must ----------------------
   height:100% on the img depends on the figure resolving a definite height,
   and WordPress' own image rules kept interfering. Taking the image out of
   flow removes the dependency entirely: the figure is the frame, the image
   is painted edge to edge inside it, and any overflow is clipped. */
.tws-card__thumb {
	position: relative;
	display: block;
	line-height: 0;
	font-size: 0;
	padding: 0 !important;
}

.tws-card__thumb img {
	position: absolute !important;
	inset: 0 !important;
	width: 100% !important;
	height: 100% !important;
	max-width: none !important;
	min-width: 0 !important;
	padding: 0 !important;
	margin: 0 !important;
	border-radius: 0 !important;
	object-fit: cover !important;
	object-position: center !important;
}

/* --- 4. Title and description centred against the picture --------------- */
.tws-card {
	align-items: center !important;
}

.tws-card__body {
	align-self: center !important;
	display: flex;
	flex-direction: column;
	justify-content: center;
}

/* --- Drawer box model ---------------------------------------------------
   Measured on staging, not guessed: .tws-mmenu__bar computed to
   box-sizing: content-box while carrying width:100% and 16px side padding,
   so it rendered 32px wider than the drawer (1711 vs 1679) and pushed "Menu"
   to x=0 while the headings below sat correctly at x=16.

   Cause: the bar is a plain <div> from a wp:html block, so it never receives
   the border-box reset that WordPress applies to block wrappers. Every other
   part of the drawer is a real block and was already border-box, which is why
   only this one row was off.

   width:auto is NOT the fix: .tws-mmenu does not stretch its children, so the
   bar shrink-wraps to its content and floats in the middle. Keep the width
   and correct the box model. Verified: overflow 0, label and headings both
   at 16px, close button 16px from the right. */
.tws-mmenu,
.tws-mmenu *,
.tws-mmenu *::before,
.tws-mmenu *::after {
	box-sizing: border-box;
}

.tws-mmenu {
	align-items: stretch;
}

.tws-mmenu > * {
	width: 100% !important;
}

/* =========================================================================
   LEGACY CONTENT FALLBACK          <-- TEMPORARY. DELETE WHEN CONVERTED.
   =========================================================================

   Applies only to posts and pages whose content is not blocks, via the
   .tws-legacy-content body class set in functions.php (has_blocks() test).
   A page rebuilt in Gutenberg loses the class and every rule below stops
   applying to it, so this shim retires itself page by page. It cannot
   affect converted content, which is why it is safe to be this broad.

   The state it is patching, measured on staging: deactivating Beaver Builder
   removed all of its wrapper markup, so .fl-row / .fl-col / .fl-module no
   longer exist anywhere. What remains is bare <h2>, <p>, <img> as direct
   children of .wp-block-post-content, with no styling behind them.

   The skew: those <img> tags carry width/height attributes from the old
   editor. With max-width capping the width but nothing setting height, a
   2560x2560 image rendered 1240 wide and still 2560 tall. Measured on
   /about-tiny-wood-stove/: 1240x2560, a 0.48 ratio where 1.00 was correct.
   height:auto is the actual fix; everything else here is tidying.
   ========================================================================= */

/* Reading measure. 1240px of unbroken text is roughly 150 characters a line,
   well past the 45-90 that is comfortable, and the old layout never showed
   it that wide because Beaver Builder's columns were doing the constraining.

   Constrain the CONTAINER, not each child. A per-child `max-width` cannot
   reach inline elements or bare text nodes: max-width and margin:auto do
   nothing on an inline box. Beaver Builder left plenty of both, for example
   the row of bare <a> links under "Jump to:" on /learn/, which sat 356px to
   the left of every heading on the page because nothing could constrain them.
   Capping the container catches every child whatever its display type.

   The extra width is the block's own global padding, added back so the text
   column itself lands at 860px rather than 860 minus the gutters. */
.tws-legacy-content .wp-block-post-content {
	/* Box and gutters both pinned, so the text column measures 860px whether
	   or not a given template gives this block WordPress' global padding.
	   Deriving the width from the root-padding variables looked tidier but
	   those are defined globally even when unused, which produced a 920px
	   column on templates that had no padding to subtract. */
	max-width: 920px !important;
	margin-left: auto !important;
	margin-right: auto !important;
	padding-left: 30px !important;
	padding-right: 30px !important;
	box-sizing: border-box;
}

.tws-legacy-content .wp-block-post-content > * {
	max-width: 100%;
}

/* Bare anchors used as a link row. Without a wrapper they run together as one
   unbroken line of text, so give them their own spacing. */
.tws-legacy-content .wp-block-post-content > a {
	display: inline-block;
	margin: 0 16px 8px 0;
	color: var(--tws-accent-text);
	text-decoration: underline;
}

.tws-legacy-content .wp-block-post-content > a:hover {
	color: var(--tws-hover);
}

.tws-legacy-content .wp-block-post-content > :where(h2, h3, h4, h5, h6) {
	margin-top: 1.9em;
	margin-bottom: 0.45em;
	line-height: 1.25;
}

.tws-legacy-content .wp-block-post-content > h2 { font-size: clamp(24px, 3vw, 30px); }
.tws-legacy-content .wp-block-post-content > h3 { font-size: clamp(20px, 2.4vw, 24px); }
.tws-legacy-content .wp-block-post-content > h4 { font-size: 19px; }

.tws-legacy-content .wp-block-post-content > :where(p, ul, ol) {
	margin-top: 0;
	margin-bottom: 1.15em;
}

.tws-legacy-content .wp-block-post-content > :where(ul, ol) { padding-left: 1.35em; }
.tws-legacy-content .wp-block-post-content li { margin-bottom: 0.4em; }

.tws-legacy-content .wp-block-post-content > :first-child { margin-top: 0; }

/* Media.

   !important because the max-width being beaten is emitted by WordPress at
   runtime, so its specificity is not fixed and cannot be reliably matched.

   object-fit: contain is the safety net. Some of these images are lazy-loaded
   behind a 1x1 placeholder, so until the real file arrives the browser has
   the wrong intrinsic ratio to work from. contain guarantees that whatever
   box the image ends up in, the picture inside is never stretched: worst case
   it is letterboxed for a moment. */
.tws-legacy-content .wp-block-post-content :where(img, svg, video, iframe, embed, object) {
	max-width: 100%;
}

.tws-legacy-content .wp-block-post-content img {
	max-width: 100% !important;
	/* Caps the 825x1275 portrait manual covers, 30 of them on one page. */
	max-height: 80vh !important;
	height: auto !important;
	object-fit: contain;
	display: block;
	margin: 1.8em auto;
	border-radius: 4px;
}

.tws-legacy-content .wp-block-post-content a > img { border-radius: 4px; }

.tws-legacy-content .wp-block-post-content iframe {
	display: block;
	width: 100%;
	aspect-ratio: 16 / 9;
	height: auto;
	margin: 1.8em auto;
	border: 0;
}

/* Wide tables scroll rather than blowing out the page. */
.tws-legacy-content .wp-block-post-content table {
	display: block;
	width: 100%;
	max-width: 100%;
	overflow-x: auto;
	border-collapse: collapse;
	font-size: 14px;
}

.tws-legacy-content .wp-block-post-content :where(th, td) {
	padding: 8px 12px;
	border: 1px solid var(--tws-border);
	text-align: left;
}

.tws-legacy-content .wp-block-post-content blockquote {
	margin: 1.8em auto;
	padding: 4px 0 4px 20px;
	border-left: 3px solid var(--tws-accent);
	color: var(--tws-price-was);
	font-style: normal;
}

.tws-legacy-content .wp-block-post-content > p a {
	color: var(--tws-accent-text);
	text-decoration: underline;
}

.tws-legacy-content .wp-block-post-content > p a:hover { color: var(--tws-hover); }

/* The embedded newsletter forms lost their stylesheet too, so the inputs
   render as browser defaults in the middle of the page. */
.tws-legacy-content .wp-block-post-content :where(input[type="text"], input[type="email"], input[type="tel"], input[type="url"], select, textarea) {
	width: 100%;
	max-width: 420px;
	/* 16px exactly, or iOS Safari zooms the page on focus. */
	font: inherit;
	font-size: 16px;
	padding: 10px 13px;
	border: 1px solid var(--tws-border);
	border-radius: 4px;
	background: #ffffff;
	color: var(--tws-ink);
}

.tws-legacy-content .wp-block-post-content :where(input, select, textarea):focus-visible {
	outline: 2px solid var(--tws-accent-deep);
	outline-offset: 1px;
	border-color: var(--tws-accent-border);
}

.tws-legacy-content .wp-block-post-content :where(input[type="submit"], button[type="submit"]) {
	width: auto;
	font: inherit;
	font-size: 15px;
	font-weight: 500;
	padding: 11px 22px;
	border: 0;
	border-radius: 3px;
	background: var(--tws-accent);
	/* Dark text on amber. White would be 2.42:1 and fail AA. */
	color: var(--tws-ink);
	cursor: pointer;
}

.tws-legacy-content .wp-block-post-content :where(input[type="submit"], button[type="submit"]):hover {
	background: var(--tws-hover);
	color: #ffffff;
}

.tws-legacy-content .wp-block-post-content label {
	display: block;
	margin-bottom: 4px;
	font-size: 14px;
	color: var(--tws-price-was);
}

@media (max-width: 780px) {
	.tws-legacy-content .wp-block-post-content img { max-height: 65vh !important; }
}

/* --- Logo must not be able to resize the header -------------------------
   Lazy-loading swaps a 1x1 placeholder into the logo. A 1x1 is a *loaded*
   image, so its 1:1 intrinsic ratio overrides the width/height attributes,
   and with height:auto the 250px-wide logo resolved to 250px tall. Measured
   on staging: header 122px -> 313px until the real file arrived, taking the
   sticky offset and everything below it along with it.

   functions.php stops the logo being lazy-loaded at all. This is the belt to
   that braces: clamping max-height means no wrong intrinsic ratio can grow
   the header, whatever a caching or image plugin does later. object-fit keeps
   the logo undistorted inside the clamped box. */
.tws-header__logo,
.tws-header--checkout .tws-header__logo {
	min-height: var(--tws-logo-h, 50px);
}

.tws-header__logo img,
.tws-header .wp-block-site-logo img {
	max-height: var(--tws-logo-h, 50px) !important;
	object-fit: contain;
	object-position: left center;
}

@media (max-width: 900px) {
	:root { --tws-logo-h: 40px; }
}

@media (max-width: 600px) {
	.tws-legacy-content .wp-block-post-content {
		padding-left: 20px !important;
		padding-right: 20px !important;
	}
}


/* ===============================================================
   404 PAGE

   Everything the templates/404.html markup needs. Kept here rather
   than as inline block styles so the look is editable in one place
   and the template stays readable.

   Layout is three stacked bands — stoves, guides, stories — over a
   short hero, closing on a charcoal support band. Each band is a
   three-column grid that drops to two at 980px and one at 620px.
   =============================================================== */

/* --- Layout plumbing ---------------------------------------------------
   Every band is a plain flow group holding one .tws-404-inner, rather than
   a WordPress "constrained" group. Constrained layout emits
   `margin-left:auto !important; margin-right:auto !important` on its
   children, which no class rule can beat, so anything meant to sit flush
   left (the support heading and its intro, for one) got centred instead.
   Doing the 1240px box here keeps alignment under this stylesheet's
   control. */
.tws-404-inner {
	max-width: 1240px;
	margin-left: auto;
	margin-right: auto;
	padding-left: 20px;
	padding-right: 20px;
}

/* Flow layout also adds margin-block-start to every child after the first.
   Inside a grid that pushes cards 2 and 3 down while card 1 stays put,
   which is what made the first card look taller than the other two.
   WordPress sets it from a :where() rule, so a plain class resets it. */
.tws-404 > *,
.tws-404-inner > *,
.tws-404-grid > *,
.tws-404-support__grid > *,
.tws-404-hero .wp-block-cover__inner-container > * {
	margin-block-start: 0;
}

/* --- Hero: short on purpose. The joke is one line; the useful part is
       the search field and the two tools underneath it. ---------------- */
.tws-404-hero .wp-block-cover__inner-container {
	max-width: 680px;
	margin-left: auto;
	margin-right: auto;
}
.tws-404-hero .wp-block-cover__inner-container {
	text-align: center;
}

.tws-404-hero__eyebrow {
	margin: 0 0 6px;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--tws-accent);
}

.tws-404-hero__title {
	margin: 0 0 10px;
	font-size: clamp(28px, 5vw, 46px);
	font-weight: 400;
	line-height: 1.15;
	color: #ffffff;
}

.tws-404-hero__text {
	margin: 0 auto 26px;
	max-width: 460px;
	font-size: 16px;
	color: #d9d7d4;
}

.tws-404-search {
	max-width: 460px;
	margin: 0 auto 20px;
}

.tws-404-search .wp-block-search__inside-wrapper {
	background: #ffffff;
	border: 1px solid #ffffff;
	border-radius: 3px;
	overflow: hidden;
}

.tws-404-search .wp-block-search__input {
	border: 0;
	background: transparent;
	padding: 12px 14px;
	font-size: 15px;
	color: var(--tws-ink);
}

.tws-404-search .wp-block-search__input:focus { outline: 0; }

.tws-404-search .wp-block-search__button {
	border: 0;
	background: var(--tws-accent);
	color: var(--tws-ink);
	padding: 0 16px;
	margin: 0;
}

.tws-404-search .wp-block-search__button:hover {
	background: var(--tws-hover);
	color: #ffffff;
}

.tws-404-hero__ctas {
	justify-content: center;
	gap: 12px;
}

/* White outline against the photo, flipping to the shared charcoal hover
   so it behaves like every other button on the site. */
.tws-404-ghost .wp-block-button__link {
	background: transparent;
	border: 1px solid #ffffff;
	color: #ffffff;
}

.tws-404-ghost .wp-block-button__link:hover,
.tws-404-ghost .wp-block-button__link:focus-visible {
	background: #ffffff;
	color: var(--tws-ink);
	border-color: #ffffff;
}

/* --- Bands ------------------------------------------------------------- */
.tws-404-section {
	padding: 60px 0;
}

/* Alternating tint so three card rows in a row don't read as one long
   undifferentiated scroll. */
.tws-404-section--tint {
	background: #faf9f7;
	border-top: 1px solid var(--tws-border);
	border-bottom: 1px solid var(--tws-border);
}

/* Section head: eyebrow and title on the left, the "see all" link pushed
   to the right on desktop and dropping underneath on narrow screens. */
.tws-404-head {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 6px 24px;
	margin-bottom: 28px;
}

.tws-404-head__eyebrow {
	flex: 1 0 100%;
	margin: 0 0 4px;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--tws-accent-text);
}

.tws-404-head__title {
	margin: 0;
	font-size: clamp(24px, 3.2vw, 34px);
	font-weight: 400;
	line-height: 1.2;
	color: var(--tws-ink);
}

.tws-404-head__link {
	margin: 0;
	font-size: 15px;
}

.tws-404-head__link a {
	color: var(--tws-accent-text);
	font-weight: 500;
	text-decoration: none;
}

.tws-404-head__link a:hover {
	color: var(--tws-hover);
	text-decoration: underline;
}

/* --- Cards -------------------------------------------------------------
   One link per card, on the heading, stretched over the whole card by the
   ::after below: the picture and the body text are clickable without
   adding duplicate links to the tab order or the accessibility tree.
   Same approach as the mega-menu cards, separate class so the two can be
   tuned independently. */
.tws-404-grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 26px;
}

.tws-404-card {
	position: relative;
	display: flex;
	flex-direction: column;
	/* The gap under the text is padding on the card, NOT a bottom margin on
	   the last paragraph. WordPress's flow layout emits
	   `.is-layout-flow > :last-child { margin-block-end: 0 }`, and a class +
	   pseudo-class beats a plain class, so any margin put there is stripped.
	   Padding on the card is out of that rule's reach. */
	padding-bottom: 24px;
	background: #ffffff;
	border: 1px solid var(--tws-border);
	border-radius: 6px;
	overflow: hidden;
	transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}

.tws-404-card:hover {
	border-color: var(--tws-accent-border);
	box-shadow: 0 10px 24px rgba(0, 0, 0, 0.08);
	transform: translateY(-2px);
}

.tws-404-card__thumb {
	margin: 0;
	background: var(--tws-border-light, #f3f3f3);
}

.tws-404-card__thumb img {
	display: block;
	width: 100%;
	height: auto;
}

.tws-404-card__kicker {
	margin: 16px 18px 0;
	font-size: 11.5px;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--tws-muted);
}

.tws-404-card__title {
	margin: 14px 18px 0;
	font-size: 18px;
	font-weight: 500;
	line-height: 1.3;
}

/* A card that has a kicker needs less space above the title. */
.tws-404-card__kicker + .tws-404-card__title {
	margin-top: 5px;
}

.tws-404-card__title a {
	color: var(--tws-ink);
	text-decoration: none;
}

.tws-404-card__title a::after {
	content: "";
	position: absolute;
	inset: 0;
}

.tws-404-card:hover .tws-404-card__title a { color: var(--tws-accent-text); }

.tws-404-card__title a:focus-visible::after {
	outline: 2px solid var(--tws-accent-deep);
	outline-offset: 2px;
	border-radius: 6px;
}

.tws-404-card__text {
	margin: 8px 18px 0;
	font-size: 14px;
	line-height: 1.55;
	color: var(--tws-price-was);
}

/* --- Built for Life Guarantee ------------------------------------------
   Badge beside the promise, so the band reads at a glance without needing
   a card grid. The badge artwork is black line work on an opaque WHITE
   ground (that is what "_white" means in the filename - it is the variant
   drawn for dark backgrounds), which would sit on this tinted band as a
   white sticker. multiply blends the white away and leaves the line art.
   Drop that one line to get the white badge back. */
.tws-404-guarantee {
	display: flex;
	align-items: center;
	gap: 32px;
}

.tws-404-guarantee__badge {
	flex: none;
	margin: 0;
	width: 132px;
	mix-blend-mode: multiply;
}

.tws-404-guarantee__badge img {
	display: block;
	width: 100%;
	height: auto;
}

.tws-404-guarantee__body {
	max-width: 680px;
}

.tws-404-guarantee__title {
	margin: 0 0 10px;
	font-size: clamp(24px, 3.2vw, 34px);
	font-weight: 400;
	line-height: 1.2;
	color: var(--tws-ink);
}

.tws-404-guarantee__text {
	margin: 0 0 14px;
	font-size: 15px;
	line-height: 1.6;
	color: var(--tws-price-was);
}

.tws-404-guarantee__text strong {
	color: var(--tws-ink);
	font-weight: 600;
}

.tws-404-guarantee__link {
	margin: 0;
	font-size: 15px;
}

.tws-404-guarantee__link a {
	color: var(--tws-accent-text);
	font-weight: 500;
	text-decoration: none;
}

.tws-404-guarantee__link a:hover {
	color: var(--tws-hover);
	text-decoration: underline;
}

/* --- Support band ------------------------------------------------------
   Charcoal, so the page ends on something visually different from three
   rows of white cards and the contact details are impossible to miss. */
.tws-404-support {
	padding: 60px 0 56px;
	background: var(--tws-hover);
	color: #d9d7d4;
}

.tws-404-support__title {
	margin: 0 0 8px;
	font-size: clamp(24px, 3.2vw, 34px);
	font-weight: 400;
	line-height: 1.2;
	color: #ffffff;
}

.tws-404-support__text {
	margin: 0 0 32px;
	max-width: 620px;
	font-size: 15px;
	color: #b9b6b2;
}

.tws-404-support__grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 20px;
}

.tws-404-contact {
	background: rgba(255, 255, 255, 0.05);
	border: 1px solid rgba(255, 255, 255, 0.14);
	border-radius: 6px;
	padding: 22px 22px 20px;
}

.tws-404-contact__title {
	margin: 0 0 8px;
	font-size: 17px;
	font-weight: 500;
	color: #ffffff;
}

.tws-404-contact__text {
	margin: 0 0 14px;
	font-size: 14px;
	line-height: 1.55;
	color: #b9b6b2;
}

.tws-404-contact__link {
	margin: 0;
	font-size: 15px;
}

/* Accent on charcoal is 4.70:1 against --tws-ink but only needs to clear
   AA as text on this background, which it does at 5.6:1. */
.tws-404-contact__link a {
	color: var(--tws-accent);
	font-weight: 500;
	text-decoration: none;
}

.tws-404-contact__link a:hover {
	color: #ffffff;
	text-decoration: underline;
}

/* --- Quick answers strip ----------------------------------------------
   Sits directly under the hero. These are the pages people most often
   arrive looking for, so they get found before the browsing starts rather
   than after a full page of scrolling. */
.tws-404-quickbar {
	border-bottom: 1px solid var(--tws-border);
	background: #ffffff;
}

.tws-404-quicklinks {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: center;
	gap: 4px 14px;
	margin: 0;
	padding: 16px 0;
	font-size: 14px;
	color: var(--tws-muted);
}

.tws-404-quicklinks a {
	color: var(--tws-accent-text);
	font-weight: 500;
	text-decoration: none;
}

.tws-404-quicklinks a:hover { color: var(--tws-hover); text-decoration: underline; }

/* --- Responsive --------------------------------------------------------
   Three up, then two, then one. The support band goes single column a bit
   earlier because its cards are text-only and read badly when narrow. */
@media (max-width: 980px) {
	.tws-404-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.tws-404-support__grid { grid-template-columns: minmax(0, 1fr); }
	.tws-404-section { padding: 48px 0; }
}

@media (max-width: 760px) {
	/* Badge above the promise rather than beside it. */
	.tws-404-guarantee {
		flex-direction: column;
		align-items: flex-start;
		gap: 20px;
	}

	.tws-404-guarantee__badge { width: 104px; }
}

@media (max-width: 620px) {
	.tws-404-grid { grid-template-columns: minmax(0, 1fr); gap: 20px; }
	.tws-404-section { padding: 40px 0; }
	.tws-404-support { padding: 44px 0 40px; }
	.tws-404-head { margin-bottom: 22px; }
	.tws-404-hero__ctas { width: 100%; }
	.tws-404-hero__ctas .wp-block-button { flex: 1 1 100%; }
	.tws-404-hero__ctas .wp-block-button__link { display: block; text-align: center; }
}

/* Honour a reduced-motion preference: the card lift is decoration. */
@media (prefers-reduced-motion: reduce) {
	.tws-404-card { transition: none; }
	.tws-404-card:hover { transform: none; }
}

/* ===============================================================
   PAGE HEADER GALLERY  (.twsheader-gallery)

   The landing-page heroes are core Gallery blocks - one column, a few
   slides, rendered as a slider. Core's gallery CSS sizes their images with

       .wp-block-gallery.has-nested-images figure.wp-block-image img {
           width: auto;
       }

   which is the image's INTRINSIC width, not the width of the figure it sits
   in. That is harmless while the browser picks a source at least as wide as
   the column, and wrong here: Jetpack's Site Accelerator rewrites every
   sizes attribute to "(max-width: 1000px) 100vw, 1000px", so the browser
   never picks anything wider than 1000px. Measured on the home page at a
   1440px viewport: a 1000x563 image in a 1240px figure, 240px short of it,
   while the slider around it still stood 682px tall.

   Filling the figure is what the slider expects, so the image is stretched
   to it. Lifting the 1000px cap at the Jetpack end is still worth doing -
   the hero is now scaled up by a quarter and slightly soft - but that is a
   site setting rather than something the theme can reach.

   Scoped to the header gallery on purpose: a gallery inside an article
   should still be free to show its images at their own size.
   =============================================================== */
.wp-block-gallery.has-nested-images.twsheader-gallery figure.wp-block-image img {
	width: 100%;
}

/* ===============================================================
   ABOUT PAGE  (/about/)

   Same approach as the knowledgebase hub: the page is plain core blocks
   carrying tws-about-* and tws-team-* class names, and everything visual
   lives here. The section headings and the three "Why Tiny Wood Stove?"
   cards reuse the knowledgebase rules above by name rather than restating
   them, so the two pages cannot drift apart.
   =============================================================== */

/* --- Our story -----------------------------------------------------------
   Portrait beside the prose rather than above it. The three paragraphs are
   long, and the Beaver Builder version put a 2560px square photo on top of
   them, which pushed the whole story below the fold. */
.tws-about-intro { margin-bottom: 8px; }

.tws-about-portrait img {
	display: block;
	width: 100%;
	border-radius: 6px;
}

.tws-about-intro__text p { margin-top: 0; }
.tws-about-intro__text p + p { margin-top: 16px; }
.tws-about-intro__text a { color: var(--tws-accent-text); font-weight: 500; }

/* --- Team cards ----------------------------------------------------------
   Three to a row; core stacks the columns itself below 782px, so there is
   no media query for the grid itself. The photo is flush to the card edge,
   which is why the padding sits on the text rather than on the card.

   The fixed 4:3 ratio is what keeps a row level: the nine photos are stored
   at everything from 2560x2560 to 531x398, and all but the first are
   already 4:3, so the crop is doing almost no work on eight of them. */
.tws-team-grid { margin-bottom: 24px; }

.tws-team-card {
	height: 100%;
	background: #ffffff;
	border: 1px solid var(--tws-border);
	border-radius: 6px;
	overflow: hidden;
	box-sizing: border-box;
}

.tws-team-card__photo { margin: 0; }

.tws-team-card__photo img {
	display: block;
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
}

.tws-team-card__name {
	margin: 18px 0 2px;
	padding: 0 20px;
	font-size: 18px;
	font-weight: 500;
	line-height: 1.3;
}

/* The role is the only accent-coloured text on the page, which is enough to
   separate it from the name above and the bio below without a rule or a
   second type size doing the job. */
.tws-team-card__role {
	margin: 0 0 12px;
	padding: 0 20px;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--tws-accent-text);
}

.tws-team-card__text {
	margin: 0 0 12px;
	padding: 0 20px;
	font-size: 15px;
	line-height: 1.6;
	color: var(--tws-price-was);
}

.tws-team-card__text:last-child { margin-bottom: 20px; }

/* --- Why Tiny Wood Stove? ------------------------------------------------ */
.tws-about-why { margin-top: 8px; }

/* --- Narrow screens ------------------------------------------------------
   Core stacks the columns on its own AND keeps the layout gap on both axes,
   so a stacked card already has 24px under it. Adding a margin here as well
   is what produced 42px between two cards and 24px between two rows of them
   - the same mistake the knowledgebase query above used to make. The only
   thing left to do is drop the grid's own bottom margin, which would sit on
   top of that gap. */
@media (max-width: 781px) {
	.tws-team-grid { margin-bottom: 0; }
}
