/*
Theme Name: Redteam
Author: Tiller Digital
Description: A lightweight tiller theme built for Elementor.
Version: 1.0.0
Requires at least: 6.0
Requires PHP: 7.4
License: GNU General Public License v3 or later
Text Domain: redteam
*/

/* ==========================================================================
 * CSS OWNERSHIP & LAYERING
 *
 * Six layers, in cascade order. A rule belongs to exactly one of them; when in
 * doubt, the lowest layer that can own it wins.
 *
 *   1. TOKENS — this file, the `html { }` block below. Every design value the
 *      theme uses: the rem scale (--s*), spacers, column grid, gradients, and
 *      the shared inline icons. Elementor's Kit globals arrive as --color-* /
 *      --font-* from includes/elementor-tokens.php; nothing else may define
 *      them. Widget-local variables are named --redteam-<widget>-* and stay in
 *      that widget's own stylesheet.
 *   2. GLOBAL TYPOGRAPHY & UTILITIES — this file. Base tags, .b-* type classes,
 *      .alt-* WYSIWYG formats (paired with the Formats dropdown in
 *      functions.php), and the .bg-* / margin utilities. Anything an editor can
 *      apply from the classic editor or a CSS Classes field lives here.
 *   3. ELEMENTOR INTEGRATION OVERRIDES — this file's GLOBAL NAV section, plus
 *      each extensions/<widget>/style.css. Rules whose selectors target
 *      Elementor's own markup (.e-con, .elementor-widget-*, .e-n-menu, …).
 *      These are the only rules allowed to out-specify Elementor's generated
 *      CSS, and each such rule documents what it is beating and why.
 *   4. SHARED COMPONENTS — this file: ARROW LINK, HUBSPOT FORMS, the chip list
 *      formats. Treatments used by more than one widget or by raw embeds, so no
 *      single widget stylesheet can own them. Consumers opt in by adding their
 *      selector to the shared rule; they never restate the treatment.
 *   5. WIDGET STYLES — widgets/<name>/style.css, loaded lazily by Elementor via
 *      the widget's get_style_depends(). Scoped to .redteam-<widget>* markup.
 *   6. EXTENSION STYLES — extensions/<widget>/style.css, enqueued unconditionally
 *      (an extension has no widget class, so there is nothing to lazy-load off).
 *      Scoped to the variant class the extension stamps.
 *
 * LOAD ORDER, which the cascade depends on: this file, then the extension
 * stylesheets, then any widget stylesheets on the page, then Elementor's own
 * Kit and per-post stylesheets LAST. A tie with an Elementor selector therefore
 * loses — see the notes throughout on `:root:root`, `#content` and the handful
 * of unavoidable `!important`s.
 *
 * REM-AS-PX: `html { font-size: 1px }` below, scaled per breakpoint, so every
 * `rem` in the theme is a px-equivalent that scales fluidly. Size things in rem.
 * Below 960px the scaling is switched off (font-size returns to 1px) and layout
 * steps down through explicit tokens instead.
 * ========================================================================== */

html {font-size: 1px;}

@media (width <=1400px) { html {font-size: 0.975px;}}
@media (width <=1360px) { html {font-size: 0.950px;}}
@media (width <=1320px) { html {font-size: 0.925px;}}
@media (width <=1280px) { html {font-size: 0.900px;}}
@media (width <=1240px) { html {font-size: 0.875px;}}
@media (width <=1200px) { html {font-size: 0.850px;}}
@media (width <=1160px) { html {font-size: 0.825px;}}
@media (width <=1120px) { html {font-size: 0.800px;}}
@media (width <=1080px) { html {font-size: 0.775px;}}
@media (width <=1040px) { html {font-size: 0.750px;}}
@media (width <=1000px) { html {font-size: 0.725px;}}
@media (width <=960px) { html {font-size: 1.000px;}}
@media (width > 1920px) { html {font-size: 1.25px;}}

html {
	--ps: 0.75em;

	--s0: 0rem;
	--s05: 4rem;
	--s1: 8rem;
	--s2: 12rem;
	--s3: 16rem;
	--s4: 24rem;
	--s5: 32rem;
	--s6: 48rem;
	--s7: 64rem;
	--s8: 96rem;
	--s9: 128rem;
	--s10: 192rem;
	--s11: 256rem;
	--s12: 384rem;

	--ns1: -8rem;
	--ns2: -12rem;
	--ns3: -16rem;
	--ns4: -24rem;
	--ns5: -32rem;
	--ns6: -48rem;
	--ns7: -64rem;
	--ns8: -96rem;
	--ns9: -128rem;
	--ns10: -192rem;
	--ns11: -256rem;
	--ns12: -384rem;

	--col-width: 72rem;
	--col-gutter: 32rem;

	--col-1: calc((var(--col-width) + var(--col-gutter)) * 1 - var(--col-gutter));
	--col-2: calc((var(--col-width) + var(--col-gutter)) * 2 - var(--col-gutter));
	--col-3: calc((var(--col-width) + var(--col-gutter)) * 3 - var(--col-gutter));
	--col-4: calc((var(--col-width) + var(--col-gutter)) * 4 - var(--col-gutter));
	--col-5: calc((var(--col-width) + var(--col-gutter)) * 5 - var(--col-gutter));
	--col-6: calc((var(--col-width) + var(--col-gutter)) * 6 - var(--col-gutter));
	--col-7: calc((var(--col-width) + var(--col-gutter)) * 7 - var(--col-gutter));
	--col-8: calc((var(--col-width) + var(--col-gutter)) * 8 - var(--col-gutter));
	--col-9: calc((var(--col-width) + var(--col-gutter)) * 9 - var(--col-gutter));
	--col-10: calc((var(--col-width) + var(--col-gutter)) * 10 - var(--col-gutter));
	--col-11: calc((var(--col-width) + var(--col-gutter)) * 11 - var(--col-gutter));
	--col-12: calc((var(--col-width) + var(--col-gutter)) * 12 - var(--col-gutter));

	--spacer-small: var(--s5);
	--spacer-medium: var(--s7);
	--spacer-large: var(--s8);
	--spacer-xlarge: var(--s9);
	--spacer-xxlarge: var(--s10);

	--nav-height: 96rem;

	/*
	 * Section-background gradients. Elementor's Global Colors store flat colours
	 * only, so gradients live here as theme tokens. Applied by the .bg-<name>
	 * utility class (extensions/container/style.css), which the Container's
	 * "Custom BG Color" control stamps and which can also be typed into any
	 * widget's CSS Classes field. Stops reference the Kit's own --color-* globals
	 * so they track those edits.
	 */
	--color-white-200--pearl-200: linear-gradient(180deg, var(--color-white-200-base, #FFFFFD) 0%, var(--color-pearl-200-base, #F0EBE5) 100%);
	--color-white-200--red-200: linear-gradient(180deg, var(--color-white-200-base, #FFFFFD) 0%, var(--color-white-200-base, #FFFFFD) 50%, var(--color-red-200-base, #C8102E) 50%, var(--color-red-200-base, #C8102E) 100%);

	/*
	 * SHARED INLINE ICONS. Each is a complete `url()` value, so a consumer writes
	 * `mask: var(--icon-arrow-right)` — the geometry lives here once instead of being
	 * pasted into every widget and extension stylesheet that needs it.
	 *
	 * Inline data URIs, not files in assets/: these are applied as MASKS, and a mask
	 * request is a separate network fetch that would delay the glyph on first paint.
	 * Their `fill` is irrelevant while masking (a mask reads alpha only) — the colour
	 * always comes from the consumer's own `background-color`, which is what keeps
	 * `currentColor` and hover states working.
	 *
	 * NOT for a background-image: there the fill IS the visible colour and cannot
	 * inherit, so a background-image consumer needs its own copy with the colour baked
	 * in (see the HubSpot submit button below).
	 */
	--icon-arrow-right: url("data:image/svg+xml,%3Csvg width='9' height='10' viewBox='0 0 9 10' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8.26558 4.64868L0 9.29883L-4.06462e-07 5.14984e-05L8.26558 4.64868Z' fill='currentColor'/%3E%3C/svg%3E%0A");
	--icon-user: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='currentColor' x='7.33594' y='2.63867' width='8.33333' height='8.33333' rx='4.16667'/%3E%3Cpath fill='currentColor' d='M2.92969 20.511C2.92969 16.1956 6.42804 12.6973 10.7435 12.6973H12.6969C17.0123 12.6973 20.5107 16.1956 20.5107 20.511V20.511H2.92969V20.511Z'/%3E%3C/svg%3E%0A");
}


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


/* TYPOGRAPHY */

html {
	overflow-y: scroll;
	text-size-adjust: 100%;
	-webkit-font-smoothing: antialiased;
	-webkit-tap-highlight-color: transparent;
	scroll-behavior: smooth;
	scroll-padding-top: calc(var(--nav-height) + var(--s6));
}

body {
	margin: 0;
	color: var(--navy);
	background: var(--white);
	overflow-x: hidden;
}

/*
 * Sizes/families come from the Kit's global fonts (includes/elementor-tokens.php);
 * the literals are fallbacks for a Kit whose globals were renamed or never set.
 * `:root:root` buys specificity past Elementor's per-kit `.elementor-kit-<id> h1`
 * rules (0-1-1, loaded after this file) without !important.
 */
:root:root body {
	font-family: var(--font-text, 'Archivo'), sans-serif;
	font-size: var(--font-text-size, 18rem);
	line-height: var(--font-text-line-height, 1.5);
	word-wrap: break-word;
}

:root:root :is(h1, h2, h3, h4, h5, h6),
:root:root :is(.b-h1, .b-h2, .b-h3, .b-h4, .b-h5, .b-h6) {
	margin: 1.25em 0 0 0;
}

:root:root h1,
:root:root .b-h1 {
	font-family: var(--font-h1, 'Archivo'), sans-serif;
	font-weight: var(--font-h1-weight, 400);
	font-size: var(--font-h1-size, 84rem);
	line-height: var(--font-h1-line-height, 1.3);
}

:root:root h2,
:root:root .b-h2 {
	font-family: var(--font-h2, 'Archivo'), sans-serif;
	font-weight: var(--font-h2-weight, 400);
	font-size: var(--font-h2-size, 58rem);
	line-height: var(--font-h2-line-height, 1.3);
}

:root:root h3,
:root:root .b-h3 {
	font-family: var(--font-h3, 'Archivo'), sans-serif;
	font-weight: var(--font-h3-weight, 400);
	font-size: var(--font-h3-size, 48rem);
	line-height: var(--font-h3-line-height, 1.3);
}

:root:root h4,
:root:root .b-h4 {
	font-family: var(--font-h4, 'Archivo'), sans-serif;
	font-weight: var(--font-h4-weight, 400);
	font-size: var(--font-h4-size, 36rem);
	line-height: var(--font-h4-line-height, 1.3);
}

:root:root h5,
:root:root .b-h5 {
	font-family: var(--font-h5, 'Archivo'), sans-serif;
	font-weight: var(--font-h5-weight, 400);
	font-size: var(--font-h5-size, 24rem);
	line-height: var(--font-h5-line-height, 1.3);
}

:root:root h6,
:root:root .b-h6 {
	font-family: var(--font-h6, 'Archivo'), sans-serif;
	font-weight: var(--font-h6-weight, 400);
	font-size: var(--font-h6-size, 18rem);
	line-height: var(--font-h6-line-height, 1.3);
}

:root:root :is(h1 a, h2 a, h3 a, h4 a, h5 a, h6 a) {
	color: inherit;
	text-decoration: none;
}

:root:root :is(h1, h2, h3, h4, h5, h6)+ :is(h1, h2, h3, h4, h5, h6) {
	margin-top: 0;
}

:root:root .b-text-stats {
	font-family: var(--font-stats, 'Archivo'), sans-serif;
	font-weight: var(--font-stats-weight, 300);
	font-size: var(--font-stats-size, 62rem);
	line-height: var(--font-stats-line-height, 1.3);
	margin: 0 !important;
}

:root:root .b-text-large {
	font-family: var(--font-body-large, 'Archivo'), sans-serif;
	font-weight: var(--font-body-large-weight, 400);
	font-size: var(--font-body-large-size, 20rem);
	line-height: var(--font-body-large-line-height, 1.4);
}

:root:root .b-text-small {
	font-family: var(--font-body-small, 'Archivo'), sans-serif;
	font-weight: var(--font-body-small-weight, 400);
	font-size: var(--font-body-small-size, 16rem);
	line-height: var(--font-body-small-line-height, 1.3);
}

:root:root :is(.b-text-eyebrow-light, .b-text-eyebrow-dark) {
	font-family: var(--font-text, 'Archivo'), sans-serif;
	font-weight: var(--font-text-weight, 400);
	font-size: var(--font-text-size, 18rem);
	line-height: var(--font-text-line-height, 1.5);
	display: inline-flex;
	align-items: center;
	padding: var(--s1) var(--s2);
	border-radius: 4rem;
	backdrop-filter: blur(16rem);
}

:root:root .b-text-eyebrow-light {
	color: var(--color-white);
	background: rgba(255, 255, 255, 0.05);
}

:root:root .b-text-eyebrow-dark {
	color: var(--color-black-500);
	background: rgba(0, 0, 0, 0.05);
}

:is(.b-text-eyebrow-light, .b-text-eyebrow-dark).alt-red-dot::before {
	content: "";
	display: inline-block;
	width: 10rem;
	height: 10rem;
	margin-right: var(--s2);
	border-radius: 50%;
	background-color: var(--color-red-200-base);
	vertical-align: middle;
}

:root:root :is(.b-text-eyebrow-light, .b-text-eyebrow-dark)[style*="text-align: center"] {
	display: table;
	margin-inline: auto;
}

:root:root :is(.b-text-eyebrow-light, .b-text-eyebrow-dark)[style*="text-align: right"] {
	display: table;
	margin-inline-start: auto;
}

:root:root :is(.b-text-eyebrow-light, .b-text-eyebrow-dark)[style*="text-align: left"] {
	display: table;
	margin-inline-end: auto;
}

[data-inverted-text] {
	color: var(--white);
}

.alt-text-red {color: var(--color-red-200-base);}
.alt-text-black-300 {color: var(--color-black-300);}
.alt-text-pearl-100 {color: var(--color-pearl-100);}
.alt-text-pearl-300 {color: var(--color-pearl-300);}
.alt-text-pearl-500 {color: var(--color-pearl-500);}
.alt-text-white {color: var(--color-white);}

:is(.b-text-eyebrow-light, .b-text-eyebrow-dark)+ :is(h1, .b-h1, h2, .b-h2, h3, .b-h3, h4, .b-h4, h5, .b-h5, h6, .b-h6) {
	margin-top: 0 !important;
}

:is(.b-text-eyebrow-light, .b-text-eyebrow-dark):has(+ :is(h1, .b-h1, h2, .b-h2, h3, .b-h3, h4, .b-h4, h5, .b-h5, h6, .b-h6)) {
	margin-bottom: var(--s5) !important;
}

@media (width <=960px) {
	:is(.b-text-eyebrow-light, .b-text-eyebrow-dark):has(+ :is(h1, .b-h1, h2, .b-h2, h3, .b-h3, h4, .b-h4, h5, .b-h5, h6, .b-h6)) {
		margin-bottom: var(--s4) !important;
	}
}

/*
 * `alt-prose-spaced` — opt-in vertical rhythm for a Text Editor widget whose body
 * is a whole eyebrow → heading → paragraph → list stack in ONE WYSIWYG field. Add
 * it in the widget's Advanced > CSS Classes.
 *
 * Unclassed, every gap in such a stack collapses to ~`--ps` (0.75em): the Kit's
 * `p { margin-block-end }`, the eyebrow rule and the `.b-h*` margins all land on
 * about the same value, where the design spaces them on the --s5 step.
 *
 * The children are siblings inside one rich-text blob, so there is nothing to put
 * a flex `gap` on — the rhythm has to be margins. Zero them, then re-add one gap
 * between adjacent blocks with `+`, so the stack never opens or closes with stray
 * space. Override --prose-gap, not the margins.
 *
 * PREREQUISITE: Elementor's Text Editor does NOT run wpautop, so a paragraph that
 * reached the field as a bare text node or bare <span> is inline — vertical
 * margins don't apply and this class silently does nothing. Fix the content (wrap
 * it in a real <p>); CSS cannot reach that case.
 *
 * `!important` + `:root:root` are unavoidable: the eyebrow rule above already uses
 * it, and Elementor bakes per-widget typography into a 0-3-0 rule in a per-post
 * stylesheet loaded after this file.
 *
 * Scoped by DESCENDANT — keep it on the text widget; on a container it would
 * re-space every widget inside.
 */
.alt-prose-spaced {
	--prose-gap: var(--s5);
}

:root:root .alt-prose-spaced :is(h1, h2, h3, h4, h5, h6, p, ul, ol, .b-h1, .b-h2, .b-h3, .b-h4, .b-h5, .b-h6) {
	margin-top: 0 !important;
	margin-bottom: 0 !important;
}

:root:root .alt-prose-spaced :is(h1, h2, h3, h4, h5, h6, p, ul, ol, .b-h1, .b-h2, .b-h3, .b-h4, .b-h5, .b-h6)+ :is(h1, h2, h3, h4, h5, h6, p, ul, ol, .b-h1, .b-h2, .b-h3, .b-h4, .b-h5, .b-h6) {
	margin-top: var(--prose-gap) !important;
}

/*
 * Heading immediately after heading stays at 0: editors write a two-line heading
 * as two consecutive <h2>s, and the gap rule above would otherwise beat this
 * file's own `h + h { margin-top: 0 }` and split the lines.
 *
 * The eyebrow must be excluded from BOTH sides — an eyebrow is itself an <h2>
 * carrying .b-text-eyebrow-*, so a bare heading list would also zero the
 * eyebrow → heading gap, which is the one gap the design wants at --s5.
 */
:root:root .alt-prose-spaced :is(h1, h2, h3, h4, h5, h6, .b-h1, .b-h2, .b-h3, .b-h4, .b-h5, .b-h6):not(.b-text-eyebrow-light, .b-text-eyebrow-dark)+ :is(h1, h2, h3, h4, h5, h6, .b-h1, .b-h2, .b-h3, .b-h4, .b-h5, .b-h6):not(.b-text-eyebrow-light, .b-text-eyebrow-dark) {
	margin-top: 0 !important;
}

@media (width <=960px) {
	/* Matches --spacer-small's own collapse at this breakpoint, so the stack stays
	 * in step with the Spacer widgets around it. Theme convention, not a spec. */
	.alt-prose-spaced {
		--prose-gap: var(--s4);
	}
}

/*
 * "Contained" list-item format (functions.php's Formats dropdown, `ul li` — a
 * pearl chip per <li> with a red bullet dot in place of the native marker).
 *
 * MARKER LAYOUT — absolutely positioned marker + hanging indent, NOT flex, and
 * don't convert it back. These items are authored in the WYSIWYG and routinely
 * bold their first clause; under `display: flex` the <strong> and the text after
 * it become separate flex items, so the marker `gap` is also inserted
 * mid-sentence and a wrapping item lays out as two side-by-side columns instead
 * of one paragraph. Out of flow, the <li>'s contents are ordinary inline content
 * again.
 *
 * Geometry comes from the four --marker-* vars — override those, not the padding
 * or the ::before box.
 */

ul:has(>li.alt-contained) {
	padding-left: 0;
}

ul li.alt-contained {
	--marker-size: 10rem;
	--marker-gap: var(--s3);
	--marker-inset: var(--s4);
	/* Vertically centres the dot on the first line: padding-top plus half the
	 * leftover of a 1.7 line box. */
	--marker-top: 10rem;

	position: relative;
	padding: var(--s2) var(--s4);
	padding-inline-start: calc(var(--marker-inset) + var(--marker-size) + var(--marker-gap));
	background-color: var(--color-pearl-100);
	border-radius: var(--s1);
	color: var(--color-black-300, #555555);
	line-height: 1.7;
	letter-spacing: 0.18rem;
	list-style: none;
}

ul li.alt-contained::before {
	content: "";
	position: absolute;
	inset-inline-start: var(--marker-inset);
	top: calc(var(--s2) + var(--marker-top));
	width: var(--marker-size);
	height: var(--marker-size);
	border-radius: 50%;
	background-color: var(--color-red-200-base);
}

/*
 * "Checkmark" list-item format — the same chip layout as .alt-contained with a
 * white chip and the checkmark icon for a marker. Same out-of-flow marker for
 * the same reason (see MARKER LAYOUT above): same authoring surface, so the
 * flex bug would apply here just as much.
 */

ul:has(>li.alt-checkmark) {
	padding-left: 0;
}

ul:has(>li.alt-checkmark.alt-transparent) {
	gap: var(--s0);
}

ul li.alt-checkmark {
	--marker-size: var(--s4);
	--marker-gap: var(--s3);
	--marker-inset: var(--s4);
	--marker-top: 3rem;

	position: relative;
	padding: var(--s2) var(--s4);
	padding-inline-start: calc(var(--marker-inset) + var(--marker-size) + var(--marker-gap));
	background-color: var(--color-white);
	border-radius: var(--s1);
	color: var(--color-black-300, #555555);
	line-height: 1.7;
	letter-spacing: 0.18rem;
	list-style: none;
}

/* The `padding` shorthand resets padding-inline-start, so any rule that
 * restates it has to restate the marker allowance too. */
ul li.alt-checkmark.alt-transparent {
	--marker-inset: var(--s3);
	padding: var(--s2) var(--s3);
	padding-inline-start: calc(var(--marker-inset) + var(--marker-size) + var(--marker-gap));
}

ul li.alt-checkmark::before {
	content: "";
	position: absolute;
	inset-inline-start: var(--marker-inset);
	top: calc(var(--s2) + var(--marker-top));
	width: var(--marker-size);
	height: var(--marker-size);
	background-image: url(assets/images/icon-checkmark.svg);
	background-size: contain;
	background-repeat: no-repeat;
	border-radius: 100%;
}

ul li.alt-checkmark.alt-dark {
	background-color: var(--color-pearl-100);
}

ul li.alt-checkmark.alt-transparent {
	background-color: transparent;
}

ul li.alt-checkmark.alt-transparent::before {
	background-image: url(assets/images/icon-checkmark--white.svg);
}

ul li:is(.alt-checkmark, .alt-checkmark):not(:last-child) {
	margin-bottom: var(--s2);
}

ul li.alt-checkmark.alt-transparent:not(:first-child) {
	margin-top: var(--s0);
}

ul li.alt-checkmark.alt-transparent:not(:last-child) {
	margin-bottom: var(--s0);
}

/*
 * `alt-list-compact` — opt-in, for a WYSIWYG checkmark list that must line up
 * with the Card widget's own icon-list rows (a hand-built container sitting in a
 * row of real icon-list card widgets). Adopts that widget's geometry exactly:
 * see widgets/card/style.css's `.redteam-card__list` / `__list-item` /
 * `__list-icon` — 24 icon, --s1 icon→text, --s1 between rows, no padding.
 *
 * Those numbers don't change at <=960px there, so they don't here either —
 * hence `:root:root` (0-4-2), which also stops the checkmark block's own mobile
 * padding override winning it back. Every other checkmark list keeps its
 * roomier chip spacing.
 */
:root:root .alt-list-compact ul li.alt-checkmark {
	--marker-gap: var(--s1);
	--marker-inset: var(--s0);
	padding: 0;
	padding-inline-start: calc(var(--marker-inset) + var(--marker-size) + var(--marker-gap));
}

:root:root .alt-list-compact ul li.alt-checkmark::before {
	top: 2rem;
}

:root:root .alt-list-compact ul li.alt-checkmark:not(:last-child) {
	margin-bottom: var(--s1);
}


@media (width <=960px) {
	/* The mobile bar is shorter (~78rem), so the desktop gap reads as too much here. */
	html {
		--nav-height: 78rem;
		scroll-padding-top: calc(var(--nav-height) + var(--s3));
	}

	:root:root body {
		font-size: var(--font-text-size-tablet, 16rem);
	}

	:root:root h1,
	:root:root .b-h1 {
		font-size: var(--font-h1-size-tablet, 40rem);
	}

	:root:root h2,
	:root:root .b-h2 {
		font-size: var(--font-h2-size-tablet, 28rem);
	}

	:root:root h3,
	:root:root .b-h3 {
		font-size: var(--font-h3-size-tablet, 24rem);
	}

	:root:root h4,
	:root:root .b-h4 {
		font-size: var(--font-h4-size-tablet, 20rem);
	}

	:root:root h5,
	:root:root .b-h5 {
		font-size: var(--font-h5-size-tablet, 18rem);
	}

	:root:root h6,
	:root:root .b-h6 {
		font-size: var(--font-h6-size-tablet, 16rem);
	}

	:root:root .b-text-stats {
		font-size: var(--font-stats-size-tablet, 62rem);
	}

	:root:root .b-text-large {
		font-size: var(--font-body-large-size-tablet, 18rem);
	}

	:root:root .b-text-small {
		font-size: var(--font-body-small-size-tablet, 14rem);
	}

	:root:root :is(.b-text-eyebrow-light, .b-text-eyebrow-dark) {
		font-size: var(--font-text-size-tablet, 16rem);
	}

	:root:root :is(h1, h2, h3, h4, h5, h6, p) br,
	:root:root .elementor-widget-text-editor br,
	:root:root .elementor-widget-heading br {
		display: none !important;
	}
}



/* BASIC TAGS */

p {
	margin: var(--ps) 0;
}

ul,
ol {
	margin: var(--ps) 0;
	padding: 0 0 0 1em;
}

li ul,
li ol {
	margin-top: 0;
}

li {
	margin: calc(var(--ps) / 2) 0;
}

strong,
b {
	font-weight: 700;
}

em,
i {
	font-style: italic;
}

img,
svg {
	border: none;
}

blockquote {
	position: relative;
	background: var(--light-grey);
	margin: var(--s7) 0;
	padding: var(--s7);
}

/*
 * "Minimal" blockquote format (functions.php's Formats dropdown): no card
 * background, a left red rule, Body Large typography. The format also stamps
 * .b-text-large, so only the treatments that class doesn't cover belong here.
 */
blockquote.alt-minimal {
	background: none;
	padding: 0 var(--s6);
	border-left: 1rem solid var(--color-red-200-base);
	color: var(--color-black-300);
}

hr {
	margin: var(--s7) 0;
	padding: 0;
	background: none;
	border: none;
	border-bottom: 1rem solid var(--dark-grey);
}

table {
	margin: var(--s5) 0;
	width: 100%;
	border-spacing: 0;
	border-collapse: collapse;
}

table td {
	padding: 4rem;
	border: 1rem solid var(--light-grey);
	border-width: 1rem 0;
}

iframe {
	margin: var(--s5) 0;
	width: 100%;
	border: none;
	overflow: auto;
	display: block;
}

nav ul {
	margin: 0;
	padding: 0;
	list-style: none;
}

article,
aside,
footer,
header,
main,
section {
	display: block;
}

@media (width <=960px) {
	blockquote {
		margin: var(--s5) 0;
		padding: var(--s3);
	}

	blockquote.alt-minimal {
		padding: 0 var(--s4);
	}

	hr {
		margin: var(--s5) 0;
	}

	/* No bullet at this breakpoint, so the shorthand's plain var(--s2) inline
	 * start is right — it also resets the desktop rule's marker allowance. */
	ul li.alt-contained {
		padding: var(--s2) var(--s2);
	}

	ul li.alt-contained::before {
		display: none;
	}

	/* The checkmark DOES still show, so its allowance has to be restated after
	 * the shorthand. --marker-gap replaces what used to be the flex `gap`. */
	ul li.alt-checkmark {
		--marker-gap: var(--s2);
		--marker-inset: var(--s2);
		--marker-top: 1rem;
		padding: var(--s2);
		padding-inline-start: calc(var(--marker-inset) + var(--marker-size) + var(--marker-gap));
	}

	html {
		--spacer-small: var(--s4);
		--spacer-medium: var(--s4);
		--spacer-large: var(--s5);
		--spacer-xlarge: var(--s7);
		--spacer-xxlarge: var(--s7);
	}
}


a {
	background-color: transparent;
}

button,
input,
optgroup,
select,
textarea {
	font: inherit;
}



/* MARGIN OVERWRITES */

h1:first-child,
h2:first-child,
h3:first-child,
h4:first-child,
h5:first-child,
h6:first-child,
p:first-child,
ul:first-child,
ol:first-child,
li:first-child,
hr:first-child,
blockquote:first-child,
table:first-child,
iframe:first-child {
	margin-top: 0 !important;
}

h1:last-child,
h2:last-child,
h3:last-child,
h4:last-child,
h5:last-child,
h6:last-child,
p:last-child,
ul:last-child,
ol:last-child,
li:last-child,
hr:last-child,
blockquote:last-child,
table:last-child,
iframe:last-child {
	margin-bottom: 0 !important;
}



.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.screen-reader-text:focus {
	position: fixed;
	top: 0.5rem;
	left: 0.5rem;
	z-index: 100000;
	width: auto;
	height: auto;
	padding: 0.75rem 1rem;
	margin: 0;
	overflow: visible;
	clip: auto;
	white-space: normal;
	background: #000;
	color: #fff;
}



/* --------------------------------------------------------------------------
 * ARROW LINK (shared component) — one "text + red triangle" treatment for every
 * consumer: the Button widget's Link variant, the Card widget's Numbered and
 * Login links, the Pricing Calculator's "Contact sales" row link and its CTA /
 * Start Over buttons, and `.alt-arrow-link` for a bare <a> in a WYSIWYG. A new
 * consumer opts in by adding its selector to the rules below; each still owns
 * its own layout (gap, box reset, native icon colours).
 *
 * COLOUR IS KEYED TO THE SURFACE, not to the widget, via two custom properties
 * rather than per-variant selector lists:
 *
 *   --redteam-card-fg          rest colour and arrow fill; defaults to
 *                              walnut-400 text with a red arrow.
 *   --redteam-arrow-link-hover hover colour; defaults to red.
 *
 * A dark surface therefore declares --redteam-card-fg and nothing else — the
 * Card widget's dark background tokens do this (widgets/card/style.css), as does
 * `.alt-on-dark` below, so adding a dark token fixes its links for free.
 *
 * The hover is RED on every light surface and does not vary by widget, which is
 * why the hover selector is `.redteam-card__link` unqualified: a link shouldn't
 * lose its hover because its card uses a different layout.
 * --redteam-arrow-link-hover is the escape hatch for a surface where red cannot
 * work (a red-200 card); don't reach for it otherwise.
 *
 * The Pricing Calculator's row link stays out of the hover rule — it needs a
 * light-surface hover and sets its own with !important in that widget's sheet.
 * -------------------------------------------------------------------------- */

/* Icon shape — shared with Button's primary/secondary/tertiary "arrow" toggle,
 * which keeps the currentColor default; Link + Card override it to red below. */
.elementor-widget-button:is(.redteam-button--primary, .redteam-button--secondary, .redteam-button--tertiary, .redteam-button--link).redteam-button-arrow--yes .elementor-button-content-wrapper::after,
:is(.redteam-card--numbered, .redteam-card--login) .redteam-card__link::before,
.redteam-pricing-calculator__row-link::after,
.redteam-pricing-calculator__start-over::after,
.alt-arrow-link::after {
	content: "";
	display: block;
	mask: var(--icon-arrow-right);
	mask-repeat: no-repeat;
	mask-position: right center;
	width: 9rem;
	height: 10rem;
	background-color: currentColor;
	transition: background-color 0.3s;
}

/* Red on a light surface, but a red arrow on a red card is invisible, so dark
 * card tokens repoint it via --redteam-card-fg (undefined outside a card, so
 * the fallback stands). */
.elementor-widget-button.redteam-button--link.redteam-button-arrow--yes .elementor-button-content-wrapper::after,
:is(.redteam-card--numbered, .redteam-card--login) .redteam-card__link::before,
.redteam-pricing-calculator__row-link::after,
.alt-arrow-link::after {
	background-color: var(--redteam-card-fg, var(--color-red-200-base));
}

.elementor-widget-button.redteam-button--link.redteam-button-arrow--yes .elementor-button-text,
:is(.redteam-card--numbered, .redteam-card--login) .redteam-card__link,
.redteam-pricing-calculator .redteam-pricing-calculator__row-link {
	text-decoration: underline;
}

/* The `!important` beats the Kit's bare `a`, but it also out-ranks the card
 * widget's own 0-3-0 dark-token repaint — which is why the colour has to route
 * through --redteam-card-fg rather than a competing rule. */
.elementor-widget-button.redteam-button--link .elementor-button,
:is(.redteam-card--numbered, .redteam-card--login) .redteam-card__link,
.redteam-pricing-calculator__row-link {
	color: var(--redteam-card-fg, var(--color-walnut-400)) !important;
}

/* Every arrow link, standalone or inside a card — unqualified by variant. */
.elementor-widget-button.redteam-button--link .elementor-button:is(:hover, :focus),
.redteam-card__link:is(:hover, :focus) {
	color: var(--redteam-arrow-link-hover, var(--color-red-200-base)) !important;
}

/* Arrow follows the label: a no-op on a light surface (already red at rest);
 * on a dark card both go white together. */
.elementor-widget-button.redteam-button--link.redteam-button-arrow--yes .elementor-button:is(:hover, :focus) .elementor-button-content-wrapper::after,
:is(.redteam-card--numbered, .redteam-card--login) .redteam-card__link:is(:hover, :focus)::before,
a.alt-arrow-link:is(:hover, :focus)::after {
	background-color: currentColor;
}

/*
 * `alt-arrow-link` — the same treatment for a bare <a> authored in a WYSIWYG,
 * which none of the widget-markup selectors above can reach. Add the class to
 * the link in the text editor.
 *
 * The Kit emits `.elementor-kit-<id> a { text-decoration: none }` at 0-1-1 in a
 * stylesheet loaded AFTER this file, so `a.alt-arrow-link` would merely TIE it
 * and lose on source order. `:root:root` lifts it to 0-3-1 — no !important.
 */
:root:root a.alt-arrow-link {
	display: inline-flex;
	align-items: center;
	gap: var(--s1);
	color: var(--redteam-card-fg, var(--color-walnut-400));
	text-decoration: underline;
	transition: color 0.3s;
}

:root:root a.alt-arrow-link:is(:hover, :focus) {
	color: var(--redteam-arrow-link-hover, var(--color-red-200-base));
}

/*
 * Surface opt-in: flips the arrow link's REST colour to white. Put it on the
 * widget (Advanced > CSS Classes) when the link sits on a dark photo or panel.
 * The hover is left alone, so it stays the site's red like every other one.
 */
.alt-on-dark {
	--redteam-card-fg: var(--color-white);
}

/*
 * Plain WYSIWYG link — any <a> authored inside a Text Editor widget's body copy
 * (e.g. the accordion items on the homepage) that ISN'T opted into
 * `.alt-arrow-link`. Reuses the same --redteam-card-fg / --redteam-arrow-link-hover
 * tokens as ARROW LINK so it stays in step with whatever surface it's on, but
 * skips the arrow: this link sits inline within a sentence, and an arrow glyph
 * mid-paragraph would read as a stray bullet rather than a link affordance.
 */
:root:root .elementor-widget-text-editor a:not(.alt-arrow-link) {
	color: var(--redteam-card-fg, var(--color-walnut-400));
	text-decoration: underline;
	transition: color 0.3s;
}

:root:root .elementor-widget-text-editor a:not(.alt-arrow-link):is(:hover, :focus) {
	color: var(--redteam-arrow-link-hover, var(--color-red-200-base));
}



/* --------------------------------------------------------------------------
 * HUBSPOT FORMS (shared component) — every HubSpot form on the site is a Raw
 * HTML embed, which ships with ZERO CSS of its own, so this section is the only
 * styling any of them get. Selectors target HubSpot's own generated classes
 * (.hs-form, .hs-form-field, .hs-input, …), which are the same across every
 * portal and form, so a new embed anywhere on the site is styled automatically.
 *
 * STYLE is global (this section); LAYOUT is not. The card shell, the 2-column
 * grid and full-width-by-default fields are safe to assume for any form, but
 * WHICH fields sit side by side is a property of one form's field set — that
 * lives in a per-form "<NAME> FORM LAYOUT" block below, scoped to a CSS class
 * added to the Elementor widget holding the embed. The `fieldset.form-columns-*`
 * rule stays global: it is driven by HubSpot's own column configuration.
 *
 * Two colours in the design (label/consent text, placeholder text) match no Kit
 * global, so they are local custom properties — same convention as
 * widgets/pricing-comparison/.
 * -------------------------------------------------------------------------- */

.hs-form {
	--redteam-hs-form-text: #2b1818;
	--redteam-hs-form-placeholder: #726565;

	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: var(--s3);
	width: 100%;
	max-width: 592rem;
	padding: var(--s5);
	background-color: var(--color-white);
	border-radius: var(--s1);
}

/* Full width by default — every field, the submit row and the consent container
 * take the whole grid unless a per-form layout below (or a HubSpot fieldset,
 * which places its own children) says otherwise. */
.hs-form>* {
	grid-column: 1 / -1;
	min-width: 0;
}

.hs-form fieldset {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: var(--s3);
	margin: 0;
	padding: 0;
	border: none;
}

.hs-form fieldset.form-columns-1 {
	grid-template-columns: 1fr;
}

.hs-form fieldset.form-columns-3 {
	grid-template-columns: repeat(3, 1fr);
}

@media (width <=960px) {
	.hs-form fieldset {
		grid-template-columns: 1fr;
	}
}

.hs-form-field {
	display: flex;
	flex-direction: column;
	gap: var(--s1);
}

.hs-form-field label {
	font-family: var(--font-body-small, 'Archivo'), sans-serif;
	font-weight: var(--font-body-small-weight, 400);
	font-size: var(--font-body-small-size, 16rem);
	line-height: var(--font-body-small-line-height, 1.3);
	color: var(--redteam-hs-form-text);
}

.hs-form-field .input {
	display: block;
	width: 100%;
}

.hs-form input.hs-input:not([type="checkbox"]):not([type="radio"]),
.hs-form select.hs-input,
.hs-form textarea.hs-input {
	display: block;
	width: 100%;
	padding: var(--s1) var(--s3);
	font-family: var(--font-body-small, 'Archivo'), sans-serif;
	font-weight: var(--font-body-small-weight, 400);
	font-size: var(--font-body-small-size, 16rem);
	line-height: var(--font-body-small-line-height, 1.3);
	color: var(--redteam-hs-form-text);
	background-color: var(--color-white);
	border: 1rem solid var(--color-pearl-400);
	border-radius: var(--s1);
	transition: border-color 0.3s;
}

.hs-form input.hs-input:not([type="checkbox"]):not([type="radio"]),
.hs-form select.hs-input {
	height: var(--s6);
}

.hs-form textarea.hs-input {
	min-height: 228rem;
	resize: vertical;
}

.hs-form .hs-input::placeholder {
	color: var(--redteam-hs-form-placeholder);
}

.hs-form .hs-input:focus {
	outline: none;
	/* !important: the base rule's :not([type="checkbox"]):not([type="radio"]) clauses give
	 * text/email/tel/select inputs higher specificity than this selector. */
	border-color: var(--color-red-200-base) !important;
}

/* Error messages are hidden rather than shown below the field — the field
 * turning red (below) is the only error indicator, so a failed validation
 * never adds extra height/reflows the form. */
.hs-form .hs-error-msgs {
	display: none;
}

/* HubSpot's default `errorClass` is `.invalid.error` on the input itself.
 * !important for the same specificity reason as the `:focus` rule above. */
.hs-form .hs-input.invalid.error {
	border-color: var(--color-red-200-base) !important;
}

/* Consent/legal checkbox — HubSpot renders no styling of its own here, so this
 * replaces the native checkbox entirely (background-image checkmark, the same
 * asset the "checkmark" list format uses). The :has() row layout is
 * deliberately generic: HubSpot's exact wrapper class around a checkbox+label
 * pair has changed across form versions, so this targets ANY .hs-form-field
 * containing a checkbox.
 *
 * UNVERIFIED against live markup — no form on the site currently has a consent
 * field. Re-check this block once one does. */
.hs-form-field:has(input[type="checkbox"].hs-input),
.legal-consent-container .hs-form-booleancheckbox-display,
.legal-consent-container .hs-richtext {
	display: flex;
	flex-direction: row;
	align-items: flex-start;
	gap: var(--s2);
}

.hs-form-field:has(input[type="checkbox"].hs-input) label,
.legal-consent-container label,
.legal-consent-container p {
	font-family: var(--font-body-small, 'Archivo'), sans-serif;
	font-weight: var(--font-body-small-weight, 400);
	font-size: var(--font-body-small-size, 16rem);
	line-height: var(--font-body-small-line-height, 1.3);
	color: var(--redteam-hs-form-text);
	margin: 0;
}

.hs-form input[type="checkbox"].hs-input {
	appearance: none;
	flex-shrink: 0;
	width: 21rem;
	height: 21rem;
	margin: 0;
	background-color: var(--color-white);
	background-repeat: no-repeat;
	background-position: center;
	border: 1rem solid var(--color-pearl-400);
	border-radius: 2rem;
	cursor: pointer;
	transition: background-color 0.3s, border-color 0.3s;
}

.hs-form input[type="checkbox"].hs-input:checked {
	background-color: var(--color-red-200-base);
	background-image: url(assets/images/icon-checkmark--white.svg);
	background-size: 14rem;
	border-color: var(--color-red-200-base);
}

.hs-form>.legal-consent-container,
.hs-form>.hs_submit,
.hbspt-form>.legal-consent-container {
	margin-top: var(--s3);
}

/* Submit button — the Button widget's Primary variant restated for HubSpot's
 * plain <input type="submit">. Being a replaced element it can't take a ::after
 * icon like the other Primary restatements do, so the arrow is a background
 * image with its fill baked in (an <input> gives a mask no `currentColor`
 * context, only the one known button colour).
 *
 * !important on the font, background-color and padding properties: the Kit's
 * "Theme Style > Buttons" rule (`.elementor-kit-<id> input[type="submit"]`)
 * ties this selector's specificity exactly and loads after this file, so it
 * would win those properties on source order. Same reasoning as
 * extensions/button/style.css's !importants beating Style-tab overrides.
 *
 * `appearance: none` is also required — an <input type="submit"> keeps native
 * OS button chrome that can ignore authored padding and background.
 */
.hs-form .hs_submit .actions {
	display: flex;
}

.hs-form input.hs-button {
	appearance: none;
	display: inline-block;
	padding: var(--s3) calc(var(--s4) + 9rem + var(--s2)) var(--s3) var(--s4) !important;
	font-family: var(--font-body-small, 'Archivo'), sans-serif !important;
	font-weight: var(--font-body-small-weight, 400) !important;
	font-size: var(--font-body-small-size, 16rem) !important;
	line-height: var(--font-body-small-line-height, 1.3) !important;
	color: var(--color-white-200-base, #FFFFFD);
	background-color: var(--color-red-200-base) !important;
	background-image: url("data:image/svg+xml,%3Csvg width='9' height='10' viewBox='0 0 9 10' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8.26558 4.64868L0 9.29883L-4.06462e-07 5.14984e-05L8.26558 4.64868Z' fill='%23FFFFFD'/%3E%3C/svg%3E%0A");
	background-repeat: no-repeat;
	background-position: right var(--s4) center;
	background-size: 9rem 10rem;
	border: none;
	border-radius: var(--s05);
	cursor: pointer;
	transition: background-color 0.3s, color 0.3s;
}

.hs-form input.hs-button:hover,
.hs-form input.hs-button:focus {
	background-color: var(--color-red-500) !important;
	color: var(--color-pearl-200-base);
}

@media (width <=960px) {
	.hs-form {
		padding: var(--s4);
	}
}



/* --------------------------------------------------------------------------
 * CONTACT US FORM LAYOUT — this form pairs Name, then Email+Phone. Scoped to a
 * `CONTACT-FORM` class rather than to `.hs-form`, so no other embed inherits
 * one form's field pairing.
 *
 * HubSpot's markup can't carry that class (it is a Raw HTML embed we don't
 * author), so it goes on the Elementor widget/container HOLDING the embed:
 * select it → Advanced → CSS Classes → add `CONTACT-FORM`. That makes these
 * DESCENDANT selectors, since the class sits several levels above the .hs-form
 * HubSpot renders, at a depth that varies by embed type.
 *
 * `CONTACT-FORM` is all-caps and hyphenated because class selectors are
 * case-sensitive and that is exactly how it was entered in Elementor — a
 * deliberate break from the theme's lowercase `redteam-` convention.
 *
 * The fields are plain siblings (no HubSpot fieldset), so pairing is by field
 * name: with the grid's row-by-row auto-flow, `grid-column: span 1` on these
 * four is enough — firstname/lastname land in one row, email/phone the next.
 * Reuse the class on any embed with the same field names.
 * -------------------------------------------------------------------------- */

.CONTACT-FORM .hs-form> :is(.hs_firstname, .hs_lastname, .hs_email, .hs_phone) {
	grid-column: span 1;
}

@media (width <=960px) {
	.CONTACT-FORM .hs-form> :is(.hs_firstname, .hs_lastname, .hs_email, .hs_phone) {
		grid-column: 1 / -1;
	}
}



/* --------------------------------------------------------------------------
 * BOOK A DEMO FORM LAYOUT — same pattern as CONTACT-FORM above; this form pairs
 * Name only, with Business Email / Company Name / Country each full width.
 * Scoped to `DEMO-FORM`, added to this embed's Elementor widget.
 * -------------------------------------------------------------------------- */

.DEMO-FORM .hs-form> :is(.hs_firstname, .hs_lastname) {
	grid-column: span 1;
}

@media (width <=960px) {
	.DEMO-FORM .hs-form> :is(.hs_firstname, .hs_lastname) {
		grid-column: 1 / -1;
	}
}



/* --------------------------------------------------------------------------
 * CTA DEMO FORM LAYOUT — same pattern as the two blocks above (Name paired,
 * everything else full width), scoped to `CTA-DEMO-FORM`. Used by the Pricing
 * Calculator's results CTA, whose live embed renders HubSpot's standard
 * .hs_firstname / .hs_lastname / .hs_email / .hs_company / .hs_phone.
 *
 * This is the only form with a masked background, so the mask lives here rather
 * than as a global `.hs-form` change. Same mask-driven-shape idiom as card/'s
 * notches: assets/masks/mask-cta-form.svg is a rounded rect plus a lower-left
 * extension, leaving a diagonal gap at the bottom-right for the page background
 * to show through. Desktop only — `mask-image: none` at <=960px, where the card
 * falls back to the global plain white background and radius.
 *
 * NO `aspect-ratio` on the box, deliberately: this form's height is
 * field-count-driven. aspect-ratio sets a PREFERRED height from the width,
 * which per spec becomes a FLOOR once the content is shorter — so removing a
 * field left the box at its old height with dead space inside the mask. With
 * height auto the box hugs its fields and the mask re-fits on every render, at
 * the cost of the notch's diagonal shifting slightly as the field count moves
 * the box away from the asset's own 726x568 ratio. Re-verify the notch if this
 * form's fields change.
 *
 * `align-content: start` for the same reason: Grid's default `normal` stretches
 * auto-sized row tracks to fill leftover block-axis space, which would inflate
 * the gaps between fields whenever the grid has slack.
 * -------------------------------------------------------------------------- */

.CTA-DEMO-FORM .hs-form {
	max-width: 726rem;
	align-content: start;
	mask-image: url(assets/masks/mask-cta-form.svg);
	mask-repeat: no-repeat;
	mask-size: cover;
	mask-position: bottom left;
}

.CTA-DEMO-FORM .hs-form> :is(.hs_firstname, .hs_lastname) {
	grid-column: span 1;
}

@media (width <=960px) {
	.CTA-DEMO-FORM .hs-form> :is(.hs_firstname, .hs_lastname) {
		grid-column: 1 / -1;
	}

	.CTA-DEMO-FORM .hs-form {
		mask-image: none;
	}
}



/* --------------------------------------------------------------------------
 * CTA DEMO FORM — OTHER EMBED. HubSpot's non-raw-HTML embed renders the form
 * inside a cross-origin iframe, so this document never gets a `.hs-form` to
 * style — CTA-DEMO-FORM's mask and field-pairing rules above have nothing to
 * reach. The wrapper itself stands in as the card instead: the same white
 * background, `--s5` padding and `--s1` radius the raw-HTML variant gets for
 * free from the global `.hs-form` rule, with no mask — there's no matching
 * cut-corner asset for this embed's shape.
 * -------------------------------------------------------------------------- */

.CTA-DEMO-FORM-EMBED {
	padding: var(--s5);
	background-color: var(--color-white);
	border-radius: var(--s1);
}



/* --------------------------------------------------------------------------
 * GLOBAL NAV — MOBILE
 *
 * The global header is an Elementor Pro Mega Menu (`n-menu`) inside a container
 * carrying a hand-added `NAV` CSS class (Advanced > CSS Classes). THAT CLASS IS
 * THE ENTIRE CONTRACT this section depends on — remove it and every rule below
 * goes dark. Elementor's widget controls can't style a widget's mobile rendering
 * independently of desktop, which is why this lives in CSS at all.
 *
 * Desktop is untouched: everything is inside `@media (width <= 960px)`, which is
 * both the theme's own breakpoint and the Mega Menu's configured
 * `breakpoint_selector: tablet`, so the native hamburger toggle already appears
 * there. Below it the root font-size returns to 1px, so every `rem` here is
 * literally the design's px measurement.
 *
 * SPECIFICITY: `.NAV` appears ONCE per selector. Weight comes from qualifiers
 * that are genuinely true of the target — the container classes it carries
 * (`.e-con`, `.e-parent`, `.e-con-full`), the widget wrapper it lives in
 * (`.elementor-widget-n-menu`, `.elementor-widget-image`), real `>` relations, or
 * the attribute Elementor's own selector uses (`.e-n-menu[data-layout=
 * "dropdown"]`). Where a rule overrides an Elementor rule it MIRRORS that rule's
 * selector shape, so winning the cascade and documenting what is being beaten are
 * the same act. Two Elementor rules are out-specified this way, both loaded AFTER
 * this file — so a tie is not enough:
 *
 *   0-3-0  the per-instance `.elementor-<page> .elementor-element.elementor-
 *          element-<id>` rule, baked into a per-post CSS file
 *   0-4-0  Elementor Pro's mega-menu rules of the same shape, in
 *          widget-mega-menu.min.css
 *
 * Per the theme's STYLING RULE, padding/gap/wrap/width are driven through
 * Elementor's own container custom properties (`--padding-*`, `--row-gap` /
 * `--column-gap`, `--flex-wrap`, `--justify-content`, `--width`, `--display`)
 * rather than physical properties, so the native
 * pipeline keeps doing the work. `.e-con` derives its `--padding-inline-*` /
 * `--padding-block-*` from the four physical `--padding-*` vars, so those four
 * are the correct entry point.
 *
 * The design's `backdrop-filter: blur(15.625px)` on the bar is deliberately
 * omitted — the bar's background is fully opaque white, so it would be a no-op.
 * -------------------------------------------------------------------------- */

/* MOBILE LOGIN ROW — a plain top-level item in the Mega Menu's own `menu_items`
 * repeater (Title "Login", Link /login, Dropdown Content off), NOT the standalone
 * Login Button widget desktop uses: that widget is a sibling outside the menu's
 * DOM subtree, so CSS alone can't move it into the dropdown panel. Set that
 * repeater row's CSS ID field to the id below and it renders as
 * `<div id="…" class="e-n-menu-title">`; the id beats every class selector here,
 * so nothing below needs !important.
 *
 * It is a real top-level item, so it would also render in the DESKTOP bar —
 * hidden by this rule, which sits outside the media query on purpose. */
.NAV #nav-login-mobile {
	display: none;
}

@media (width <=960px) {

	/* ---------- CLOSED BAR ---------- */

	/* Wrapper: `--s2` padding all round. 0-4-0 via the container's own
	 * `.e-con.e-parent` classes plus the template-location ancestor Elementor
	 * always renders the header inside, which beats the per-instance 0-3-0 rule. */
	.elementor-location-header .NAV.e-con.e-parent {
		--padding-top: var(--s2);
		--padding-right: var(--s2);
		--padding-bottom: var(--s2);
		--padding-left: var(--s2);
	}

	/* The bar itself (the flex row holding logo / CTA / toggle). `nowrap` is
	 * load-bearing: without it the three items wrap at real content widths.
	 * `.e-con-full` is the qualifier that reaches 0-4-0. */
	.NAV>.e-con-inner>.e-con.e-con-full {
		--padding-top: var(--s1);
		--padding-right: var(--s1);
		--padding-bottom: var(--s1);
		--padding-left: var(--s2);
		--justify-content: flex-start;
		--row-gap: var(--s1);
		--column-gap: var(--s1);
		--flex-wrap: nowrap;
	}

	/* Logo: shrink rather than wrap or overflow the row, and push everything
	 * after it to the right edge. */
	.NAV .elementor-widget-theme-site-logo {
		flex: 0 1 auto;
		min-width: 0;
		margin-right: auto;
	}

	/* Logo image: `max-height`/`max-width` rather than a fixed `height`, as
	 * deliberate graceful degradation. The design's row only fits at the full
	 * 24rem logo height with a short CTA label; this site's longer label overruns
	 * it, so the logo scales down proportionally (width and height both auto,
	 * capped by max-*, never distorted) instead of blowing out the viewport.
	 *
	 * `.elementor-widget-image a img` (0-3-2) beats the per-instance
	 * `… .elementor-element-<id> img` rule (0-3-1) on element count. */
	.NAV .elementor-widget-theme-site-logo.elementor-widget-image a img {
		display: block;
		width: auto;
		height: auto;
		max-width: 100%;
		max-height: var(--s4);
	}

	/* The two inner containers (the CTA's own wrapper and the mega-menu's own
 * wrapper) shouldn't stretch to fill the row — each should size to its own
 * content and sit in the flex row like a normal item. */
	.NAV>.e-con-inner>.e-con>.e-con {
		display: var(--display);
		--width: auto;
		flex: 0 0 auto;
	}

	/* The mobile design shows only ONE button in the header — the primary CTA
 * — not the Login link that also renders on desktop, so Login is simply
 * hidden at this breakpoint rather than restyled. */
	.NAV .elementor-widget-button.redteam-button--login {
		display: none;
	}

	/* CTA button: `10rem`/`14rem` padding and `14rem` font-size are literal
 * values, not tokens — no spacing or type token on the scale matches them.
 * The Kit's Body Small is 16rem, which would render the button 41rem tall
 * against the design's 38rem and push the whole bar to 57rem instead of
 * 54rem. Same convention as `widgets/pricing-comparison/`'s off-scale
 * `--redteam-pricing-comparison-value-size: 14rem`. */
	.NAV .elementor-widget-button.redteam-button--primary .elementor-button {
		padding: 10rem var(--s2) 10rem 14rem !important;
		font-size: 14rem !important;
	}

	.NAV .elementor-widget-button.redteam-button--primary .elementor-button-content-wrapper {
		gap: var(--s1);
	}

	.NAV .elementor-widget-button.redteam-button--primary .elementor-button-content-wrapper::after {
		width: 6rem;
		height: 7rem;
	}

	/* Elementor's own responsive-visibility classes (`elementor-hidden-mobile` /
 * `elementor-hidden-tablet`, 0-2-0, no `!important`) hide the CTA's
 * container at this breakpoint by default — but the mobile design DOES show
 * the primary CTA, so it's revealed here with a higher-specificity
 * `display: var(--display)` (see the `.e-con > .e-con` rule above, which is
 * what actually supplies that var). `--width: auto` on that same rule stops
 * the now-visible container stretching to the bar's full width, since
 * `.e-con`'s own default is `--width: 100%`.
 *
 * DOM order is logo → mega-menu → CTA, but the Figma source order is
 * logo → CTA → hamburger, so the mega-menu widget is pulled to the end of
 * the row with `order: 1` rather than reordering the CTA — the CTA stays in
 * document order right after the logo, and `margin-right: auto` on the logo
 * (above) is what pushes the CTA + toggle pair over to the right edge.
 *
 * `position: static` on the widget wrapper (and on `.e-n-menu` in the next
 * rule) is what re-parents the dropdown panel's containing block — see the
 * `.e-n-menu-wrapper` rule below in OPEN MENU for the full reasoning; it's
 * set here rather than duplicated because it's a property of this same
 * widget wrapper element, not a separate concern. */
	.NAV .elementor-widget-n-menu {
		order: 1;
		flex: 0 0 auto;
		position: static;
		--n-menu-toggle-icon-size: 24rem;
	}

	/* Elementor's `.elementor-widget-n-menu .e-n-menu { position: relative }` is
 * 0-2-0, so the old `.NAV .e-n-menu` (also 0-2-0) tied and lost on source
 * order — leaving the dropdown panel anchored to the 42x34 toggle instead of
 * the bar (measured: the open menu rendered 42px wide). Qualifying with the
 * widget wrapper reaches 0-3-0 and wins. */
	.NAV .elementor-widget-n-menu .e-n-menu {
		position: static;
	}

	/* Toggle hit box: 42×34 per the design, centred content, walnut-200-base to
 * match the hamburger glyph colour (the close/X glyph below inherits this
 * via currentColor too). */
	.NAV .e-n-menu .e-n-menu-toggle {
		width: 42rem;
		height: 34rem;
		justify-content: center;
		align-items: center;
		color: var(--color-walnut-200-base, #5A413D);
	}

	/* Elementor's inline <svg> for the hamburger is core markup, so it is
	 * `display: none`d rather than removed and replaced with a mask-driven icon
	 * below — the theme's usual technique: the SVG supplies alpha only,
	 * `background-color` supplies the colour. The close (X) icon is left as
	 * Elementor's own, inheriting the resized icon size and colour. */
	.NAV .e-n-menu-toggle .e-n-menu-toggle-icon.e-open svg {
		display: none;
	}

	.NAV .e-n-menu-toggle .e-n-menu-toggle-icon.e-open {
		width: 42rem;
		height: 34rem;
		mask-image: url("assets/images/icon-hamburger.svg");
		mask-size: 100% 100%;
		mask-repeat: no-repeat;
		background-color: var(--color-walnut-200-base, #5A413D);
	}

	/* ---------- OPEN MENU (dropdown panel) ---------- */
	/* INVENTED, not designed — no mobile open-menu frame exists. Assembled from
	 * three existing sources: the desktop dropdown's language (white surface,
	 * pearl group pills with a red dot, plain link lists), the mobile bar's own
	 * geometry (`--s2` gutters, `var(--s05)` radius, white), and the theme's
	 * accordion divider idiom (dashed `var(--color-black-300)`, as in
	 * extensions/nested-accordion/'s FAQ variant). Same convention as the
	 * comparison-table and pricing-comparison widgets' mobile layouts.
	 *
	 * The whole <=960px band is one tier — no separate tablet treatment. */

	/* The dropdown wrapper is absolutely positioned against `.e-n-menu`, which on
	 * mobile is just the 42x34 toggle button — so Elementor's own `top: 100%`
	 * lands the panel under the hamburger and its JS-set inline `--stretch-left` /
	 * `--stretch-width` drag it back out to viewport width. Making the widget
	 * wrapper and `.e-n-menu` `position: static` (in CLOSED BAR above) promotes
	 * the nav BAR container (already `position: relative`) to be the containing
	 * block, so plain top/left/right/width land on the bar's own edges.
	 *
	 * SPECIFICITY: mirrors Elementor Pro's own 0-4-0 selector with `.NAV`
	 * prepended (0-5-0). A tie would lose — its stylesheet loads after this one.
	 * Its inline JS-set custom properties (`--stretch-left`, `--stretch-width`,
	 * `--n-menu-dropdown-content-box-height`) can't be beaten from a stylesheet at
	 * all, which is why the physical properties are overridden instead.
	 *
	 * `max-height: calc(100dvh - 90rem)` replaces Elementor's JS-computed
	 * `--n-menu-dropdown-content-box-height`, which measures the space below the
	 * TOGGLE rather than below the repositioned panel and so overhangs the
	 * viewport. 90 is the nav bar's own height (12 + 54 + 12) plus a matching
	 * `--s2` bottom gutter, so the panel always ends one gutter above the viewport
	 * bottom and scrolls internally. `overscroll-behavior: contain` keeps that
	 * scroll from chaining to the page behind it.
	 *
	 * `overflow-y` / `overflow-x` NEED `!important`, unavoidably. Elementor Pro's
	 * rule for this exact element pairs `overflow-y: auto` with `animation:
	 * hide-scroll .3s backwards`, whose keyframes are just
	 * `{ 0%, to { overflow: hidden } }` — it exists to suppress the scrollbar
	 * while the companion max-height transition runs. An ANIMATED value outranks
	 * every normal declaration regardless of specificity, so while hide-scroll is
	 * running the wrapper isn't scrollable at ANY specificity, and it re-runs on
	 * every open and every sub-panel toggle. `overflow-x` is pinned too because
	 * hide-scroll sets the `overflow` SHORTHAND, i.e. both axes. */
	.NAV .elementor-widget-n-menu .e-n-menu[data-layout="dropdown"] .e-n-menu-wrapper {
		top: calc(100% + var(--s2));
		left: 0;
		right: 0;
		width: auto;
		max-height: calc(100dvh - 90rem);
		overflow-y: auto !important;
		overflow-x: hidden !important;
		overscroll-behavior: contain;
		background-color: var(--color-white);
		border-radius: var(--s05);
		padding: var(--s1) var(--s2);
	}

	/* Stack each group's heading row into one column. The pills are deliberately
	 * FULL-WIDTH: desktop hugs them to their text, but stacked, a text-hugged pill
	 * reads as an arbitrary width where full-width reads as a section header. */
	.NAV .elementor-widget-n-menu .e-n-menu-heading {
		flex-direction: column;
		align-items: stretch;
		gap: 0;
		width: 100%;
	}

	/* Let the item take that full width. Beats Elementor's own
	 * `… .e-n-menu-item { width: var(--stretch-width) }` (0-4-0) by mirroring its
	 * selector shape at 0-5-0 — a tie would lose on source order. */
	.NAV .elementor-widget-n-menu .e-n-menu[data-layout="dropdown"] .e-n-menu-item {
		width: 100%;
	}

	/* Dashed divider between items — the same idiom as
	 * extensions/nested-accordion/'s FAQ variant. */
	.NAV .e-n-menu-item+.e-n-menu-item {
		border-top: 1rem dashed var(--color-pearl-500);
	}

	/* Elementor's own `… .e-n-menu-title` rule sets justify-content/width/wrap at
	 * 0-4-0, so `space-between` here needs the mirrored 0-5-0 selector or the
	 * dropdown caret sits next to the label instead of at the right edge. */
	.NAV .elementor-widget-n-menu .e-n-menu[data-layout="dropdown"] .e-n-menu-title {
		padding: var(--s2) 0;
		justify-content: space-between;
	}

	.NAV .e-n-menu-title-container {
		flex-grow: 1;
	}

	/* Elementor sizes each mega-panel to the full VIEWPORT width for the desktop
	 * full-bleed dropdown, which inside the inset mobile card overflows sideways
	 * and gives the panel its own horizontal scrollbar. */
	.NAV .elementor-widget-n-menu .e-n-menu[data-layout="dropdown"] .e-n-menu-content {
		width: 100%;
	}

	/* Zero the mega-panel's own padding — it already sits inside
	 * `.e-n-menu-wrapper`'s padding above — through Elementor's own container vars
	 * per the STYLING RULE.
	 *
	 * `animation: none` + `opacity: 1` disable the container's `fadeIn` entrance
	 * animation, for a deterministic render: no redundant fade on a section
	 * already inside an opening menu, and the group-pill red dots paint
	 * immediately instead of staying unpainted. Scoped to the DIRECT child of
	 * `.e-n-menu-content` so an animation set on a container INSIDE a panel still
	 * runs.
	 *
	 * `height: auto !important` / `overflow: visible !important` fight an INLINE
	 * style: Elementor's mega-menu JS writes `height: …px; overflow-y: scroll`
	 * onto this element whenever it measures that the panel doesn't fit, which
	 * gives the open menu a SECOND scroll area nested inside
	 * `.e-n-menu-wrapper`'s. Only !important beats an inline style. The wrapper is
	 * meant to be the only scroller. */
	.NAV .elementor-widget-n-menu .e-n-menu-content>.e-con {
		--padding-top: var(--s0);
		--padding-right: var(--s0);
		--padding-bottom: var(--s0);
		--padding-left: var(--s0);
		animation: none;
		opacity: 1;
		height: auto !important;
		overflow: visible !important;
	}

	/* Group pills: Elementor emits their width as
	 * `@media(min-width:768px){ … { --width: fit-content } }` — fit-content from
	 * tablet UP with nothing set below 768px, so <=767 was already full width
	 * while 768-960 collapsed to text width. This section treats <=960 as one
	 * band, so force `--width: 100%` on every container inside an open panel
	 * across all of it (0-4-0 beats that per-instance 0-3-0 rule). It also
	 * supplies `--width` for the group card below, which is why that rule
	 * doesn't set it itself.
 * full 787. */
	.NAV .e-n-menu-content .e-con-inner .e-con {
		--width: 100%;
	}

	/* The mega-panel's desktop 3-columns-plus-media row becomes one column here
 * (`--flex-direction: column`, full width via the rule above), with `--s2`
 * bottom padding between stacked groups and the other three sides zeroed,
 * since the outer padding is already supplied by the wrapper above.
 *
 * `--row-gap: var(--s4)` separates one GROUP from the next. Measured before
 * this fix, the gap between a group's last link and the next group's pill
 * heading was 2px — on desktop the three groups are only separated by
 * column-divider spacer widgets (see below), which stacked into one column
 * reads as no separation at all. `--s4` (24) sets a clear hierarchy against
 * the rhythm already inside a group: 9 between links, `--s3` (16) between a
 * group's pill and its link list, 24 between groups. Set through Elementor's
 * own `--row-gap` custom property (which the card consumes via
 * `gap: var(--row-gap) var(--column-gap)`) per the theme's STYLING RULE,
 * not as a hard-coded `gap`. Verified: groups now sit 24 apart (group 1 ends
 * 336, group 2 starts 360). */
	.NAV .e-n-menu-content .e-con-inner>.e-con {
		--flex-direction: column;
		--padding-top: var(--s0);
		--padding-right: var(--s0);
		--padding-bottom: var(--s2);
		--padding-left: var(--s0);
		--row-gap: var(--s4);
	}

	/* Those column-divider spacers themselves: on desktop they're the mega-
 * panel's VERTICAL dividers between the 3 columns — each carries a
 * `1px dashed rgb(85,85,85)` border (the same `--color-black-300` the item
 * dividers above use) and is 0-2px tall. Stacked into one column they
 * render as meaningless 2px dashed stubs between groups, so they're hidden
 * outright here. Verified they are the ONLY spacers in every one of the
 * three dropdown panels and are always DIRECT children of the panel's card,
 * so the selector is scoped to direct children — a spacer nested INSIDE a
 * group (intentional vertical spacing an editor might add later) is
 * deliberately left alone. */
	.NAV .e-n-menu-content .e-con-inner>.e-con>.elementor-widget-spacer {
		display: none;
	}

	/* The promo video widget is a desktop-only flourish that would dominate a
	 * phone-width accordion. */
	.NAV .e-n-menu-content .elementor-widget-video {
		display: none;
	}

	/* The "Login" menu item — turn its plain link row into a bordered button.
	 * Resets the outer item's own padding (the `.e-n-menu-title` rule above
	 * otherwise applies it) and takes a plain gap in place of the dashed divider
	 * every other item gets. */
	.NAV #nav-login-mobile {
		display: flex;
		padding: 0;
		margin-top: var(--s4);
	}

	.NAV .e-n-menu-item:has(#nav-login-mobile) {
		border-top: none;
	}

	/* The button box lives on the real `<a>` (`.e-n-menu-title-container`), not the
	 * outer item div. The id alone already beats the Kit's bare `a` rule and
	 * Elementor's own menu-title-container styles, so nothing needs !important. */
	.NAV #nav-login-mobile .e-n-menu-title-container {
		display: flex;
		align-items: center;
		justify-content: center;
		gap: var(--s2);
		width: 100%;
		padding: var(--s3) var(--s4);
		border: 1rem solid var(--color-rock-brown-300, #3F2E2B);
		border-radius: var(--s05);
		background-color: var(--color-white);
		color: var(--color-black);
		text-decoration: none;
		transition: background-color 150ms, color 150ms;
	}

	/* Same hover/focus treatment as the standalone Login button variant
	 * (extensions/button/style.css), for consistency. */
	.NAV #nav-login-mobile .e-n-menu-title-container:hover,
	.NAV #nav-login-mobile .e-n-menu-title-container:focus {
		background-color: var(--color-walnut-400);
		color: var(--color-pearl-200-base);
	}

	/* The hover colour must be re-declared on the label SPAN, not just the `<a>`:
	 * Elementor Pro pins `.e-n-menu-title-text`'s colour directly on that span for
	 * the dropdown layout, ungated by :hover. A colour set ON an element always
	 * beats one merely inherited from an ancestor, whatever the ancestor rule's
	 * specificity — so the `<a>` rule above can never reach it. The icon needs no
	 * equivalent: it reads currentColor and has no competing rule. */
	.NAV #nav-login-mobile .e-n-menu-title-container:hover .e-n-menu-title-text,
	.NAV #nav-login-mobile .e-n-menu-title-container:focus .e-n-menu-title-text {
		color: var(--color-pearl-200-base);
	}

	/* Icon — the same shared glyph the Login button variant uses
	 * (extensions/button/style.css). This menu item isn't a Button widget instance,
	 * so it has no `.elementor-button-content-wrapper` to hook into and needs its
	 * own rule; `background-color: currentColor` is what lets the hover rule above
	 * recolour it for free. */
	.NAV #nav-login-mobile .e-n-menu-title-container::after {
		content: "";
		display: block;
		flex: 0 0 auto;
		mask: var(--icon-user);
		mask-size: cover;
		mask-repeat: no-repeat;
		width: var(--s4);
		height: var(--s4);
		background-color: currentColor;
		transition: background-color 150ms;
	}


	/* ---------- BACKDROP (menu open) ---------- */
	.NAV:not(.elementor-sticky__spacer)::after {
		content: "";
		position: fixed;
		inset: 0;
		z-index: 2147483630;
		background-color: var(--redteam-nav-backdrop, rgba(0, 0, 0, 0.5));
		opacity: 0;
		visibility: hidden;
		pointer-events: none;
		/* Matches Elementor's own `.3s` max-height transition on the panel, so the
		 * dim and the panel arrive together. `visibility` is stepped at the end of
		 * the fade out so the scrim is not left hit-testable or exposed to
		 * assistive tech while closed. */
		transition: opacity 300ms, visibility 0s linear 300ms;
	}

	.NAV:not(.elementor-sticky__spacer):has(.e-n-menu-toggle[aria-expanded="true"])::after {
		opacity: 1;
		visibility: visible;
		transition: opacity 300ms, visibility 0s;
	}

	/* Keep the bar above the scrim while the menu is open — see the z-index note
	 * above. Mirrors the CLOSED BAR rule's own `.e-con-full` qualifier. */
	.NAV:not(.elementor-sticky__spacer):has(.e-n-menu-toggle[aria-expanded="true"])>.e-con-inner>.e-con.e-con-full {
		z-index: 2147483635;
	}

	@media (prefers-reduced-motion: reduce) {
		.NAV:not(.elementor-sticky__spacer)::after,
		.NAV:not(.elementor-sticky__spacer):has(.e-n-menu-toggle[aria-expanded="true"])::after {
			transition: none;
		}
	}

}