/*
Theme Name: GLOAM Base
Theme URI: https://gloam.shop
Author: GLOAM Studio
Author URI: https://gloam.shop
Description: Editorial e-commerce theme for a curated smoking-goods brand. Built 1:1 on the GLOAM design system (cream paper + ink + one ember spot, Instrument Serif / Archivo / Space Mono). Position-driven menus with built-in fallbacks, zero database writes on activation, full WooCommerce support, working newsletter + contact forms, and every colour, font and piece of copy editable from the Customizer or Elementor. Never hardcode appearance — edit through the front end.
Version: 1.6.3
Requires at least: 6.0
Tested up to: 6.6
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: gloam
Tags: e-commerce, custom-colors, custom-logo, custom-menu, translation-ready, three-columns
*/

/* ==========================================================================
   PART 1 — DESIGN SYSTEM
   Authored in design/gloam-design-system.css. Do not edit these lines here;
   edit the source file and re-run build/build_css.py.
   ========================================================================== */
/* ==========================================================================
   GLOAM — DESIGN SYSTEM  (PART 1 · single source of truth)
   --------------------------------------------------------------------------
   This file is the ONLY place the design is authored. build/build_css.py
   concatenates it with design/gloam-compat.css and a theme header to produce
   gloam-base/style.css. Never hand-edit style.css — edit this file and rebuild.

   Design logic: two-colour print. Cream paper + ink, with a single ember-red
   spot colour. Zero border-radius, zero shadow. Every separation is a 1px
   hairline. Asymmetric grid, deliberate editorial whitespace.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. TOKENS
   Colours / fonts / logo height are re-declared at higher specificity by
   functions.php from Customizer values, so everything below stays live.
   -------------------------------------------------------------------------- */
:root {
	/* colour */
	--gl-paper:      #F5EFE3;   /* cream ground            */
	--gl-surface:    #EDE5D5;   /* paper, one step darker  */
	--gl-ink:        #141414;   /* ink black               */
	--gl-ember:      #E03A17;   /* the single spot colour  */
	--gl-ember-dark: #C22F10;
	--gl-swatch:     #26221C;   /* dark swatch (mega mark) */
	--gl-line:       #3A342A;   /* hairline on ink         */
	--gl-line-paper: #D8CEBB;   /* hairline on paper       */
	--gl-muted:      #6B6558;   /* tertiary text on paper  */
	--gl-muted-2:    #A79E8C;   /* body text on ink        */
	--gl-muted-3:    #8A8272;   /* fine print on ink       */
	--gl-body:       #3A342A;   /* body text on paper      */
	--gl-hero-body:  #E8DFD0;   /* body text over photo    */
	--gl-hero-fine:  #BDB4A2;   /* fine print over photo   */
	--gl-on-ember:   #FBD9CE;   /* secondary text on ember */

	/* type */
	--gl-serif: 'Instrument Serif', Georgia, 'Times New Roman', serif;
	--gl-sans:  'Archivo', system-ui, -apple-system, 'Segoe UI', Arial, sans-serif;
	--gl-mono:  'Space Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

	/* metrics */
	--gl-pad:    56px;   /* section side padding at 1440 */
	--gl-sec-y:  96px;   /* section vertical padding     */
	--gl-gutter: 56px;   /* grid gutter                  */
	--gl-wrap:   1328px; /* 1440 - 2x56                  */
	--gl-logo-h: 56px;   /* header logo height           */
	--gl-mark-speed: 120s; /* footer mega mark: one full drift. Slow on
	                        * purpose — at 360px the wordmark reads as
	                        * texture, and anything faster turns the last
	                        * thing on the page into a moving advert. */
}

/* --------------------------------------------------------------------------
   2. BASE
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

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

body {
	margin: 0;
	background: var(--gl-paper);
	color: var(--gl-ink);
	font-family: var(--gl-sans);
	font-size: 16px;
	line-height: 1.6;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	overflow-wrap: break-word;
}

img, svg, video { max-width: 100%; height: auto; }
figure { margin: 0; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
table { border-collapse: collapse; }

/* --------------------------------------------------------------------------
   3. TYPE HELPERS
   -------------------------------------------------------------------------- */
.gl-wrap { width: 100%; max-width: var(--gl-wrap); margin: 0 auto; }

.gl-kicker {
	font-family: var(--gl-mono);
	font-weight: 700;
	font-size: 11px;
	letter-spacing: 1.4px;
	text-transform: uppercase;
	color: var(--gl-ember);
}

.gl-mono {
	font-family: var(--gl-mono);
	font-size: 10px;
	letter-spacing: 1.2px;
	text-transform: uppercase;
	color: var(--gl-muted);
}

.gl-rule      { height: 1px; background: var(--gl-ink); }
.gl-rule--ink { height: 1px; background: var(--gl-line); }
.gl-rule--paper { height: 1px; background: var(--gl-line-paper); }

/* --------------------------------------------------------------------------
   4. BUTTONS
   Zero radius. Uppercase Archivo. Padding 18/32.
   -------------------------------------------------------------------------- */
.gl-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 18px 32px;
	font-family: var(--gl-sans);
	font-weight: 700;
	font-size: 12px;
	letter-spacing: 1.4px;
	text-transform: uppercase;
	line-height: 1;
	border: 0;
	border-radius: 0;
	cursor: pointer;
	transition: background .16s ease, color .16s ease, border-color .16s ease;
}
.gl-btn--paper { background: var(--gl-paper); color: var(--gl-ink); }
.gl-btn--paper:hover { background: #fff; }
.gl-btn--ghost { background: transparent; color: var(--gl-paper); box-shadow: inset 0 0 0 1px rgba(245,239,227,.45); }
.gl-btn--ghost:hover { box-shadow: inset 0 0 0 1px var(--gl-paper); background: rgba(245,239,227,.08); }
.gl-btn--ember { background: var(--gl-ember); color: #fff; }
.gl-btn--ember:hover { background: var(--gl-ember-dark); }
.gl-btn--ink { background: var(--gl-ink); color: var(--gl-paper); }
.gl-btn--ink:hover { background: #000; }
.gl-btn--block { width: 100%; }

.gl-btnrow { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }

/* --------------------------------------------------------------------------
   5. IMAGE PLATE  (.gl-ph)
   Empty  -> ink gradient placeholder (looks deliberate, never "broken").
   Filled -> uploaded image covers the plate.
   -------------------------------------------------------------------------- */
.gl-ph {
	position: relative;
	overflow: hidden;
	background-color: var(--gl-swatch);
	background-image: linear-gradient(155deg, #322C24 0%, #1B1814 100%);
	box-shadow: inset 0 0 0 1px rgba(245,239,227,.07);
}
.gl-ph::after {
	content: "";
	position: absolute;
	inset: 0;
	background-image:
		linear-gradient(rgba(245,239,227,.055) 1px, transparent 1px),
		linear-gradient(90deg, rgba(245,239,227,.055) 1px, transparent 1px);
	background-size: 64px 64px;
	pointer-events: none;
}
.gl-ph > img { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; object-fit: cover; display: block; }
.gl-ph--paper { background-color: var(--gl-surface); background-image: linear-gradient(155deg, #F1EADC 0%, #E2D8C4 100%); box-shadow: inset 0 0 0 1px rgba(20,20,20,.08); }
.gl-ph--paper::after { background-image: none; }

/* --------------------------------------------------------------------------
   6. UTILITY BAR  (.util)
   -------------------------------------------------------------------------- */
.util {
	background: var(--gl-ink);
	color: var(--gl-paper);
	min-height: 40px;
	display: flex;
	align-items: center;
	padding: 0 var(--gl-pad);
}
.util-in {
	width: 100%;
	max-width: var(--gl-wrap);
	margin: 0 auto;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 24px;
}
.util.has-links .util-in { justify-content: space-between; }
.util .promo {
	font-family: var(--gl-mono);
	font-weight: 700;
	font-size: 11px;
	letter-spacing: 1.2px;
	text-transform: uppercase;
	text-align: center;
}
.util .r { display: flex; align-items: center; gap: 20px; }
.util .r a, .util .r span {
	font-family: var(--gl-mono);
	font-size: 11px;
	letter-spacing: 1.2px;
	text-transform: uppercase;
	color: var(--gl-paper);
	opacity: .8;
	transition: opacity .16s;
}
.util .r a:hover { opacity: 1; }

/* --------------------------------------------------------------------------
   7. MASTHEAD  (.mast)
   Height 78. Wordmark left, nav centre, utilities right.
   -------------------------------------------------------------------------- */
.hdr { position: relative; z-index: 60; }
.mast {
	background: var(--gl-paper);
	padding: 0 var(--gl-pad);
}
.mast-in {
	width: 100%;
	max-width: var(--gl-wrap);
	margin: 0 auto;
	height: 78px;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
}
.hdr-rule { height: 1px; background: var(--gl-ink); }

/* wordmark */
.mast .brand { display: flex; align-items: center; gap: 6px; flex: none; }
.mast .mark {
	font-family: var(--gl-serif);
	font-weight: 400;
	font-size: 30px;
	line-height: 1;
	letter-spacing: -.5px;
	color: var(--gl-ink);
}
.mast .sub {
	font-family: var(--gl-mono);
	font-size: 10px;
	letter-spacing: 1.6px;
	text-transform: uppercase;
	color: var(--gl-muted);
}
.mast .custom-logo-link { display: inline-flex; align-items: center; line-height: 0; }
.mast .custom-logo-link img { display: block; height: var(--gl-logo-h); width: auto; }

/* primary nav */
.mast nav { display: flex; align-items: center; gap: 32px; }
.mast nav a {
	font-family: var(--gl-sans);
	font-weight: 600;
	font-size: 12px;
	letter-spacing: 1.2px;
	text-transform: uppercase;
	color: var(--gl-ink);
	white-space: nowrap;
	transition: color .16s;
}
.mast nav a:hover { color: var(--gl-ember); }
.mast nav .current-menu-item > a,
.mast nav .current_page_item > a { color: var(--gl-ember); }

/* right utilities */
.mast .rt { display: flex; align-items: center; gap: 22px; flex: none; }
.mast .rt a, .mast .rt button {
	font-family: var(--gl-sans);
	font-weight: 500;
	font-size: 12px;
	letter-spacing: 1.2px;
	text-transform: uppercase;
	color: var(--gl-ink);
	white-space: nowrap;
	transition: color .16s;
}
.mast .rt a:hover, .mast .rt button:hover { color: var(--gl-ember); }
.mast .rt .cart { color: var(--gl-ember); font-weight: 600; }

/* burger (small screens) */
.mast .burger { display: none; padding: 8px; margin-right: -8px; }
.mast .burger span { display: block; width: 20px; height: 1px; background: var(--gl-ink); }
.mast .burger span + span { margin-top: 5px; }

/* --------------------------------------------------------------------------
   8. HEADER SEARCH  (native WP search, collapsed until opened)
   -------------------------------------------------------------------------- */
.gl-search { display: flex; align-items: center; gap: 8px; min-width: 0; }
.gl-search-field {
	width: 0; padding: 0; border: 0;
	border-bottom: 1px solid transparent;
	background: transparent;
	font-family: var(--gl-sans);
	font-size: 12px;
	letter-spacing: 1px;
	color: var(--gl-ink);
	height: 24px;
	opacity: 0;
	outline: none;
	transition: width .25s ease, opacity .2s ease, padding .25s ease, border-color .25s ease;
}
.gl-search.is-open .gl-search-field { width: 150px; padding: 2px 4px; opacity: 1; border-bottom-color: var(--gl-ink); }
.gl-search-field::placeholder { color: var(--gl-muted); text-transform: uppercase; font-size: 10.5px; letter-spacing: 1px; }
.gl-search-btn {
	display: inline-flex; align-items: center; gap: 7px;
	font-family: var(--gl-sans); font-weight: 500; font-size: 12px;
	letter-spacing: 1.2px; text-transform: uppercase;
	color: var(--gl-ink);
	transition: color .16s;
}
.gl-search-btn:hover { color: var(--gl-ember); }
.gl-search-btn svg { width: 13px; height: 13px; display: block; flex: none; }

/* --------------------------------------------------------------------------
   9. HERO
   Full-bleed photo, ink scrim, text floating top + bottom.
   -------------------------------------------------------------------------- */
.hero {
	position: relative;
	background: var(--gl-ink);
	color: var(--gl-paper);
	min-height: 820px;
	display: flex;
	align-items: stretch;
	padding: 44px var(--gl-pad);
	overflow: hidden;
}
.hero-bg { position: absolute; inset: 0; z-index: 0; }
.hero-bg > img { width: 100%; height: 100%; object-fit: cover; display: block; }
.hero-scrim {
	position: absolute; inset: 0; z-index: 1; pointer-events: none;
	background: linear-gradient(180deg,
		rgba(20,20,20,.55) 0%,
		rgba(20,20,20,0) 42%,
		rgba(20,20,20,.92) 100%);
}
.hero-in {
	position: relative;
	z-index: 2;
	width: 100%;
	max-width: var(--gl-wrap);
	margin: 0 auto;
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	gap: 40px;
}
.hero-top { display: flex; align-items: center; justify-content: space-between; gap: 24px; }
/* The two mono notes carry a CLASS as well as the descendant selector. An
 * Elementor build puts the role on the WIDGET wrapper and the visible text one
 * level inside it, where `.hero-top span` can never reach — and writing the
 * numbers a second time for the widget version is exactly how the two
 * renderings of this page would drift apart. One rule, two carriers. */
.hero-top span,
.hero-note {
	font-family: var(--gl-mono);
	font-size: 11px;
	letter-spacing: 1.2px;
	text-transform: uppercase;
	color: var(--gl-paper);
}
.hero-top span:first-child,
.hero-note--strong { font-weight: 700; }
.hero-mid { display: flex; flex-direction: column; gap: 26px; }
.hero-rule { width: 72px; height: 2px; background: var(--gl-ember); }
.hero-title {
	font-family: var(--gl-serif);
	font-weight: 400;
	font-size: 116px;
	line-height: .97;
	letter-spacing: -1.5px;
	color: var(--gl-paper);
	margin: 0;
}
.hero-foot {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 48px;
}
.hero-lead { font-size: 17px; line-height: 1.6; color: var(--gl-hero-body); max-width: 620px; }
.hero-cta { display: flex; flex-direction: column; gap: 14px; }
.hero-fine {
	font-family: var(--gl-mono);
	font-size: 10px;
	letter-spacing: 1.2px;
	text-transform: uppercase;
	color: var(--gl-hero-fine);
}

/* THE INNER-PAGE HERO (canvas: "About — Page" 3:401).
 *
 * Same shell, four different numbers, and every one of them is read off the
 * canvas rather than chosen: 620 tall instead of 820, the SECTION rhythm (96)
 * in place of the hero's own 44, a 92/90 headline in place of 116/.97, and a
 * 660 measure for the lead in place of 620. Its copy sits at the BOTTOM of the
 * block — measured, not assumed: the copy's box ends 96px above the band's
 * bottom edge, which is exactly the band's own bottom padding — and there is
 * no notes row and no button row, because the canvas has a single copy stack.
 *
 * WRITTEN AS TWO CLASSES (`.hero.hero--inner`) AND THAT IS THE WHOLE POINT OF
 * THE SHAPE. The base `.hero` rule and all three of its media blocks are read
 * LATER in this file, and `@media (max-width: 900px) .hero { padding: 32px … }`
 * is the same specificity as a one-class `.hero--inner` — so a one-class
 * variant would lose the tie on source order and this hero's padding would
 * collapse to 32px on a tablet. Three other ties in this file are settled by
 * order and carry a comment saying so; this one cannot be, because the rules it
 * ties with are in a different section and are shared with the home page.
 *
 * THE RESPONSIVE STEPS LIVE IN SECTION 20 and follow two different rules:
 * min-height keeps the HOME hero's own ratios (640/820 = .78, 560/820 = .68,
 * 480/820 = .59 — applied to 620 and rounded to the nearest 10); the headline
 * takes the design system's existing title scale (84 / 62 / 42). The canvas
 * carries no inner-page breakpoints at all, so neither number is a transcription
 * — they are the system's own, and inventing a parallel scale for one page is
 * how a system stops being one.
 *
 * The one canvas number NOT honoured here is the About scrim's own gradient:
 * 50% / 40% / 90% against the hero's 55% / 42% / 92%. A 5% alpha step on a
 * photograph is below the threshold of a visible edge, and the scrim is one of
 * the parts these two heroes share, so the hero's is kept rather than forked.
 * Recorded so the next reader knows it was seen. */
.hero.hero--inner {
	min-height: 620px;
	padding: var(--gl-sec-y) var(--gl-pad);
}
.hero--inner .hero-in { justify-content: flex-end; }
.hero--inner .hero-mid { gap: 24px; }
.hero--inner .hero-title { font-size: 92px; line-height: .978; }
.hero--inner .hero-lead { max-width: 660px; }

/* --------------------------------------------------------------------------
   10. MARQUEE BAND
   -------------------------------------------------------------------------- */
.mq {
	background: var(--gl-ink);
	color: var(--gl-paper);
	min-height: 84px;
	display: flex;
	align-items: center;
	justify-content: center;
	flex-wrap: wrap;
	gap: 26px;
	padding: 16px var(--gl-pad);
}
.mq span { font-family: var(--gl-serif); font-size: 34px; line-height: 1.1; }
.mq .sep { color: var(--gl-ember); font-size: 30px; }

/* --------------------------------------------------------------------------
   11. SECTION SHELL
   -------------------------------------------------------------------------- */
.sec { padding: var(--gl-sec-y) var(--gl-pad); }
.sec--paper   { background: var(--gl-paper); }
.sec--surface { background: var(--gl-surface); }
.sec--ink     { background: var(--gl-ink); color: var(--gl-paper); }
.sec--ember   { background: var(--gl-ember); color: var(--gl-paper); }

/* A band that runs tighter than the section rhythm: 24 less than it, which is
 * 72 at 1440 — where the canvas has it — and 48 / 32 below, because the token
 * steps and this band steps with it. See section 20. */
.sec--tight { padding: calc(var(--gl-sec-y) - 24px) var(--gl-pad); }

.sec-in { width: 100%; max-width: var(--gl-wrap); margin: 0 auto; display: flex; flex-direction: column; }
.sec-in--g44 { gap: 44px; }
.sec-in--g48 { gap: 48px; }
.sec-in--g40 { gap: 40px; }

.sec-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 32px; }
.sec-head .lead { display: flex; flex-direction: column; gap: 12px; }
.sec-title {
	font-family: var(--gl-serif);
	font-weight: 400;
	font-size: 62px;
	line-height: 1.04;
	letter-spacing: -.5px;
	margin: 0;
}
.sec-link {
	font-family: var(--gl-mono);
	font-weight: 700;
	font-size: 11px;
	letter-spacing: 1.4px;
	text-transform: uppercase;
	white-space: nowrap;
	padding-bottom: 2px;
	border-bottom: 1px solid transparent;
	transition: border-color .16s;
}
.sec-link:hover { border-bottom-color: currentColor; }
.sec--ink .sec-link { color: var(--gl-muted-2); }

/* --------------------------------------------------------------------------
   12. CATEGORY SHELF (01)
   -------------------------------------------------------------------------- */
.shelf-row { display: flex; gap: var(--gl-gutter); align-items: flex-start; }
.shelf-row .gcard { flex: 1 1 0; min-width: 0; }
.shelf-row--wide .gcard--wide { flex: 0 0 760px; }

.gcard { display: flex; flex-direction: column; }
.gcard .gl-ph { height: 400px; }
.gcard .gl-ph > img { transition: transform .6s cubic-bezier(.2,.7,.2,1); }
.gcard:hover .gl-ph > img { transform: scale(1.03); }
.gcard .rule { height: 1px; background: var(--gl-ink); }
.gcard .meta { display: flex; align-items: center; justify-content: space-between; gap: 20px; padding: 18px 0; }
.gcard .meta .t { font-family: var(--gl-serif); font-size: 26px; line-height: 1; color: var(--gl-ink); }
.gcard .meta .c {
	font-family: var(--gl-mono); font-size: 10px; letter-spacing: 1.2px;
	text-transform: uppercase; color: var(--gl-muted); white-space: nowrap;
}

/* --------------------------------------------------------------------------
   13. THE EDIT (02)
   -------------------------------------------------------------------------- */
.edit-row { display: flex; gap: 48px; align-items: flex-start; }
.edit-media { flex: 0 0 700px; display: flex; flex-direction: column; }
.edit-media .gl-ph { height: 520px; }
.edit-media .cap {
	font-family: var(--gl-mono); font-size: 10px; letter-spacing: 1.2px;
	text-transform: uppercase; color: var(--gl-muted); padding: 16px 0;
}
.edit-info { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 24px; }
.edit-info h3 { font-family: var(--gl-serif); font-weight: 400; font-size: 46px; line-height: 1.05; margin: 0; }
.edit-info .body { font-size: 16px; line-height: 1.7; color: var(--gl-body); }
.edit-info .pull { font-family: var(--gl-serif); font-style: italic; font-size: 20px; line-height: 1.5; color: var(--gl-muted); }
.edit-info .rule { height: 1px; background: var(--gl-ink); }

.spec { display: flex; flex-direction: column; gap: 6px; font-family: var(--gl-mono); font-size: 12px; color: var(--gl-body); }
.spec-row { display: flex; gap: 24px; }
.spec-row .k { flex: 0 0 118px; text-transform: uppercase; letter-spacing: 1px; }
.spec-row .v { flex: 1 1 auto; }

.price-row { display: flex; align-items: center; justify-content: space-between; gap: 24px; flex-wrap: wrap; }
.price-row .price { font-family: var(--gl-sans); font-weight: 500; font-size: 26px; color: var(--gl-ink); }

/* --------------------------------------------------------------------------
   14. MATERIALS (03)
   -------------------------------------------------------------------------- */
.mats-grid { display: flex; gap: 16px; }
.mat { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 16px; }
.mat .gl-ph { height: 260px; }
.mat .n { font-family: var(--gl-mono); font-weight: 700; font-size: 10px; letter-spacing: 1.4px; color: var(--gl-ember); }
.mat h3 { font-family: var(--gl-serif); font-weight: 400; font-size: 30px; line-height: 1.1; margin: 0; color: var(--gl-paper); }
.mat p { font-size: 15px; line-height: 1.7; color: var(--gl-muted-2); margin: 0; }

.quote { font-family: var(--gl-serif); font-weight: 400; font-size: 46px; line-height: 1.15; color: var(--gl-paper); margin: 0; }
.quote-credit {
	font-family: var(--gl-mono); font-size: 11px; letter-spacing: 1.2px;
	text-transform: uppercase; color: var(--gl-muted-3);
}

/* --------------------------------------------------------------------------
   15. VOICES (05)
   -------------------------------------------------------------------------- */
.stats { display: flex; align-items: flex-start; justify-content: space-between; gap: 32px; }
.stat { display: flex; flex-direction: column; gap: 6px; }
.stat .n { font-family: var(--gl-serif); font-size: 40px; line-height: 1; color: var(--gl-ink); }
.stat .n.is-ember { color: var(--gl-ember); }
.stat .l { font-family: var(--gl-mono); font-size: 10px; letter-spacing: 1.4px; text-transform: uppercase; color: var(--gl-muted); }
/* One size up, and deliberately a variant rather than a change of the rule: the
 * home page's proof figures and the About page's three figures are BOTH read off
 * the canvas and they differ — 40 there (3:179), 44 here (3:421). Rounding one
 * into the other would have been easier and would have made both pages wrong. */
.stat--lg .n { font-size: 44px; }

.voices { display: flex; gap: 16px; }
.voice { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 18px; background: var(--gl-paper); padding: 28px 26px; }
.voice .score { font-family: var(--gl-mono); font-weight: 700; font-size: 10px; letter-spacing: 1.4px; text-transform: uppercase; color: var(--gl-ember); }
.voice blockquote { font-family: var(--gl-serif); font-style: italic; font-size: 20px; line-height: 1.5; color: var(--gl-ink); margin: 0; }
.voice cite { font-family: var(--gl-mono); font-style: normal; font-size: 10px; letter-spacing: 1.2px; text-transform: uppercase; color: var(--gl-muted); }

/* --------------------------------------------------------------------------
   16. THE LIST — newsletter band (06)
   -------------------------------------------------------------------------- */
.join-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 56px; }
.join-copy { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 16px; }
.join-copy .gl-kicker { color: var(--gl-paper); }
.join-title { font-family: var(--gl-serif); font-weight: 400; font-size: 62px; line-height: 1.04; letter-spacing: -.5px; color: var(--gl-paper); margin: 0; }
.join-lead { font-size: 17px; line-height: 1.6; color: var(--gl-on-ember); max-width: 560px; }
.join-list { flex: 0 0 460px; display: flex; flex-direction: column; gap: 14px; }
.join-list .h { font-family: var(--gl-mono); font-weight: 700; font-size: 10px; letter-spacing: 1.6px; text-transform: uppercase; color: var(--gl-on-ember); }
.join-list ul { display: flex; flex-direction: column; gap: 6px; }
.join-list li { font-family: var(--gl-mono); font-size: 11px; letter-spacing: 1px; text-transform: uppercase; line-height: 1.8; color: var(--gl-paper); }

.join-form { display: flex; min-height: 62px; }
.join-form input[type="email"], .join-form input[type="text"] {
	flex: 1 1 auto; min-width: 0;
	background: var(--gl-paper); border: 0; border-radius: 0;
	padding: 0 22px;
	font-family: var(--gl-sans); font-size: 15px; color: var(--gl-ink);
	outline: none;
}
.join-form input::placeholder { color: var(--gl-muted-3); text-transform: none; letter-spacing: 0; }
.join-form button {
	background: var(--gl-ink); color: var(--gl-paper);
	padding: 0 40px; border-radius: 0;
	font-family: var(--gl-sans); font-weight: 700; font-size: 12px;
	letter-spacing: 1.6px; text-transform: uppercase;
	transition: background .16s;
}
.join-form button:hover { background: #000; }
.join-fine {
	font-family: var(--gl-mono); font-size: 10px; letter-spacing: 1.2px;
	text-transform: uppercase; color: var(--gl-paper);
}

/* --------------------------------------------------------------------------
   17. FOOTER
   -------------------------------------------------------------------------- */
.ftr { background: var(--gl-ink); color: var(--gl-paper); padding: 80px var(--gl-pad); }
.ftr-in { width: 100%; max-width: var(--gl-wrap); margin: 0 auto; display: flex; flex-direction: column; gap: 56px; }
.ftr-top { display: flex; align-items: flex-start; gap: 48px; }
.ftr-rule { height: 1px; background: var(--gl-line); }

.ftr-brand { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 16px; }
.ftr-brand .mark { font-family: var(--gl-serif); font-size: 40px; line-height: 1; color: var(--gl-paper); }
.ftr-brand .about { font-size: 15px; line-height: 1.6; color: var(--gl-muted-2); max-width: 380px; }
.ftr-brand .contact { font-family: var(--gl-mono); font-size: 11px; letter-spacing: 1.2px; text-transform: uppercase; color: var(--gl-muted-3); }
.ftr-brand .custom-logo-link { line-height: 0; }
.ftr-brand .custom-logo-link img { display: block; height: var(--gl-logo-h); width: auto; }

.ftr-cols { display: flex; gap: 52px; }
.ftr-col { display: flex; flex-direction: column; gap: 14px; }
.ftr-col h4 { font-family: var(--gl-mono); font-weight: 700; font-size: 10px; letter-spacing: 1.6px; text-transform: uppercase; color: var(--gl-ember); margin: 0; }
.ftr-col ul { display: flex; flex-direction: column; gap: 8px; margin: 0; padding: 0; list-style: none; }
.ftr-col li { list-style: none; }
.ftr-col li a { font-size: 14px; color: var(--gl-muted-2); transition: color .16s; }
.ftr-col li a:hover { color: var(--gl-paper); }

.pay { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.pay .h { font-family: var(--gl-mono); font-size: 10px; letter-spacing: 1.4px; text-transform: uppercase; color: var(--gl-muted-3); }
.pay .chip {
	width: 54px; height: 34px; border-radius: 3px;
	background: var(--gl-paper);
	display: inline-flex; align-items: center; justify-content: center;
	overflow: hidden;
}
.pay .chip img { height: 34px; width: auto; display: block; border-radius: 3px; }
.pay .chip--text { font-family: var(--gl-sans); font-weight: 900; font-size: 11px; letter-spacing: .5px; color: var(--gl-ink); }
.pay .chip--visa { font-size: 13px; letter-spacing: 1px; color: #1A1F71; }
.pay .chip--mc svg { display: block; }

/* The oversized wordmark drifts sideways, slowly enough to read as texture
 * rather than as movement.
 *
 * How the seam is made invisible: the moving track holds the wordmark an even
 * number of times, and the animation travels EXACTLY -50% — one whole half. The
 * two halves are identical, so at the moment the animation resets, the second
 * half is sitting precisely where the first one started and the jump is
 * unobservable. Any other offset leaves a visible snap.
 *
 * The half must also be at least as wide as the viewport, or the loop exposes
 * blank space at the end. Each repeat is one copy of the site name at 360px, so
 * four repeats per half (eight in total, written by footer.php) covers a name as
 * short as five characters out to roughly a 3600px viewport. */
.ftr-mark {
	margin: 0;
	overflow: hidden;
	line-height: 1.03;
	color: var(--gl-swatch);
}
.ftr-mark-run {
	display: flex;
	width: max-content;
	animation: gl-mark-drift var(--gl-mark-speed) linear infinite;
}
.ftr-mark-run > span {
	font-family: var(--gl-serif);
	font-weight: 400;
	font-size: 360px;
	letter-spacing: -4px;
	white-space: nowrap;
	padding-right: .16em;
}
@keyframes gl-mark-drift {
	from { transform: translate3d(0, 0, 0); }
	to   { transform: translate3d(-50%, 0, 0); }
}
/* Honouring the system setting is not optional: a 360px glyph sliding for two
 * minutes is exactly the kind of motion that setting exists to stop. Degrades
 * to the previous behaviour — the wordmark cropped by the viewport, standing
 * still. */
@media (prefers-reduced-motion: reduce) {
	.ftr-mark-run { animation: none; }
}
.ftr-bot { display: flex; align-items: center; justify-content: space-between; gap: 24px; flex-wrap: wrap; }
.ftr-bot span, .ftr-bot a {
	font-family: var(--gl-mono); font-size: 10px; letter-spacing: 1.2px;
	text-transform: uppercase; color: var(--gl-muted-3);
}
.ftr-bot a:hover { color: var(--gl-paper); }
.ftr-bot .r { display: flex; gap: 22px; flex-wrap: wrap; }

/* --------------------------------------------------------------------------
   18. INNER PAGES — ABOUT  (canvas: "About — Page" 3:399)
   The first page in this file that is not the home page. Three blocks the home
   page never needed, each read off its own canvas frame.

   WHERE THESE LIVE, AND WHY HERE RATHER THAN IN PART 2. A8 of
   gloam-compat.css holds the contact page's three pieces on the grounds that
   the theme's own templates do not render a contact page yet, and tells the
   next reader to move them here if one ever is. These come here directly, for
   the stronger version of the same reason: the theme's own About layout is on
   the roadmap, and a block authored in the compatibility layer is a block
   somebody has to move later — which is the drift that note exists to prevent.

   ROLES CARRY CLASS NAMES, never element selectors, except where a scoped
   descendant is the only honest form (`.step .n`, `.story-body .pull`). There
   is no native About markup yet; when there is, it carries these classes.
   -------------------------------------------------------------------------- */

/* 01 · OUR STORY (canvas 3:408) — a fixed 400px title rail beside the copy, 64
 * apart, both starting at the band's own top edge. Same SHAPE as `.edit-row` and
 * a separate block on purpose: `.edit-info h3` (46) and `.edit-media .gl-ph`
 * (520) are the home page's own sizes and would follow the row in here, and the
 * story's are 52 and no plate at all. */
.story-row { display: flex; gap: 64px; align-items: flex-start; }
.story-rail { flex: 0 0 400px; display: flex; flex-direction: column; gap: 14px; }
.story-title {
	font-family: var(--gl-serif);
	font-weight: 400;
	font-size: 52px;
	line-height: 1.038;   /* the canvas's own pair, 52 / 54 */
	letter-spacing: -.5px;
	margin: 0;
}
.story-body { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 22px; }
.story-p { font-size: 17px; line-height: 1.647; color: var(--gl-body); margin: 0; }
/* The pull quote keeps PART 1's muted ink (`.edit-info .pull`) at the story's own
 * size: the canvas sets it at 26/36, against the edit band's 20. */
.story-body .pull {
	font-family: var(--gl-serif);
	font-style: italic;
	font-size: 26px;
	line-height: 1.385;
	color: var(--gl-muted);
	margin: 0;
}
/* THE ONE FLEX ITEM IN THIS FILE THAT MUST NOT STRETCH, and it needs saying
 * because the default is invisible until hover. `.sec-link` draws its underline
 * as a `border-bottom` on a transparent border, so in a COLUMN stack —
 * `align-items: stretch` — that border would run the width of the column
 * instead of the width of the words. On the home page the same class is a flex
 * item of `.sec-head`, which is a ROW, so its size is its content and the
 * problem cannot arise there. Canvas 3:416 measures the box at 154px, which is
 * the label's own width. */
.story-body .sec-link { align-self: flex-start; }

/* 02 · HOW IT'S MADE (canvas 3:429) — four equal steps, 16 apart, each opened by
 * a hairline. The hairline is the cell's own top border rather than an element:
 * the canvas draws 1px, then 14px of air, then the index — which is a border and
 * its padding, with nothing extra to keep in sync. */
.steps { display: flex; gap: 16px; align-items: flex-start; }
.step {
	flex: 1 1 0;
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 14px;
	border-top: 1px solid var(--gl-ink);
	padding-top: 14px;
}
.step .n {
	font-family: var(--gl-mono);
	font-weight: 700;
	font-size: 10px;
	letter-spacing: 1.4px;
	text-transform: uppercase;
	color: var(--gl-ember);
}
.step-name {
	font-family: var(--gl-serif);
	font-weight: 400;
	font-size: 30px;
	line-height: 1.1;
	color: var(--gl-ink);
	margin: 0;
}
.step-p { font-size: 15px; line-height: 1.6; color: var(--gl-body); margin: 0; }

/* 03 · VISIT (canvas 3:456) — an ink band whose lead and button are pushed to
 * opposite ends. `.hero-foot` does the same job on the hero, and this row
 * aligns its items the same way it does: to the BOTTOM.
 *
 * `flex-end` is what the canvas says twice over, and the first spelling of
 * this rule had it as `center`. Canvas 3:459 carries counterAxisAlignItems
 * MAX, which is `flex-end`; and the measurement agrees — its button box is
 * 161 x 49 inside a 52px row at y 2191, i.e. offset 3 from the top, which is
 * 52 - 49 exactly. Centred would have been offset 1.5. A 1.5px error is not
 * worth a fix on its own; the reason it is worth writing down is that the
 * comment here CLAIMED the canvas was centred, so the next reader would have
 * kept it.
 *
 * The band is split into `.cta-band` and `.cta-in` exactly as `.sec` is split
 * into `.sec` and `.sec-in` — the band holds the padding, the inner element
 * holds the measure and the stack. An Elementor section is one element playing
 * both parts, so A9.11 of gloam-compat.css gives the container the second half.
 *
 * `.cta-band` CARRIES THE PADDING AND NOTHING ELSE, which is what that split
 * means. Its first spelling also had `display: flex; flex-direction: column;
 * gap: 28px`, and all three were wrong: the band has one child, so the gap was
 * inert AND a second statement of `.cta-in`'s 28 — one number, two places to
 * change it — while the flex was a layout the inner element already owns, and
 * `.sec` (the element this one is modelled on) has neither.
 *
 * Its 88 of vertical padding is 8 less than the section rhythm (which is 88 at
 * 1440, where the canvas lands it) and follows the token down from there, so this
 * band tightens with every other band on a narrow screen instead of holding a
 * desktop number. The numbers strip above does the same, 24 less. */
.cta-band {
	padding: calc(var(--gl-sec-y) - 8px) var(--gl-pad);
}
.cta-in {
	width: 100%;
	max-width: var(--gl-wrap);
	margin: 0 auto;
	display: flex;
	flex-direction: column;
	gap: 28px;
}
.cta-title {
	font-family: var(--gl-serif);
	font-weight: 400;
	font-size: 58px;
	line-height: 1.034;   /* 58 / 60 */
	letter-spacing: -.5px;
	margin: 0;
}
.cta-row { display: flex; align-items: flex-end; justify-content: space-between; gap: 48px; }
.cta-lead { font-size: 16px; line-height: 1.625; color: var(--gl-muted-2); max-width: 620px; }

/* --------------------------------------------------------------------------
   19. THEME-LEVEL HELPERS
   -------------------------------------------------------------------------- */
.gl-ok, .gl-err { padding: 16px 20px; font-family: var(--gl-sans); font-weight: 600; font-size: 14px; margin-bottom: 18px; }
.gl-ok  { background: rgba(245,239,227,.16); color: var(--gl-paper); box-shadow: inset 0 0 0 1px rgba(245,239,227,.5); }
.gl-err { background: #fff; color: var(--gl-ember); box-shadow: inset 0 0 0 1px var(--gl-ember); }
.sec--paper .gl-ok, .sec--surface .gl-ok { background: var(--gl-paper); color: var(--gl-ink); box-shadow: inset 0 0 0 1px var(--gl-ink); }

/* honeypot — present in the DOM, invisible to humans */
.gl-hp { position: absolute !important; left: -9999px !important; top: -9999px !important; width: 1px; height: 1px; overflow: hidden; border: 0; padding: 0; }

/* built-in page fallback content area (kept so Elementor always finds it) */
.gl-classic { max-width: 860px; margin: 46px auto 0; padding: 0 var(--gl-pad); }

/* --------------------------------------------------------------------------
   20. RESPONSIVE
   -------------------------------------------------------------------------- */
@media (max-width: 1180px) {
	:root { --gl-pad: 40px; --gl-sec-y: 72px; --gl-gutter: 40px; --gl-wrap: 100%; }
	.hero { min-height: 640px; }
	.hero-title { font-size: 84px; letter-spacing: -1px; }
	/* THE INNER HERO'S STEPS. Every number is the home hero's own, applied to
	 * 620 rather than to 820 — 640/820, 560/820 and 480/820 of it are 480 / 420
	 * / 360 — because the canvas carries no inner-page breakpoints and a second
	 * scale for one page is how a system stops being one. Two classes, so the
	 * tie with `.hero` above is settled by specificity and not by position. */
	.hero.hero--inner { min-height: 480px; }
	.hero--inner .hero-title { font-size: 84px; }
	.steps { flex-wrap: wrap; }
	.step { flex: 1 1 calc(50% - 8px); }
	/* The page's two smaller serif titles take the system's own 1180 size, the
	 * same one `.sec-title` takes, rather than a ratio of their own. */
	.story-title, .cta-title { font-size: 48px; }
	.sec-title, .join-title { font-size: 48px; }
	.edit-media { flex-basis: 52%; }
	.edit-media .gl-ph { height: 420px; }
	.ftr-mark-run > span { font-size: 220px; letter-spacing: -2px; }

	/* The masthead's three groups are all content-sized — .brand and .rt are
	 * flex: none and the menu is as wide as its words — so nothing can shrink
	 * and a long menu pushes the utilities past the right edge. Measured: at a
	 * 991px viewport the row ended 5px wide, which is 5px of horizontal
	 * scrollbar on every page. The gaps come in and the row is allowed to wrap
	 * rather than overflow; when it fits, wrapping changes nothing. Scoped to
	 * this breakpoint on purpose — the 1328px desktop spacing is untouched. */
	.mast-in { height: auto; min-height: 78px; gap: 16px; flex-wrap: wrap; }
	.mast nav { gap: 20px; flex-wrap: wrap; }
	.mast .rt { gap: 16px; }

	.mats-grid { flex-wrap: wrap; }
	.mat { flex: 1 1 calc(50% - 8px); }
	.shelf-row { flex-wrap: wrap; }
	.shelf-row .gcard { flex: 1 1 calc(50% - 20px); }
	/* MUST stay after `.shelf-row .gcard`: both selectors score (0,2,0), so
	 * source order is what keeps the featured card full-width on tablet.
	 * Reversing them silently collapses the 01 block into a plain 2-up grid. */
	.shelf-row--wide .gcard--wide { flex: 0 0 100%; }
	.voices { flex-wrap: wrap; }
	.voice { flex: 1 1 calc(50% - 8px); }
}

@media (max-width: 900px) {
	.mast .burger { display: block; }
	.mast nav {
		display: none;
		position: absolute;
		left: 0; right: 0; top: 100%;
		background: var(--gl-paper);
		flex-direction: column;
		align-items: flex-start;
		gap: 0;
		padding: 8px var(--gl-pad) 20px;
		box-shadow: inset 0 1px 0 var(--gl-ink);
	}
	.mast nav.is-open { display: flex; }
	.mast nav a { padding: 12px 0; font-size: 14px; }
	.mast-in { position: relative; flex-wrap: wrap; }

	.hero { padding: 32px var(--gl-pad); min-height: 560px; }
	.hero-title { font-size: 62px; }
	.hero-foot { flex-direction: column; align-items: flex-start; gap: 32px; }
	.hero-lead { max-width: 100%; }
	.hero-top { flex-direction: column; align-items: flex-start; gap: 6px; }
	/* The inner hero keeps its own padding — the two-class rule in section 9
	 * outranks `.hero` above — and only its height and headline step down. Its
	 * 660 measure is the same measure the home hero gives up here. */
	.hero.hero--inner { min-height: 420px; }
	.hero--inner .hero-title { font-size: 62px; }
	.hero--inner .hero-lead { max-width: 100%; }
	/* Both inner-page rows stack where `.edit-row` and `.join-top` stack, and the
	 * CTA's row uses the direction AND the 32px gap `.hero-foot` uses. */
	.story-row { flex-direction: column; gap: 32px; }
	.story-rail { flex-basis: auto; width: 100%; }
	.cta-row { flex-direction: column; align-items: flex-start; gap: 32px; }

	.edit-row { flex-direction: column; }
	.edit-media { flex-basis: auto; width: 100%; }
	.join-top { flex-direction: column; gap: 32px; }
	.join-list { flex-basis: auto; width: 100%; }
	.ftr-top { flex-direction: column; gap: 40px; }
	.ftr-cols { flex-wrap: wrap; gap: 36px; }
	.stats { flex-wrap: wrap; gap: 24px 40px; }
	.sec-head { flex-direction: column; align-items: flex-start; gap: 20px; }
}

@media (max-width: 680px) {
	:root { --gl-pad: 20px; --gl-sec-y: 56px; --gl-gutter: 24px; --gl-logo-h: 40px; }
	.util { padding: 10px var(--gl-pad); }
	.util-in { flex-direction: column; gap: 8px; }
	/* min-height as well as height: the 1180px block relaxes the header to
	 * `height: auto; min-height: 78px` so it can wrap, and a later `height: 64px`
	 * does not undo that on its own — it would leave a 78px header on a 680px
	 * screen. The render check caught it as exactly +14px of page height. */
	.mast-in { height: 64px; min-height: 0; }
	.mast .mark { font-size: 22px; }
	.mast .sub { display: none; }
	.mast .rt { gap: 14px; }
	.mast .rt a, .mast .rt button { font-size: 11px; }
	.gl-search.is-open .gl-search-field { width: 96px; }

	.hero { padding: 24px var(--gl-pad); min-height: 480px; }
	.hero-title { font-size: 42px; letter-spacing: -.5px; }
	.hero-mid { gap: 18px; }
	.hero-rule { width: 48px; }
	/* The inner hero's copy stack takes the same tight gap its parent takes. */
	.hero.hero--inner { min-height: 360px; }
	.hero--inner .hero-title { font-size: 42px; }
	.hero--inner .hero-mid { gap: 18px; }
	.steps { flex-direction: column; gap: 24px; }
	.step { flex: 1 1 auto; width: 100%; }
	.story-title, .cta-title { font-size: 34px; }
	.mq { min-height: 64px; gap: 14px; padding: 14px var(--gl-pad); }
	.mq span { font-size: 22px; }
	.mq .sep { font-size: 18px; }

	.sec-title, .join-title { font-size: 34px; }
	.sec-link, .gl-kicker { font-size: 10px; }
	.gcard .gl-ph { height: 260px; }
	.gcard .meta .t { font-size: 20px; }
	.shelf-row { flex-direction: column; gap: 24px; }
	.shelf-row .gcard { flex: 1 1 auto; width: 100%; }
	.edit-media .gl-ph { height: 300px; }
	.edit-info h3 { font-size: 30px; }
	.edit-info .pull { font-size: 18px; }
	.mat { flex: 1 1 100%; }
	.mat .gl-ph { height: 220px; }
	.voice { flex: 1 1 100%; }
	.quote { font-size: 28px; }
	.stat .n { font-size: 30px; }
	.join-form { flex-direction: column; }
	.join-form input { min-height: 56px; }
	.join-form button { min-height: 56px; }
	.ftr { padding: 56px var(--gl-pad); }
	.ftr-in { gap: 36px; }
	.ftr-mark-run > span { font-size: 84px; letter-spacing: -1px; }
	.ftr-bot { flex-direction: column; align-items: flex-start; gap: 10px; }
	.gl-btn { padding: 16px 24px; }
}

/* ==========================================================================
   PART 2 — WORDPRESS / WOOCOMMERCE / ELEMENTOR COMPATIBILITY LAYER
   Authored in design/gloam-compat.css.
   ========================================================================== */
/* ==========================================================================
   GLOAM — WORDPRESS / WOOCOMMERCE COMPATIBILITY LAYER  (PART 2)
   --------------------------------------------------------------------------
   WP core, WooCommerce and Elementor each ship their own CSS. This layer
   dresses all of it in the GLOAM design system so the site wears one skin
   everywhere, and restores the "implicit" rules that WooCommerce's default
   stylesheet normally provides (it is switched off in functions.php).
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. WP CORE
   -------------------------------------------------------------------------- */
.screen-reader-text {
	position: absolute !important;
	width: 1px; height: 1px;
	overflow: hidden;
	clip: rect(1px,1px,1px,1px);
	white-space: nowrap;
}
.skip-link {
	position: absolute;
	left: -9999px; top: 0;
	z-index: 100000;
	background: var(--gl-ink);
	color: var(--gl-paper);
	padding: 10px 18px;
	font-family: var(--gl-mono);
	font-size: 11px;
	letter-spacing: 1.2px;
	text-transform: uppercase;
}
.skip-link:focus { left: 0; }
::selection { background: var(--gl-ember); color: #fff; }

.alignleft   { float: left;  margin: 6px 28px 18px 0; }
.alignright  { float: right; margin: 6px 0 18px 28px; }
.aligncenter { margin-left: auto; margin-right: auto; }
.wp-caption-text, .wp-element-caption, figcaption {
	font-family: var(--gl-mono);
	font-size: 10px;
	letter-spacing: 1.2px;
	text-transform: uppercase;
	color: var(--gl-muted);
	padding-top: 8px;
	text-align: center;
}

/* post / page entry */
.gl-entry { padding: 56px var(--gl-pad) 90px; max-width: 860px; margin: 0 auto; }
.gl-entry h1 { font-family: var(--gl-serif); font-weight: 400; font-size: 46px; line-height: 1.1; margin: 10px 0 24px; letter-spacing: -.5px; }
.gl-entry h2, .gl-entry h3, .gl-entry h4 { font-family: var(--gl-serif); font-weight: 400; margin: 32px 0 12px; color: var(--gl-ink); }
.gl-entry h2 { font-size: 32px; }
.gl-entry h3 { font-size: 24px; }
.gl-entry p { margin: 0 0 16px; color: var(--gl-body); font-size: 16px; line-height: 1.75; }
.gl-entry a { color: var(--gl-ember); border-bottom: 1px solid currentColor; }
.gl-entry ul, .gl-entry ol { margin: 0 0 16px 22px; color: var(--gl-body); }
.gl-entry ul li { list-style: disc; }
.gl-entry ol li { list-style: decimal; }
.gl-entry blockquote { border-left: 2px solid var(--gl-ember); padding: 4px 0 4px 22px; margin: 24px 0; font-family: var(--gl-serif); font-style: italic; font-size: 22px; color: var(--gl-body); }

/* WP block bits the theme uses */
.wp-block-button__link { background: var(--gl-ember) !important; color: #fff !important; border-radius: 0 !important; font-weight: 700; }
.wp-block-search__button { background: var(--gl-ink); color: var(--gl-paper); border: 0; border-radius: 0; padding: 12px 20px; font-weight: 700; cursor: pointer; }

/* --------------------------------------------------------------------------
   2. REAL WP MENUS INSIDE THE DESIGN
   A custom menu renders <ul><li><a>. The draft markup is bare <a> tags.
   Zero the list and hand the flex layout to the <ul> so both look identical.
   (Without this you get the classic "bullet points in the nav" defect.)
   -------------------------------------------------------------------------- */
.mast nav ul { display: flex; align-items: center; gap: 32px; list-style: none; margin: 0; padding: 0; flex-wrap: wrap; }
.mast nav li { list-style: none; }

.mast .rt ul { display: flex; align-items: center; justify-content: flex-end; gap: 22px; list-style: none; margin: 0; padding: 0; flex-wrap: wrap; }
.mast .rt li { list-style: none; }

.util .r ul { display: flex; align-items: center; gap: 20px; list-style: none; margin: 0; padding: 0; }
.util .r li { list-style: none; }

.ftr-col ul li { list-style: none; }

/* mobile nav panel turns the same ul vertical */
@media (max-width: 900px) {
	.mast nav ul { flex-direction: column; align-items: flex-start; gap: 0; width: 100%; }
	.mast nav li { width: 100%; }
}

/* --------------------------------------------------------------------------
   3. HEADER SEARCH (native WP search dressed as a masthead link)
   -------------------------------------------------------------------------- */
.gl-search input[type="search"] { -webkit-appearance: none; appearance: none; }
.gl-search input[type="search"]::-webkit-search-decoration,
.gl-search input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; }
@media (max-width: 680px) {
	.gl-search-btn .gl-search-label { display: none; }
}

/* cart count badge (ajax-refreshed fragment) */
.cartpill { color: inherit; }

/* --------------------------------------------------------------------------
   4. THEME TEXT HELPERS
   -------------------------------------------------------------------------- */
.gl-empty-note {
	font-family: var(--gl-mono);
	font-size: 12px;
	letter-spacing: 1.2px;
	text-transform: uppercase;
	color: var(--gl-muted);
	padding: 40px 0;
}

/* --- inner-page masthead band -------------------------------------------
   One band shared by every non-Woo page (page / archive / search / 404) so
   the site keeps a single editorial rhythm instead of five bespoke headers. */
.gl-shophead {
	background: var(--gl-surface);
	border-bottom: 1px solid var(--gl-ink);
	padding: 44px var(--gl-pad) 34px;
}
.gl-shophead .in { width: 100%; max-width: var(--gl-wrap); margin: 0 auto; }
.gl-shophead h1 {
	font-family: var(--gl-serif); font-weight: 400;
	font-size: 46px; line-height: 1.05; margin: 0; letter-spacing: -.5px;
}
.gl-shophead p { color: var(--gl-body); margin: 10px 0 0; max-width: 620px; font-size: 14.5px; line-height: 1.7; }

/* breadcrumb — a mono trail, never the Woo default <nav class="woocommerce-breadcrumb"> */
.crumb {
	font-family: var(--gl-mono); font-size: 10px; letter-spacing: 1.2px;
	text-transform: uppercase; color: var(--gl-muted);
	display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
}
.crumb a { color: var(--gl-muted); transition: color .16s; }
.crumb a:hover { color: var(--gl-ember); }
.crumb .sep { color: var(--gl-line-paper); }
.crumb .here { color: var(--gl-ink); }

/* --- body container -----------------------------------------------------
   .gl-entry is the comfortable reading measure for prose; .gl-wide drops the
   cap so cart / checkout / account / Elementor pages can use the full grid. */
.gl-wide { max-width: var(--gl-wrap); }
.gl-wide .gl-entry { padding-left: 0; padding-right: 0; }

/* --- archive / search result list --------------------------------------- */
.gl-list { display: flex; flex-direction: column; }
.gl-item { border-bottom: 1px solid var(--gl-line-paper); }
.gl-item:first-child { border-top: 1px solid var(--gl-line-paper); }
.gl-item > a { display: flex; gap: 40px; align-items: flex-start; padding: 34px 0; }
.gl-item .gl-ph { flex: 0 0 320px; height: 210px; }
.gl-item .txt { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 12px; }
.gl-item .meta {
	font-family: var(--gl-mono); font-size: 10px; letter-spacing: 1.2px;
	text-transform: uppercase; color: var(--gl-muted);
}
.gl-item h2 {
	font-family: var(--gl-serif); font-weight: 400; font-size: 34px;
	line-height: 1.1; margin: 0; color: var(--gl-ink); transition: color .16s;
}
.gl-item:hover h2 { color: var(--gl-ember); }
.gl-item p { margin: 0; font-size: 15.5px; line-height: 1.7; color: var(--gl-body); }
.gl-item .more {
	font-family: var(--gl-mono); font-weight: 700; font-size: 10px;
	letter-spacing: 1.4px; text-transform: uppercase; color: var(--gl-ember);
}

/* --- forms used by the built-in contact / newsletter shortcodes ---------- */
.gl-form-slot { display: flex; flex-direction: column; }
.gl-form { display: flex; flex-direction: column; gap: 20px; }
.gl-form .gl-field { display: flex; flex-direction: column; gap: 8px; }
.gl-form label {
	font-family: var(--gl-mono); font-weight: 700; font-size: 10px;
	letter-spacing: 2px; text-transform: uppercase; color: var(--gl-ink);
}
.gl-form input[type="text"], .gl-form input[type="email"],
.gl-form input[type="tel"], .gl-form textarea {
	width: 100%; padding: 14px 16px;
	border: 1px solid var(--gl-ink); border-radius: 0;
	background: var(--gl-paper);
	font-family: var(--gl-sans); font-size: 15px; color: var(--gl-ink);
	line-height: 1.5; outline: none; resize: vertical;
	transition: background .16s;
}
.gl-form input:focus, .gl-form textarea:focus { background: #fff; }
.gl-form .gl-btn { align-self: flex-start; }

/* --- container shapes --------------------------------------------------- */
.gl-canvas-wrap { width: 100%; }         /* Elementor: Elementor owns padding  */
.gl-canvas { width: 100%; }              /* Woo cart / checkout / account      */
.gl-shop-body > .gl-entry { padding: 0 0 20px; }
.gl-pagelinks { font-family: var(--gl-mono); font-size: 11px; letter-spacing: 1.2px; text-transform: uppercase; color: var(--gl-muted); margin: 24px 0 0; }
.gl-pagelinks a { color: var(--gl-ember); }

/* --- single post -------------------------------------------------------- */
.gl-post-hero { width: 100%; max-width: var(--gl-wrap); margin: 0 auto; padding: 38px var(--gl-pad) 0; }
.gl-tags { display: flex; gap: 8px; flex-wrap: wrap; margin: 34px 0 0; padding-top: 20px; border-top: 1px solid var(--gl-line-paper); }
.gl-tags a {
	font-family: var(--gl-mono); font-size: 10px; letter-spacing: 1.4px;
	text-transform: uppercase; color: var(--gl-muted);
	border: 1px solid var(--gl-line-paper); padding: 6px 12px;
	transition: color .16s, border-color .16s;
}
.gl-tags a:hover { color: var(--gl-ember); border-color: var(--gl-ember); }

.gl-postnav { border-top: 1px solid var(--gl-ink); margin-top: 60px; }
.gl-postnav .in { width: 100%; max-width: var(--gl-wrap); margin: 0 auto; display: flex; justify-content: space-between; gap: 40px; }
.gl-postnav a { display: flex; flex-direction: column; gap: 8px; padding: 26px 0; max-width: 46%; }
.gl-postnav a.next { text-align: right; margin-left: auto; }
.gl-postnav .k { font-family: var(--gl-mono); font-weight: 700; font-size: 10px; letter-spacing: 1.6px; text-transform: uppercase; color: var(--gl-ember); }
.gl-postnav .t { font-family: var(--gl-serif); font-size: 26px; line-height: 1.15; color: var(--gl-ink); transition: color .16s; }
.gl-postnav a:hover .t { color: var(--gl-ember); }

/* --- comments ----------------------------------------------------------- */
.gl-comments { width: 100%; max-width: 860px; margin: 0 auto; padding: 0 var(--gl-pad) 90px; }
.gl-comments-title { font-family: var(--gl-serif); font-weight: 400; font-size: 26px; margin: 34px 0 18px; }
.gl-comments .comment-list { list-style: none; margin: 0 0 10px; padding: 0; }
.gl-comments .comment-list .comment { list-style: none; padding: 20px 0; border-bottom: 1px solid var(--gl-line-paper); }
.gl-comments .comment-meta { font-family: var(--gl-mono); font-size: 10px; letter-spacing: 1.2px; text-transform: uppercase; color: var(--gl-muted); margin-bottom: 10px; }
.gl-comments .comment-meta a { color: var(--gl-muted); }
.gl-comments .comment-meta a:hover { color: var(--gl-ember); }
.gl-comments .comment-content p { font-size: 15.5px; line-height: 1.7; color: var(--gl-body); margin: 0 0 12px; }
.gl-comments .comment-content a { color: var(--gl-ember); border-bottom: 1px solid currentColor; }
.gl-comments .comment-list .children { list-style: none; margin: 18px 0 0 26px; padding: 0; }
.gl-comments .comment-reply-link { font-family: var(--gl-mono); font-weight: 700; font-size: 10px; letter-spacing: 1.4px; text-transform: uppercase; color: var(--gl-ember); }
.gl-comments .comment-respond { margin-top: 30px; }
.gl-comments .comment-respond .logged-in-as,
.gl-comments .comment-respond .comment-notes { font-family: var(--gl-mono); font-size: 10px; letter-spacing: 1.2px; text-transform: uppercase; color: var(--gl-muted); }
.gl-comments .comment-respond .comment-form p { margin: 0 0 18px; }
.gl-comments .comment-respond label { display: block; font-family: var(--gl-mono); font-weight: 700; font-size: 10px; letter-spacing: 2px; text-transform: uppercase; color: var(--gl-ink); margin-bottom: 8px; }
.gl-comments .comment-respond input[type="text"], .gl-comments .comment-respond input[type="email"],
.gl-comments .comment-respond input[type="url"], .gl-comments .comment-respond textarea {
	width: 100%; padding: 14px 16px; border: 1px solid var(--gl-ink); border-radius: 0;
	background: var(--gl-paper); font-family: var(--gl-sans); font-size: 15px; color: var(--gl-ink);
	outline: none;
}
.gl-comments .comment-respond .form-submit { margin: 0; }

/* --- 404 ---------------------------------------------------------------- */
.gl-404-mark { font-family: var(--gl-serif); font-size: 160px; line-height: .9; letter-spacing: -4px; color: var(--gl-surface); margin: 0 0 10px; }
.gl-404-sub { font-family: var(--gl-serif); font-weight: 400; font-size: 30px; margin: 50px 0 20px; }

/* --- outline button variant (used on 404) -------------------------------- */
.gl-btn--outline { background: transparent; color: var(--gl-ink); box-shadow: inset 0 0 0 1px var(--gl-ink); }
.gl-btn--outline:hover { background: var(--gl-ink); color: var(--gl-paper); }

/* --- archive grid column must be allowed to shrink ---------------------- */
.gl-results { min-width: 0; }

/* --------------------------------------------------------------------------
   5. ELEMENTOR
   -------------------------------------------------------------------------- */

/* --- Elementor global token baseline ------------------------------------
   Sixteen tokens, and the SELECTOR is the whole point of them.

   functions.php re-declares these from the Customizer through the same
   selector and emits that block last in the document, so on the live site the
   values there are the ones that take effect — including any the owner has
   changed. This copy carries the shipped defaults.

   `body[class*="elementor-kit-"]` is not decoration: Elementor puts its
   globals on the KIT'S OWN CLASS, which it writes onto `<body>`
   (`body.elementor-kit-9`), NOT on `:root`. A rule that says only `:root`, or
   only `body`, therefore loses — `:root` is the wrong element, and `body`
   (0,0,1) loses to `.elementor-kit-9` (0,1,0) on the same element. Matching the
   kit's own class shape at (0,1,1) is what beats it outright, and it is why
   the site cannot silently revert to Elementor's blue-violet defaults or its
   Roboto: this block IS the fallback, and it is effective on its own — if a
   caching plugin strips or defers the inline <style id="gloam-tokens">, the
   design's palette and faces still hold. */
:root,
body[class*="elementor-kit-"] {
	--e-global-color-primary:                    #141414;
	--e-global-color-secondary:                  #141414;
	--e-global-color-text:                       #3A342A;
	--e-global-color-accent:                     #E03A17;
	--e-global-typography-primary-font-family:   'Instrument Serif';
	--e-global-typography-primary-font-weight:   400;
	--e-global-typography-secondary-font-family: 'Instrument Serif';
	--e-global-typography-secondary-font-weight: 400;
	--e-global-typography-text-font-family:      'Archivo';
	--e-global-typography-text-font-weight:      400;
	--e-global-typography-accent-font-family:    'Archivo';
	--e-global-typography-accent-font-weight:    700;
}

/* Elementor owns its section padding — never let our .sec padding leak in */
section.elementor-section { padding: 0; }

/* Elementor columns must not add their own gutters inside our design rows */
.elementor-column .elementor-widget-wrap { padding: 0; }

/* --- Elementor buttons, re-skinned at >= (0,2,0) ---
   Elementor styles buttons via .elementor-widget-button .elementor-button
   (specificity 0,2,0). Single-class rules lose to it, so we match the shape. */
/* WHY EVERY SELECTOR HERE CARRIES `body`. The base look is (0,2,0), and so is
   the kit's own button rule in Elementor's generated `post-N.css`:
   `.elementor-widget-button .elementor-button { background-color:
   var(--e-global-color-accent); font-family: … }`. That stylesheet prints
   AFTER the theme's on the live site, so the tie went to the kit and every
   button came out in the kit accent (#E03A17) rather than the design's ink —
   measured in the browser, not inferred. `body` adds one element to the
   specificity and is the house lever for this; §8's `body .gl-row …` rules use
   the same one. */
body .elementor-widget-button .elementor-button,
body .elementor-button.elementor-size-sm,
body .elementor-button.elementor-size-md,
body .elementor-button.elementor-size-lg {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	background: var(--gl-ink);
	color: var(--gl-paper);
	border: 0;
	border-radius: 0;
	padding: 18px 32px;
	font-family: var(--gl-sans);
	font-weight: 700;
	font-size: 12px;
	letter-spacing: 1.4px;
	text-transform: uppercase;
	line-height: 1;
	transition: background .16s, color .16s;
}
body .elementor-widget-button .elementor-button:hover { background: var(--gl-ember); color: #fff; }
body .elementor-widget-button .elementor-button .elementor-button-text { font-family: inherit; }

/* VARIANTS RIDE ON THE COLUMN, WHICH IS THE ONLY PLACE THAT WORKS.
   They used to ride on the widget wrapper — no class channel on a widget in
   Elementor 4.2.4 — and on the `<a>`, which the button widget owns and the
   template cannot reach. Every button in a `.gl-btnrow` is the only child of
   its own column, so the column is where the class lands; verified on live.
   (0,3,0) against the base rules above at (0,2,1). */
.elementor-column.gl-btnv-paper .elementor-button { background: var(--gl-paper); color: var(--gl-ink); }
.elementor-column.gl-btnv-paper .elementor-button:hover { background: #fff; color: var(--gl-ink); }
.elementor-column.gl-btnv-ghost .elementor-button { background: transparent; color: var(--gl-paper); box-shadow: inset 0 0 0 1px rgba(245,239,227,.45); }
.elementor-column.gl-btnv-ghost .elementor-button:hover { background: rgba(245,239,227,.08); color: var(--gl-paper); box-shadow: inset 0 0 0 1px var(--gl-paper); }
.elementor-column.gl-btnv-ember .elementor-button { background: var(--gl-ember); color: #fff; }
.elementor-column.gl-btnv-ember .elementor-button:hover { background: var(--gl-ember-dark); color: #fff; }

/* --- the kit's tokens are re-pointed at the design's, so the kit's OWN widget
       rules compute the design's type and colour ---
   THE PROBLEM. Elementor's page stylesheet declares a family, a weight and a
   colour on every native widget:
     .elementor-widget-heading .elementor-heading-title { font-family:
       var(--e-global-typography-primary-font-family), Sans-serif;
       font-weight: var(--e-global-typography-primary-font-weight);
       color: var(--e-global-color-primary) }                          (0,2,0)
     .elementor-widget-text-editor { font-family: …; font-weight: …;
       color: var(--e-global-color-text) }                             (0,1,0)
   and it is enqueued AFTER this stylesheet, so every tie goes to the kit.
   PART 1's element rules for the same properties (`.mat h3` is (0,1,1)) sit
   BELOW that and keep only the properties the kit is silent about — which is
   why a live `.mat h3` read 30px, PART 1's own number, in the wrong face.

   THE FIX IS NOT A STRONGER SELECTOR, IT IS A REDIRECT. Out-specifying the kit
   was tried: `body .elementor-widget-heading .elementor-heading-title { … }` is
   (0,2,1) and beats the kit — and it also beats PART 1's own element rules, so
   the neutraliser destroys the declarations it was written to protect. There is
   no window between the two, because PART 1's element rules sit below the kit.
   So the kit is not fought, it is re-pointed: its rule already reads a custom
   property, and the theme declares that property to be the design's own token.

   WHERE THE PROPERTY MUST BE DECLARED, which was got wrong once. Not on `body`:
   the kit carries its own id as a CLASS ON `<body>` (`body.elementor-kit-9`
   live), so a rule aimed at `body` is a SAME-ELEMENT contest and loses —
   `.elementor-kit-9` is (0,1,0), `body` is (0,0,1). Inheritance does not rescue
   it either, for the same reason: the property is already declared on the very
   element being styled. `body[class*="elementor-kit-"]` is (0,1,1) and wins
   outright. That is the selector `gloam_css_vars()` emits, with the live
   Customizer values, last in the document; the token block above carries the
   same selector and the shipped defaults, so the static preview and the live
   site reach the same numbers by the same route. **There is nothing to add to
   this section — the redirect IS the fix, and it lives in the block above.**

   WHY NOTHING ELSE IS DECLARED HERE. The design's colours already equal the
   kit's copy of them (#141414 / #3A342A), and the redirect keeps them in step
   when the palette moves, so there is no colour to re-assert at this level; the
   four grounds are A4's job, at (0,3,0), above the kit. Nor `font-size`: the kit
   sets none on a title, which is exactly why PART 1's 30px and 46px survive. And
   never a `font` SHORTHAND — it resets font-size, so it would erase those sizes
   while looking like it was helping.

   THE `Microsoft YaHei` READING, WHICH POINTED SOMEWHERE ELSE ENTIRELY. The
   live probe on 2026-09-14 found every heading computing `"Microsoft YaHei"`,
   and the first version of this comment recorded that as the kit winning the
   family. It was not the kit. It was `esc_attr()` in `gloam_css_vars()`, which
   encoded the quote inside `--gl-serif`, and the `;` that terminates the entity
   `&#039;` terminated the DECLARATION with it — so `var(--gl-serif)` was
   invalid at computed-value time, the property inherited instead, and the page
   fell through to the browser's default font. Colours were untouched because a
   hex value has nothing to escape. See `gloam_css_value()`; the two defects are
   indistinguishable from a computed style, and only one of them is about
   specificity. */
/* Two optional heading roles. They are dead today — no template names them — but
   they used to read `.elementor-widget-heading.gl-h-mono …`, which required the
   class ON the widget and therefore could never fire; fixed to the ancestor
   shape so the first template that uses one is not a silent no-op. `body` here
   is safe: these are the design's own roles, so there is no PART 1 element rule
   for them to overrun. */
body .gl-h-serif .elementor-heading-title {
	font-family: var(--gl-serif); font-weight: 400; letter-spacing: -.5px;
}
body .gl-h-mono .elementor-heading-title {
	font-family: var(--gl-mono); font-weight: 700; font-size: 11px;
	letter-spacing: 1.4px; text-transform: uppercase; color: var(--gl-ember);
}

/* --- the image plate: PART 1's `.gl-ph`, built the only way that works here ---
   PART 1 states the plate's height from the SCOPE (`.gcard .gl-ph { height:
   400px }`, `.edit-media .gl-ph { 520 }`, `.mat .gl-ph { 260 }`), and that is
   fortunate, because Elementor 4.2.4 gives an image widget no class channel at
   all. The classes this section used to rely on were all inert on live:
   `gl-plate` and `gl-imhNNN` on the widget, and the `.elementor-image` /
   `.elementor-widget-container` divs they reached through — 4.2.4 emits a bare
   `<img>` with no class, no wrapper div and no width/height attribute. Every
   pixel of the plate's box therefore has to come from these rules.
   The plate's own look (gradient + grid) is baked into `assets/img/ph-*.png`;
   only the box and the photo's fit are CSS. */
.gcard > .elementor-widget-wrap > .elementor-widget-image,
.edit-media > .elementor-widget-wrap > .elementor-widget-image,
.mat > .elementor-widget-wrap > .elementor-widget-image {
	position: relative;
	overflow: hidden;
}
.gcard > .elementor-widget-wrap > .elementor-widget-image { height: 400px; }
.edit-media > .elementor-widget-wrap > .elementor-widget-image { height: 520px; }
.mat > .elementor-widget-wrap > .elementor-widget-image { height: 260px; }
.gcard > .elementor-widget-wrap > .elementor-widget-image > img,
.edit-media > .elementor-widget-wrap > .elementor-widget-image > img,
.mat > .elementor-widget-wrap > .elementor-widget-image > img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform .6s cubic-bezier(.2,.7,.2,1);
}
/* PART 1: .gcard:hover .gl-ph > img — the same 3% push, on the same image. */
.gcard:hover > .elementor-widget-wrap > .elementor-widget-image > img { transform: scale(1.03); }

/* --- caption overlays: pull the caption up over the image with a negative
       margin instead of Elementor's absolute-position controls, which do not
       render consistently across Elementor versions --- */
.gl-cap { position: relative; z-index: 2; margin: -92px 22px 0; }
.gl-cap .k { font-family: var(--gl-mono); font-size: 10px; letter-spacing: 2.6px; text-transform: uppercase; color: var(--gl-paper); }
.gl-cap .t { font-family: var(--gl-serif); font-size: 26px; line-height: 1.15; color: var(--gl-paper); }
@media (max-width: 680px) { .gl-cap { margin: -70px 16px 0; } }

/* --------------------------------------------------------------------------
   6. WOOCOMMERCE
   woocommerce_enqueue_styles is filtered to an empty array in functions.php,
   so EVERYTHING Woo needs below is provided here.
   -------------------------------------------------------------------------- */

/* --- archive shell ---
   The band itself is defined in section 4 (.gl-shophead) and shared with the
   plain WP templates; only the Woo-specific bits live here. */
.gl-shophead .crumb { margin-bottom: 14px; }
.gl-shop-body { width: 100%; max-width: var(--gl-wrap); margin: 0 auto; padding: 38px var(--gl-pad) 90px; }

/* --- product grid = the design's 3-column card language --- */
.woocommerce ul.products {
	display: grid;
	grid-template-columns: repeat(3, minmax(0,1fr));
	gap: var(--gl-gutter);
	list-style: none;
	margin: 0 0 10px;
	padding: 0;
}
.woocommerce ul.products::before, .woocommerce ul.products::after { display: none; }
.woocommerce ul.products li.product {
	float: none; width: auto; margin: 0;
	display: flex; flex-direction: column;
	background: transparent;
	border: 0; border-radius: 0;
	position: relative;
}
.woocommerce ul.products li.product a.woocommerce-LoopProduct-link { display: block; }
.woocommerce ul.products li.product img {
	width: 100%; height: 380px;
	object-fit: cover;
	display: block;
	margin: 0;
	background: var(--gl-swatch);
}
.woocommerce ul.products li.product .woocommerce-loop-product__title {
	font-family: var(--gl-serif); font-weight: 400; font-size: 26px; line-height: 1.1;
	color: var(--gl-ink);
	margin: 0; padding: 18px 0 6px;
	border-top: 1px solid var(--gl-ink);
	transition: color .16s;
}
.woocommerce ul.products li.product:hover .woocommerce-loop-product__title { color: var(--gl-ember); }
.woocommerce ul.products li.product .price {
	padding: 0 0 14px;
	color: var(--gl-muted);
	font-family: var(--gl-mono);
	font-size: 10px;
	letter-spacing: 1.2px;
	text-transform: uppercase;
}
.woocommerce ul.products li.product .price ins { text-decoration: none; background: none; }
.woocommerce ul.products li.product .price del { opacity: .6; }
.woocommerce ul.products li.product .star-rating { margin: 0 0 10px; font-size: 11px; color: var(--gl-ember); }
.woocommerce ul.products li.product .button {
	margin: auto 0 0;
	align-self: flex-start;
	display: inline-flex; align-items: center; justify-content: center;
	background: transparent;
	color: var(--gl-ink);
	box-shadow: inset 0 0 0 1px var(--gl-ink);
	border: 0; border-radius: 0;
	padding: 14px 24px;
	font-family: var(--gl-sans); font-weight: 700; font-size: 11px;
	letter-spacing: 1.4px; text-transform: uppercase;
	transition: background .16s, color .16s;
}
.woocommerce ul.products li.product .button:hover { background: var(--gl-ink); color: var(--gl-paper); }
.woocommerce ul.products li.product .button.loading::after { display: none; }
.woocommerce ul.products li.product-category { padding: 0; }
.woocommerce ul.products li.product-category h2 { font-family: var(--gl-serif); font-weight: 400; font-size: 22px; margin: 14px 0 0; }
.woocommerce ul.products li.product-category h2 mark { background: none; color: var(--gl-ember); font-family: var(--gl-mono); font-size: 10px; }
.woocommerce span.onsale {
	position: absolute; top: 14px; left: 14px; z-index: 3;
	min-width: 0; min-height: 0;
	background: var(--gl-ember); color: #fff;
	font-family: var(--gl-mono); font-size: 9.5px; font-weight: 700;
	letter-spacing: 2px; text-transform: uppercase;
	padding: 6px 11px; border-radius: 0; line-height: 1.4; margin: 0;
}

/* --- toolbar: result count + ordering on one line --- */
.gl-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin: 0 0 30px; }
.gl-toolbar .woocommerce-result-count, .gl-toolbar .woocommerce-ordering { margin: 0; }
.woocommerce .woocommerce-result-count {
	font-family: var(--gl-mono); font-size: 11px; letter-spacing: 1.2px;
	text-transform: uppercase; color: var(--gl-muted);
}
.woocommerce .woocommerce-ordering select {
	padding: 10px 14px;
	border: 1px solid var(--gl-ink); border-radius: 0;
	background: var(--gl-paper);
	font-family: var(--gl-mono); font-size: 11px; letter-spacing: 1px;
	color: var(--gl-ink);
}

/* --- filter rail --- */
.gl-shoplay { display: grid; grid-template-columns: 250px minmax(0,1fr); gap: 56px; align-items: start; }
.gl-rail { position: sticky; top: 110px; display: flex; flex-direction: column; gap: 34px; }
.gl-fgroup { display: flex; flex-direction: column; gap: 12px; }
.gl-fgroup h4, .gl-fgroup h6 {
	font-family: var(--gl-mono); font-weight: 700; font-size: 10px;
	letter-spacing: 1.6px; text-transform: uppercase; color: var(--gl-ink);
	margin: 0; padding-bottom: 10px; border-bottom: 1px solid var(--gl-ink);
}
.gl-fgroup ul { display: flex; flex-direction: column; gap: 8px; margin: 0; padding: 0; list-style: none; }
.gl-fgroup li { list-style: none; }
.gl-fgroup li a {
	display: flex; align-items: center; justify-content: space-between; gap: 10px;
	width: 100%;
	font-size: 14px; color: var(--gl-body);
	transition: color .16s;
}
.gl-fgroup li a:hover { color: var(--gl-ember); }
.gl-fgroup li.on a { color: var(--gl-ember); font-weight: 600; }
.gl-fgroup .c { font-family: var(--gl-mono); font-size: 10px; letter-spacing: 1px; color: var(--gl-muted); }
.gl-fgroup ul.sub { margin: 8px 0 2px 12px; padding-left: 12px; border-left: 1px solid var(--gl-line-paper); gap: 6px; }
.gl-fgroup ul.sub li a { font-size: 13px; }
.gl-rail-all {
	font-family: var(--gl-mono); font-weight: 700; font-size: 10px;
	letter-spacing: 1.4px; text-transform: uppercase; color: var(--gl-ember);
	border-bottom: 1px solid transparent; align-self: flex-start;
}
.gl-rail-all:hover { border-bottom-color: currentColor; }

/* --- the default WP search form, dressed to match the design ------------- */
.gl-searchbox .search-form { display: flex; gap: 0; max-width: 520px; margin: 18px 0 26px; }
.gl-searchbox .search-form label { flex: 1 1 auto; min-width: 0; }
.gl-searchbox .search-field {
	width: 100%; height: 54px; padding: 0 18px;
	border: 1px solid var(--gl-ink); border-right: 0; border-radius: 0;
	background: var(--gl-paper);
	font-family: var(--gl-sans); font-size: 15px; color: var(--gl-ink);
	outline: none;
}
.gl-searchbox .search-submit {
	height: 54px; padding: 0 28px;
	border: 1px solid var(--gl-ink); border-radius: 0;
	background: var(--gl-ink); color: var(--gl-paper);
	font-family: var(--gl-sans); font-weight: 700; font-size: 12px;
	letter-spacing: 1.4px; text-transform: uppercase; cursor: pointer;
	transition: background .16s;
}
.gl-searchbox .search-submit:hover { background: var(--gl-ember); border-color: var(--gl-ember); }
.gl-searchbox .screen-reader-text { position: absolute !important; }

/* --- pagination (Woo default CSS off -> zero the bullets ourselves) --- */
.woocommerce nav.woocommerce-pagination { margin-top: 40px; }
.woocommerce nav.woocommerce-pagination ul { display: flex; gap: 8px; justify-content: center; border: 0; margin: 0; padding: 0; }
.woocommerce nav.woocommerce-pagination ul li { border: 0; float: none; overflow: visible; list-style: none; margin: 0; }
.woocommerce nav.woocommerce-pagination ul li a,
.woocommerce nav.woocommerce-pagination ul li span {
	display: inline-flex; align-items: center; justify-content: center;
	min-width: 40px; padding: 10px 14px;
	border: 1px solid var(--gl-ink); border-radius: 0;
	font-family: var(--gl-mono); font-size: 12px;
	background: transparent; color: var(--gl-ink);
	line-height: 1;
}
.woocommerce nav.woocommerce-pagination ul li span.current { background: var(--gl-ink); border-color: var(--gl-ink); color: var(--gl-paper); }
.woocommerce nav.woocommerce-pagination ul li a:hover { background: var(--gl-ember); border-color: var(--gl-ember); color: #fff; }
.nav-links { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; list-style: none; margin: 40px 0 0; padding: 0; }
.nav-links .page-numbers {
	display: inline-flex; align-items: center; justify-content: center;
	min-width: 40px; padding: 10px 14px;
	border: 1px solid var(--gl-ink); border-radius: 0;
	font-family: var(--gl-mono); font-size: 12px;
	color: var(--gl-ink); line-height: 1;
}
.nav-links span.page-numbers.current { background: var(--gl-ink); color: var(--gl-paper); }
.nav-links a.page-numbers:hover { background: var(--gl-ember); border-color: var(--gl-ember); color: #fff; }

/* --- single product --- */
.woocommerce div.product { display: flow-root; }
.woocommerce div.product div.images { float: left; width: 47%; margin-bottom: 40px; }
.woocommerce div.product div.summary { float: right; width: 49%; margin-bottom: 40px; }

/* gallery skeleton — without it the main image stretches and deforms */
.woocommerce div.product div.images .woocommerce-product-gallery { position: relative; }
.woocommerce div.product div.images .woocommerce-product-gallery__wrapper { margin: 0; }
.woocommerce div.product div.images .woocommerce-product-gallery__image img {
	width: 100% !important; height: auto !important; display: block;
}
.woocommerce div.product div.images .flex-viewport { width: 100%; max-height: none; margin: 0 0 4px; }
.woocommerce div.product div.images .flex-viewport ul.slides { list-style: none; margin: 0; padding: 0; }
.woocommerce div.product div.images .flex-viewport ul.slides li { list-style: none; float: none; width: 100%; }
/* thumbnails are a real <ol> — zero the numbers (the stray 1/2/3 defect) */
.woocommerce div.product div.images .flex-control-thumbs {
	list-style: none; margin: 12px 0 0; padding: 0;
	display: grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap: 12px;
}
.woocommerce div.product div.images .flex-control-thumbs li { list-style: none; float: none; width: auto; }
.woocommerce div.product div.images .flex-control-thumbs img { height: 112px; object-fit: cover; border: 1px solid transparent; opacity: 1; }
.woocommerce div.product div.images .flex-control-thumbs img.flex-active { border-color: var(--gl-ember); }
/* zoom support is removed in functions.php; hide the trigger as a second line of defence */
.woocommerce div.product div.images .woocommerce-product-gallery__trigger { display: none !important; }

.woocommerce div.product .product_title { font-family: var(--gl-serif); font-weight: 400; font-size: 46px; line-height: 1.05; letter-spacing: -.5px; margin: 8px 0 14px; }
.woocommerce div.product .product_meta { font-family: var(--gl-mono); font-size: 10px; letter-spacing: 1.2px; text-transform: uppercase; color: var(--gl-muted); margin: 0 0 12px; }
.woocommerce div.product .product_meta a { color: var(--gl-ember); }
.woocommerce div.product p.price, .woocommerce div.product span.price { font-family: var(--gl-sans); font-weight: 500; font-size: 30px; color: var(--gl-ink); margin: 14px 0 6px; }
.woocommerce div.product p.price del, .woocommerce div.product p.price ins { font-family: var(--gl-mono); font-size: 12px; font-weight: 400; color: var(--gl-muted); }
.woocommerce div.product p.price ins { text-decoration: none; color: var(--gl-ink); }
.woocommerce div.product .woocommerce-product-details__short-description { font-size: 16px; line-height: 1.7; color: var(--gl-body); margin: 16px 0 22px; }

.woocommerce div.product form.cart { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; margin: 24px 0 18px; padding: 0; }
.woocommerce div.product form.cart.variations_form { display: block; }
.woocommerce div.product form.cart .button {
	background: var(--gl-ember); color: #fff;
	border: 0; border-radius: 0;
	padding: 18px 32px;
	font-family: var(--gl-sans); font-weight: 700; font-size: 12px;
	letter-spacing: 1.4px; text-transform: uppercase;
	flex: 1; min-width: 210px;
	transition: background .16s;
}
.woocommerce div.product form.cart .button:hover { background: var(--gl-ember-dark); }
.woocommerce div.product form.cart .button:disabled { opacity: .45; cursor: not-allowed; }
.woocommerce div.product form.cart .reset_variations { font-family: var(--gl-mono); font-size: 10px; letter-spacing: 1.2px; text-transform: uppercase; color: var(--gl-muted); }
.woocommerce div.product .quantity .qty {
	border: 1px solid var(--gl-ink); border-radius: 0;
	background: var(--gl-paper);
	height: 52px; width: 64px; text-align: center;
	font-family: var(--gl-sans); font-weight: 700; font-size: 15px; color: var(--gl-ink);
	-moz-appearance: textfield;
}
.woocommerce div.product .quantity input::-webkit-outer-spin-button,
.woocommerce div.product .quantity input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.woocommerce-variation-price { margin-bottom: 14px; }
.woocommerce-variation-price .price { font-family: var(--gl-sans); font-weight: 500; font-size: 24px; }
.woocommerce-variation-availability { font-family: var(--gl-mono); font-size: 10px; letter-spacing: 1.2px; text-transform: uppercase; color: var(--gl-muted); }

/* quantity stepper + attribute pills injected by theme.js */
.gl-qty { display: inline-flex; align-items: stretch; border: 1px solid var(--gl-ink); height: 52px; background: var(--gl-paper); }
.gl-qty button { width: 42px; background: transparent; font-size: 17px; line-height: 1; color: var(--gl-ink); transition: background .16s; }
.gl-qty button:hover { background: rgba(20,20,20,.06); }
.gl-qty input { border: 0; background: transparent; }

/* variant pills — the visible control; the real <select> keeps driving Woo */
.gl-sw { display: flex; flex-wrap: wrap; gap: 8px; }
.gl-sw .sw {
	border: 1px solid var(--gl-ink); border-radius: 0;
	background: var(--gl-paper); color: var(--gl-ink);
	padding: 11px 18px;
	font-family: var(--gl-sans); font-weight: 600; font-size: 11px;
	letter-spacing: 1.2px; text-transform: uppercase; line-height: 1;
	cursor: pointer;
	transition: background .16s, color .16s, border-color .16s, opacity .16s;
}
.gl-sw .sw:hover { border-color: var(--gl-ember); color: var(--gl-ember); }
.gl-sw .sw.is-on { background: var(--gl-ink); border-color: var(--gl-ink); color: var(--gl-paper); }
.gl-sw .sw.disabled { opacity: .32; cursor: not-allowed; text-decoration: line-through; }
.gl-sw .sw.disabled:hover { border-color: var(--gl-ink); color: var(--gl-ink); }

/* the select that theme.js took over: out of sight, still in the DOM */
.woocommerce table.variations select.gl-sw-src {
	position: absolute !important;
	left: -9999px !important;
	width: 1px; height: 1px; overflow: hidden;
	border: 0; padding: 0;
}
.woocommerce table.variations td.value.has-sw { padding-bottom: 18px; }

.woocommerce table.variations { border-collapse: collapse; margin: 0 0 8px; width: 100%; }
.woocommerce table.variations tr, .woocommerce table.variations th, .woocommerce table.variations td { border: 0; padding: 0 0 18px; display: block; background: none; }
.woocommerce table.variations td.label { padding: 0 0 10px; }
.woocommerce table.variations td.label label { font-family: var(--gl-mono); font-weight: 700; font-size: 10px; letter-spacing: 2px; text-transform: uppercase; color: var(--gl-ink); margin: 0; }
.woocommerce table.variations select { padding: 12px 14px; border: 1px solid var(--gl-ink); border-radius: 0; background: var(--gl-paper); font-family: var(--gl-sans); font-size: 14px; color: var(--gl-ink); }

/* tabs */
.woocommerce div.product .woocommerce-tabs { clear: both; padding-top: 30px; }
.woocommerce div.product .woocommerce-tabs ul.tabs { display: flex; gap: 0; flex-wrap: wrap; list-style: none; margin: 0; padding: 0; border-bottom: 1px solid var(--gl-ink); }
.woocommerce div.product .woocommerce-tabs ul.tabs::before, .woocommerce div.product .woocommerce-tabs ul.tabs::after { display: none; }
.woocommerce div.product .woocommerce-tabs ul.tabs li { background: none; border: 0; border-radius: 0; margin: 0; padding: 0; list-style: none; }
.woocommerce div.product .woocommerce-tabs ul.tabs li::before, .woocommerce div.product .woocommerce-tabs ul.tabs li::after { display: none; }
.woocommerce div.product .woocommerce-tabs ul.tabs li a {
	display: block; padding: 14px 20px;
	font-family: var(--gl-mono); font-weight: 700; font-size: 11px;
	letter-spacing: 1.4px; text-transform: uppercase;
	color: var(--gl-muted);
	border-bottom: 2px solid transparent;
}
.woocommerce div.product .woocommerce-tabs ul.tabs li.active a { color: var(--gl-ink); border-bottom-color: var(--gl-ember); }
.woocommerce div.product .woocommerce-tabs .woocommerce-Tabs-panel { padding: 26px 0 0; font-size: 16px; line-height: 1.75; color: var(--gl-body); }
.woocommerce div.product .woocommerce-tabs .woocommerce-Tabs-panel h2:first-child { font-family: var(--gl-serif); font-weight: 400; font-size: 26px; color: var(--gl-ink); margin-bottom: 14px; }

/* related / cross-sells */
.woocommerce .related.products, .woocommerce .upsells.products, .woocommerce .cross-sells { clear: both; padding-top: 56px; }
.woocommerce .related.products > h2, .woocommerce .upsells.products > h2, .woocommerce .cross-sells > h2 { font-family: var(--gl-serif); font-weight: 400; font-size: 32px; margin: 0 0 28px; }

/* --- global Woo buttons (cart / checkout / account) --- */
.woocommerce #respond input#submit,
.woocommerce a.button, .woocommerce button.button, .woocommerce input.button,
.woocommerce #respond input#submit.alt, .woocommerce a.button.alt,
.woocommerce button.button.alt, .woocommerce input.button.alt,
.woocommerce a.button.wc-forward {
	background: var(--gl-ink); color: var(--gl-paper);
	border: 0; border-radius: 0;
	padding: 16px 28px;
	font-family: var(--gl-sans); font-weight: 700; font-size: 12px;
	letter-spacing: 1.4px; text-transform: uppercase;
	line-height: 1; cursor: pointer;
	transition: background .16s, color .16s;
}
.woocommerce #respond input#submit:hover, .woocommerce a.button:hover,
.woocommerce button.button:hover, .woocommerce input.button:hover,
.woocommerce a.button.alt:hover, .woocommerce button.button.alt:hover { background: var(--gl-ember); color: #fff; }
.woocommerce .woocommerce-message .button, .woocommerce .woocommerce-info .button, .woocommerce .woocommerce-error .button {
	float: right; background: none; color: inherit; box-shadow: none;
	padding: 0; text-transform: none; letter-spacing: 0; text-decoration: underline;
}
.woocommerce button.button:disabled, .woocommerce button.button.disabled { opacity: .45; cursor: not-allowed; }

/* --- notices --- */
.woocommerce-message, .woocommerce-info, .woocommerce-error {
	background: var(--gl-paper);
	border: 0; border-left: 3px solid var(--gl-ink);
	color: var(--gl-ink);
	list-style: none;
	padding: 16px 20px;
	margin: 0 0 24px;
	font-size: 14px;
}
.woocommerce-message { border-left-color: var(--gl-ink); }
.woocommerce-info { border-left-color: var(--gl-muted); }
.woocommerce-error { border-left-color: var(--gl-ember); }
.woocommerce-error li { margin: 2px 0; list-style: none; }

/* --- cart / checkout --- */
.woocommerce table.shop_table {
	background: transparent; border: 0; border-collapse: collapse;
	margin: 0 0 30px; width: 100%;
}
.woocommerce table.shop_table th {
	font-family: var(--gl-mono); font-weight: 700; font-size: 10px;
	letter-spacing: 1.6px; text-transform: uppercase; color: var(--gl-ink);
	text-align: left; padding: 0 16px 12px 0;
	border-bottom: 1px solid var(--gl-ink);
}
.woocommerce table.shop_table td { padding: 18px 16px 18px 0; border-bottom: 1px solid var(--gl-line-paper); font-size: 15px; vertical-align: middle; }
.woocommerce table.shop_table img { width: 90px; height: 100px; object-fit: cover; border: 0; }
.woocommerce table.shop_table .quantity .qty { border: 1px solid var(--gl-ink); width: 64px; height: 44px; text-align: center; background: var(--gl-paper); }
.woocommerce a.remove { color: var(--gl-ember) !important; font-weight: 700; display: inline-flex; }
.woocommerce a.remove:hover { background: var(--gl-ember); color: #fff !important; }
.woocommerce .cart_totals { background: var(--gl-surface); padding: 28px 26px; }
.woocommerce .cart_totals h2, .woocommerce-billing-fields h3, .woocommerce-additional-fields h3,
#order_review_heading, .woocommerce-account .woocommerce h2 {
	font-family: var(--gl-serif); font-weight: 400; font-size: 26px; margin: 0 0 18px; letter-spacing: -.5px;
}
.woocommerce form .form-row { padding: 0; margin-bottom: 16px; }
.woocommerce form .form-row label {
	display: block;
	font-family: var(--gl-mono); font-weight: 700; font-size: 10px;
	letter-spacing: 2px; text-transform: uppercase; color: var(--gl-ink);
	margin-bottom: 8px;
}
.woocommerce form .form-row label .required { color: var(--gl-ember); text-decoration: none; }
.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--single {
	width: 100%;
	padding: 14px 16px;
	border: 1px solid var(--gl-ink); border-radius: 0;
	background: var(--gl-surface);
	font-family: var(--gl-sans); font-size: 15px; color: var(--gl-ink);
	height: auto; line-height: 1.5; outline: none;
}
.woocommerce form .form-row input.input-text:focus,
.woocommerce form .form-row textarea:focus { background: var(--gl-paper); }
.select2-container--default .select2-selection--single { border: 1px solid var(--gl-ink) !important; border-radius: 0 !important; height: 52px !important; background: var(--gl-surface); }
.select2-container--default .select2-selection--single .select2-selection__rendered { line-height: 50px !important; padding-left: 16px !important; color: var(--gl-ink); }
.select2-container--default .select2-selection--single .select2-selection__arrow b { border-color: var(--gl-ink) transparent transparent transparent !important; }
.select2-dropdown { border: 1px solid var(--gl-ink) !important; border-radius: 0 !important; }
#add_payment_method #payment, .woocommerce-cart #payment, .woocommerce-checkout #payment {
	background: var(--gl-surface); border: 0; padding: 26px;
}
#add_payment_method #payment div.payment_box, .woocommerce-cart #payment div.payment_box, .woocommerce-checkout #payment div.payment_box {
	background: var(--gl-paper); border: 0; padding: 16px 18px; font-size: 14px;
}
#add_payment_method #payment div.payment_box::before, .woocommerce-checkout #payment div.payment_box::before { display: none; }

/* --- my account --- */
.woocommerce-account .woocommerce-MyAccount-navigation { float: left; width: 26%; }
.woocommerce-account .woocommerce-MyAccount-navigation ul { list-style: none; margin: 0; padding: 0; }
.woocommerce-account .woocommerce-MyAccount-navigation li { list-style: none; }
.woocommerce-account .woocommerce-MyAccount-navigation li a {
	display: block; padding: 13px 16px;
	border: 1px solid var(--gl-ink); border-bottom: 0;
	font-family: var(--gl-mono); font-weight: 700; font-size: 11px;
	letter-spacing: 1.2px; text-transform: uppercase;
	color: var(--gl-ink); background: transparent;
	transition: background .16s, color .16s;
}
.woocommerce-account .woocommerce-MyAccount-navigation li:last-child a { border-bottom: 1px solid var(--gl-ink); }
.woocommerce-account .woocommerce-MyAccount-navigation li.is-active a { background: var(--gl-ink); color: var(--gl-paper); }
.woocommerce-account .woocommerce-MyAccount-content { float: right; width: 70%; }
.woocommerce-account .woocommerce::after { content: ""; display: table; clear: both; }
.woocommerce-account .woocommerce h2, .woocommerce-account .woocommerce h3 { font-family: var(--gl-serif); font-weight: 400; font-size: 26px; }

/* --- reviews / stars --- */
.woocommerce #reviews #comments ol.commentlist { list-style: none; margin: 0; padding: 0; }
.woocommerce #reviews #comments ol.commentlist li { border-bottom: 1px solid var(--gl-line-paper); padding: 20px 0; list-style: none; }
.woocommerce #reviews .comment-text .meta { font-family: var(--gl-mono); font-size: 10px; letter-spacing: 1.2px; text-transform: uppercase; color: var(--gl-muted); }
.woocommerce p.stars a { color: var(--gl-ember); }
.woocommerce .star-rating::before { color: rgba(20,20,20,.2); }
.woocommerce .star-rating span { color: var(--gl-ember); }

/* --- store notice --- */
.woocommerce-store-notice { background: var(--gl-ink); color: var(--gl-paper); text-align: center; padding: 12px; position: fixed; bottom: 0; width: 100%; z-index: 99; font-family: var(--gl-mono); font-size: 11px; letter-spacing: 1.2px; text-transform: uppercase; }

/* --- blocks/plugin blind spots: keep list bullets out of our own rows --- */
.woocommerce .gl-shoplay ul, .woocommerce .gl-rail ul, .woocommerce .gl-rail li { list-style: none; }

/* --------------------------------------------------------------------------
   7. RESPONSIVE (compat layer)
   -------------------------------------------------------------------------- */
@media (max-width: 1180px) {
	.woocommerce ul.products { grid-template-columns: repeat(2, minmax(0,1fr)); }
	.woocommerce div.product div.images, .woocommerce div.product div.summary { float: none; width: 100%; }
	.woocommerce-account .woocommerce-MyAccount-navigation,
	.woocommerce-account .woocommerce-MyAccount-content { float: none; width: 100%; }
	.gl-shoplay { grid-template-columns: 1fr; gap: 40px; }
	.gl-rail { position: static; }
}

@media (max-width: 680px) {
	.woocommerce ul.products { grid-template-columns: 1fr; }
	.woocommerce ul.products li.product img { height: 300px; }
	.gl-shophead h1 { font-size: 34px; }
	.gl-shophead { padding: 30px var(--gl-pad) 24px; }
	.gl-shop-body { padding: 28px var(--gl-pad) 64px; }
	.woocommerce table.shop_table th, .woocommerce table.shop_table td { padding: 12px 10px 12px 0; }
	.gl-toolbar { flex-direction: column; align-items: flex-start; }

	.gl-entry { padding: 34px var(--gl-pad) 60px; }
	.gl-entry h1 { font-size: 32px; }
	.gl-item > a { flex-direction: column; gap: 20px; padding: 26px 0; }
	.gl-item .gl-ph { flex: 0 0 auto; width: 100%; height: 200px; }
	.gl-item h2 { font-size: 26px; }
}

@media (max-width: 900px) {
	.gl-item .gl-ph { flex: 0 0 220px; height: 168px; }
}

/* The plate's responsive heights, restating PART 1's own breakpoints for the
   three scopes — and restating them as SELECTORS, not as numbers invented here:
   PART 1 says `.edit-media .gl-ph { 520 }` at base, `{ 420 }` at 1180 and
   `{ 300 }` at 680; `.gcard .gl-ph` 400 → 260; `.mat .gl-ph` 260 → 220.
   Selector specificity matches the rules above (0,3,0) on purpose, so the
   narrower scope wins on SOURCE ORDER and this block cannot be defeated by the
   base rules merely being more specific.
   These used to be `.gl-imh820 / 520 / 400 / 260` — a height class ON THE
   WIDGET, which Elementor 4.2.4 drops (rule 5 of make_templates.py), so the
   whole block was inert on live and the three breakpoints never happened. */
@media (max-width: 1180px) {
	.edit-media > .elementor-widget-wrap > .elementor-widget-image { height: 420px; }
}
@media (max-width: 680px) {
	.gcard      > .elementor-widget-wrap > .elementor-widget-image { height: 260px; }
	.edit-media > .elementor-widget-wrap > .elementor-widget-image { height: 300px; }
	.mat        > .elementor-widget-wrap > .elementor-widget-image { height: 220px; }
}

/* --------------------------------------------------------------------------
   8. ELEMENTOR PAGE BUILDING KIT
   --------------------------------------------------------------------------
   The JSON files under templates/ in this theme are import-ready Elementor
   pages that rebuild the design with Elementor FREE widgets only. This section
   is everything they need FROM the theme, and nothing else.

   The division of labour is deliberate:

     · the THEME owns the page skeleton — band geometry, vertical rhythm,
       gutters, the type scale and the four grounds;
     · ELEMENTOR owns what sits in it — copy, images, buttons and the
       WooCommerce shortcodes.

   So the shipped templates carry almost no styling of their own, and
   re-skinning the whole site stays a Customizer job.

   Two constraints shape every rule below. Both were paid for already:

   1. BAND GEOMETRY READS THE SAME TOKENS AS THE BUILT-IN TEMPLATES.
      `.gl-sec` reproduces `.sec` + `.sec-in` from PART 1 out of --gl-sec-y,
      --gl-pad and --gl-wrap, which PART 1 already re-declares at 1180px and
      680px. An Elementor page therefore follows the theme's own breakpoints
      with no second set of numbers to keep in step. Never inline them.

   2. A NATIVE IMAGE WIDGET CANNOT LIVE INSIDE AN HTML WIDGET, AND CANNOT
      CARRY ITS OWN SIZE EITHER.
      The first half is a DOM limit, not a preference: an image inside an HTML
      widget is simply not rendered. The SHMOVEW line shipped that wrong in both
      directions (bare empty image widgets collapsed to zero height; HTML-widget
      slots showed raw code and could not be swapped).
      The second half is the v1.6.0 defect and it is the same shape: Elementor
      4.2.4 has NO class channel on a widget, so a height class written on the
      image widget never reaches the page. The rule:
        · a VISUAL SLOT is a native `image` widget with NO CLASS AT ALL;
        · the CELL around it is an Elementor column wearing the design's own
          class (.gcard / .mat / .edit-media), and THAT is what sizes the photo
          — see section 3, where the three scopes are stated and re-stated at
          the theme's 1180px and 680px breakpoints.
      That is why part A6 puts PART 1's class names on COLUMNS: the design
      system's descendant rules then style the widget output unchanged, and
      the two renderings cannot drift.
      A widget-level class is now refused at build time in two files —
      make_templates.py check() (E) and pack.py check_templates().

   3. GEOMETRY LIVES IN THIS FILE, NEVER IN THE TEMPLATE.
      A column width written into a template comes back out of Elementor as a
      class name, `elementor-col-<value>`, and its stylesheet defines only the
      19 preset integers. A fractional value therefore produces a class that
      matches no rule: the column has no width, falls back to its content
      width, and the row cannot wrap. The v1.3.0 front page overflowed to
      twice the viewport and sat hard right for exactly that reason. A3 and A7
      own the row geometry outright, mirroring PART 1's own flex arithmetic.

   Nothing in this section may target a selector outside the .elementor-*
   namespace, or it would restyle the built-in templates too.
   -------------------------------------------------------------------------- */

/* --- A0. the one Elementor default every row depends on -------------------
   Elementor's widget-wrap is a WRAPPING flex box with `align-content:
   flex-start`. With a single line that makes the line hug its items instead of
   filling the column, so a child that PART 1 expects to be a full-width block
   comes out at its own max-content width instead. It is invisible until
   something actually depends on the measure: the hero's two inner sections
   measured 1108px inside a 1328px column, and the mono note that should sit
   against the right edge sat 218px short of it.

   `align-content: normal` resolves to `stretch`, which lets a single line take
   the column's full width — the reading PART 1 gets for free from block
   layout — while still leaving `flex-wrap` alone for the case it exists for,
   a column genuinely too narrow for its content.

   Stated once here rather than in each section below, because A1–A9 all
   assume it. */
.elementor-column > .elementor-widget-wrap { align-content: normal; }

/* --- A1. section geometry -----------------------------------------------
   .gl-sec   = the design's .sec + .sec-in: full-bleed padding on the
               section, then the measure held by the container.
   .gl-bleed = full bleed, no padding: for the hero, the marquee and the
               newsletter band, each of which brings its own .hero / .mq / .sec
               shell inside the widget. */
.elementor-section.gl-sec { padding: var(--gl-sec-y) var(--gl-pad); }
.elementor-section.gl-sec > .elementor-container { max-width: var(--gl-wrap); }

.elementor-section.gl-bleed { padding: 0; }
.elementor-section.gl-bleed > .elementor-container { max-width: 100%; }

/* --- A2. vertical rhythm -------------------------------------------------
   .sec-in--g44 / --g48 in PART 1 is the space between the blocks of one
   section. Elementor stacks widgets with its own 20px default margin, which
   is neither number, so the column takes the job over. `margin-block-end` as
   well as `margin-bottom` because Elementor 3.16+ writes the logical
   property.

   THE SECOND SELECTOR IS NOT A DUPLICATE OF THE FIRST, and leaving it out cost
   every cell in the page 20px. The first one reaches a widget that is a direct
   child of a BAND's column. A cell inside a `.gl-row` — `.gcard`, `.edit-media`,
   `.edit-info`, `.mat` — is one section deeper, so Elementor's
   `.elementor-widget:not(:last-child) { margin-block-end: 20px }` (0,3,0) kept
   winning there while this file's own comment beside `.gl-cell--g16` promised
   "card cells take no gap at all: the rule sits directly under the plate".

   Measured against the design with build/_gaps.py, before and after:
       .gcard       design 0 / 0          was 20 / 0        (the plate's own
                                                            20px, pushing the
                                                            hairline down)
       .edit-media  design 0              was 20
       .mat         design 16 / 16 / 16   was 36 / 16 / 36
   `.mat` was the irregular one and the reason this could not wait: v1.6.2
   turned `.n` from an `html` widget into a role_section, and a section is not
   an `.elementor-widget`, so the margin vanished from that one child only —
   36 / 16 / 36 where the design has 16 three times. A uniform error reads as
   the design being a little loose; an irregular one reads as a mistake, which
   it was.

   Note that this does NOT make a cell's spacing equal its gap on its own:
   `.edit-info`'s paragraphs still carry the design's own 1em margins (see the
   paragraph-rhythm note under A9.1), and those are part of the mockup's 40 and
   60. Clearing the widget margin is what lets them be the only thing left. */
.elementor-section.gl-sec > .elementor-container > .elementor-column > .elementor-widget-wrap,
.elementor-column.gl-cell > .elementor-widget-wrap {
	display: flex;
	flex-direction: column;
}
.gl-sec--g44 > .elementor-container > .elementor-column > .elementor-widget-wrap { gap: 44px; }
.gl-sec--g48 > .elementor-container > .elementor-column > .elementor-widget-wrap { gap: 48px; }
.elementor-section.gl-sec > .elementor-container > .elementor-column > .elementor-widget-wrap > .elementor-widget,
.elementor-column.gl-cell > .elementor-widget-wrap > .elementor-widget {
	margin-bottom: 0;
	margin-block-end: 0;
}

/* --- A3. rows and fixed gutters ------------------------------------------
   `.shelf-row` / `.mats-grid` / `.edit-row` are flex rows in PART 1, and a
   fixed-gutter flex row is exactly what an Elementor row already is. So this
   MIRRORS PART 1's arithmetic instead of inventing a second one:

     PART 1                              here
     .shelf-row   gap: --gl-gutter        .gl-row        gap: --gl-row-gap
     .gcard       flex: 1 1 0             column         flex: 1 1 0
     .gcard--wide flex: 0 0 760px         .gl-row--wide  first child 0 0 760px
     .edit-media  flex: 0 0 700px         .gl-row--edit  first child 0 0 700px
     .mat         flex: 1 1 0             (the column default)

   THE WIDTHS ARE DELIBERATELY NOT IN THE TEMPLATE. Until v1.3.0 they were, as
   `_column_size` percentages, and that is what broke the front page: Elementor
   writes that setting verbatim into a class name (`elementor-col-33.73`),
   while its stylesheet defines only the 19 preset integers — 10 11 12 14 16 20
   25 30 33 40 50 60 66 70 75 80 83 90 100. A fractional class matches no rule,
   so the column had no width at all, fell back to its content width, and the
   row could not wrap: the document grew to twice the viewport and every
   centred container landed in the right-hand half of it. Keeping the numbers
   in ONE place — here, beside PART 1's own — makes that unrepresentable.

   THE COLUMN DEFAULT BELOW IS WHAT ACTUALLY SIZES A COLUMN, so the row
   modifier is load-bearing, not decorative. PART 1's own `.edit-media { flex: 0
   0 700px }` is a (0,1,0) class rule; it cannot survive the (0,3,0) default
   three lines down. A row that forgets its modifier therefore reads as EQUAL
   SHARES rather than as PART 1's numbers — silently, because an unmatched class
   is not an error to anything. `make_templates.py` asserts the pairing: every
   two-column row must carry `--wide`, `--edit` or `--cform`.

   --gl-row-gap defaults to the design's --gl-gutter and is overridden only
   where PART 1 uses a tighter number: .mats-grid 16px, .edit-row 48px. */
.gl-row { --gl-row-gap: var(--gl-gutter); }
.gl-row--g16 { --gl-row-gap: 16px; }
.gl-row--g48 { --gl-row-gap: 48px; }

/* `body` on the container rules, and it is load-bearing rather than house
   style. Elementor ships `.elementor-section .elementor-container { display:
   flex; margin-inline: auto; position: relative }` and a SECOND declaration
   `.elementor-section .elementor-container { flex-wrap: wrap }` — both (0,2,0),
   both printing after this stylesheet. At (0,2,0) our `flex-wrap: nowrap` was
   therefore dead and the rows could wrap; on a row whose first cell is a fixed
   760px that is a layout the design does not contain. One element of
   specificity settles it. (The rows happen to fit at every breakpoint today,
   which is exactly why nobody would have noticed: a rule that cannot fire looks
   identical to a rule that is not needed.) */
body .gl-row > .elementor-container { flex-wrap: nowrap; gap: var(--gl-row-gap); }
.gl-row > .elementor-container > .elementor-column { flex: 1 1 0; min-width: 0; }

/* The rows whose first cell is a FIXED width, exactly as PART 1 sets it.
   Scoped to the desktop breakpoint rather than listed again below it: PART 1
   re-expresses all three at 1180px and 900px, and A7 does the same. */
@media (min-width: 1181px) {
	.gl-row--wide  > .elementor-container > .elementor-column:first-child { flex: 0 0 760px; }
	.gl-row--edit  > .elementor-container > .elementor-column:first-child { flex: 0 0 700px; }
	.gl-row--cform > .elementor-container > .elementor-column:first-child { flex: 0 0 720px; }
}

/* Elementor's column-gap classes put their own padding on the widget-wrap,
   which would stack on top of the gutter above. Neutralised at (0,4,0), one
   step above those classes, so the number stays a single token. */
.gl-row > .elementor-container > .elementor-column > .elementor-widget-wrap { padding: 0; }

/* --- A4. the four grounds ------------------------------------------------
   Backgrounds are tokens, not literals, so re-colouring the brand in the
   Customizer re-colours Elementor pages too. A background set by hand in
   Elementor's own Style tab is generated at higher specificity and still
   wins — that is the escape hatch for a one-off band. */
.elementor-section.gl-band-paper   { background-color: var(--gl-paper); }
.elementor-section.gl-band-surface { background-color: var(--gl-surface); }
.elementor-section.gl-band-ink     { background-color: var(--gl-ink); color: var(--gl-paper); }
.elementor-section.gl-band-ember   { background-color: var(--gl-ember); color: var(--gl-paper); }

/* On a dark ground, headings and body text from Elementor's OWN widgets have
   to be re-coloured: section 5 pins them to ink, which would be ink-on-ink.
   (.sec-title and .sec-link inherit, so the HTML-widget blocks are already
   covered by the `color` above — only Elementor's widgets need this.) */
.gl-band-ink .sec-link,
.gl-band-ember .sec-link { color: var(--gl-muted-2); }

.gl-band-ink .elementor-widget-heading .elementor-heading-title,
.gl-band-ember .elementor-widget-heading .elementor-heading-title,
.gl-band-ink .elementor-widget-text-editor,
.gl-band-ink .elementor-widget-text-editor p,
.gl-band-ember .elementor-widget-text-editor,
.gl-band-ember .elementor-widget-text-editor p { color: var(--gl-paper); }

/* The hero's photo is the Elementor SECTION BACKGROUND — the only carrier the
   editor's own "Choose Image" control edits — so nothing may paint over it.
   Nothing does, and the reason is worth stating rather than leaving to luck:
   `background-image` paints ABOVE `background-color` on the same box, so
   `.gl-band-ink`'s ink ground sits UNDER the photo and survives as the
   no-photo fallback for free. Measured on the live site: the hero section's own
   computed style carries
     background-image: url("…/assets/img/ph-hero.png")
   with `background-color` still ink beneath it.
   The rule that used to sit here — `.elementor-section.gl-bleed .hero {
   background-color: transparent }` — was left over from when the band wore
   PART 1's `.hero` class; the Elementor build names the section `gl-hero`
   instead, so it matched nothing. Deleted rather than kept: a rule that cannot
   fire reads as protection that does not exist. */

/* --- A5. visual slots ----------------------------------------------------
   A photo's height is set by the CARD scope it sits in — section 3 states the
   three scopes, because that is the only channel Elementor 4.2.4 offers (a
   class on the image widget is dropped; section 8 constraint 2). What A5 adds
   is the one thing section 3 cannot know: in a shipped template every plate
   ALSO sits in a cell, so it must never be squeezed by the cell's flex layout. */
.gl-cell .elementor-widget-image { flex: 0 0 auto; }

/* --- A6. design cells rebuilt from widgets -------------------------------
   The column wears the design's class (.gcard / .mat / .edit-media /
   .edit-info) so PART 1's descendant rules style the widget output as-is.

   PART 1 sizes these cells itself — `.edit-media { flex: 0 0 700px }`,
   `.mat { flex: 1 1 0 }`, `.edit-info { flex: 1 1 0 }` — but those are (0,1,0)
   class rules and A3's column default is (0,3,0), so on an Elementor column
   A3 wins and PART 1's own declarations are superseded. A3 therefore states
   the same geometry at the same specificity as the default, as `.gl-row--*`
   modifiers (760 / 700 / 720 for the fixed first cell). Nothing is lost, but
   the row's modifier is REQUIRED — see the note at the end of A3.

   Until v1.3.0 the widths were supposed to come from the template's own Width
   control, and these counter-rules existed to stop PART 1's flex-basis fighting
   it. With the width back in the stylesheet that reversal is what breaks the
   row, so it is gone. If a row needs a width PART 1 does not already state, add
   it to A3 — never here, and never in the template.

   One thing still has to be said explicitly: a bare <span class="rule"> /
   <span class="cap"> / <span class="gl-mono"> is a FLEX ITEM in PART 1's
   markup, so it blockifies and its height or padding applies. Inside an HTML
   widget it stays inline and those declarations paint nothing at all.
   Blockified here.

   ONLY `.rule` IS LEFT IN THIS LIST, and the four that left it did not leave
   because they stopped being needed — they left because nothing writes them as
   markup any more. v1.6.2 moved `.cap` / `.gl-mono` / `.gl-rule--ink` out of
   the HTML widgets and onto a carrier of their own (A9.1's bridge), so a
   selector still naming them here could no longer fire, and a rule that cannot
   fire reads as protection that does not exist. `.rule` stays because its two
   remaining homes — the shelf card's name row and the spec table — are
   STRUCTURAL blocks that are still markup on purpose. */
.elementor-column.gl-cell { min-width: 0; }

.elementor-widget-html .rule { display: block; }

/* cell gaps — the design's own numbers, from PART 1: .mat 16px, .edit-info
   24px. Card cells take no gap at all: the rule sits directly under the plate
   and .meta carries its own 18px padding. */
.gl-cell--g16 > .elementor-widget-wrap { gap: 16px; }
.gl-cell--g24 > .elementor-widget-wrap { gap: 24px; }

/* --- A7. rows at the theme's breakpoints ---------------------------------
   Mirrors PART 1 line for line, so an Elementor page wraps exactly where the
   built-in templates do: the shelf and the material grid go 2-up at 1180px,
   the edit row stacks at 900px, everything is one-up at 680px. Same numbers,
   read off the same tokens — --gl-row-gap follows --gl-gutter, which PART 1
   already re-declares at 1180px and 680px.

   `flex`, not `width`: every column in A3 is sized by flex-basis, and a
   flex-basis other than `auto` ignores `width` entirely, so a `width` override
   would silently do nothing. Specificity here is (0,3,1) / (0,4,1) — one
   element above Elementor's own generated column rules at (0,3,0) — so
   nothing needs !important and nothing depends on stylesheet order. */
@media (max-width: 1180px) {
	body .gl-row > .elementor-container { flex-wrap: wrap; }
	body .gl-row > .elementor-container > .elementor-column { flex: 1 1 calc(50% - var(--gl-row-gap) * 0.5); }
	body .gl-row--wide > .elementor-container > .elementor-column:first-child { flex: 0 0 100%; }
	body .gl-row--edit > .elementor-container > .elementor-column:first-child { flex: 0 0 52%; }
}

@media (max-width: 900px) {
	body .gl-row--edit > .elementor-container { flex-direction: column; }
	body .gl-row--edit > .elementor-container > .elementor-column:first-child { flex-basis: auto; width: 100%; }
}

@media (max-width: 680px) {
	body .gl-row > .elementor-container > .elementor-column,
	body .gl-row--wide > .elementor-container > .elementor-column:first-child { flex: 1 1 auto; width: 100%; }
}

/* --- A8. composed pieces for the inner-page templates ---------------------
   The home template reuses PART 1's blocks one for one, so it needed no new
   styling at all. The inner-page templates (contact) need three small pieces
   PART 1 has no equivalent for, because the theme's own templates do not
   render a contact page yet. If one is ever added, MOVE these into PART 1 as
   .icard / .hours / .faq and delete them here — two sources for one block is
   exactly the drift this file exists to prevent. */

/* a heading authored as `class="gl-hNN"` inside an HTML widget: PART 1's cell
   headings are bound to their own cells (.mat h3, .edit-info h3), so an
   HTML-widget block needs the same type scale under its own name. */
.gl-h46 { font-family: var(--gl-serif); font-weight: 400; font-size: 46px; line-height: 1.05; letter-spacing: -.5px; margin: 0; }
.gl-h30 { font-family: var(--gl-serif); font-weight: 400; font-size: 30px; line-height: 1.1;  letter-spacing: -.5px; margin: 0; }
.gl-h26 { font-family: var(--gl-serif); font-weight: 400; font-size: 26px; line-height: 1.15; letter-spacing: -.5px; margin: 0; }
.gl-band-ink .gl-h26, .gl-band-ink .gl-h30, .gl-band-ink .gl-h46,
.gl-band-ember .gl-h26, .gl-band-ember .gl-h30, .gl-band-ember .gl-h46 { color: var(--gl-paper); }

/* contact cards */
.gl-cards { display: flex; flex-direction: column; gap: 16px; }
.gl-icard { background: var(--gl-paper); padding: 26px 24px; display: flex; flex-direction: column; gap: 10px; }
/* contact cards. The second selector is the same heading built as a widget:
   `css_classes` lands on the WRAPPER, so the declarations have to be stated
   for the wrapper and inherited down (A9's bridge), not for the h4 element
   Elementor's own heading rule would out-rank. */
.gl-icard h4,
.gl-icard .gl-icard-h {
	font-family: var(--gl-mono); font-weight: 700; font-size: 10px;
	letter-spacing: 1.6px; text-transform: uppercase; color: var(--gl-ember); margin: 0;
}
.gl-icard p, .gl-icard a { font-size: 14.5px; line-height: 1.7; color: var(--gl-body); margin: 0; }
.gl-icard a { color: var(--gl-ink); border-bottom: 1px solid var(--gl-line-paper); display: inline-block; }
.gl-icard a:hover { color: var(--gl-ember); border-bottom-color: var(--gl-ember); }

/* opening hours: a two-column mono list */
.gl-hours { display: flex; flex-direction: column; gap: 6px; font-family: var(--gl-mono); font-size: 12px; color: var(--gl-body); }
.gl-hours > div { display: flex; justify-content: space-between; gap: 20px; }

/* FAQ on native <details> — no widget, no script, works with JS off */
.gl-faq { display: flex; flex-direction: column; }
.gl-faq details { border-top: 1px solid var(--gl-ink); padding: 18px 0; }
.gl-faq details:last-child { border-bottom: 1px solid var(--gl-ink); }
.gl-faq summary {
	display: flex; align-items: baseline; justify-content: space-between; gap: 20px;
	font-family: var(--gl-serif); font-size: 22px; line-height: 1.25;
	color: var(--gl-ink); cursor: pointer; list-style: none;
}
.gl-faq summary::-webkit-details-marker { display: none; }
.gl-faq summary::after { content: "+"; font-family: var(--gl-sans); font-size: 18px; line-height: 1; color: var(--gl-ember); }
.gl-faq details[open] summary::after { content: "\2013"; }
.gl-faq p { margin: 12px 0 0; max-width: 760px; font-size: 15px; line-height: 1.75; color: var(--gl-body); }

/* --- A9. NATIVE WIDGETS WEARING THE DESIGN'S OWN CLOTHES -----------------
   IN USE SINCE v1.6.0, for the home page's hero. The rest of that page — and
   all of the contact page — still carries each band inside a single `html`
   widget holding a whole markup tree, which renders correctly but leaves the
   owner a wall of code where the copy should be. The remaining bands move over
   as they are touched; the rules below are what makes a native control wear
   the design's own clothes, and they are the same rules either way.

   The hero is the one that had to move first, because an `html` widget cannot
   carry a swappable photograph at all: PART 1's `.hero` paints an opaque ink
   ground, so a section background Image sits UNDER it and is invisible. The
   hero now emits ordinary widgets, its photo is the SECTION background — the
   only carrier Elementor's own "Choose Image" control edits — and the two
   renderings of this page agree again.

   The look is unchanged, and it is unchanged by one idea:

     THE DESIGN'S OWN TYPE CLASS GOES ON THE WIDGET'S ANCESTOR — THE COLUMN IT
     SITS IN — AND THE BRIDGE BELOW COPIES IT DOWN TO THE VISIBLE TEXT.

   The carrier moved there in v1.6.1 and that is not an editorial preference:
   Elementor 4.2.4 has no class channel on a widget at all (the measurement is
   quoted in A9.1 under THE CARRIER IS AN ANCESTOR, and it cost v1.6.0 its
   entire hero), so a class written on the widget is dropped in silence on the
   live site while every local render styles it. `make_templates.py` now refuses
   to emit one.

   The bridge then does the second half of the job: the visible text sits one or
   two levels inside the widget (.elementor-heading-title, or a bare <p> under
   the text-editor), and this bridge copies the ancestor's type down to it.
   Family, size, weight and colour still come from PART 1's own rule for that
   class, so no number is written twice and an Elementor page cannot drift from
   the built-in template when the brand is re-skinned from the Customizer.

   Specificity: the heading bridge is (0,3,0) and lands on
   `.role .elementor-widget-heading .elementor-heading-title`. Elementor's own
   `.elementor-widget-heading .elementor-heading-title`, which carries the
   site's global typography, is (0,2,0), so nothing needs !important. The
   text-editor shape has no inner element to reach — see A9.1, where that
   difference is the reason a text role stops at the ancestor and the bridge
   deliberately does NOT write a `font` shorthand.

   STRUCTURAL blocks are the one place a number IS restated, for a mechanical
   reason rather than an editorial one: PART 1 expresses those as `display:
   flex` on a wrapper ELEMENT (.hero-in, .sec-head, .stats, .voices,
   .spec-row, .hero-top), and an Elementor section keeps its layout on the
   inner `.elementor-container` instead. Each mirror below names the PART 1
   rule it copies and quotes its numbers verbatim, so the pair can be audited
   side by side. Every mirror is a `.gl-*` class the template puts on a
   section or a column.

   Nothing here targets a selector outside .elementor-*, so the built-in
   templates are untouched — the four-breakpoint render heights must stay
   byte-identical to v1.4.0, and render_check.py proves it. */

/* --- A9.1 the inheritance bridge -----------------------------------------
   A class named here is one PART 1 already defines standalone, which is what
   makes this list sufficient: the carrier receives PART 1's declarations and
   the inner element inherits them. The element-scoped roles (.t .c .n .l .k
   .v .score) are PART 1's own names for the parts of a cell: when the cell is
   a COLUMN the role rides that column and this bridge carries it in, and when
   the cell is markup inside an `html` widget the class is genuinely in the
   document and needs no bridge at all.

   THE CARRIER IS AN ANCESTOR — A COLUMN OR A SECTION — AND THAT IS NOT A
   STYLE CHOICE, IT IS THE ONLY CHANNEL ELEMENTOR OFFERS. Measured on the live
   site (Elementor 4.2.4, 2026-09-14): `css_classes` is a control on sections
   and columns only. `column.php` and `section.php` each register one, with
   `'prefix_class' => ''`; `widget-base.php` and `element-base.php` contain
   neither `css_classes` nor `_css_classes`, and `element-base.php` writes a
   wrapper class only for controls that declare `prefix_class`. A role class on
   a WIDGET therefore has no effect at all — the hero's five text roles, the
   two button variants and nine image plates were all inert on live while every
   local render styled them. `make_templates.py` now refuses to emit a
   widget-level `css_classes` (gate), so a rule written as
   `.elementor-widget-heading.role` could never match anything again.

   THE LIST IS STILL SPLIT IN TWO, for a reason that survives the change. A
   heading widget has its visible text one level further in, on
   `.elementor-heading-title`; a text-editor does not — 4.2.4 emits a bare <p>
   under the widget itself — so the widget IS the thing PART 1 styled.

   Which breaks the naive form, twice, for a text-editor:

     · `font` is a SHORTHAND. `.hero-lead .elementor-widget-text-editor`
       matches the widget that inherits `.hero-lead`, and `font: inherit`
       resets font-size — so the bridge would erase the very declaration it was
       written to carry. Size, family and spacing must therefore reach the
       INNER element, never the widget that already has the role's own values
       from its ancestor.
     · A colour written here would outrank PART 1, because PART 2 loads after
       PART 1 in the concatenated stylesheet and (0,1,0) beats (0,1,0) only on
       source order. That is exactly the collision §3's default and A4's dark
       ground already have with `.hero-lead` / `.gl-mono`.

   So a PART 1 TEXT role is carried by the text-editor's ANCESTOR — normally
   the column — and this bridge is what copies it in. Anything PART 2 writes
   for the widget itself then loses to the bridge (3 classes beat 2, and
   Elementor's own `.elementor-widget-heading .elementor-heading-title` is
   (0,2,0) while this is (0,3,0)), which is the whole mechanism. Roles that
   must keep a colour of their own that differs from the band's default are
   safer as heading widgets: the hero's four text roles are, and A9.2 says
   which is which. */
.sec-title    .elementor-widget-heading .elementor-heading-title,
.sec-link     .elementor-widget-heading .elementor-heading-title,
.gl-kicker    .elementor-widget-heading .elementor-heading-title,
.gl-mono      .elementor-widget-heading .elementor-heading-title,
/* The .gl-h* family is PART 2's own heading scale. They belong here for the
   same reason .gl-kicker does: they are roles, and a role that rides a heading
   and is missing from THIS list does not fail — it silently takes Elementor's
   kit typography instead. Measured before this line existed: .gl-h26 on the
   contact page rendered 30.42px (the kit's H3) against its own 26px rule, with
   the bridge's absence as the only symptom. The build gate now checks both
   widget shapes, so the day one of these is dropped the build stops instead. */
.gl-h46       .elementor-widget-heading .elementor-heading-title,
.gl-h30       .elementor-widget-heading .elementor-heading-title,
.gl-h26       .elementor-widget-heading .elementor-heading-title,
.hero-title   .elementor-widget-heading .elementor-heading-title,
.hero-note    .elementor-widget-heading .elementor-heading-title,
.hero-lead    .elementor-widget-heading .elementor-heading-title,
.hero-fine    .elementor-widget-heading .elementor-heading-title,
.price        .elementor-widget-heading .elementor-heading-title,
.quote        .elementor-widget-heading .elementor-heading-title,
.quote-credit .elementor-widget-heading .elementor-heading-title,
.pull         .elementor-widget-heading .elementor-heading-title,
.cap          .elementor-widget-heading .elementor-heading-title,
.t            .elementor-widget-heading .elementor-heading-title,
.c            .elementor-widget-heading .elementor-heading-title,
.n            .elementor-widget-heading .elementor-heading-title,
.l            .elementor-widget-heading .elementor-heading-title,
.k            .elementor-widget-heading .elementor-heading-title,
.v            .elementor-widget-heading .elementor-heading-title,
.score        .elementor-widget-heading .elementor-heading-title,
.gl-icard-h   .elementor-widget-heading .elementor-heading-title,
/* The About page's three heading roles (PART 1 section 18). They arrive with
   the first template that uses them, which is what the paragraph above says must
   happen: a role that rides a heading and is missing from THIS list does not
   fail, it silently takes the kit typography instead. */
.story-title  .elementor-widget-heading .elementor-heading-title,
.step-name    .elementor-widget-heading .elementor-heading-title,
.cta-title    .elementor-widget-heading .elementor-heading-title {
	font: inherit;
	letter-spacing: inherit;
	line-height: inherit;
	text-transform: inherit;
	color: inherit;
	margin: 0;
}

.hero-lead  .elementor-widget-text-editor,
.quote      .elementor-widget-text-editor,
.pull       .elementor-widget-text-editor,
.cap        .elementor-widget-text-editor,
.gl-mono    .elementor-widget-text-editor,
/* The About page's three text roles (PART 1 section 18). A text-editor role in
   the list above but NOT here keeps Elementor's own typography and loses the
   role's colour, which reads as a design choice — check() (F) of
   make_templates.py is what stops that. The list is READ by that check
   (`bridge_roles`), so a role it does not name here cannot silently ride a
   paragraph; it fails the build. */
.story-p    .elementor-widget-text-editor,
.step-p     .elementor-widget-text-editor,
.cta-lead   .elementor-widget-text-editor {
	font: inherit;
	letter-spacing: inherit;
	line-height: inherit;
	text-transform: inherit;
	color: inherit;
	margin: 0;
}

/* A role class carried on a widget still has to BEAT Elementor's own colour
   rule for headings, which is (0,2,0) — `color: inherit` above is (0,3,0) and
   already wins, but only because the class is present. Stated once here so a
   future role class added to the bridge is not silently colourless. */
.elementor-widget-heading[class] .elementor-heading-title { color: inherit; }

/* A text-editor's own paragraph rhythm: Elementor ships a bottom margin per
   paragraph, which is neither of the design's numbers. The cell's gap is. */
.gl-sec .elementor-widget-text-editor p,
.gl-bleed .elementor-widget-text-editor p { margin: 0 0 1em; }
.gl-sec .elementor-widget-text-editor p:last-child,
.gl-bleed .elementor-widget-text-editor p:last-child { margin-bottom: 0; }
.gl-sec .elementor-widget-text-editor blockquote,
.gl-bleed .elementor-widget-text-editor blockquote { margin: 0; }

/* --- A9.1b `.edit-info` KEEPS PART 1's paragraph rhythm --------------------
   The rule above is right for almost every cell, and this is the exception that
   proves it is a rule rather than a coincidence: in a cell whose spacing comes
   from its gap, a paragraph must contribute nothing. `.edit-info` is the cell
   where PART 1 deliberately gives BOTH, and the mockup's own numbers say so.

   PART 1 (.edit-info) is `gap: 24px`, and `.body` / `.pull` are plain flow
   paragraphs that never had their margin written, so they keep the browser's
   `1em`. Margins on a flex item never collapse, so every one of those ADDS to
   the gap instead of replacing it. Measured against `preview/frame.html`, the
   cell's seven spacings are 40 / 60 / 44 and then 24 four times:

     h3      → p.body   24 +  0 + 16 = 40    (.body is 16px → 1em = 16px)
     p.body  → p.pull   24 + 16 + 20 = 60    (.pull is 20px → 1em = 20px)
     p.pull  → .rule    24 + 20 +  0 = 44
     the rest           24 +  0 +  0 = 24    (no margin on either side)

   Flattened by the rule above, all seven read 24 and the cell is 36px short —
   which is what the build measured before this rule existed.

   TWO PARAGRAPHS GET A RHYTHM BACK; NOT ALL OF THEM. `.gl-mono`'s paragraph is
   the cell's last child and the mockup gives it nothing, so a blanket
   `.edit-info .elementor-widget-text-editor p { margin: 1em 0 }` would have
   added its own 10px and turned a correct 24 into a wrong 34. Name the two
   roles, not the cell.

   Written as `1em` rather than 16px and 20px so each paragraph derives it from
   its own font-size — the same reason A9.2 spells the hero's that way, and the
   reason `.pull` needs no second number here.

   These are (0,3,1) and (0,4,1) against the rule above at (0,2,1) and (0,3,1),
   so they win on SPECIFICITY and do not depend on source order being preserved.
   `flow-root` is here for the same reason A9.2 needs it: the paragraph sits one
   block level inside a widget, and without a formatting context of its own its
   margins collapse out through the widget instead of staying where PART 1 keeps
   them. Declared on the widget, because Elementor 4.2.4 prints no
   `.elementor-widget-container` div at all (measured live: zero on the page). */
.edit-info .elementor-widget-text-editor { display: flow-root; }
.edit-info .elementor-widget-text-editor p.body,
.edit-info .elementor-widget-text-editor p.body:last-child,
.edit-info .pull .elementor-widget-text-editor p,
.edit-info .pull .elementor-widget-text-editor p:last-child { margin: 1em 0; }

/* --- A9.2 hero ------------------------------------------------------------
   Mirrors PART 1's `.hero` (min-height 820, padding 44px side --gl-pad) and
   `.hero-in` (measure --gl-wrap, column, space-between, gap 40).
   The scrim was a .hero-scrim element; with no html widget to put it in it
   becomes a pseudo-element carrying the same three stops. The photo stays the
   SECTION background so "Choose Image" still swaps it.

   HOW PART 1's TREE LANDS ON ELEMENTOR'S, because the shapes differ:

     PART 1                          Elementor build
     .hero (div)                     section.gl-hero          photo = section bg
       .hero-scrim (span)            section.gl-hero::after
       .hero-in (flex div)           column.gl-hero-in
         .hero-top (flex div)        section.gl-hero-top + 2 columns
         .hero-mid (flex div)        section.gl-hero-mid + 1 column
           .hero-rule (span)         the column wrap's first widget ::before
           h1.hero-title             heading widget, h1
           .hero-foot (flex div)     section.gl-hero-foot + 2 columns
             p.hero-lead             column.hero-lead > text-editor
             .hero-cta (flex div)    column.gl-hero-cta
               .gl-btnrow            section.gl-btnrow + 2 columns
               span.hero-fine        heading widget, span
       ^ .hero-top / .hero-mid / .hero-foot are SECTIONS because each is a row
         of boxes; .gl-hero-in / .gl-hero-mid's column / .gl-hero-cta are
         COLUMNS because each is a stack.

   The four text roles are heading widgets — including `.hero-fine`, which is a
   label rather than body copy — and only `.hero-lead` is a text-editor, for
   the reason A9.1 sets out: it is the one whose colour must differ from the
   band's own default, so its role rides the COLUMN rather than the widget. */
.elementor-section.gl-hero {
	position: relative;
	display: flex;
	flex-direction: column;
	min-height: 820px;
	padding: 44px var(--gl-pad);
	overflow: hidden;
}
/* `flex-direction: column` and `flex: 1 1 auto` are how PART 1's
   `align-items: stretch` is reproduced here, and neither is decoration.

   PART 1's `.hero` is a ROW flex box, so `.hero-in` stretches to the 820px
   minimum along the CROSS axis and `justify-content: space-between` then has
   something to distribute. Copying `display: flex` alone onto the section put
   the container on the MAIN axis instead, where `flex-basis: auto` makes a
   shrink-to-fit flex item — the measure collapsed to the width of the headline
   and the scrim's edges no longer matched the band. Column direction makes
   the container's width the stretch axis (full bleed) and `flex: 1 1 auto`
   makes its height the grow axis (the 820 minimum), which is what PART 1
   actually expresses. `width: 100%` because a flex item in a column box has no
   width of its own to stretch from. */
.elementor-section.gl-hero > .elementor-container {
	display: flex;
	flex: 1 1 auto;
	width: 100%;
	max-width: var(--gl-wrap);
	align-items: stretch;
	margin: 0 auto;
	position: relative;
	z-index: 2;
}
.elementor-section.gl-hero::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;
	background: linear-gradient(180deg,
		rgba(20,20,20,.55) 0%,
		rgba(20,20,20,0) 42%,
		rgba(20,20,20,.92) 100%);
}
/* PART 1's hero is a stack of ROW flex boxes; on an Elementor build each of
   those boxes is a column, and `.elementor-column { display: flex }` is where
   Elementor makes it one. Restated for the reason above — a rule whose preview
   depends on a stylesheet the previewer does not load cannot be checked — and
   scoped to `.gl-hero` so it can never reach another section. `align-items:
   stretch`, Elementor's own default, is what makes the column's widget-wrap
   fill the 820px minimum so `space-between` has room to work. */
.gl-hero .elementor-column { display: flex; }
/* Elementor puts a 20px bottom margin on every widget that is not a last child.
   PART 1's hero takes all of its spacing from flex `gap`, so that margin is a
   number the design does not contain — A2 clears it for .gl-sec and .gl-cell,
   and the hero needs the same because its boxes are parts of one composition
   rather than a stack of bands.

   THE SHAPE IS COPIED FROM A2 ON PURPOSE, and this rule used to have the wrong
   one. `.gl-hero .elementor-widget` is (0,2,0); Elementor's
   `.elementor-widget:not(:last-child)` is (0,3,0) — `:not()` counts as its
   argument — so the 20px won on live and every widget in the hero sat 20px
   lower than the design. The full chain is (0,6,0), and being rooted at
   `section.gl-hero` it reaches the nested sections (top / mid / foot / btnrow)
   as well. */
.elementor-section.gl-hero .elementor-container > .elementor-column > .elementor-widget-wrap > .elementor-widget {
	margin-bottom: 0;
	margin-block-end: 0;
}
.gl-hero-in > .elementor-widget-wrap {
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	gap: 40px;
	width: 100%;
}
/* PART 1: .hero-top — two mono notes on one line, pushed apart.
   `body` CARRIES THE FIX HERE, and this is the one place in the design where a
   tie was lost rather than won. `.gl-hero-top .elementor-column` and
   Elementor's own `.elementor-column.elementor-col-100 { width: 100% }` are
   BOTH (0,2,0), and Elementor prints later, so ITS width won. Because
   `flex: 0 0 auto` leaves flex-basis at `auto`, `width` is the property that
   decides — and it decided 100%: measured live, the two notes' columns were
   1310px each inside a 1310px row, at x=56 and x=1390, so the row overflowed
   the document by a full column and the right-hand note was cut off.
   Note the contrast with A3, which needs no such help: `.gl-row > … >
   .elementor-column { flex: 1 1 0 }` is (0,3,0) and wins outright, AND a
   flex-basis of `0` makes `width` irrelevant whatever Elementor says. It is
   only the shrink-to-content rows, where basis is `auto`, that have to win on
   `width` — hence the extra element. */
body .gl-hero-top > .elementor-container { display: flex; align-items: center; justify-content: space-between; gap: 24px; flex-wrap: nowrap; }
body .gl-hero-top .elementor-column { flex: 0 0 auto; width: auto; }
/* PART 1: .hero-mid — the ember rule, the title, then the foot. The 2px ember
   rule was an element; as ::before on the first widget it needs no widget and
   no HTML.

   THE SCOPE IS LOAD-BEARING. `.gl-hero-mid .elementor-widget:first-child` looks
   right and is wrong: the lead text-editor inside .gl-hero-foot is ALSO a first
   child — of its own widget-wrap — so a descendant match draws a second ember
   rule above the paragraph. Every step down to the column's own wrap is named so
   only the title can match. */
/* PART 1's `.hero-mid` is a flex COLUMN of three items; here it holds two
   columns (the title, then the foot) instead of one column holding everything,
   so the container has to become the stack. It is two columns because
   `.hero-title` needs a column of its own to exist at all: a widget has no
   class channel on Elementor 4.2.4 (A9.1), and reaching the heading
   structurally would restate PART 1's four breakpoint sizes (116 / 84 / 62 /
   42) inside this file — the drift this whole section exists to prevent.
   A9.2's mapping states the shape. */
.gl-hero-mid > .elementor-container { display: flex; flex-direction: column; gap: 26px; }
.gl-hero-mid > .elementor-container > .elementor-column > .elementor-widget-wrap {
	display: flex;
	flex-direction: column;
	gap: 26px;
}
/* `.gl-hero:not(.hero--inner)` IS PART OF THE RULE, NOT A GUARD ON IT. In PART 1
   the hairline is an ELEMENT (`.hero-rule`) and only the home page's canvas has
   one; the inner hero's copy is a single stack of three items with no rule at
   all (canvas 3:404: kicker, headline, lead, 24 apart — measured). A9.11 builds
   that hero out of the same `.gl-hero-mid` box, so without this scope the inner
   hero would grow a 72px ember rule the design does not contain, and it would
   grow it above a widget whose role is carrying no margin of its own. The
   condition belongs here beside the declaration rather than in A9.11 as a
   `content: none` cancel, because "which hero has a rule" is a fact about the
   design, and a cancel would state it twice.
   IF AN INNER PAGE EVER NEEDS A RULE, the honest fix is a third variant on
   PART 1's `.hero-rule`, not a hole in this scope. */
.gl-hero:not(.hero--inner) .gl-hero-mid > .elementor-container > .elementor-column > .elementor-widget-wrap > .elementor-widget:first-child::before {
	content: "";
	display: block;
	width: 72px;
	height: 2px;
	margin-bottom: 26px;
	background: var(--gl-ember);
}
/* PART 1: .hero-foot — measure and buttons on one baseline, pushed apart.
   Same tie as .gl-hero-top above, same lever, same reason: `align-items:
   flex-end` and `justify-content: space-between` only mean anything if the two
   columns shrink to their content, and at (0,2,0) the columns took 100% each
   instead and stacked out of the row. */
body .gl-hero-foot > .elementor-container { display: flex; align-items: flex-end; justify-content: space-between; gap: 48px; }
body .gl-hero-foot .elementor-column { flex: 0 0 auto; width: auto; }
/* PART 1's hero paragraphs KEEP the browser's own 1em margin, and this
   restores what A9.1 clears. It is not cosmetic: `.hero-foot` is a flex row,
   so the lead's 1em top and bottom margins are part of that row's height —
   88px rather than 78px — and the row's height is what decides where the whole
   column above it sits. Clearing them moved the 116px headline 9px down and
   the lead 17px down, which is exactly the drift this whole section exists to
   prevent. Expressed the way the browser expresses it (`1em`), so it follows
   `.hero-lead`'s own font-size instead of restating 17px. */
/* The last-child selector is named explicitly and has to be: A9.1 clears a
   trailing paragraph's bottom margin at (0,3,1), one step above this rule, and
   in PART 1 the hero's last paragraph KEEPS both margins because it is a flex
   item rather than a flowing block. */
.gl-hero .elementor-widget-text-editor p,
.gl-hero .elementor-widget-text-editor p:last-child { margin: 1em 0; }
/* …and they have to stay INSIDE the widget to do their job. In PART 1 the lead
   paragraph is itself a flex item of `.hero-foot`, and margins on a flex item
   never collapse. Here it sits one block level deeper, so its margins collapsed
   out through the widget and the row came out 78px instead of 88px — the same
   9px drift, one level down. A flow-root container keeps them where PART 1 keeps
   them, which is what makes the height arithmetic agree.

   ON THE WIDGET, NOT ON A `> .elementor-widget-container` CHILD. That was the
   first spelling of this rule and it never fired: Elementor 4.2.4 emits no
   widget-container div at all (measured live: zero on the page), so the
   selector matched nothing and the paragraph's margins went on collapsing while
   the comment here claimed they did not. check_cascade.py flags a rule whose
   subject is a class Elementor never prints for exactly this reason. The widget
   itself is the paragraph's parent, so it is the right box to be a flow-root. */
.gl-hero .elementor-widget-text-editor { display: flow-root; }
.gl-hero-cta > .elementor-widget-wrap { display: flex; flex-direction: column; gap: 14px; }
/* PART 1: .gl-btnrow — the two buttons on one line, 12px apart. In an Elementor
   build the row is an INNER SECTION rather than an element, so the flex has to
   be declared on the container that actually holds the buttons, and the columns
   must shrink to their content instead of taking A3's equal shares. */
.gl-hero-cta .gl-btnrow > .elementor-container { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.gl-hero .gl-hero-cta .gl-btnrow > .elementor-container > .elementor-column { flex: 0 0 auto; width: auto; }

/* --- THE HERO'S FOUR BREAKPOINTS, AND EVERY NUMBER HERE IS PART 1's ---------
   This block used to carry them ONE STEP LATE: 640px at 900 instead of at 1180,
   and 560px at 680 instead of at 900, with the 680 value (480) and its padding
   missing altogether. Nobody would ever see that in a diff, and it is plainly
   visible on a 1280-wide laptop, where the hero stood 820px tall against the
   design's 640. `.gl-hero-top`'s direction was late by the same step and its
   gap was 8 where PART 1 says 6; `.gl-hero-foot`'s was 28 where PART 1 says 32.
   `check_mirror.py` now compares the two sequences out of the built stylesheet
   — same media conditions, same numbers — so the next one cannot drift
   quietly. Source of truth is gloam-design-system.css §9, read, not restated.

   ORDER MATTERS TWICE HERE, and both are source order rather than specificity:
   the base rules sit at lines ~1440 / ~1528 / ~1547 / ~1566 above, so these
   later blocks win by printing after them — and inside the 680 block the
   `::before` override must follow nothing else or it would be shadowed. Do not
   hoist any of this above its base rule. */
@media (max-width: 1180px) {
	.elementor-section.gl-hero { min-height: 640px; }
}
@media (max-width: 900px) {
	.elementor-section.gl-hero { padding: 32px var(--gl-pad); min-height: 560px; }
	body .gl-hero-top > .elementor-container {
		flex-direction: column; align-items: flex-start; gap: 6px;
	}
	body .gl-hero-foot > .elementor-container {
		flex-direction: column; align-items: flex-start; gap: 32px;
	}
}
@media (max-width: 680px) {
	.elementor-section.gl-hero { padding: 24px var(--gl-pad); min-height: 480px; }
	.gl-hero-mid > .elementor-container,
	.gl-hero-mid > .elementor-container > .elementor-column > .elementor-widget-wrap {
		gap: 18px;
	}
	/* PART 1: .hero-rule { width: 48px } at this width, and the 18px above is
	   the gap the rule's margin stands in for — see the note on the base rule.
	   Same `.gl-hero:not(.hero--inner)` scope, for the same reason: the two
	   selectors are one rule split across two breakpoints, and scoping only the
	   base one would leave the inner hero growing a rule at 680px and nowhere
	   else. */
	.gl-hero:not(.hero--inner) .gl-hero-mid > .elementor-container > .elementor-column > .elementor-widget-wrap > .elementor-widget:first-child::before {
		width: 48px;
		margin-bottom: 18px;
	}
}

/* --- A9.3 marquee ---------------------------------------------------------
   PART 1: .mq (ink ground, min-height 84, centred row, gap 26). The band is
   now a COLUMN carrying .mq, and the words are a text-editor, so the copy is
   editable and the ember separators keep their own colour. */
.elementor-column.mq {
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--gl-ink);
	color: var(--gl-paper);
	min-height: 84px;
	padding: 16px var(--gl-pad);
}
.elementor-column.mq > .elementor-widget-wrap { justify-content: center; width: 100%; }
.mq .elementor-widget-text-editor { text-align: center; }
.mq .elementor-widget-text-editor p { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 26px; }

/* --- A9.4 the section head ------------------------------------------------
   PART 1: .sec-head (flex, align-items flex-end, space-between, gap 32) and
   .sec-head .lead (column, gap 12). The kicker and the title are two heading
   widgets, each in an inner section wearing `.gl-kicker` / `.sec-title` (a
   widget has no class channel — A9.1), and the right-hand slot is a heading
   wearing `.sec-link`, which is also carries the link.

   THREE THINGS THIS RULE HAD TO LEARN WHEN IT WAS FIRST USED, all of them
   invisible until a template actually emitted this shape:

     · THE LEAD COLUMN NEEDS A WIDTH. `column()` pins `_column_size` to 100
       (A3), so without the first rule below the lead would carry Elementor's
       own `.elementor-col-100 { width: 100% }` — (0,2,0) and printed later,
       the same tie A9.2 records losing on the hero's top row. `flex: 1 1 0`
       puts a flex-basis of 0 in front of it, so `width` stops deciding.
     · `:not(:only-child)`, because the FAQ head has no right-hand slot at all.
       With one column, `:last-child` shrank it to its content and the title
       stopped filling the band.
     · THE STACK IS AT 900PX, NOT 680PX. PART 1 wraps `.sec-head` into a column
       at max-width 900 with gap 20; this rule said 680 with gap 18, which is
       both the wrong breakpoint and the wrong number — the "one step late"
       failure check_mirror.py was written for, and the reason those numbers are
       mirror rows now.

   `body` on the container for the reason A3 sets out: Elementor declares
   `flex-wrap: wrap` on every `.elementor-section .elementor-container` at
   (0,2,0) and prints later. PART 1's `.sec-head` is a plain flex row, which is
   `nowrap`. */
body .gl-sec-head > .elementor-container { align-items: flex-end; justify-content: space-between; gap: 32px; flex-wrap: nowrap; }
.gl-sec-head .elementor-column:first-child { flex: 1 1 0; width: auto; min-width: 0; }
.gl-sec-head .elementor-column:first-child > .elementor-widget-wrap { display: flex; flex-direction: column; gap: 12px; }
.gl-sec-head .elementor-column:last-child:not(:only-child) { flex: 0 0 auto; width: auto; }
.gl-sec-head .elementor-column:last-child:not(:only-child) > .elementor-widget-wrap { justify-content: flex-end; }

/* The right-hand slot is a heading widget carrying a LINK, so PART 1's
   `.sec-link` type reaches the heading title through A9.1's bridge and the rule
   PART 1 draws under it (a 2px padding and a transparent border) lands on the
   carrier column, whose width is the label's own. Elementor writes an <a>
   inside the title; told to inherit so the design's colour survives, and with
   the underline suppressed because PART 1's `.sec-link` did not have one. */
.sec-link .elementor-heading-title a { color: inherit; text-decoration: none; }

@media (max-width: 900px) {
	body .gl-sec-head > .elementor-container { flex-direction: column; align-items: flex-start; gap: 20px; }
}

/* --- A9.10 the price row and the closing quote -----------------------------
   The two blocks of the edit / materials bands that were still markup trees.
   Both are the same substitution A9.2 made for the hero's ember rule: a
   hairline is not content, so it stops being a widget and becomes a
   pseudo-element carrying PART 1's two declarations and PART 1's gap to the
   thing below it, arriving as a margin rather than as a flex gap.

   PRICE ROW. PART 1: .price-row (flex, align-items centre, space-between,
   gap 24, wrap) and .price-row .price (sans 500 26px, ink). The row is a
   section and the price is a heading widget, so the row's flex moves onto the
   container — A2's reason: an Elementor section keeps its layout there, not on
   itself. `price-row` is STILL put on the section for exactly one reason: it
   is the ancestor PART 1's `.price-row .price` is written against, so keeping
   the class keeps that rule reaching the price's carrier without a number
   being restated. Its `display: flex` is DECLINED, because on a section it
   would be a second opinion about a layout the container already owns. */
body .gl-price-row > .elementor-container {
	align-items: center;
	justify-content: space-between;
	gap: 24px;
	flex-wrap: wrap;
}
/* Both cells shrink to their own content and `space-between` does the rest.
   `body` is load-bearing here for the reason A9.2 records for `.gl-hero-top`:
   `column()` pins `_column_size` to 100 (A3), so Elementor's own
   `.elementor-column.elementor-col-100 { width: 100% }` applies at (0,2,0),
   prints later, and would give BOTH cells the full width — the row would wrap
   into two stacked lines. `flex: 0 0 auto` leaves flex-basis at `auto`, so
   `width` is the deciding property and one element of specificity wins it. */
body .gl-price-row > .elementor-container > .elementor-column { flex: 0 0 auto; width: auto; }
.elementor-section.price-row { display: block; }
.elementor-section.price-row::before {
	content: "";
	display: block;
	height: 1px;
	background: var(--gl-ink);
	margin-bottom: 24px;
}

/* CLOSING QUOTE. PART 1: .gl-rule--ink (a 1px --gl-line rule) then .quote
   (serif 46px, paper) then .quote-credit (mono 11px, --gl-muted-3). Each is now
   a section of its own, so the rule is the quote's ::before and PART 1's gap
   from the rule to the quote — the section's own `.sec-in--g48` column gap —
   arrives as a margin. Scoped to `.elementor-section` because `.quote` and
   `.price-row` are PART 1's own names: the theme's built-in templates render
   both, and an unscoped ::before would draw a hairline on them too. */
.elementor-section.quote::before {
	content: "";
	display: block;
	height: 1px;
	background: var(--gl-line);
	margin-bottom: 48px;
}

/* --- A9.5 the shelf card's name row ---------------------------------------
   PART 1 hangs these off .gcard .meta with a 1px rule above. The rule is now
   the row's own top border — a hairline needs no widget — and the name and
   count are heading widgets in a two-column row. */
.gcard .gl-meta > .elementor-container {
	justify-content: space-between;
	align-items: center;
	gap: 20px;
	flex-wrap: nowrap;
	border-top: 1px solid var(--gl-ink);
	padding-top: 18px;
}
.gcard .gl-meta .elementor-column { flex: 0 0 auto; width: auto; }
.gcard .gl-meta .elementor-column:first-child { flex: 1 1 auto; min-width: 0; }

/* --- A9.6 the spec table --------------------------------------------------
   PART 1: .spec (column, gap 6, mono 12px) with .spec-row (flex, gap 24) and
   .spec-row .k (flex 0 0 118px). .spec goes on the column that holds the
   rows; each row is an inner section, because a row IS two columns. */
.spec > .elementor-widget-wrap { display: flex; flex-direction: column; gap: 6px; }
/* `body` for the reason A3 sets out: Elementor declares `flex-wrap: wrap` on
   every `.elementor-section .elementor-container` at (0,2,0) and prints later,
   so without the extra element this `nowrap` never fires. */
body .spec-row > .elementor-container { gap: 24px; flex-wrap: nowrap; }
.spec-row .elementor-column:first-child { flex: 0 0 118px; }
.spec-row .elementor-column:last-child { flex: 1 1 auto; min-width: 0; }

/* --- A9.7 the statistics row ----------------------------------------------
   PART 1: .stats (flex, space-between, gap 32) and .stat (column, gap 6).
   Each figure is now a column carrying .stat, holding two heading widgets.
   `body` for the same reason as .gl-hero-top: each figure shrinks to its own
   content, so `width` is the deciding property and Elementor's col-100 rule
   ties at (0,2,0) and prints later. */
body .gl-stats > .elementor-container { align-items: flex-start; justify-content: space-between; gap: 32px; }
body .gl-stats .elementor-column { flex: 0 0 auto; width: auto; }
.stat > .elementor-widget-wrap { display: flex; flex-direction: column; gap: 6px; }

/* --- A9.8 the voices row --------------------------------------------------
   PART 1: .voices (flex, gap 16) and .voice (flex 1 1 0, column, gap 18,
   paper ground, padding 28px 26px). Each card is a column: the background and
   the padding come from PART 1's .voice rule, unchanged, because a column is
   still the element PART 1 styles.
   These columns take EQUAL shares, so unlike the rows above they do not depend
   on `width` at all — `flex-basis: 0` makes it irrelevant — but the 680px rule
   below does fall back to `width: 100%`, and `body` keeps every one of them on
   the same side of the tie. */
body .gl-voices > .elementor-container { gap: 16px; align-items: stretch; flex-wrap: nowrap; }
body .gl-voices .elementor-column { flex: 1 1 0; min-width: 0; }
.voice > .elementor-widget-wrap { display: flex; flex-direction: column; gap: 18px; }
.voice .elementor-widget-text-editor p { margin: 0; }

@media (max-width: 900px) {
	body .gl-voices > .elementor-container { flex-wrap: wrap; }
	body .gl-voices .elementor-column { flex: 1 1 calc(50% - 8px); }
}
@media (max-width: 680px) {
	body .gl-voices .elementor-column { flex: 1 1 auto; width: 100%; }
	body .gl-stats > .elementor-container { flex-direction: column; gap: 22px; }
}

/* --- A9.9 the contact page's composed pieces ------------------------------
   A8 defines .gl-cards / .gl-icard / .gl-hours / .gl-faq as element trees.
   Rebuilt from widgets the trees become Elementor columns, so the rules that
   were written for a div now have to hold a widget-wrap together as well. */
.gl-cards > .elementor-widget-wrap { display: flex; flex-direction: column; gap: 16px; }
.gl-icard > .elementor-widget-wrap { display: flex; flex-direction: column; gap: 10px; background: var(--gl-paper); padding: 26px 24px; }
/* A8 writes the card's small ember heading as `.gl-icard h4`. A widget's
   heading IS still an h4 element, but Elementor's `color: var(--gl-ink)` rule
   for `.elementor-heading-title` is (0,2,0) and would beat a (0,1,1) element
   rule — so A8 also names `.gl-icard-h`, which the template puts on the
   widget, and the bridge above hands the type down. The declarations live in
   A8 only; nothing is stated twice. */
/* A8 writes the hours list as `.gl-hours > div`, direct children of an
   element. Inside a text-editor widget the rows are one level deeper, so the
   descendant form is what actually matches. */
.gl-hours div { display: flex; justify-content: space-between; gap: 20px; }

/* --- A9.11 the About page's inner-page blocks ------------------------------
   PART 1's section 18, plus the inner hero variant in its section 9, mirrored
   the way A9.2 mirrors the home hero — and, like A9.7 to A9.10, written before
   anything used it. A9.4's lesson applies here in full: three of those rules
   were wrong in ways nobody could see while no template emitted their shape, so
   every number below is a MIRROR row in check_mirror.py rather than a
   hand-copied value.
   
   ONLY GEOMETRY IS HERE, AND THE REASON IS WORTH STATING. Everything about TYPE
   already arrives on its own: a role class rides the column or the section that
   carries it, so PART 1's own rule for that class applies to that element
   unchanged, and A9.1's bridge copies it inward. `.story-title`'s 52px serif,
   `.step-name`'s 30px, `.cta-title`'s 58px, the 44px `.stat--lg` figures and
   all four of the inner hero's headline sizes are therefore stated ONCE, in
   PART 1, and read here rather than restated. What a container cannot inherit
   is the LAYOUT PART 1 expresses on a row or a grid element, because in an
   Elementor build that element is a section whose only child is the container —
   so the flex has to move down one level, and moving it is what makes it a
   number in two places.

   WHY THREE OF THE WRAPPERS ARE `gl-*` NAMES. The same rule A9.7 to A9.9
   follow: where PART 1's class is a ROW, the section takes a `gl-` name of its
   own. Leaving PART 1's name on a section would put its `display: flex` on a
   box whose only child is the container, and `flex-basis: auto` would then make
   that container a SHRINK-TO-FIT flex item — the `.gl-hero` failure in
   miniature, and the reason `.gl-sec` and `.gl-hero` are named the way they
   are. `.story-row`, `.steps` and `.cta-row` are rows, so each is `.gl-story-row`,
   `.gl-steps` and `.gl-cta-row` here. `.story-rail`, `.story-body`, `.step`,
   `.cta-lead` and `.cta-title` KEEP PART 1's names: each is a STACK, and a
   column is still the element PART 1 styles (A9.8's reason for `.voice`).

   WHAT IS DELIBERATELY NOT HERE, so that a later reader does not add it:
   `.story-rail`'s 400px, `.story-body`'s equal share, `.step`'s equal share and
   its 1px + 14px opening rule, `.cta-lead`'s 620 measure, and every value in
   PART 1's section 20 blocks that lands on one of those columns. Each of them
   rides PART 1's own selector on the column, which is the whole point of
   putting PART 1's class there. */

/* --- the inner hero (PART 1 §9 `.hero.hero--inner`) ----------------------
   Two classes on the section, exactly as PART 1 writes them, and that is what
   makes the 900 and 680 blocks of A9.2 lose: they set `padding: 32px` / `24px`
   and `min-height: 560px` / `480px` on the ONE-class `.elementor-section.gl-hero`,
   and a media query carries no specificity of its own — the same way PART 1's
   `.hero.hero--inner` outranks `.hero`. So the padding is stated once here and
   is never restated below: it follows `--gl-sec-y`, which is what "the section
   rhythm in place of the home hero's 44" means at every width. */
.elementor-section.gl-hero.hero--inner {
	min-height: 620px;
	padding: var(--gl-sec-y) var(--gl-pad);
}
/* PART 1: `.hero--inner .hero-in { justify-content: flex-end }` — the copy sits
   at the BOTTOM of the band, which is what the canvas measures: the copy block
   ends 96px above the hero's bottom edge, and 96 is exactly the band's own
   bottom padding. A9.2 gives `.gl-hero-in`'s widget-wrap `space-between` for the
   home hero, where a notes row and a copy block are pushed apart; with one child
   `space-between` resolves to the TOP, so without this rule the whole hero would
   render 226px higher than the design. It is a real 226 and not a rounding: the
   container is `flex: 1 1 auto` and the column stretches (A9.2), so the wrap's
   height is the band's and the free space is the whole top gap. */
.hero--inner .gl-hero-in > .elementor-widget-wrap { justify-content: flex-end; }
/* PART 1: `.hero--inner .hero-mid { gap: 24px }` against `.hero-mid`'s 26.
   BOTH carriers are named because A9.2 needs both: the container holds the
   columns and each column's widget-wrap holds the widgets, and which of the two
   actually produces the 26 depends on nothing this file can see. One class more
   than A9.2's pair, so as with the height and the padding the win is on
   specificity and not on order. */
.hero--inner .gl-hero-mid > .elementor-container,
.hero--inner .gl-hero-mid > .elementor-container > .elementor-column > .elementor-widget-wrap {
	gap: 24px;
}
/* PART 1 §20's three steps for this hero, read out and not recomputed: 620
   falls to 480 / 420 / 360 exactly the way the home hero's 820 falls to 640 /
   560 / 480 — the same ratios applied to 620 and rounded to the nearest ten,
   which is the arithmetic PART 1's own note records. The headline needs no
   block here for the reason at the top of A9.11. */
@media (max-width: 1180px) {
	.elementor-section.gl-hero.hero--inner { min-height: 480px; }
}
@media (max-width: 900px) {
	.elementor-section.gl-hero.hero--inner { min-height: 420px; }
}
@media (max-width: 680px) {
	.elementor-section.gl-hero.hero--inner { min-height: 360px; }
	.hero--inner .gl-hero-mid > .elementor-container,
	.hero--inner .gl-hero-mid > .elementor-container > .elementor-column > .elementor-widget-wrap {
		gap: 18px;
	}
}

/* --- a band that runs tighter than the section rhythm --------------------
   PART 1 has `.sec--tight` for this, and the numbers band is the one band on the
   page that uses it (canvas 3:418: 72 of padding where the rhythm is 96). The
   class cannot simply be added to the section: `.elementor-section.gl-sec` is
   (0,2,0) and `.sec--tight` is (0,1,0), so the tighter value would lose to the
   fuller one — silently, because 96 is a plausible number for a band. Named
   here at one class more rather than as a second `gl-` name, so that
   check_mirror.py can hold the two spellings of the number side by side. */
.elementor-section.gl-sec.sec--tight {
	padding: calc(var(--gl-sec-y) - 24px) var(--gl-pad);
}

/* --- 01 · our story (canvas 3:408) --------------------------------------
   PART 1: `.story-row` (flex, 64 apart, tops aligned) holding a 400px rail and
   the copy beside it. Only the row moves; the rail's 400 and the body's equal
   share stay on PART 1's own selectors, because both are COLUMNS here.
   `flex-wrap: nowrap` needs `body` for A3's reason — Elementor declares
   `flex-wrap: wrap` on every container at (0,2,0) and prints later, and a rail
   at a fixed 400 with the copy beside it is a row the design does not let wrap. */
body .gl-story-row > .elementor-container {
	display: flex;
	align-items: flex-start;
	gap: 64px;
	flex-wrap: nowrap;
}
/* The two stacks. PART 1 gives each of these a `display: flex; flex-direction:
   column; gap`, and on a column the flex does reach the widget-wrap — but the
   widget-wrap is ONE child, so the gap has to be restated on it. A9.8 spells
   the same two declarations for `.voice` and for the same reason. */
.elementor-column.story-rail > .elementor-widget-wrap,
.elementor-column.story-body > .elementor-widget-wrap {
	display: flex;
	flex-direction: column;
}
.elementor-column.story-rail > .elementor-widget-wrap { gap: 14px; }
.elementor-column.story-body > .elementor-widget-wrap { gap: 22px; }
@media (max-width: 900px) {
	body .gl-story-row > .elementor-container { flex-direction: column; gap: 32px; }
}

/* --- 02 · how it's made (canvas 3:429) ----------------------------------
   PART 1: `.steps` (flex, 16 apart, tops aligned) of four equal `.step` cells.
   The four breakpoints come along with the columns (PART 1 §20 re-expresses
   `.step`'s share at 1180 and 680, and `.steps`'s direction and gap at the
   same two), so only the container's own three are restated. */
body .gl-steps > .elementor-container {
	display: flex;
	align-items: flex-start;
	gap: 16px;
	flex-wrap: nowrap;
}
/* PART 1: `.step` — a stack whose first child is a hairline. The 1px and its
   14px of air are PART 1's border-top and padding-top on the column and are
   already right there; what the widget-wrap needs is the gap. */
.elementor-column.step > .elementor-widget-wrap {
	display: flex;
	flex-direction: column;
	gap: 14px;
}
@media (max-width: 1180px) {
	body .gl-steps > .elementor-container { flex-wrap: wrap; }
}
@media (max-width: 680px) {
	body .gl-steps > .elementor-container { flex-direction: column; gap: 24px; }
}

/* --- 03 · visit (canvas 3:456) ------------------------------------------
   PART 1 splits this band into `.cta-band` (the padding and nothing else) and
   `.cta-in` (the measure and the stack), and an Elementor section is one element
   playing both parts — so the section wears `.cta-band` for its padding and its
   CONTAINER plays `.cta-in`. Nothing has to be declined here, and that is the
   point of how PART 1 states the pair: `.cta-band` carries no `display`, so the
   section is never asked to be a flex box that would then have to be talked out
   of it. The band's ink ground and its `color: var(--gl-paper)` come from
   `.gl-band-ink` (A4), which is where the canvas's own ground is stated.
   The three children of `.cta-in` are the kicker, the title and the row, and
   here they are two role carriers and one inner section — which is why the
   stack has to live on the widget-wrap rather than on the container: a
   container's children are COLUMNS, and only the widget-wrap can hold sections
   (A2's split of labour: rows on the container, stacks on the wrap). */
body .cta-band > .elementor-container { max-width: var(--gl-wrap); }
body .cta-band > .elementor-container > .elementor-column > .elementor-widget-wrap {
	display: flex;
	flex-direction: column;
	gap: 28px;
}
/* The row itself. `align-items: flex-end` is the canvas's own
   counterAxisAlignItems MAX — the button's 49px box sits at offset 3 inside the
   52px row — and PART 1's `.cta-row` states it, so this is a mirror of a
   mirrored number rather than a second reading of the canvas. `body` and the
   two `flex: 0 0 auto` columns for A9.10's reason: `column()` pins
   `_column_size` to 100 (A3), so Elementor's own `.elementor-col-100` would give
   both cells the full width and the row would stack into two lines. The lead
   column's 620 measure arrives from PART 1's `.cta-lead` on that column. */
body .gl-cta-row > .elementor-container {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 48px;
	flex-wrap: nowrap;
}
body .gl-cta-row > .elementor-container > .elementor-column { flex: 0 0 auto; width: auto; }
@media (max-width: 900px) {
	body .gl-cta-row > .elementor-container {
		flex-direction: column; align-items: flex-start; gap: 32px;
	}
}

/* --------------------------------------------------------------------------
   9. WIDGET AREAS — the header and footer slots
   --------------------------------------------------------------------------
   The nine areas registered in functions.php, section 7b. They are OPT-IN: an
   area with nothing in it prints nothing at all and the theme's own markup
   stands, so an untouched install — and every site this theme is resold to —
   renders exactly as it did before the areas existed. Nothing has to be
   emptied out to get the old behaviour back; remove the widget.

   What follows is only the small amount a DROPPED-IN widget needs in order to
   look like it belongs.

   THE SLOT WRAPPER DISSOLVES. `display: contents` takes `.gl-wslot` out of the
   box tree, so the widget wrappers become direct children of whatever shell the
   slot lives in — and each of those shells already declares its own gap, in
   PART 1 (.mast .brand 6, .mast nav 32, .mast .rt 22, .ftr-brand 16,
   .ftr-col 14, .pay 12) or in section 2 above (the menu lists). A widget
   therefore receives THE SAME spacing the built-in element received, and not
   one of those numbers is restated here. That is the whole trick: the widget
   inherits the layout instead of being fitted to a copy of it.

   The cost, stated plainly: `.gl-wslot` has no box of its own and can never
   carry a background, a padding or a border. Style the shell instead
   (`.ftr-col`, `.mast .rt` ..) when a slot needs to look different. */

.gl-wslot { display: contents; }

/* WordPress puts roughly one em under a widget while the theme's rhythm is
 * gap-driven, so the two would fight and every dropped-in block would sit a
 * little too far from the next. Flatten the wrapper ... */
.gl-wslot > .gl-w { margin: 0; }

/* ... and the margins WordPress gives the blocks a widget renders. Only
 * block-level children are named: a Custom HTML block that styles its own
 * nested divs keeps whatever it declares. */
.gl-wslot .gl-w p,
.gl-wslot .gl-w ul,
.gl-wslot .gl-w ol,
.gl-wslot .gl-w dl,
.gl-wslot .gl-w h1,
.gl-wslot .gl-w h2,
.gl-wslot .gl-w h3,
.gl-wslot .gl-w h4,
.gl-wslot .gl-w h5,
.gl-wslot .gl-w h6,
.gl-wslot .gl-w blockquote,
.gl-wslot .gl-w figure,
.gl-wslot .gl-w form { margin: 0; }

/* No shell in the masthead or the footer has bullets or indentation, so a
 * widget must not arrive with either. */
.gl-wslot .gl-w ul,
.gl-wslot .gl-w ol { padding: 0; list-style: none; }
.gl-wslot .gl-w li { list-style: none; }

/* THE ROW-SHAPED SHELLS. Where the shell runs horizontally a widget has to run
 * horizontally too, so the wrapper copies the shell's own arrangement rather
 * than starting a column inside a row. The gap is `inherit`, never a number:
 * change the design's gap and the widget follows with no second edit. The
 * masthead's three groups, the payment row and the bottom bar are all rows; the
 * footer's brand column and the three menu columns are columns and are NOT in
 * this group, because there a widget should stack. */
.mast .brand .gl-wslot > .gl-w,
.mast nav .gl-wslot > .gl-w,
.mast .rt .gl-wslot > .gl-w,
.pay .gl-wslot > .gl-w,
.ftr-bot .gl-wslot > .gl-w {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: inherit;
}

/* A list dropped into the payment row or the bottom bar is meant to read along
 * the row — those two are the places where a list IS the expected content.
 * Dropdowns are excluded: a submenu has to keep running downwards. */
.pay .gl-wslot .gl-w ul:not(.sub-menu),
.ftr-bot .gl-wslot .gl-w ul:not(.sub-menu) {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: inherit;
}

/* Below 900px PART 1 turns the masthead navigation into a column, so a widget
 * standing in that slot has to turn with it. */
@media (max-width: 900px) {
	.mast nav .gl-wslot > .gl-w { flex-direction: column; align-items: flex-start; }
}
