/*
Theme Name: SeriousWeb
Theme URI: https://seriousweb.com/
Description: Child theme of Divi for the SeriousWeb marketing site. All template overrides, custom functions and CSS belong here — never in the Divi parent theme.
Author: SeriousWeb
Author URI: https://seriousweb.com/
Template: Divi
Version: 1.0.0
License: GNU General Public License v2
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: seriousweb
*/

/* Divi loads the parent style.css automatically before this file — no @import needed. */

/* ===========================================================================
   SeriousWeb design system
   ---------------------------------------------------------------------------
   Companion CSS for the Divi Theme Builder template
   "SeriousWeb — Homepage (AI & Automation)".

   Layout values here are sampled from sampletemplate/mockup.png, and every rule
   is scoped to an `sw-` class that the template applies via each module's CSS
   Class field — so nothing leaks into other layouts. Rename a class in the
   builder and you must rename it here too.

   Colour is a different story: nothing below hardcodes a colour by eye. The
   brand palette is the four values in the first block of :root, and every other
   colour on the site is a step on the same 207° blue ramp derived from them.
   Change a brand value and the whole site follows.
   =========================================================================== */

:root {
	/* ---- brand palette — the only four colours that are given ------------- */
	--seriousweb-dark-blue: #085296;
	--seriousweb-blue: #5b9bd5;
	--seriousweb-light-blue: #9bc2e5;
	--seriousweb-white: #ffffff;

	/* ---- the ramp: one hue (~207°), light to dark ------------------------- */
	/* Dark end is the brand dark blue carried down in lightness, so the dark
	   sections read as the same colour family rather than a neutral black. */
	--sw-navy-950: #03182c;   /* footer — deepest */
	--sw-navy-900: #041f38;   /* header + hero */
	--sw-navy-850: #052846;   /* success stories, stat panels */
	--sw-navy-800: #063355;   /* raised panels on dark, dropdowns */
	--sw-blue-600: #085296;   /* = brand dark blue */
	--sw-blue-500: #2a6fad;
	--sw-blue-400: #5b9bd5;   /* = brand blue */
	--sw-blue-300: #7dafdd;
	--sw-blue-200: #9bc2e5;   /* = brand light blue */
	--sw-blue-150: #c3dbef;
	--sw-blue-100: #dce9f5;
	--sw-blue-50: #edf4fa;
	--sw-blue-25: #f5f9fc;

	/* ---- semantic surfaces ------------------------------------------------ */
	--sw-ink: var(--sw-navy-900);       /* header + hero */
	--sw-dark-alt: var(--sw-navy-850);  /* success stories */
	--sw-footer: var(--sw-navy-950);
	--sw-light: #f2f7fb;                /* projects / automation / services / process */
	--sw-light-alt: var(--sw-blue-50);  /* final CTA */
	--sw-white: var(--seriousweb-white);

	/* ---- accents ----------------------------------------------------------
	   These names are historical (the palette used to be blue/violet). They now
	   all resolve to steps on the blue ramp; the names are kept because the
	   Theme Builder layouts reference the classes that use them. */
	--sw-blue: var(--sw-blue-600);
	--sw-purple: var(--sw-blue-400);
	--sw-indigo: var(--sw-blue-500);
	--sw-cyan-txt: var(--sw-blue-200);
	--sw-lilac-txt: var(--sw-blue-200);

	/* Process steps — a progression down the ramp, so 01→04 still reads as a
	   sequence now that they are no longer four unrelated hues. */
	--sw-step-1: var(--sw-blue-600);
	--sw-step-2: var(--sw-blue-500);
	--sw-step-3: var(--sw-blue-400);
	--sw-step-4: var(--sw-blue-200);

	/* ---- text and lines --------------------------------------------------- */
	--sw-slate: var(--sw-blue-600);  /* headings on light — 7.4:1 on white */
	--sw-muted: #47617a;             /* body on light — 7.6:1 on white */
	--sw-muted-dark: var(--sw-blue-200); /* body on dark — 8.2:1 on --sw-ink */
	--sw-border-light: var(--sw-blue-100);
	--sw-border-dark: rgba(155, 194, 229, 0.16);

	--sw-gradient: linear-gradient(90deg, #085296 0%, #5b9bd5 100%);
	--sw-radius: 14px;

	/* ---- the card ---------------------------------------------------------
	   One definition of what a card is. Before these existed the site had
	   twenty card-like components carrying fourteen different paddings and
	   three different radii, because each page's section was written on its own
	   and nothing compared them.

	   The values are not new: 26/24/28 and a 14px radius are what the largest
	   group already used, so this moves the minority onto the existing house
	   value rather than inventing a twenty-first.

	   Two shadow layers, not one — a tight contact shadow plus a wide soft one.
	   Cards sit on white here, where a single 3px shadow leaves them reading as
	   faint outlines rather than raised surfaces. */
	--sw-card-pad: 26px 24px 28px;
	--sw-card-radius: var(--sw-radius);
	--sw-card-border: 1px solid var(--sw-border-light);
	--sw-card-shadow: 0 1px 2px rgba(4, 31, 56, 0.05), 0 12px 28px -20px rgba(4, 31, 56, 0.35);
	--sw-card-shadow-hover: 0 2px 4px rgba(4, 31, 56, 0.06), 0 22px 46px -22px rgba(4, 31, 56, 0.45);
	--sw-card-transition: transform 0.25s var(--sw-ease), border-color 0.25s var(--sw-ease),
		box-shadow 0.25s var(--sw-ease);
	--sw-shadow-sm: 0 1px 3px rgba(4, 31, 56, 0.05);
	--sw-shadow-md: 0 18px 40px -22px rgba(4, 31, 56, 0.32);
	--sw-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* ---------------------------------------------------------------------------
   1. Header
   --------------------------------------------------------------------------- */

/* Divi reserves room for its own fixed navigation bar on #page-container:
   `.et_fixed_nav.et_show_nav #page-container { padding-top: 80px }` and three
   taller variants for the centred and secondary-nav header styles. Neither the
   Theme Builder header nor header.php renders Divi's #main-header, so that
   reservation is just dead space above the hero.

   `body` plus the id gives 1-2-1, out-ranking Divi's 1-2-0; !important also
   covers the inline padding Divi's fixed-nav script can set. */
body.et_fixed_nav.et_show_nav #page-container,
body.et_fixed_nav.et_show_nav.et_header_style_centered #page-container,
body.et_fixed_nav.et_show_nav.et_secondary_nav_enabled #page-container,
body.et_fixed_nav.et_show_nav.et_secondary_nav_enabled.et_header_style_centered #page-container {
	padding-top: 0 !important;
}

/* Opaque and the same colour as the hero, so it reads as one surface until the
   page scrolls — the mockup has no divider line under the nav. */
.sw-header {
	border-bottom: 1px solid transparent;
	transition: border-color 0.3s var(--sw-ease), box-shadow 0.3s var(--sw-ease);
}

.sw-header.et_pb_sticky {
	border-bottom-color: rgba(255, 255, 255, 0.08);
	box-shadow: 0 12px 40px -26px rgba(0, 0, 0, 0.9);
}

.sw-header-row .sw-header-col {
	display: flex;
	align-items: center;
}

.sw-header-col--logo { justify-content: flex-start; }
.sw-header-col--nav { justify-content: center; }
.sw-header-col--cta { justify-content: flex-end; }

.sw-header-row .sw-header-col > .et_pb_module {
	margin-bottom: 0 !important;
}

/* Logo size for the Theme Builder header/footer. Divi writes the image module
   width straight from the layout — `.et_pb_image_0_tb_header { width: 205px }`
   at 0-1-0, plus 185/158px in its own media queries — so these 0-2-0 selectors
   win without !important, and each breakpoint needs its own override.
   The logo is 800x213, so 230px wide renders 61px tall. */
.sw-header .sw-logo { width: 230px; }
.sw-footer .sw-footer-logo { width: 210px; }

@media (max-width: 980px) {
	.sw-header .sw-logo { width: 205px; }
	.sw-footer .sw-footer-logo { width: 195px; }
}

@media (max-width: 767px) {
	.sw-header .sw-logo { width: 175px; }
	.sw-footer .sw-footer-logo { width: 175px; }
}

.sw-nav .et_pb_menu__wrap { justify-content: center; }

/* Spacing is measured from mockup.png and scaled to this row width (x1.66):
   41.5px between labels, and an active pill of 17px horizontal / 14px vertical
   padding around its label.

   Divi splits that budget across two boxes — `.et-menu > li { padding: 0 11px }`
   plus whatever the anchor carries — which left 46px gaps but only 12px inside
   the pill, so the highlight looked cramped against generous gaps. Most of the
   budget now sits on the anchor, where it shapes the pill; the li keeps a small
   remainder. 4 + 17 + 17 + 4 = 42px between labels. */
.sw-nav.et_pb_menu .et-menu {
	margin-left: -4px;
	margin-right: -4px;
}

.sw-nav.et_pb_menu .et-menu > li {
	padding-left: 4px;
	padding-right: 4px;
}

.sw-nav .et-menu > li > a {
	position: relative;
	padding: 14px 17px;
	border-radius: 8px;
	opacity: 0.85;
	transition: opacity 0.2s var(--sw-ease), background-color 0.2s var(--sw-ease);
}

.sw-nav .et-menu > li > a:hover { opacity: 1; }

/* Active item sits in a raised pill with a gradient underline, as in the mockup. */
.sw-nav .et-menu > li.current-menu-item > a,
.sw-nav .et-menu > li.current_page_item > a {
	opacity: 1;
	background: rgba(255, 255, 255, 0.06);
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
}

/* Underline uses ::before, not ::after — Divi renders the submenu arrow as
   `a:first-child:after`, so using ::after here would erase the arrow on any
   active item that has a dropdown. */
.sw-nav .et-menu > li.current-menu-item > a::before,
.sw-nav .et-menu > li.current_page_item > a::before {
	content: "";
	position: absolute;
	left: 17px;
	right: 17px;
	bottom: 7px;
	height: 2px;
	border-radius: 2px;
	background: var(--sw-gradient);
}

/* Divi absolutely positions the dropdown arrow at `right: 0; top: 0` and
   reserves room with `padding-right: 20px` on the anchor. The padding shorthand
   above replaces that reservation, and `top: 0` sits the arrow against the top
   edge of the taller anchor — so re-reserve the space and centre it. */
.sw-nav .et-menu > li.menu-item-has-children > a:first-child {
	padding-right: 32px;
}

.sw-nav .et-menu > li.menu-item-has-children > a:first-child::after {
	top: 50%;
	right: 15px;
	transform: translateY(-50%);
	font-size: 15px;
	line-height: 1;
}

/* Keep the underline under the label only, not the caret. */
.sw-nav .et-menu > li.menu-item-has-children.current-menu-item > a::before,
.sw-nav .et-menu > li.menu-item-has-children.current_page_item > a::before {
	right: 32px;
}

.sw-nav .nav li ul {
	border-top: none;
	border-radius: 12px;
	padding: 8px 0;
	box-shadow: 0 24px 60px -28px rgba(0, 0, 0, 0.95);
}

.sw-nav .et_mobile_menu {
	border-top: 1px solid var(--sw-border-dark);
	border-radius: 0 0 12px 12px;
}

.sw-nav .et_mobile_menu li a {
	border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

/* ---------------------------------------------------------------------------
   2. Buttons
   --------------------------------------------------------------------------- */

/* inline-flex so the icon is centred against the label by the layout itself,
   rather than depending on the glyph's own font metrics. */
.sw-btn.et_pb_button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.5em;
	font-weight: 700;
	line-height: 1.2;
	transition: transform 0.25s var(--sw-ease), box-shadow 0.25s var(--sw-ease),
		background-color 0.25s var(--sw-ease), border-color 0.25s var(--sw-ease);
}

/* Divi renders the button glyph as an absolutely positioned ::after, sized
   1.6em when it falls back to its own arrow but `inherit` when a custom icon is
   set — two different sizes on one page. These selectors carry an id to
   out-rank Divi's own `body #page-container .et_pb_section ...` rules (1-2-2),
   which use !important and would otherwise win. */
body #page-container .et_pb_section .sw-btn.et_pb_button:after {
	position: static;
	display: inline-block;
	margin: 0;
	font-size: 1em !important;
	line-height: 1;
	opacity: 1;
}

/* Only buttons that declare an icon get one. The presets set
   button_on_hover:off, which means "always show the icon" — so without this,
   every button inherits Divi's default arrow. */
body #page-container .et_pb_section .sw-btn.et_pb_button:not([data-icon]):after,
body #page-container .et_pb_section .sw-btn.et_pb_button[data-icon=""]:after {
	display: none;
}

.sw-btn.et_pb_button:hover { transform: translateY(-2px); }
.sw-btn.et_pb_button:active { transform: translateY(0); }

.sw-btn--primary.et_pb_button {
	box-shadow: 0 16px 34px -18px rgba(8, 82, 150, 0.85);
}

.sw-btn--primary.et_pb_button:hover {
	box-shadow: 0 22px 46px -20px rgba(8, 82, 150, 0.95);
}

.sw-btn--ghost-dark.et_pb_button:hover {
	background-color: rgba(255, 255, 255, 0.09) !important;
	border-color: rgba(255, 255, 255, 0.45) !important;
}

.sw-btn--ghost-light.et_pb_button:hover {
	border-color: var(--sw-blue) !important;
	color: var(--sw-blue) !important;
}

.sw-btn--sm.et_pb_button { font-size: 14px !important; }

/* One fixed height for every button, so any two sitting side by side match
   exactly regardless of border width or icon metrics.

   Divi writes its padding per button as
   `.et_pb_button_N_wrapper .et_pb_button_N { padding-top: 14px !important }`
   (0-2-0, !important), so vertical padding has to be zeroed at a higher
   specificity — hence the id-bearing prefix, which mirrors Divi's own. The
   button is inline-flex with align-items:center, so the label stays centred in
   the fixed height, and horizontal padding is left untouched. */
body #page-container .et_pb_section .sw-btn.et_pb_button {
	min-height: 52px;
	padding-top: 0 !important;
	padding-bottom: 0 !important;
}

body #page-container .et_pb_section .sw-btn--sm.et_pb_button {
	min-height: 44px;
}

/* Divi wraps each button in a block-level element, so a pair of buttons stacks
   by default. Making the wrappers inline-block sits them side by side.
   The parent column must stay in normal flow for this to take effect. */
.sw-cta-group .et_pb_button_module_wrapper {
	display: inline-block;
	vertical-align: middle;
	margin: 0 12px 12px 0;
}

/* The button is inline-flex, so inside a block wrapper it sits on a line box
   and picks up leading and descender space. That space depends on the font
   metrics of the ::after icon — the arrow is FontAwesome weight 900, the
   WhatsApp mark is the brands face at weight 400 — so two wrappers holding
   equally sized buttons ended up different heights, and centring the wrappers
   left the buttons themselves 19px apart.

   Making each wrapper its own flex container removes the line box, so wrapper
   height equals button height exactly and the pair lines up. `flex: 0 0 auto`
   keeps the button at its natural size — stretching it here is what previously
   inflated the WhatsApp button. */
.sw-cta-group .et_pb_button_module_wrapper,
.sw-cta-right .et_pb_button_module_wrapper {
	display: inline-flex;
	align-items: center;
}

.sw-cta-group .et_pb_button_module_wrapper > .et_pb_button,
.sw-cta-right .et_pb_button_module_wrapper > .et_pb_button {
	flex: 0 0 auto;
}

.sw-cta-right { display: flex; align-items: center; }
.sw-cta-right .et_pb_button_module_wrapper { margin: 0 0 12px 12px; }

/* flex, not block — block would drop the icon out of the flex flow. */
.sw-btn--center.et_pb_button {
	display: flex;
	width: -moz-fit-content;
	width: fit-content;
	margin-left: auto;
	margin-right: auto;
}

.sw-btn.et_pb_button:focus-visible,
.sw-nav .et-menu > li > a:focus-visible,
.sw-card-more a:focus-visible {
	outline: 2px solid var(--sw-cyan-txt);
	outline-offset: 3px;
}

/* ---------------------------------------------------------------------------
   3. Typographic accents
   --------------------------------------------------------------------------- */

.sw-eyebrow p {
	text-transform: uppercase;
	margin: 0;
}

.sw-grad-text {
	background: linear-gradient(100deg, #9bc2e5 0%, #7dafdd 45%, #9bc2e5 100%);
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
	color: var(--sw-cyan-txt); /* fallback */
}

@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
	.sw-grad-text { -webkit-text-fill-color: currentColor; }
}

.sw-card-more { margin: 14px 0 0 !important; }

.sw-card-more a {
	font-weight: 600;
	color: var(--sw-blue);
	text-decoration: none;
	border-bottom: 1px solid transparent;
}

.sw-card-more a:hover { border-bottom-color: currentColor; }

/* ---------------------------------------------------------------------------
   4. Hero
   --------------------------------------------------------------------------- */

.sw-hero {
	position: relative;
	overflow: hidden;
}

/* Two soft light sources behind the orbit graphic, as in the mockup. */
.sw-hero::before,
.sw-hero::after {
	content: "";
	position: absolute;
	border-radius: 50%;
	pointer-events: none;
	z-index: 0;
}

.sw-hero::before {
	top: -180px;
	right: 4%;
	width: 620px;
	height: 620px;
	background: radial-gradient(circle, rgba(8, 82, 150, 0.3) 0%, rgba(8, 82, 150, 0) 68%);
}

.sw-hero::after {
	bottom: -260px;
	right: 22%;
	width: 540px;
	height: 540px;
	background: radial-gradient(circle, rgba(91, 155, 213, 0.26) 0%, rgba(91, 155, 213, 0) 68%);
}

.sw-hero .et_pb_row { position: relative; z-index: 1; }

/* Normal block flow on purpose. A flex column here would make every child a
   flex item on its own line, which forces the two hero CTAs to stack — they
   need to sit side by side (see .sw-cta-group below). */
.sw-hero-copy { display: block; }
.sw-hero-visual-col { display: flex; align-items: center; }

/* Trust chips under the hero CTAs. */
.sw-hero-chips {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	gap: 12px 26px;
	margin: 0;
	padding: 0;
}

.sw-hero-chips li {
	position: relative;
	padding-left: 24px;
	line-height: 1.6;
}

.sw-hero-chips li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.32em;
	width: 14px;
	height: 14px;
	border-radius: 50%;
	background: var(--sw-gradient);
	box-shadow: 0 0 0 4px rgba(8, 82, 150, 0.14);
}

/* ---------------------------------------------------------------------------
   5. Trusted-by strip
   --------------------------------------------------------------------------- */

.sw-logo-strip { align-items: center; }

.sw-client-logo img {
	filter: grayscale(100%);
	opacity: 0.55;
	transition: filter 0.25s var(--sw-ease), opacity 0.25s var(--sw-ease);
	max-height: 42px;
	width: auto;
}

.sw-client-logo img:hover {
	filter: grayscale(0);
	opacity: 1;
}

/* ---------------------------------------------------------------------------
   6. Project cards
   --------------------------------------------------------------------------- */

/* Equal-height card grids. Divi columns are floated, so a tall card leaves its
   neighbours short — the row itself has to become the flex container for
   `align-items: stretch` to level them.

   Scoped to min-width 981px, the same breakpoint Divi guards its own
   `.et_pb_equal_columns` rule with, so columns still stack normally below it. */
@media (min-width: 981px) {
	.sw-row--projects,
	.sw-row--chips,
	.sw-row--services,
	.sw-row--steps {
		display: flex;
		align-items: stretch;
	}

	/* Divi's `gutter_width: 2` puts a 3% margin between columns — roughly 37px
	   at this row width, where the mockup runs 11-12px. Swap the percentage
	   margin for a flex `gap` sized from the mockup: projects 11px, automation
	   tiles 12px, services/process 6px, each over a ~747px content width. */
	.sw-row--projects > .et_pb_column,
	.sw-row--chips > .et_pb_column,
	.sw-row--services > .et_pb_column,
	.sw-row--steps > .et_pb_column {
		width: auto;
		margin-right: 0 !important;
		flex: 1 1 0;
	}

	.sw-row--projects { gap: 1.5%; }
	.sw-row--chips { gap: 1.6%; }

	/* Services and Process are 1_5 x5 rows — the only 5-column structure Divi
	   offers — which gives the intro column an even 15.6%. The mockup runs it at
	   ~27% with the four cards sharing the rest. Divi exposes no per-column
	   width in a regular row, so the split is set explicitly here. */
	.sw-row--services,
	.sw-row--steps {
		gap: 0.9%;
	}

	.sw-row--services > .et_pb_column:first-child,
	.sw-row--steps > .et_pb_column:first-child {
		flex: 0 0 27%;
		padding-right: 2%;
	}
}

/* Each column then stretches its own card to fill the levelled height. */
.sw-row--projects > .et_pb_column,
.sw-row--services > .et_pb_column,
.sw-row--chips > .et_pb_column {
	display: flex;
}

.sw-row--projects > .et_pb_column.sw-card--project {
	flex-direction: column;
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-radius);
	overflow: hidden;
	box-shadow: var(--sw-shadow-sm);
	transition: transform 0.3s var(--sw-ease), box-shadow 0.3s var(--sw-ease),
		border-color 0.3s var(--sw-ease);
}

.sw-row--projects > .et_pb_column.sw-card--project:hover {
	transform: translateY(-4px);
	box-shadow: var(--sw-shadow-md);
	border-color: rgba(8, 82, 150, 0.3);
}

.sw-project-img { margin-bottom: 0 !important; }

.sw-project-img img {
	display: block;
	width: 100%;
	height: auto;
}

.sw-project-body {
	flex: 1 1 auto;
	padding: 22px 20px 24px;
	margin-bottom: 0 !important;
}

.sw-project-body h3 {
	margin: 0 0 8px;
	padding-bottom: 0;
}

.sw-project-body p { margin-bottom: 0; }

/* ---------------------------------------------------------------------------
   7. Automation tiles
   --------------------------------------------------------------------------- */

.sw-row--chips > .et_pb_column > .sw-chip { width: 100%; }

.sw-chip {
	text-align: center;
	transition: transform 0.25s var(--sw-ease), box-shadow 0.25s var(--sw-ease),
		border-color 0.25s var(--sw-ease);
}

.sw-chip:hover {
	transform: translateY(-3px);
	box-shadow: var(--sw-shadow-md);
	border-color: rgba(8, 82, 150, 0.3) !important;
}

.sw-chip .et_pb_main_blurb_image { margin-bottom: 10px; }

/* Divi's default for a top-placed blurb icon is
   `.et_pb_blurb_position_top .et-pb-icon { font-size: 96px }` (0-2-0). These
   selectors are 0-3-0, so they win without !important. Sizes match the
   `image_icon_width` values in the template presets. */
.sw-chip .et_pb_main_blurb_image .et-pb-icon {
	font-size: 20px;
	line-height: 1.4;
}

/* Blurb titles are <h4>, so with no per-module size from Divi they inherit the
   global `h4 { font-size: 17px }` — far too heavy for these small tiles.
   Sizes mirror the `header_font_size` values in the template presets. */
.sw-chip .et_pb_module_header {
	margin-bottom: 0;
	padding-bottom: 0;
	font-size: 13px;
	font-weight: 600;
	line-height: 1.45;
	/* The 12 tiles sit in two separate Divi rows, which equalise independently.
	   Reserving two lines here keeps all 12 the same height, since labels like
	   "E-commerce Automation" wrap while "Data Entry" does not. */
	min-height: 2.9em;
}

.sw-card--service .et_pb_module_header,
.sw-step .et_pb_module_header {
	font-size: 17px;
	line-height: 1.35;
}

@media (max-width: 980px) {
	.sw-card--service .et_pb_module_header,
	.sw-step .et_pb_module_header { font-size: 16px; }
}

@media (max-width: 767px) {
	.sw-chip .et_pb_module_header { font-size: 12px; }
}

/* The mockup alternates icon hues across the grid rather than using one colour. */
.sw-row--chips > .et_pb_column:nth-child(2n) .sw-chip .et-pb-icon { color: var(--sw-blue) !important; }
.sw-row--chips > .et_pb_column:nth-child(3n) .sw-chip .et-pb-icon { color: var(--sw-purple) !important; }

/* ---------------------------------------------------------------------------
   8. Services
   --------------------------------------------------------------------------- */

.sw-svc-intro { display: flex; flex-direction: column; justify-content: center; }

.sw-row--services > .et_pb_column > .sw-card--service { width: 100%; }

.sw-card--service {
	transition: transform 0.3s var(--sw-ease), box-shadow 0.3s var(--sw-ease),
		border-color 0.3s var(--sw-ease);
}

.sw-card--service:hover {
	transform: translateY(-4px);
	box-shadow: var(--sw-shadow-md);
	border-color: rgba(8, 82, 150, 0.3) !important;
}

/* Icon sits in a soft tinted tile, one hue per pillar. */
/* Centred to match the mockup, where each service icon sits on the card's
   centre line.

   Divi aligns blurb copy on the *inner* container via
   `.et_pb_blurb.et_pb_text_align_left .et_pb_blurb_content .et_pb_blurb_container`
   (specificity 0-4-0), so text-align on the module alone never reaches it. The
   attribute selector adds a fifth simple selector to out-rank that, and matches
   whichever et_pb_text_align_* class the module happens to carry — left in the
   copy currently in the database, center once the template is re-imported. */
.sw-card--service {
	text-align: center;
}

.sw-card--service.et_pb_blurb .et_pb_blurb_content,
.sw-card--service.et_pb_blurb[class*="et_pb_text_align_"] .et_pb_blurb_content .et_pb_blurb_container {
	text-align: center;
}

.sw-card--service .et_pb_main_blurb_image .et-pb-icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 46px;
	height: 46px;
	margin: 0 auto;
	font-size: 22px;
	line-height: 1;
	border-radius: 12px;
}

.sw-svc--1 .et_pb_main_blurb_image .et-pb-icon { background: #d6e6f4; color: var(--sw-step-1) !important; }
.sw-svc--2 .et_pb_main_blurb_image .et-pb-icon { background: #deebf6; color: var(--sw-step-2) !important; }
.sw-svc--3 .et_pb_main_blurb_image .et-pb-icon { background: #e6f0f8; color: #2a6fad !important; }
.sw-svc--4 .et_pb_main_blurb_image .et-pb-icon { background: #eef5fb; color: var(--sw-step-4) !important; }

/* Tightened to the mockup, where a service card measures ~286px rendered.
   Divi emits `.et_pb_blurb_N.et_pb_blurb p { line-height: 1.75em }` (0-2-1) and
   its custom_padding rule at 0-2-0, so these carry an extra class each to win
   while the database still holds the looser preset. */
.sw-card--service .et_pb_module_header {
	margin-bottom: 6px;
	line-height: 1.3;
}

.sw-section .sw-card--service.et_pb_blurb {
	padding: 20px 18px !important;
}

.sw-card--service.et_pb_blurb .et_pb_blurb_description p {
	line-height: 1.5;
}

.sw-card--service .et_pb_main_blurb_image {
	margin-bottom: 14px;
}

.sw-card--service .sw-card-more {
	margin-top: 12px !important;
}

/* ---------------------------------------------------------------------------
   9. Process
   --------------------------------------------------------------------------- */

.sw-process-intro { display: flex; flex-direction: column; justify-content: center; }

.sw-step { text-align: center; }

/* Blurb renders icon → title → content. The mockup wants the step number
   between the icon and the title, so reorder the flow with flexbox. */
.sw-step .et_pb_blurb_content { max-width: 100%; }

.sw-step .et_pb_blurb_container {
	display: flex;
	flex-direction: column;
}

/* The number lives inside .et_pb_blurb_description, so that wrapper is
   flattened with display:contents and all three parts are ordered explicitly.
   Every item needs an explicit order — the default of 0 would float the
   description paragraph above the number. */
.sw-step .et_pb_blurb_description { display: contents; }
.sw-step .sw-step-num { order: 1; }
.sw-step .et_pb_module_header { order: 2; margin-bottom: 6px; padding-bottom: 0; }
.sw-step .et_pb_blurb_description > p:not(.sw-step-num) { order: 3; }

.sw-step .sw-step-num {
	margin: 0 0 4px !important;
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 17px !important;
	font-weight: 800;
	line-height: 1.2 !important;
}

.sw-step .et_pb_main_blurb_image { margin-bottom: 14px; }

.sw-step .et_pb_main_blurb_image .et-pb-icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 58px;
	height: 58px;
	margin: 0 auto;
	font-size: 22px;
	line-height: 1;
	border-radius: 50%;
	color: #fff !important;
}

.sw-step--1 .et_pb_main_blurb_image .et-pb-icon { background: var(--sw-step-1); box-shadow: 0 14px 28px -14px var(--sw-step-1); }
.sw-step--2 .et_pb_main_blurb_image .et-pb-icon { background: var(--sw-step-2); box-shadow: 0 14px 28px -14px var(--sw-step-2); }
.sw-step--3 .et_pb_main_blurb_image .et-pb-icon { background: var(--sw-step-3); box-shadow: 0 14px 28px -14px var(--sw-step-3); }
.sw-step--4 .et_pb_main_blurb_image .et-pb-icon { background: var(--sw-step-4); box-shadow: 0 14px 28px -14px var(--sw-step-4); }

.sw-step--1 .sw-step-num { color: var(--sw-step-1); }
.sw-step--2 .sw-step-num { color: var(--sw-step-2); }
.sw-step--3 .sw-step-num { color: #2a6fad; }
.sw-step--4 .sw-step-num { color: var(--sw-step-4); }

/* Arrow between consecutive steps, desktop only. */
.sw-row--steps > .et_pb_column.sw-step-col { position: relative; }

.sw-row--steps > .et_pb_column.sw-step-col:not(:last-child)::after {
	content: "\2192";
	position: absolute;
	top: 16px;
	right: -20px;
	font-size: 20px;
	line-height: 1;
	color: #9bc2e5;
}

/* ---------------------------------------------------------------------------
   10. Success stories
   --------------------------------------------------------------------------- */

.sw-results-intro { display: flex; flex-direction: column; justify-content: center; }

.sw-quote { position: relative; }

.sw-quote-avatar { margin-bottom: 16px !important; }

.sw-quote-avatar img {
	border-radius: 50%;
	border: 2px solid rgba(255, 255, 255, 0.14);
}

.sw-quote-mark {
	margin: 0 !important;
	font-size: 42px !important;
	line-height: 0.7 !important;
	color: var(--sw-blue);
}

.sw-quote-by {
	margin-top: 12px !important;
	font-weight: 600;
	color: #7fa8c9 !important;
}

.sw-stats-wrap { display: flex; align-items: center; height: 100%; }

.sw-stats {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	gap: 26px;
	margin: 0;
	padding: 0;
	width: 100%;
}

.sw-stats li {
	flex: 1 1 90px;
	text-align: center;
	text-transform: none;
	line-height: 1.5;
}

.sw-stats li span {
	display: block;
	margin-bottom: 4px;
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 28px;
	font-weight: 800;
	line-height: 1.1;
	background: linear-gradient(100deg, #9bc2e5 0%, #9bc2e5 100%);
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
	color: #9bc2e5;
}

/* ---------------------------------------------------------------------------
   11. Final CTA
   --------------------------------------------------------------------------- */

/* The buttons must sit on the heading's centre line — in the mockup the two
   blocks are centred against each other. `align-items` needs an actual flex
   container, so the row has to become one; without this it was inert and the
   button column simply started at the top of the row.

   Guarded at 981px like the other flex rows, so the columns still stack below
   it. Widths and gutters are left to Divi — only the cross-axis changes. */
@media (min-width: 981px) {
	.sw-row--final {
		display: flex;
		align-items: center;
	}

	/* Size the columns to content rather than Divi's fixed 48.5% each. The two
	   buttons need ~557px side by side; a 48.5% column only clears that above a
	   ~1300px window, so on anything narrower flex-wrap broke them onto separate
	   lines. Giving the button column its content width and letting the heading
	   absorb the remainder makes the pairing hold at every desktop size. */
	.sw-row--final > .et_pb_column:first-child {
		flex: 1 1 auto;
		width: auto;
	}

	.sw-row--final > .sw-cta-right {
		flex: 0 0 auto;
		width: auto;
		flex-wrap: nowrap;
	}

	.sw-cta-right .et_pb_button {
		white-space: nowrap;
	}

}

/* Only the copy column stacks vertically. Scoped to :first-child so it cannot
   out-specify .sw-cta-right and stack that column's two buttons as well. */
.sw-row--final > .et_pb_column:first-child {
	display: flex;
	flex-direction: column;
	justify-content: center;
}

.sw-cta-right { justify-content: flex-end; flex-direction: row; flex-wrap: wrap; }

/* ---------------------------------------------------------------------------
   12. Footer
   --------------------------------------------------------------------------- */

.sw-footer-nav h4 {
	margin-bottom: 14px;
	padding-bottom: 0;
}

.sw-footer-links {
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-footer-links li { margin-bottom: 8px; }

.sw-footer-links a {
	text-decoration: none;
	transition: color 0.2s var(--sw-ease);
}

.sw-footer-links a:hover { color: var(--sw-white) !important; }

.sw-footer-contact { margin-top: 14px !important; }

.sw-social .et_pb_social_media_follow_network a.icon {
	transition: transform 0.25s var(--sw-ease), background-color 0.25s var(--sw-ease);
}

.sw-social .et_pb_social_media_follow_network a.icon:hover {
	transform: translateY(-2px);
	background-color: var(--sw-blue) !important;
}

.sw-footer-legal p { margin: 0; }
.sw-footer-legal a { text-decoration: none; }
.sw-footer-legal a:hover { color: var(--sw-white) !important; }
.sw-footer-legal span { opacity: 0.4; padding: 0 6px; }

/* ---------------------------------------------------------------------------
   13. Responsive
   --------------------------------------------------------------------------- */

@media (max-width: 980px) {
	.sw-header-col--nav,
	.sw-header-col--cta { justify-content: flex-end; }

	.sw-hero-visual-col { margin-top: 40px; }

	/* Divi stacks columns below 980px; drop the flex card treatments so the
	   stacked blocks keep their own spacing. */
	.sw-row--projects > .et_pb_column,
	.sw-row--services > .et_pb_column,
	.sw-row--chips > .et_pb_column { display: block; }

	.sw-row--projects > .et_pb_column.sw-card--project { display: flex; }

	.sw-row--steps > .et_pb_column.sw-step-col:not(:last-child)::after { display: none; }

	.sw-cta-right { justify-content: flex-start; }
	.sw-cta-right .et_pb_button_module_wrapper { margin: 0 12px 12px 0; }

	.sw-stats { gap: 18px; }
	.sw-footer-legal .et_pb_column:last-child p { text-align: left; }
}

@media (max-width: 767px) {
	.sw-header-row .sw-header-col { justify-content: center; }
	.sw-header-col--logo { justify-content: flex-start; }

	.sw-cta-group .et_pb_button_module_wrapper,
	.sw-cta-right .et_pb_button_module_wrapper {
		display: block;
		margin: 0 0 12px 0;
	}

	.sw-cta-group .et_pb_button,
	.sw-cta-right .et_pb_button {
		display: flex;
		justify-content: center;
	}

	.sw-hero-chips { gap: 10px 18px; }

	.sw-client-logo img { max-height: 34px; }

	.sw-project-body { padding: 20px 18px 22px; }

	.sw-stats li { flex: 1 1 100%; text-align: left; }
}

/* ---------------------------------------------------------------------------
   14. Motion preferences
   --------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
	/* The header animates on scroll — height, logo size, blur — plus the
	   submenu slide and the burger-to-cross fold. All of it is decoration, so
	   drop the motion and let the states switch instantly. */
	.sw-site-header,
	.sw-site-header__inner,
	.sw-site-header__logo img,
	.sw-site-nav .sw-menu > li > a,
	.sw-site-nav .sw-menu ul,
	.sw-site-nav .sw-menu ul a,
	.sw-nav-toggle,
	.sw-nav-toggle__bars,
	.sw-nav-toggle__bars::before,
	.sw-nav-toggle__bars::after,
	.sw-skip-link,
	.sw-site-header .sw-btn,
	.sw-site-footer .sw-btn {
		transition: none !important;
	}

	.sw-site-header .sw-btn:hover,
	.sw-site-footer .sw-btn:hover {
		transform: none;
	}

	.sw-btn.et_pb_button,
	.sw-chip,
	.sw-card--service,
	.sw-row--projects > .et_pb_column.sw-card--project,
	.sw-social .et_pb_social_media_follow_network a.icon {
		transition: none !important;
	}

	.sw-btn.et_pb_button:hover,
	.sw-chip:hover,
	.sw-card--service:hover,
	.sw-row--projects > .et_pb_column.sw-card--project:hover,
	.sw-social .et_pb_social_media_follow_network a.icon:hover {
		transform: none !important;
	}
}

/* ===========================================================================
   15. Code-based header & footer (header.php / footer.php)
   ---------------------------------------------------------------------------
   The rules above style the Divi Theme Builder header/footer and are scoped to
   Divi module classes (.et_pb_button, .et-menu, .et_pb_column). The PHP
   templates emit their own semantic markup, so they need equivalents here.

   Values match the Theme Builder design: header #041f38, footer #03182c,
   42px between nav labels, 17px pill padding — all measured from mockup.png.

   Only one of the two ever renders: Divi bypasses header.php/footer.php while a
   Theme Builder template supplies a header or footer.
   =========================================================================== */

.screen-reader-text {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* ---- header ------------------------------------------------------------- */

/* Sits above the header's own z-index so it is reachable, and stays off-canvas
   until focused. First stop for a keyboard user on every page. */
.sw-skip-link {
	position: fixed;
	top: 12px;
	left: 12px;
	z-index: 1100;
	padding: 12px 20px;
	border-radius: 8px;
	background: var(--sw-blue-600);
	color: #fff;
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 14px;
	font-weight: 700;
	text-decoration: none;
	transform: translateY(-200%);
	transition: transform 0.2s var(--sw-ease);
}

.sw-skip-link:focus {
	transform: translateY(0);
}

/* Zero-height marker js/header.js drops in below the header; watching it with
   an IntersectionObserver is what sets .is-scrolled. Never visible. */
.sw-header-sentinel {
	position: absolute;
	width: 1px;
	height: 1px;
	pointer-events: none;
}

.sw-site-header {
	position: sticky;
	top: 0;
	z-index: 1000;
	background: var(--sw-ink);
	border-bottom: 1px solid transparent;
	transition: background-color 0.3s var(--sw-ease), border-color 0.3s var(--sw-ease),
		box-shadow 0.3s var(--sw-ease);
}

/* Once the page leaves the top the bar has to work over both the dark hero and
   the light sections below it, so it stops being flat ink and becomes a tinted
   sheet of glass: translucent navy, blurred, with a hairline and a soft lift.
   The fallback where backdrop-filter is unsupported is the opaque colour above. */
.sw-site-header.is-scrolled {
	background: rgba(4, 31, 56, 0.86);
	border-bottom-color: var(--sw-border-dark);
	box-shadow: 0 18px 40px -30px rgba(3, 24, 44, 0.9);
}

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
	.sw-site-header.is-scrolled {
		-webkit-backdrop-filter: blur(16px) saturate(140%);
		backdrop-filter: blur(16px) saturate(140%);
	}
}

/* Three tracks with the outer two equal, so the nav is centred on the page
   rather than on whatever space the logo and button leave behind — the old
   flex layout pushed it visibly right of centre. */
.sw-site-header__inner {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
	align-items: center;
	gap: 24px;
	width: 92%;
	max-width: 1300px;
	margin: 0 auto;
	min-height: 76px;
	transition: min-height 0.3s var(--sw-ease);
}

/* Compacting on scroll buys back ~14px of the viewport and signals the state
   change without leaving the colour shift to do all the work. */
.sw-site-header.is-scrolled .sw-site-header__inner {
	min-height: 62px;
}

.sw-site-header__brand {
	min-width: 0;
}

.sw-site-header__logo {
	display: inline-block;
	line-height: 0;
	color: #fff;
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-weight: 800;
	text-decoration: none;
}

/* Sized by height with width:auto so any logo keeps its aspect ratio. The
   bundled mark is 800x213 (3.76:1), so 42px tall renders about 158px wide — a
   third narrower than the old 61px cap, which was making the bar top-heavy. */
.sw-site-header__logo img {
	display: block;
	width: auto;
	height: 42px;
	max-width: 100%;
	transition: height 0.3s var(--sw-ease);
}

.sw-site-header.is-scrolled .sw-site-header__logo img {
	height: 34px;
}

.sw-site-nav {
	display: flex;
	justify-content: center;
	min-width: 0;
}

.sw-site-header__cta {
	justify-self: end;
}

.sw-site-nav .sw-menu {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-site-nav .sw-menu > li {
	position: relative;
}

.sw-site-nav .sw-menu > li > a {
	position: relative;
	display: block;
	padding: 10px 15px;
	border-radius: 9px;
	color: var(--sw-blue-150);
	font-family: Inter, Helvetica, Arial, sans-serif;
	font-size: 15px;
	font-weight: 600;
	line-height: 1.5;
	text-decoration: none;
	white-space: nowrap;
	transition: color 0.2s var(--sw-ease), background-color 0.2s var(--sw-ease);
}

.sw-site-nav .sw-menu > li > a:hover {
	color: #fff;
	background: rgba(155, 194, 229, 0.1);
}

/* The current page gets one signal — the underline — instead of the filled
   pill, inset ring and underline it used to carry all at once. */
.sw-site-nav .sw-menu > li.current-menu-item > a,
.sw-site-nav .sw-menu > li.current_page_item > a {
	color: #fff;
}

.sw-site-nav .sw-menu > li.current-menu-item > a::before,
.sw-site-nav .sw-menu > li.current_page_item > a::before {
	content: "";
	position: absolute;
	left: 15px;
	right: 15px;
	bottom: 2px;
	height: 2px;
	border-radius: 2px;
	background: var(--sw-gradient);
}

/* NO DROPDOWN CARET, on either breakpoint.
   Removed with `.sw-submenu-toggle`: the drawer's chevron pointed at a control
   that no longer exists, and the bar's caret was the same mark doing the same
   job one breakpoint up, so keeping one and not the other would have left the
   header saying two different things about the same menu.

   Three rules went with it, and all three existed ONLY to make room for it:
   `padding-right: 30px` on a parent link, the caret's own ::after, and the
   `right: 30px` that held the current-item underline clear of it. Leaving any
   of them behind shows up as parent items sitting 30px off their neighbours'
   rhythm, or a short underline under Services and Blog only.

   WHAT THIS COSTS: on the desktop bar there is now no visual signal that
   Services and Blog have children until the pointer is over them. The submenus
   still open on hover and focus-within, so nothing is unreachable — but the
   affordance is gone, which is a real trade rather than pure cleanup. */

/* Submenu panel. Centred under its trigger and opening straight from the
   bottom edge of the link, so there is no gap for the pointer to fall through. */
.sw-site-nav .sw-menu ul {
	position: absolute;
	top: 100%;
	left: 50%;
	z-index: 20;
	min-width: 250px;
	margin: 0;
	padding: 8px;
	list-style: none;
	background: var(--sw-navy-800);
	border: 1px solid var(--sw-border-dark);
	border-radius: 14px;
	box-shadow: 0 30px 70px -32px rgba(3, 24, 44, 0.95);
	opacity: 0;
	visibility: hidden;
	transform: translate(-50%, 6px);
	transition: opacity 0.2s var(--sw-ease), transform 0.2s var(--sw-ease), visibility 0.2s;
}

/* The Services menu runs to eight children, and a single column of those is a
   thin, tall strip that overshoots short viewports. Splitting at seven keeps it
   a readable panel. Browsers without :has() simply keep the one column. */
.sw-site-nav .sw-menu ul:has(> li:nth-child(7)) {
	display: grid;
	grid-template-columns: repeat(2, minmax(190px, 1fr));
	gap: 0 4px;
}

.sw-site-nav .sw-menu > li:hover > ul,
.sw-site-nav .sw-menu > li:focus-within > ul {
	opacity: 1;
	visibility: visible;
	transform: translate(-50%, 0);
}

.sw-site-nav .sw-menu ul a {
	display: block;
	padding: 10px 14px;
	border-radius: 8px;
	color: var(--sw-blue-150);
	font-family: Inter, Helvetica, Arial, sans-serif;
	font-size: 14px;
	line-height: 1.45;
	text-decoration: none;
	transition: color 0.2s var(--sw-ease), background-color 0.2s var(--sw-ease);
}

.sw-site-nav .sw-menu ul a:hover {
	color: #fff;
	background: rgba(155, 194, 229, 0.12);
}

/* Standalone button styles — the rules in section 2 require .et_pb_button,
   which only the Theme Builder markup carries. */
.sw-site-header .sw-btn,
.sw-site-footer .sw-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.5em;
	min-height: 44px;
	padding: 0 22px;
	border-radius: 9px;
	color: #fff;
	background: var(--sw-gradient);
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 14px;
	font-weight: 700;
	line-height: 1.2;
	text-decoration: none;
	white-space: nowrap;
	box-shadow: 0 16px 34px -18px rgba(8, 82, 150, 0.85);
	transition: transform 0.25s var(--sw-ease), box-shadow 0.25s var(--sw-ease);
}

.sw-site-header .sw-btn:hover,
.sw-site-footer .sw-btn:hover {
	transform: translateY(-2px);
	box-shadow: 0 22px 46px -20px rgba(8, 82, 150, 0.95);
}

/* Toggle — a real button, so it carries aria-expanded and is reachable by
   keyboard. Hidden until the nav collapses. */
.sw-nav-toggle {
	display: none;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 1px solid var(--sw-border-dark);
	border-radius: 10px;
	background: transparent;
	color: #fff;
	cursor: pointer;
	transition: background-color 0.2s var(--sw-ease);
}

.sw-nav-toggle:hover {
	background: rgba(155, 194, 229, 0.1);
}

.sw-nav-toggle__bars,
.sw-nav-toggle__bars::before,
.sw-nav-toggle__bars::after {
	display: block;
	width: 20px;
	height: 2px;
	border-radius: 2px;
	background: currentColor;
	transition: transform 0.25s var(--sw-ease), opacity 0.2s var(--sw-ease);
	content: "";
}

.sw-nav-toggle__bars::before {
	transform: translateY(-6px);
}

.sw-nav-toggle__bars::after {
	transform: translateY(4px);
}

/* Bars fold into a cross while the drawer is open. */
.sw-site-header.is-nav-open .sw-nav-toggle__bars {
	background: transparent;
}

.sw-site-header.is-nav-open .sw-nav-toggle__bars::before {
	transform: translateY(0) rotate(45deg);
}

.sw-site-header.is-nav-open .sw-nav-toggle__bars::after {
	transform: translateY(-2px) rotate(-45deg);
}

/* The per-parent `.sw-submenu-toggle` disclosure button that used to live here
   is gone, along with the JS that injected it — the drawer now shows submenus
   as a permanently visible indented list, so there is no state to disclose.
   See the compact-header block below and js/header.js §3. */

.sw-site-header a:focus-visible,
.sw-site-header button:focus-visible {
	outline: 2px solid var(--sw-blue-200);
	outline-offset: 3px;
}
/* ---- footer ------------------------------------------------------------- */

.sw-site-footer {
	background: var(--sw-footer);
	color: #7fa8c9;
	font-family: Inter, Helvetica, Arial, sans-serif;
	font-size: 15px;
	line-height: 1.85;
}

.sw-site-footer__inner {
	display: grid;
	grid-template-columns: 1.4fr 1fr 1fr 1.3fr;
	gap: 40px;
	width: 90%;
	max-width: 1240px;
	margin: 0 auto;
	padding: 70px 0 34px;
}

.sw-site-footer__logo {
	display: inline-block;
	line-height: 0;
}

.sw-site-footer__logo img {
	display: block;
	width: auto;
	max-width: 240px;
	max-height: 56px;
}

.sw-site-footer__about {
	margin: 16px 0 20px;
	max-width: 320px;
}

.sw-site-footer h4 {
	margin: 0 0 14px;
	padding: 0;
	color: #fff;
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 17px;
	font-weight: 700;
	line-height: 1.4;
}

.sw-site-footer .sw-footer-links {
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-site-footer .sw-footer-links li {
	margin-bottom: 8px;
}

.sw-site-footer .sw-footer-links a {
	color: #7fa8c9;
	text-decoration: none;
	transition: color 0.2s var(--sw-ease);
}

.sw-site-footer .sw-footer-links a:hover {
	color: #fff;
}

.sw-social-list {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-social-list a {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 34px;
	height: 34px;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.07);
	color: #c3dbef;
	font-size: 13px;
	font-weight: 700;
	text-decoration: none;
	transition: transform 0.25s var(--sw-ease), background-color 0.25s var(--sw-ease);
}

.sw-social-list a:hover {
	transform: translateY(-2px);
	background: var(--sw-blue);
	color: #fff;
}

.sw-site-footer__bar {
	border-top: 1px solid var(--sw-border-dark);
}

.sw-site-footer__inner--bar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding: 22px 0;
	font-size: 14px;
	color: #6a8299;
}

.sw-site-footer__bar a {
	color: #6a8299;
	text-decoration: none;
}

.sw-site-footer__bar a:hover {
	color: #fff;
}

/* ---- responsive --------------------------------------------------------- */

@media (max-width: 980px) {
	/* Two rows: the bar itself, then the drawer. The CTA is not duplicated
	   into the drawer — it is the same element, moved to its own row. The old
	   layout kept it in the bar next to a 44px burger and a 260px logo, which
	   together overflowed a 390px phone and pushed the button off-screen. */
	.sw-site-header__inner {
		grid-template-columns: minmax(0, 1fr) auto;
		gap: 0 12px;
		min-height: 64px;
	}

	.sw-site-header.is-scrolled .sw-site-header__inner {
		min-height: 58px;
	}

	.sw-site-header__logo img,
	.sw-site-header.is-scrolled .sw-site-header__logo img {
		height: 34px;
	}

	.sw-nav-toggle {
		display: flex;
		grid-column: 2;
		grid-row: 1;
	}

	.sw-site-nav {
		grid-column: 1 / -1;
		grid-row: 2;
		display: block;
	}

	.sw-site-header__cta {
		grid-column: 1 / -1;
		grid-row: 3;
		justify-self: stretch;
		padding-bottom: 16px;
	}

	.sw-site-header__cta .sw-btn {
		width: 100%;
	}

	/* Collapse only once the script is running. Without JS the class stays
	   `no-js`, the drawer rows render open, and the menu is still usable —
	   long, but never stuck shut behind a button nothing is listening to. */
	.js .sw-site-nav,
	.js .sw-site-header__cta {
		display: none;
	}

	.js .sw-site-header.is-nav-open .sw-site-nav {
		display: block;
	}

	.js .sw-site-header.is-nav-open .sw-site-header__cta {
		display: block;
	}

	.sw-site-nav .sw-menu {
		flex-direction: column;
		align-items: stretch;
		margin: 0;
		padding: 8px 0 12px;
		border-top: 1px solid var(--sw-border-dark);
	}

	.sw-site-nav .sw-menu > li > a {
		border-radius: 8px;
		padding: 12px 12px;
		white-space: normal;
	}

	/* The drawer's caret-hiding rule is gone too — the caret itself no longer
	   exists at any width, so there is nothing here to hide. */

	.sw-site-nav .sw-menu > li.current-menu-item > a::before,
	.sw-site-nav .sw-menu > li.current_page_item > a::before {
		left: 12px;
		right: auto;
		bottom: auto;
		top: 12px;
		width: 3px;
		height: calc(100% - 24px);
	}

	/* Submenus become an inline, indented list gated by the disclosure button —
	   hover never fires on touch, so a submenu that is hidden here and opened
	   only on :hover leaves every child link unreachable on a phone. That was a
	   real bug once, and it is the reason this list is ALWAYS VISIBLE rather
	   than gated: the disclosure button that used to gate it has been removed,
	   and `display: block` needs no script and cannot be got wrong.

	   The trade is a taller drawer. If it ever needs collapsing again, it needs
	   a real control — :hover is not one on touch. */
	.sw-site-nav .sw-menu ul,
	.sw-site-nav .sw-menu ul:has(> li:nth-child(7)) {
		display: block;
		position: static;
		min-width: 0;
		padding: 0 0 6px 12px;
		border: 0;
		border-radius: 0;
		background: transparent;
		box-shadow: none;
		opacity: 1;
		visibility: visible;
		transform: none;
	}

	.sw-site-nav .sw-menu > li:hover > ul,
	.sw-site-nav .sw-menu > li:focus-within > ul {
		transform: none;
	}

	.sw-site-footer__inner {
		grid-template-columns: 1fr 1fr;
		gap: 32px;
	}
}

@media (max-width: 767px) {
	.sw-site-footer__inner {
		grid-template-columns: 1fr;
		gap: 28px;
		padding: 48px 0 24px;
	}

	.sw-site-footer__inner--bar {
		flex-direction: column;
		align-items: flex-start;
		padding: 18px 0;
	}
}

/* ===========================================================================
   16. Page templates — shared shell (page-services.php / page-solutions.php)
   ---------------------------------------------------------------------------
   Standalone PHP templates, so nothing here depends on Divi module classes.
   Shared shell, typography, buttons, accent tokens, core-service cards and
   process steps; page-specific sections follow in their own blocks.
   Colours come from the brand blue ramp in :root, never from the mockups.
   =========================================================================== */

.sw-page {
	--sw-accent: var(--sw-blue);
	font-family: Inter, Helvetica, Arial, sans-serif;
	color: var(--sw-muted);
}

.sw-page .sw-shell {
	width: 90%;
	max-width: 1180px;
	margin: 0 auto;
}

/* Per-service accent, set once and consumed by icon, checks and links. */
.sw-accent--purple { --sw-accent: #085296; --sw-accent-soft: #d6e6f4; }
.sw-accent--green  { --sw-accent: #2a6fad; --sw-accent-soft: #deebf6; }
.sw-accent--orange { --sw-accent: #5b9bd5; --sw-accent-soft: #e6f0f8; }
.sw-accent--blue   { --sw-accent: #085296; --sw-accent-soft: #eef5fb; }

.sw-page h1,
.sw-page h2,
.sw-page h3 {
	font-family: Manrope, Helvetica, Arial, sans-serif;
	color: var(--sw-slate);
	letter-spacing: -0.4px;
	margin: 0;
	padding: 0;
}

.sw-icon { flex: 0 0 auto; }

/* ---- shared bits -------------------------------------------------------- */

.sw-page .sw-eyebrow {
	margin: 0 0 12px;
	color: var(--sw-indigo);
	font-size: 12px;
	font-weight: 700;
	letter-spacing: 2px;
	text-transform: uppercase;
}

.sw-page .sw-eyebrow--dark { color: #9bc2e5; }

.sw-sec-head {
	max-width: 720px;
	margin: 0 auto 44px;
	text-align: center;
}

.sw-sec-head h2 {
	font-size: 36px;
	font-weight: 800;
	line-height: 1.2;
}

.sw-sec-head__sub {
	margin: 14px 0 0;
	font-size: 16px;
	line-height: 1.75;
}

.sw-btn-row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 14px;
}

.sw-btn-row--end { justify-content: flex-end; }

.sw-page .sw-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.55em;
	min-height: 52px;
	padding: 0 26px;
	border: 1px solid transparent;
	border-radius: 8px;
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 15px;
	font-weight: 700;
	line-height: 1.2;
	text-decoration: none;
	white-space: nowrap;
	transition: transform 0.25s var(--sw-ease), box-shadow 0.25s var(--sw-ease),
		background-color 0.25s var(--sw-ease), border-color 0.25s var(--sw-ease);
}

.sw-page .sw-btn:hover { transform: translateY(-2px); }

.sw-page .sw-btn--primary {
	color: #fff;
	background: linear-gradient(90deg, #085296 0%, #5b9bd5 100%);
	box-shadow: 0 16px 34px -18px rgba(8, 82, 150, 0.9);
}

.sw-page .sw-btn--primary:hover {
	box-shadow: 0 22px 46px -20px rgba(8, 82, 150, 0.95);
}

.sw-page .sw-btn--outline-dark {
	color: #fff;
	background: rgba(255, 255, 255, 0.02);
	border-color: rgba(255, 255, 255, 0.28);
}

.sw-page .sw-btn--outline-dark:hover {
	background: rgba(255, 255, 255, 0.09);
	border-color: rgba(255, 255, 255, 0.45);
}

.sw-page .sw-btn--outline-light {
	color: var(--sw-slate);
	background: #fff;
	border-color: #dce9f5;
}

.sw-page .sw-btn--outline-light:hover { border-color: var(--sw-blue); }

/* ---- hero --------------------------------------------------------------- */

.sw-svc-hero {
	position: relative;
	overflow: hidden;
	background: #041f38;
	padding: 64px 0 72px;
}

.sw-svc-hero::before {
	content: "";
	position: absolute;
	top: -180px;
	right: -6%;
	width: 620px;
	height: 620px;
	border-radius: 50%;
	background: radial-gradient(circle, rgba(8, 82, 150, 0.3) 0%, rgba(8, 82, 150, 0) 68%);
	pointer-events: none;
}

.sw-svc-hero__grid {
	position: relative;
	z-index: 1;
	display: grid;
	grid-template-columns: 1fr 1fr;
	align-items: center;
	gap: 48px;
}

.sw-crumbs {
	margin-bottom: 26px;
	font-size: 14px;
	color: #6a8299;
}

.sw-crumbs a {
	color: #9bc2e5;
	text-decoration: none;
}

.sw-crumbs a:hover { text-decoration: underline; }
.sw-crumbs span { margin: 0 8px; }
.sw-crumbs span[aria-current] { margin: 0; color: #c3dbef; }

/* Prefixed with .sw-page to reach (0,2,0). The base rule
   `.sw-page h1, .sw-page h2, .sw-page h3 { color: var(--sw-slate) }` is
   (0,1,1), so a bare `.sw-sw-svc-hero__title` (0,1,0) lost to it and painted
   the headline near-black on a near-black hero. */
.sw-page .sw-svc-hero__title {
	margin: 0 0 18px;
	color: #fff;
	font-size: 46px;
	font-weight: 800;
	line-height: 1.14;
	letter-spacing: -1.2px;
}

.sw-svc-hero__lede {
	max-width: 460px;
	margin: 0 0 30px;
	color: var(--sw-muted-dark);
	font-size: 16px;
	line-height: 1.8;
}

/* Capped by height, not width — see .sw-ow-hero__visual img. A square image
   under a width cap sets the hero height on its own and leaves the copy column
   floating in dead space. */
.sw-svc-hero__visual img {
	display: block;
	width: auto;
	max-width: 100%;
	max-height: 400px;
	height: auto;
	margin-left: auto;
}

/* ---- core services ------------------------------------------------------ */

.sw-svc-core {
	background: var(--sw-light);
	padding: 76px 0;
}

.sw-svc-grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 22px;
	align-items: stretch;
}

.sw-svc-card {
	display: flex;
	flex-direction: column;
	padding: var(--sw-card-pad);
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-card-radius);
	box-shadow: var(--sw-card-shadow);
	transition: var(--sw-card-transition);
}

.sw-svc-card:hover {
	transform: translateY(-4px);
	box-shadow: var(--sw-card-shadow-hover);
	border-color: color-mix(in srgb, var(--sw-accent) 35%, transparent);
}

.sw-svc-card__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 50px;
	height: 50px;
	margin-bottom: 18px;
	border-radius: 50%;
	color: #fff;
	background: var(--sw-accent);
}

.sw-svc-card h3 {
	margin-bottom: 10px;
	font-size: 19px;
	font-weight: 800;
	line-height: 1.3;
}

.sw-svc-card > p {
	margin: 0 0 16px;
	font-size: 14px;
	line-height: 1.7;
}

.sw-page .sw-check-list {
	flex: 1 1 auto;
	list-style: none;
	margin: 0 0 18px;
	padding: 0;
}

.sw-page .sw-check-list li {
	display: flex;
	align-items: flex-start;
	gap: 9px;
	margin-bottom: 9px;
	font-size: 13.5px;
	line-height: 1.5;
	color: var(--sw-slate);
}

.sw-page .sw-check {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 17px;
	height: 17px;
	margin-top: 1px;
	border-radius: 50%;
	color: #fff;
	background: var(--sw-accent);
}

.sw-card-link {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	margin-top: auto;
	color: var(--sw-accent);
	font-size: 14px;
	font-weight: 700;
	text-decoration: none;
}

.sw-card-link:hover { gap: 11px; }

/* ---- automation tiles --------------------------------------------------- */

.sw-svc-auto {
	background: var(--sw-light);
	padding: 0 0 76px;
}

.sw-auto-grid {
	display: grid;
	grid-template-columns: repeat(12, 1fr);
	gap: 12px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-auto-tile {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: flex-start;
	gap: 10px;
	padding: 18px 8px 16px;
	background: #fff;
	border: 1px solid var(--sw-border-light);
	border-radius: 12px;
	text-align: center;
	transition: transform 0.25s var(--sw-ease), box-shadow 0.25s var(--sw-ease),
		border-color 0.25s var(--sw-ease);
}

.sw-auto-tile:hover {
	transform: translateY(-3px);
	box-shadow: var(--sw-shadow-md);
	border-color: rgba(8, 82, 150, 0.3);
}

.sw-auto-tile__icon { color: var(--sw-indigo); }

.sw-auto-tile__label {
	font-size: 11.5px;
	font-weight: 600;
	line-height: 1.4;
	color: var(--sw-slate);
	/* Two lines reserved so all twelve tiles match height. */
	min-height: 2.8em;
}

/* ---- process ------------------------------------------------------------ */

.sw-svc-process {
	background: var(--sw-light-alt);
	padding: 72px 0;
}

.sw-steps {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 24px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-step-item {
	position: relative;
	text-align: center;
}

.sw-step-item__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 62px;
	height: 62px;
	margin: 0 auto 14px;
	border-radius: 50%;
	color: #fff;
	background: var(--sw-accent);
	box-shadow: 0 16px 30px -16px var(--sw-accent);
}

.sw-step-item__num {
	display: block;
	margin-bottom: 4px;
	color: var(--sw-accent);
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 17px;
	font-weight: 800;
}

.sw-step-item h3 {
	margin-bottom: 6px;
	font-size: 17px;
	font-weight: 700;
}

.sw-step-item p {
	margin: 0;
	font-size: 13.5px;
	line-height: 1.65;
}

/* Connector arrow between steps. */
.sw-step-item:not(:last-child)::after {
	content: "→";
	position: absolute;
	top: 22px;
	right: -18px;
	font-size: 19px;
	line-height: 1;
	color: #9bc2e5;
}

/* ---- closing CTA -------------------------------------------------------- */

.sw-svc-cta {
	background: #063355;
	padding: 56px 0;
}

.sw-svc-cta__grid {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 36px;
}

.sw-svc-cta h2 {
	max-width: 420px;
	margin-bottom: 10px;
	color: #fff;
	font-size: 30px;
	font-weight: 800;
	line-height: 1.25;
}

.sw-svc-cta p {
	max-width: 460px;
	margin: 0;
	color: #9bc2e5;
	font-size: 15px;
	line-height: 1.75;
}

/* ---- page content fallback ---------------------------------------------- */

.sw-svc-content {
	background: #fff;
	padding: 56px 0;
}

/* ---- responsive --------------------------------------------------------- */

@media (max-width: 1100px) {
	.sw-auto-grid { grid-template-columns: repeat(6, 1fr); }
}

@media (max-width: 980px) {
	.sw-svc-hero { padding: 48px 0 56px; }

	.sw-svc-hero__grid {
		grid-template-columns: 1fr;
		gap: 36px;
	}

	.sw-svc-hero__title { font-size: 38px; }
	.sw-svc-hero__visual img { margin: 0 auto; max-width: 420px; }

	.sw-svc-grid { grid-template-columns: repeat(2, 1fr); }
	.sw-sec-head h2 { font-size: 30px; }

	.sw-steps { grid-template-columns: repeat(2, 1fr); row-gap: 36px; }
	.sw-step-item:not(:last-child)::after { display: none; }

	.sw-svc-cta__grid {
		flex-direction: column;
		align-items: flex-start;
	}

	.sw-btn-row--end { justify-content: flex-start; }
}

@media (max-width: 767px) {
	.sw-svc-hero__title { font-size: 30px; }
	.sw-svc-grid { grid-template-columns: 1fr; }
	.sw-auto-grid { grid-template-columns: repeat(3, 1fr); }
	.sw-steps { grid-template-columns: 1fr; }
	.sw-sec-head h2 { font-size: 26px; }
	.sw-svc-cta h2 { font-size: 25px; }

	.sw-btn-row { width: 100%; }
	.sw-page .sw-btn { width: 100%; }
}

/* ===========================================================================
   17. Solutions page — Divi Builder layout (SeriousWeb_Solutions_Page.json)
   ---------------------------------------------------------------------------
   Real Divi sections/rows/columns, so Divi supplies the grid, gutters and
   responsive stacking. These rules only add the visual design on top, via the
   sw- classes set in each module's CSS Class field.

   Section rhythm follows the Solutions mockup; the colours are ramp steps —
   dark --sw-navy-900, light --sw-blue-25, closing CTA --sw-navy-850.
   =========================================================================== */

.sw-crumbs p { margin: 0; }
.sw-crumbs a { text-decoration: none; }
.sw-crumbs a:hover { text-decoration: underline; }
.sw-crumbs span { padding: 0 8px; opacity: 0.5; }

/* ---- core solution cards ------------------------------------------------ */

.sw-sol-card .et_pb_main_blurb_image { margin-bottom: 16px; }

.sw-sol-card .et_pb_main_blurb_image .et-pb-icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 50px;
	height: 50px;
	font-size: 26px;
	line-height: 1;
	border-radius: 50%;
	color: #fff !important;
	background: var(--sw-accent, var(--sw-blue));
}

.sw-sol-card .et_pb_module_header { margin-bottom: 10px; }

.sw-sol-card:hover {
	transform: translateY(-4px);
	box-shadow: var(--sw-shadow-md);
	border-color: var(--sw-accent, var(--sw-blue)) !important;
}

.sw-sol-card {
	transition: transform 0.3s var(--sw-ease), box-shadow 0.3s var(--sw-ease),
		border-color 0.3s var(--sw-ease);
}

/* Checklists inside the cards. The tick is drawn with CSS so the layout has no
   icon-font dependency. */
.sw-sol-card .sw-check-list {
	list-style: none;
	margin: 14px 0 0;
	padding: 0;
}

.sw-sol-card .sw-check-list li {
	position: relative;
	padding-left: 26px;
	margin-bottom: 9px;
	font-size: 13.5px;
	line-height: 1.5;
	color: var(--sw-slate);
}

.sw-sol-card .sw-check-list li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.15em;
	width: 17px;
	height: 17px;
	border-radius: 50%;
	background: var(--sw-accent, var(--sw-blue));
}

.sw-sol-card .sw-check-list li::after {
	content: "";
	position: absolute;
	left: 5.5px;
	top: 0.42em;
	width: 5px;
	height: 8px;
	border: solid #fff;
	border-width: 0 2px 2px 0;
	transform: rotate(45deg);
}

.sw-sol-card .sw-card-more a { color: var(--sw-accent, var(--sw-blue)); }

/* ---- why-band ----------------------------------------------------------- */

.sw-why-item .et_pb_main_blurb_image { margin-right: 14px; }

.sw-why-item .et_pb_main_blurb_image .et-pb-icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 42px;
	height: 42px;
	font-size: 20px;
	line-height: 1;
	border-radius: 50%;
	color: #fff !important;
	background: color-mix(in srgb, var(--sw-accent, var(--sw-blue)) 22%, transparent);
	box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--sw-accent, var(--sw-blue)) 45%, transparent);
}

.sw-why-item .et-pb-icon { color: var(--sw-accent, var(--sw-blue)) !important; }
.sw-why-item .et_pb_module_header { margin-bottom: 3px; }
.sw-why-item p:last-child { margin-bottom: 0; }

/* ---- featured solutions ------------------------------------------------- */

.sw-featured-head { align-items: center; }

.sw-head-cta { display: flex; align-items: center; justify-content: flex-end; }
.sw-head-cta .et_pb_button_module_wrapper { margin-bottom: 0; }

.sw-row--projects > .et_pb_column.sw-proj-card {
	display: flex;
	flex-direction: column;
	background: rgba(255, 255, 255, 0.035);
	border: 1px solid rgba(255, 255, 255, 0.09);
	border-radius: 14px;
	overflow: hidden;
	transition: transform 0.3s var(--sw-ease), border-color 0.3s var(--sw-ease),
		background-color 0.3s var(--sw-ease);
}

.sw-row--projects > .et_pb_column.sw-proj-card:hover {
	transform: translateY(-4px);
	background: rgba(255, 255, 255, 0.06);
	border-color: rgba(8, 82, 150, 0.45);
}

.sw-proj-img { margin-bottom: 0 !important; }

.sw-proj-img img {
	display: block;
	width: 100%;
	height: auto;
}

.sw-proj-body {
	flex: 1 1 auto;
	padding: 18px 18px 20px;
	margin-bottom: 0 !important;
}

.sw-proj-body h3 { margin: 0 0 8px; padding-bottom: 0; }
.sw-proj-body p { margin-bottom: 0; }
.sw-proj-body .sw-card-more a { color: #9bc2e5; }

/* ---- responsive --------------------------------------------------------- */

@media (min-width: 981px) {
	.sw-row--sol-cards,
	.sw-row--why,
	.sw-row--projects,
	.sw-row--steps {
		display: flex;
		align-items: stretch;
	}

	.sw-row--sol-cards > .et_pb_column,
	.sw-row--why > .et_pb_column,
	.sw-row--projects > .et_pb_column {
		display: flex;
	}

	.sw-row--sol-cards > .et_pb_column > .sw-sol-card,
	.sw-row--why > .et_pb_column > .sw-why-item { width: 100%; }
}

@media (max-width: 980px) {
	.sw-head-cta { justify-content: flex-start; margin-top: 18px; }

	.sw-row--sol-cards > .et_pb_column,
	.sw-row--why > .et_pb_column,
	.sw-row--projects > .et_pb_column { display: block; }

	.sw-row--projects > .et_pb_column.sw-proj-card { display: flex; }
}

/* ===========================================================================
   18. Solutions page template (templates/page-solutions.php)
   ---------------------------------------------------------------------------
   Reuses the shared shell from section 16 (.sw-page, .sw-btn, .sw-sec-head,
   .sw-svc-card, .sw-check-list, .sw-steps). Only the sections unique to this
   page are defined here: hero chips, the dark "why" band, featured solutions
   and the closing CTA.

   Section rhythm follows the Solutions mockup; the colours are ramp steps —
   dark --sw-navy-900, light --sw-blue-25, closing CTA --sw-navy-850.
   =========================================================================== */

.sw-page--solutions .sw-accent--violet { --sw-accent: #5b9bd5; --sw-accent-soft: #d6e6f4; }

/* ---- hero --------------------------------------------------------------- */

.sw-sol-hero {
	position: relative;
	overflow: hidden;
	background: #041f38;
	padding: 56px 0 64px;
}

.sw-sol-hero::before {
	content: "";
	position: absolute;
	top: -200px;
	right: -4%;
	width: 640px;
	height: 640px;
	border-radius: 50%;
	background: radial-gradient(circle, rgba(8, 82, 150, 0.28) 0%, rgba(8, 82, 150, 0) 68%);
	pointer-events: none;
}

.sw-sol-hero__grid {
	position: relative;
	z-index: 1;
	display: grid;
	grid-template-columns: 1fr 1fr;
	align-items: center;
	gap: 48px;
}

/* Prefixed with .sw-page to reach (0,2,0). The base rule
   `.sw-page h1, .sw-page h2, .sw-page h3 { color: var(--sw-slate) }` is
   (0,1,1), so a bare `.sw-sw-sol-hero__title` (0,1,0) lost to it and painted
   the headline near-black on a near-black hero. */
.sw-page .sw-sol-hero__title {
	margin: 0 0 18px;
	color: #fff;
	font-size: 46px;
	font-weight: 800;
	line-height: 1.14;
	letter-spacing: -1.2px;
}

.sw-sol-hero__lede {
	max-width: 470px;
	margin: 0 0 30px;
	color: var(--sw-muted-dark);
	font-size: 16px;
	line-height: 1.8;
}

/* Capped by height, not width — see .sw-ow-hero__visual img. A square image
   under a width cap sets the hero height on its own and leaves the copy column
   floating in dead space. */
.sw-sol-hero__visual img {
	display: block;
	width: auto;
	max-width: 100%;
	max-height: 400px;
	height: auto;
	margin-left: auto;
}

/* Trust chips under the hero CTAs. */
.sw-sol-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 12px 26px;
	list-style: none;
	margin: 30px 0 0;
	padding: 0;
}

.sw-sol-chips li {
	display: flex;
	align-items: center;
	gap: 9px;
	color: #c3dbef;
	font-size: 14px;
	font-weight: 600;
}

.sw-sol-chips__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 26px;
	height: 26px;
	border-radius: 50%;
	color: #9bc2e5;
	background: rgba(8, 82, 150, 0.16);
	box-shadow: inset 0 0 0 1px rgba(8, 82, 150, 0.4);
}

/* ---- why band ----------------------------------------------------------- */

.sw-why {
	background: #041f38;
	padding: 44px 0;
}

.sw-why__kicker {
	margin-bottom: 26px;
	text-align: center;
}

.sw-why__grid {
	display: grid;
	grid-template-columns: repeat(5, 1fr);
	gap: 26px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-why__item {
	display: flex;
	align-items: flex-start;
	gap: 13px;
}

.sw-why__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 42px;
	height: 42px;
	border-radius: 50%;
	color: var(--sw-accent, var(--sw-blue));
	background: rgba(255, 255, 255, 0.05);
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.09);
}

.sw-why__body { display: block; }

.sw-why__body strong {
	display: block;
	margin-bottom: 3px;
	color: #fff;
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 15px;
	font-weight: 700;
	line-height: 1.35;
}

.sw-why__body span {
	display: block;
	color: #7fa8c9;
	font-size: 12.5px;
	line-height: 1.55;
}

/* ---- featured solutions ------------------------------------------------- */

.sw-featured {
	background: #041f38;
	padding: 62px 0;
}

.sw-featured__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
	margin-bottom: 30px;
}

.sw-featured__head h2 {
	margin: 0;
	color: #fff;
	font-size: 30px;
	font-weight: 800;
	line-height: 1.25;
}

.sw-featured__grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 20px;
	align-items: stretch;
}

.sw-proj {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	background: rgba(255, 255, 255, 0.035);
	border: 1px solid rgba(255, 255, 255, 0.09);
	border-radius: 14px;
	transition: transform 0.3s var(--sw-ease), background-color 0.3s var(--sw-ease),
		border-color 0.3s var(--sw-ease);
}

.sw-proj:hover {
	transform: translateY(-4px);
	background: rgba(255, 255, 255, 0.06);
	border-color: rgba(8, 82, 150, 0.45);
}

.sw-proj__media { display: block; line-height: 0; }

.sw-proj__media img {
	display: block;
	width: 100%;
	height: auto;
}

.sw-proj__body {
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
	padding: 18px 18px 20px;
}

.sw-proj__body h3 {
	margin: 0 0 8px;
	color: #fff;
	font-size: 17px;
	font-weight: 700;
	line-height: 1.3;
}

.sw-proj__body p {
	flex: 1 1 auto;
	margin: 0 0 12px;
	color: var(--sw-muted-dark);
	font-size: 13.5px;
	line-height: 1.65;
}

.sw-proj__body .sw-card-link { color: #9bc2e5; }

/* ---- closing CTA -------------------------------------------------------- */

.sw-sol-cta {
	background: #052846;
	padding: 54px 0;
}

.sw-sol-cta__grid {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 36px;
}

.sw-sol-cta h2 {
	max-width: 430px;
	margin: 0 0 10px;
	color: #fff;
	font-size: 29px;
	font-weight: 800;
	line-height: 1.25;
}

.sw-sol-cta p {
	max-width: 440px;
	margin: 0;
	color: #9bc2e5;
	font-size: 15px;
	line-height: 1.75;
}

/* ---- responsive --------------------------------------------------------- */

@media (max-width: 1100px) {
	.sw-why__grid { grid-template-columns: repeat(3, 1fr); row-gap: 22px; }
}

@media (max-width: 980px) {
	.sw-sol-hero { padding: 44px 0 52px; }

	.sw-sol-hero__grid {
		grid-template-columns: 1fr;
		gap: 34px;
	}

	/* Prefixed to match the (0,2,0) of the base rule above. A media query adds
	   no specificity, so the bare selector lost to it and the headline stayed
	   46px at every width. */
	.sw-page .sw-sol-hero__title { font-size: 38px; }
	.sw-sol-hero__visual img { margin: 0 auto; max-width: 420px; }

	.sw-why__grid { grid-template-columns: repeat(2, 1fr); }

	.sw-featured__head { flex-direction: column; align-items: flex-start; }
	.sw-featured__grid { grid-template-columns: repeat(2, 1fr); }

	.sw-sol-cta__grid { flex-direction: column; align-items: flex-start; }
}

@media (max-width: 767px) {
	.sw-page .sw-sol-hero__title { font-size: 30px; }
	.sw-sol-chips { gap: 10px 18px; }
	.sw-why__grid { grid-template-columns: 1fr; }
	.sw-featured__grid { grid-template-columns: 1fr; }
	.sw-featured__head h2 { font-size: 25px; }
	.sw-sol-cta h2 { font-size: 24px; }
}

/* ===========================================================================
   19. Websites & Web Development page (templates/page-websites.php)
   ---------------------------------------------------------------------------
   Reuses the shared shell from section 16 (.sw-page, .sw-btn, .sw-sec-head,
   .sw-steps, .sw-crumbs) and the hero chips from section 18.

   Section rhythm follows the mockup; the colours are ramp steps — hero
   --sw-navy-950, trusted strip and feature band at the light end, recent work
   white, tech band --sw-navy-850, CTA --sw-navy-800.
   This page has six feature cards and five process steps.
   =========================================================================== */

/* Pastel tile tints for the feature cards. */
.sw-tint--pink   { --sw-tint: #d6e6f4; --sw-accent: #2a6fad; }
.sw-tint--blue   { --sw-tint: #eef5fb; --sw-accent: #2a6fad; }
.sw-tint--green  { --sw-tint: #deebf6; --sw-accent: #2a6fad; }
.sw-tint--orange { --sw-tint: #e6f0f8; --sw-accent: #5b9bd5; }
.sw-tint--purple { --sw-tint: #d6e6f4; --sw-accent: #2a6fad; }
.sw-tint--indigo { --sw-tint: #deebf6; --sw-accent: #2a6fad; }

.sw-page--websites .sw-accent--violet { --sw-accent: #2a6fad; }
.sw-page--websites .sw-accent--purple { --sw-accent: #085296; }
.sw-page--websites .sw-accent--blue   { --sw-accent: #2a6fad; }
.sw-page--websites .sw-accent--green  { --sw-accent: #2a6fad; }
.sw-page--websites .sw-accent--orange { --sw-accent: #7dafdd; }

/* ---- hero --------------------------------------------------------------- */

.sw-web-hero {
	position: relative;
	overflow: hidden;
	background: #03182c;
	padding: 56px 0 64px;
}

.sw-web-hero::before {
	content: "";
	position: absolute;
	top: -220px;
	right: -8%;
	width: 680px;
	height: 680px;
	border-radius: 50%;
	background: radial-gradient(circle, rgba(8, 82, 150, 0.26) 0%, rgba(8, 82, 150, 0) 68%);
	pointer-events: none;
}

.sw-web-hero__grid {
	position: relative;
	z-index: 1;
	display: grid;
	grid-template-columns: 0.95fr 1.05fr;
	align-items: center;
	gap: 44px;
}

/* Prefixed with .sw-page to reach (0,2,0). The base rule
   `.sw-page h1, .sw-page h2, .sw-page h3 { color: var(--sw-slate) }` is
   (0,1,1), so a bare `.sw-sw-web-hero__title` (0,1,0) lost to it and painted
   the headline near-black on a near-black hero. */
.sw-page .sw-web-hero__title {
	margin: 0 0 18px;
	color: #fff;
	font-size: 44px;
	font-weight: 800;
	line-height: 1.16;
	letter-spacing: -1.2px;
}

.sw-web-hero__lede {
	max-width: 460px;
	margin: 0 0 22px;
	color: var(--sw-muted-dark);
	font-size: 16px;
	line-height: 1.8;
}

.sw-web-hero .sw-sol-chips { margin: 0 0 26px; }

.sw-web-hero__visual img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: 14px;
	border: 1px solid rgba(255, 255, 255, 0.1);
	box-shadow: 0 34px 70px -34px rgba(8, 82, 150, 0.6);
}

/* ---- trusted-by strip --------------------------------------------------- */

.sw-web-trusted {
	background: #f8fbfd;
	padding: 40px 0;
}

.sw-web-trusted__kicker {
	margin-bottom: 22px;
	text-align: center;
}

.sw-web-trusted__grid {
	display: grid;
	grid-template-columns: repeat(6, 1fr);
	align-items: center;
	gap: 24px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-web-trusted__grid img {
	display: block;
	width: auto;
	max-width: 100%;
	max-height: 40px;
	margin: 0 auto;
	filter: grayscale(100%);
	opacity: 0.55;
	transition: filter 0.25s var(--sw-ease), opacity 0.25s var(--sw-ease);
}

.sw-web-trusted__grid img:hover {
	filter: grayscale(0);
	opacity: 1;
}

/* ---- feature cards ------------------------------------------------------ */

.sw-web-features {
	background: #f5f9fc;
	padding: 62px 0 56px;
}

.sw-web-features__grid {
	display: grid;
	grid-template-columns: repeat(6, 1fr);
	gap: 16px;
	align-items: stretch;
}

.sw-web-card {
	display: flex;
	flex-direction: column;
	align-items: center;
	padding: var(--sw-card-pad);
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-card-radius);
	text-align: center;
	box-shadow: var(--sw-card-shadow);
	transition: var(--sw-card-transition);
}

.sw-web-card:hover {
	transform: translateY(-4px);
	box-shadow: var(--sw-card-shadow-hover);
	border-color: var(--sw-accent);
}

.sw-web-card__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 52px;
	height: 52px;
	margin-bottom: 16px;
	border-radius: 14px;
	color: var(--sw-accent);
	background: var(--sw-tint);
}

.sw-web-card h3 {
	margin: 0 0 10px;
	font-size: 15.5px;
	font-weight: 800;
	line-height: 1.35;
}

.sw-web-card p {
	margin: 0;
	font-size: 12.5px;
	line-height: 1.65;
}

/* ---- process (five steps) ----------------------------------------------- */

.sw-web-process {
	background: #f5f9fc;
	padding: 0 0 66px;
}

.sw-steps--five { grid-template-columns: repeat(5, 1fr); }

/* ---- recent websites ---------------------------------------------------- */

.sw-web-work {
	background: #ffffff;
	padding: 62px 0;
}

.sw-web-work__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
	margin-bottom: 28px;
}

.sw-web-work__head h2 {
	margin: 0;
	font-size: 29px;
	font-weight: 800;
	line-height: 1.25;
}

.sw-web-work__grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 20px;
	align-items: stretch;
}

.sw-web-proj {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	background: #fff;
	border: 1px solid var(--sw-border-light);
	border-radius: 14px;
	box-shadow: var(--sw-shadow-sm);
	transition: transform 0.3s var(--sw-ease), box-shadow 0.3s var(--sw-ease),
		border-color 0.3s var(--sw-ease);
}

.sw-web-proj:hover {
	transform: translateY(-4px);
	box-shadow: var(--sw-shadow-md);
	border-color: rgba(8, 82, 150, 0.35);
}

.sw-web-proj__media { display: block; line-height: 0; }

.sw-web-proj__media img {
	display: block;
	width: 100%;
	height: auto;
}

.sw-web-proj__body {
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
	padding: 16px 16px 18px;
}

.sw-web-proj__body h3 {
	margin: 0 0 3px;
	font-size: 16px;
	font-weight: 700;
	line-height: 1.3;
}

.sw-web-proj__type {
	flex: 1 1 auto;
	margin: 0 0 10px;
	font-size: 13px;
	line-height: 1.5;
}

/* ---- technologies band -------------------------------------------------- */

.sw-web-tech {
	background: #052846;
	border-radius: 16px;
	padding: 26px 0 24px;
	margin: 0 auto;
}

.sw-web-tech__kicker {
	margin-bottom: 20px;
	text-align: center;
}

.sw-web-tech__grid {
	display: grid;
	grid-template-columns: repeat(9, 1fr);
	gap: 12px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-web-tech__grid li {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 8px;
	padding: 0 4px;
	border-left: 1px solid rgba(255, 255, 255, 0.07);
}

.sw-web-tech__grid li:first-child { border-left: 0; }

/* Monogram rather than a brand logo — we don't ship third-party marks. */
.sw-web-tech__mark {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 34px;
	height: 34px;
	border-radius: 50%;
	color: #fff;
	background: rgba(255, 255, 255, 0.07);
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12);
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 14px;
	font-weight: 800;
}

.sw-web-tech__name {
	color: #9bc2e5;
	font-size: 11.5px;
	font-weight: 600;
	line-height: 1.4;
	text-align: center;
}

/* ---- closing CTA -------------------------------------------------------- */

.sw-web-cta {
	background: #063355;
	padding: 52px 0;
}

.sw-web-cta__grid {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 36px;
}

.sw-web-cta h2 {
	max-width: 400px;
	margin: 0 0 10px;
	color: #fff;
	font-size: 28px;
	font-weight: 800;
	line-height: 1.25;
}

.sw-web-cta p {
	max-width: 430px;
	margin: 0;
	color: #9bc2e5;
	font-size: 15px;
	line-height: 1.75;
}

/* ---- responsive --------------------------------------------------------- */

@media (max-width: 1100px) {
	.sw-web-features__grid { grid-template-columns: repeat(3, 1fr); }
	.sw-web-tech__grid { grid-template-columns: repeat(5, 1fr); row-gap: 20px; }
	.sw-web-tech__grid li:nth-child(5n + 1) { border-left: 0; }
}

@media (max-width: 980px) {
	.sw-web-hero { padding: 44px 0 52px; }

	.sw-web-hero__grid {
		grid-template-columns: 1fr;
		gap: 32px;
	}

	.sw-web-hero__title { font-size: 36px; }

	.sw-web-trusted__grid { grid-template-columns: repeat(3, 1fr); row-gap: 20px; }

	.sw-steps--five { grid-template-columns: repeat(2, 1fr); row-gap: 34px; }

	.sw-web-work__head { flex-direction: column; align-items: flex-start; }
	.sw-web-work__grid { grid-template-columns: repeat(2, 1fr); }

	.sw-web-cta__grid { flex-direction: column; align-items: flex-start; }
}

@media (max-width: 767px) {
	.sw-web-hero__title { font-size: 29px; }
	.sw-web-features__grid { grid-template-columns: repeat(2, 1fr); }
	.sw-web-trusted__grid { grid-template-columns: repeat(2, 1fr); }
	.sw-steps--five { grid-template-columns: 1fr; }
	.sw-web-work__grid { grid-template-columns: 1fr; }
	.sw-web-work__head h2 { font-size: 24px; }
	.sw-web-cta h2 { font-size: 24px; }

	.sw-web-tech__grid { grid-template-columns: repeat(3, 1fr); }
	.sw-web-tech__grid li { border-left: 0; }
}

/* ===========================================================================
   20. About Us page (templates/page-about.php)
   ---------------------------------------------------------------------------
   Reuses the shared shell from section 16 (.sw-page, .sw-btn, .sw-sec-head,
   .sw-crumbs, .sw-check-list) and the pastel tints from section 19.

   Section rhythm follows the mockup; the colours are ramp steps — hero
   --sw-navy-950, stats panel --sw-navy-900, body sections --sw-light,
   closing CTA --sw-navy-850.
   =========================================================================== */

.sw-tint--teal   { --sw-tint: #deebf6; --sw-accent: #7dafdd; }
.sw-tint--violet { --sw-tint: #d6e6f4; --sw-accent: #085296; }

/* ---- hero --------------------------------------------------------------- */

.sw-ab-hero {
	position: relative;
	background: #03182c;
	padding: 52px 0 0;
}

.sw-ab-hero__grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	align-items: start;
	gap: 46px;
}

/* Prefixed with .sw-page to reach (0,2,0). The base rule
   `.sw-page h1, .sw-page h2, .sw-page h3 { color: var(--sw-slate) }` is
   (0,1,1), so a bare `.sw-sw-ab-hero__title` (0,1,0) lost to it and painted
   the headline near-black on a near-black hero. */
.sw-page .sw-ab-hero__title {
	margin: 0 0 18px;
	color: #fff;
	font-size: 40px;
	font-weight: 800;
	line-height: 1.18;
	letter-spacing: -1.1px;
}

.sw-ab-hero__lede {
	max-width: 440px;
	margin: 0 0 14px;
	color: var(--sw-muted-dark);
	font-size: 15px;
	line-height: 1.8;
}

.sw-ab-hero__visual img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: 12px;
	border: 1px solid rgba(255, 255, 255, 0.08);
}

.sw-ab-trust {
	display: flex;
	flex-wrap: wrap;
	gap: 14px 34px;
	list-style: none;
	margin: 26px 0 0;
	padding: 0;
}

.sw-ab-trust li {
	display: flex;
	align-items: center;
	gap: 11px;
	color: var(--sw-muted-dark);
	font-size: 12.5px;
	line-height: 1.45;
}

.sw-ab-trust strong {
	display: block;
	color: #fff;
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 13px;
	font-weight: 700;
}

.sw-ab-trust__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 34px;
	height: 34px;
	border-radius: 9px;
	color: #9bc2e5;
	background: rgba(8, 82, 150, 0.14);
	box-shadow: inset 0 0 0 1px rgba(8, 82, 150, 0.32);
}

/* Stats panel, overlapping the hero's lower edge as in the mockup. */
.sw-ab-stats-wrap {
	position: relative;
	z-index: 2;
	display: flex;
	justify-content: flex-end;
	margin-top: -34px;
	transform: translateY(34px);
}

.sw-ab-stats {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 10px;
	width: 100%;
	max-width: 620px;
	margin: 0;
	padding: 20px 10px;
	list-style: none;
	background: #041f38;
	border: 1px solid rgba(255, 255, 255, 0.08);
	border-radius: var(--sw-card-radius);
	box-shadow: 0 30px 60px -30px rgba(0, 0, 0, 0.9);
}

.sw-ab-stats li {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 6px;
	text-align: center;
}

.sw-ab-stats__icon { color: #9bc2e5; }

.sw-ab-stats__value {
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 23px;
	font-weight: 800;
	line-height: 1.1;
	background: linear-gradient(100deg, #9bc2e5 0%, #9bc2e5 100%);
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
	color: #9bc2e5;
}

.sw-ab-stats__label {
	color: #9bc2e5;
	font-size: 11.5px;
	line-height: 1.4;
}

/* ---- mission ------------------------------------------------------------ */

.sw-ab-mission {
	background: #f2f7fb;
	padding: 76px 0 62px;
}

.sw-ab-mission__grid {
	display: grid;
	grid-template-columns: 0.85fr 1.15fr;
	gap: 46px;
	align-items: start;
}

.sw-ab-mission__copy h2 {
	margin: 0 0 16px;
	font-size: 30px;
	font-weight: 800;
	line-height: 1.25;
}

.sw-ab-mission__copy p {
	margin: 0 0 14px;
	font-size: 14.5px;
	line-height: 1.75;
}

.sw-ab-mission__copy .sw-btn { margin-top: 10px; }

.sw-ab-pillars {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 16px;
}

.sw-ab-pillar {
	padding: var(--sw-card-pad);
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-card-radius);
	box-shadow: var(--sw-card-shadow);
	transition: var(--sw-card-transition);
}

.sw-ab-pillar:hover {
	transform: translateY(-4px);
	box-shadow: var(--sw-card-shadow-hover);
	border-color: var(--sw-accent);
}

.sw-ab-pillar__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	margin-bottom: 14px;
	border-radius: 50%;
	color: var(--sw-accent);
	background: var(--sw-tint);
}

.sw-ab-pillar h3 {
	margin: 0 0 8px;
	font-size: 15px;
	font-weight: 800;
	line-height: 1.35;
}

.sw-ab-pillar p {
	margin: 0;
	font-size: 12.5px;
	line-height: 1.65;
}

/* ---- our work ----------------------------------------------------------- */

.sw-ab-work {
	background: #f2f7fb;
	padding: 0 0 70px;
}

.sw-ab-work__grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 18px;
	align-items: stretch;
}

.sw-ab-proj {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	background: #fff;
	border: 1px solid var(--sw-border-light);
	border-radius: 14px;
	box-shadow: var(--sw-shadow-sm);
	transition: transform 0.3s var(--sw-ease), box-shadow 0.3s var(--sw-ease),
		border-color 0.3s var(--sw-ease);
}

.sw-ab-proj:hover {
	transform: translateY(-4px);
	box-shadow: var(--sw-shadow-md);
	border-color: rgba(8, 82, 150, 0.35);
}

.sw-ab-proj__media { display: block; line-height: 0; }

.sw-ab-proj__media img {
	display: block;
	width: 100%;
	height: auto;
}

.sw-ab-proj__body {
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
	padding: 16px 16px 18px;
}

.sw-ab-proj__body h3 {
	margin: 0 0 8px;
	font-size: 15px;
	font-weight: 700;
	line-height: 1.35;
}

.sw-ab-proj__body p {
	flex: 1 1 auto;
	margin: 0 0 12px;
	font-size: 12.5px;
	line-height: 1.65;
}

.sw-ab-work__cta {
	margin: 30px 0 0;
	text-align: center;
}

.sw-ab-work__cta .sw-btn { display: inline-flex; }

/* ---- founder + company -------------------------------------------------- */

.sw-ab-founder {
	background: #f2f7fb;
	padding: 0 0 72px;
}

.sw-ab-founder__grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 22px;
	align-items: start;
}

.sw-ab-card {
	padding: var(--sw-card-pad);
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-card-radius);
	box-shadow: var(--sw-card-shadow);
}

.sw-ab-bio {
	display: grid;
	grid-template-columns: 140px 1fr;
	gap: 22px;
	align-items: start;
}

.sw-ab-bio__photo img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: 50%;
}

.sw-ab-bio__body h3 {
	margin: 0 0 3px;
	font-size: 22px;
	font-weight: 800;
	line-height: 1.25;
}

.sw-ab-bio__role {
	margin: 0 0 12px;
	color: var(--sw-slate);
	font-size: 13.5px;
	font-weight: 600;
}

.sw-ab-bio__body > p {
	margin: 0 0 14px;
	font-size: 13px;
	line-height: 1.7;
}

.sw-ab-bio .sw-check-list { margin-bottom: 16px; }
.sw-ab-bio .sw-check-list li { font-size: 12.5px; }
.sw-ab-bio { --sw-accent: #085296; }

.sw-ab-bio__place {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	margin: 0;
	padding: 8px 14px;
	border-radius: 8px;
	background: #f0f6fb;
	color: var(--sw-slate);
	font-size: 12.5px;
	font-weight: 600;
}

/* Company information list */
.sw-ab-company__list { margin: 4px 0 0; }

.sw-ab-company__row {
	display: grid;
	grid-template-columns: 190px 1fr;
	gap: 14px;
	padding: 9px 0;
	border-bottom: 1px solid #dce9f5;
}

.sw-ab-company__row:last-child { border-bottom: 0; }

.sw-ab-company__row dt {
	display: flex;
	align-items: center;
	gap: 9px;
	margin: 0;
	color: var(--sw-muted);
	font-size: 13px;
	font-weight: 500;
}

.sw-ab-company__icon { color: #6a8299; }

.sw-ab-company__row dd {
	margin: 0;
	color: var(--sw-slate);
	font-size: 13px;
	font-weight: 600;
	line-height: 1.6;
}

.sw-ab-company__row dd a { color: var(--sw-blue); text-decoration: none; }
.sw-ab-company__row dd a:hover { text-decoration: underline; }

/* ---- closing CTA -------------------------------------------------------- */

.sw-ab-cta {
	background: #052846;
	padding: 46px 0;
}

.sw-ab-cta__grid {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 36px;
}

.sw-ab-cta h2 {
	margin: 0 0 8px;
	color: #fff;
	font-size: 27px;
	font-weight: 800;
	line-height: 1.25;
}

.sw-ab-cta p {
	max-width: 420px;
	margin: 0;
	color: #9bc2e5;
	font-size: 14.5px;
	line-height: 1.7;
}

/* ---- responsive --------------------------------------------------------- */

@media (max-width: 1100px) {
	.sw-ab-pillars { grid-template-columns: repeat(2, 1fr); }
	.sw-ab-company__row { grid-template-columns: 160px 1fr; }
}

@media (max-width: 980px) {
	.sw-ab-hero { padding: 42px 0 0; }

	.sw-ab-hero__grid {
		grid-template-columns: 1fr;
		gap: 30px;
	}

	.sw-ab-hero__title { font-size: 33px; }

	.sw-ab-stats-wrap {
		justify-content: flex-start;
		margin-top: 26px;
		transform: translateY(30px);
	}

	.sw-ab-stats { max-width: none; }

	.sw-ab-mission { padding-top: 66px; }

	.sw-ab-mission__grid {
		grid-template-columns: 1fr;
		gap: 34px;
	}

	.sw-ab-work__grid { grid-template-columns: repeat(2, 1fr); }

	.sw-ab-founder__grid { grid-template-columns: 1fr; }

	.sw-ab-cta__grid { flex-direction: column; align-items: flex-start; }
}

@media (max-width: 767px) {
	.sw-ab-hero__title { font-size: 27px; }
	.sw-ab-stats { grid-template-columns: repeat(2, 1fr); row-gap: 20px; }
	.sw-ab-pillars { grid-template-columns: 1fr; }
	.sw-ab-work__grid { grid-template-columns: 1fr; }

	.sw-ab-bio {
		grid-template-columns: 1fr;
		justify-items: center;
		text-align: center;
	}

	.sw-ab-bio__photo { width: 130px; }
	.sw-ab-bio .sw-check-list li { text-align: left; }

	.sw-ab-company__row { grid-template-columns: 1fr; gap: 4px; }
	.sw-ab-cta h2 { font-size: 23px; }
}

/* ===========================================================================
   20b. About Us page — Divi builder layout
   ---------------------------------------------------------------------------
   Companion to section 20 for when the page is built from Divi modules
   (templates/jsonimports/SeriousWeb_About_Page.json) rather than
   templates/page-about.php. Section 20 owns the design; this block only
   re-attaches it to Divi's DOM, exactly as 21b does for Our Work.

   Each grid goes on a Divi COLUMN so its modules become direct grid children
   and section 20's grid rules apply unchanged. Cards are et_pb_blurb, so the
   rest is mapping Divi's blurb internals onto the class names section 20 wants:

     .et_pb_main_blurb_image  ->  .sw-ab-pillar__icon / .sw-ab-proj__media
     .et_pb_module_header     ->  the card's h3
     .et_pb_blurb_description ->  the card body

   This block is also embedded verbatim in the exported JSON's code module, so
   the layout imports correctly onto a host that has not had this stylesheet
   deployed yet. Keep the two copies in step.
   =========================================================================== */

.sw-ab-styles { display: none; }

/* ---- rows that need side-by-side columns --------------------------------- */

.sw-ab-hero .et_pb_row,
.sw-ab-mission .et_pb_row,
.sw-ab-founder .et_pb_row,
.sw-ab-cta .et_pb_row {
	display: flex;
	flex-wrap: wrap;
}

.sw-ab-hero .et_pb_row > .et_pb_column,
.sw-ab-mission .et_pb_row > .et_pb_column,
.sw-ab-founder .et_pb_row > .et_pb_column,
.sw-ab-cta .et_pb_row > .et_pb_column {
	float: none;
}

.sw-ab-cta .et_pb_row { align-items: center; }

/* ---- hero ---------------------------------------------------------------- */

.sw-ab-hero__visual .et_pb_image { margin: 0; }
.sw-ab-hero__visual .et_pb_image_wrap { display: block; }

.sw-ab-hero .et_pb_column.sw-ab-stats-wrap { float: none; }
.sw-ab-hero .sw-ab-stats-wrap .et_pb_module { margin-bottom: 0; }

/* ---- grids on columns ---------------------------------------------------- */

.et_pb_column.sw-ab-pillars,
.et_pb_column.sw-ab-work__grid {
	float: none;
	display: grid;
}

.sw-ab-pillars > .et_pb_module,
.sw-ab-work__grid > .et_pb_module {
	margin-bottom: 0;
}

.sw-ab-pillar .et_pb_blurb_content,
.sw-ab-proj .et_pb_blurb_content {
	max-width: none;
	width: 100%;
	margin: 0;
}

/* ---- pillar cards -------------------------------------------------------- */

.sw-ab-pillar.et_pb_blurb { margin: 0; text-align: left; }

.sw-ab-pillar .et_pb_main_blurb_image {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	margin: 0 0 14px;
	border-radius: 50%;
	line-height: 1;
}

.sw-ab-pillar .et_pb_blurb_container { text-align: left; }

.sw-ab-pillar .et_pb_module_header {
	margin: 0 0 7px;
	padding: 0;
	font-size: 15.5px;
	font-weight: 700;
	line-height: 1.3;
}

.sw-ab-pillar .et_pb_blurb_description p {
	margin: 0;
	font-size: 13px;
	line-height: 1.65;
}

/* ---- project cards ------------------------------------------------------- */

.sw-ab-proj.et_pb_blurb { margin: 0; text-align: left; }

.sw-ab-proj .et_pb_blurb_content {
	display: flex;
	flex-direction: column;
	height: 100%;
}

.sw-ab-proj .et_pb_main_blurb_image {
	display: block;
	margin: 0;
	line-height: 0;
}

.sw-ab-proj .et_pb_main_blurb_image .et_pb_image_wrap { display: block; }

.sw-ab-proj .et_pb_main_blurb_image img {
	display: block;
	width: 100%;
	height: auto;
}

.sw-ab-proj .et_pb_blurb_container {
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
	padding: 18px 18px 20px;
	text-align: left;
}

.sw-ab-proj .et_pb_module_header {
	margin: 0 0 8px;
	padding: 0;
	font-size: 16px;
	font-weight: 700;
	line-height: 1.3;
}

.sw-ab-proj .et_pb_blurb_description {
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
}

.sw-ab-proj .et_pb_blurb_description p {
	margin: 0 0 12px;
	font-size: 13px;
	line-height: 1.65;
}

/* ---- founder + company cards --------------------------------------------- */

.et_pb_column.sw-ab-card { float: none; }
.sw-ab-card > .et_pb_module:last-child { margin-bottom: 0; }
.sw-ab-bio .et_pb_image { margin: 0; }
.sw-ab-bio .et_pb_image_wrap { display: block; }

/* ---- closing CTA --------------------------------------------------------- */

.sw-ab-cta .sw-btn-row .et_pb_button_module_wrapper { display: inline-block; margin: 0 0 0 12px; }
.sw-ab-cta .sw-btn-row { text-align: right; }

@media (max-width: 980px) {
	.sw-ab-cta .sw-btn-row { text-align: left; }
	.sw-ab-cta .sw-btn-row .et_pb_button_module_wrapper { margin: 0 12px 0 0; }
}

/* ===========================================================================
   21. Our Work page (templates/page-our-work.php)
   ---------------------------------------------------------------------------
   Reuses the shared shell from section 16 and the five-step process grid from
   section 19.

   Section rhythm follows the mockup; the colours are ramp steps — hero
   --sw-navy-950, project band --sw-light, impact band --sw-navy-900,
   closing CTA --sw-navy-850.
   =========================================================================== */

/* ---- hero --------------------------------------------------------------- */

.sw-ow-hero {
	position: relative;
	overflow: hidden;
	background: #03182c;
	padding: 44px 0 48px;
}

.sw-ow-hero::before {
	content: "";
	position: absolute;
	top: -200px;
	right: -6%;
	width: 660px;
	height: 660px;
	border-radius: 50%;
	background: radial-gradient(circle, rgba(8, 82, 150, 0.26) 0%, rgba(8, 82, 150, 0) 68%);
	pointer-events: none;
}

.sw-ow-hero__grid {
	position: relative;
	z-index: 1;
	display: grid;
	grid-template-columns: 0.9fr 1.1fr;
	align-items: center;
	gap: 44px;
}

/* Prefixed with .sw-page to reach (0,2,0). The base rule
   `.sw-page h1, .sw-page h2, .sw-page h3 { color: var(--sw-slate) }` is
   (0,1,1), so a bare `.sw-sw-ow-hero__title` (0,1,0) lost to it and painted
   the headline near-black on a near-black hero. */
.sw-page .sw-ow-hero__title {
	margin: 0 0 16px;
	color: #fff;
	font-size: 42px;
	font-weight: 800;
	line-height: 1.16;
	letter-spacing: -1.2px;
}

.sw-ow-hero__lede {
	max-width: 440px;
	margin: 0 0 30px;
	color: var(--sw-muted-dark);
	font-size: 15px;
	line-height: 1.8;
}

/* Capped by height, not width. The art is square, so a 540px width cap made it
   540px tall — and since the copy column only needs ~400px, the image alone was
   setting the hero height and leaving the text floating in 70px of dead space
   top and bottom. Height is the dimension that actually matters here, and
   capping it works whatever aspect the image turns out to be. */
.sw-ow-hero__visual img {
	display: block;
	width: auto;
	max-width: 100%;
	max-height: 400px;
	height: auto;
	margin-left: auto;
}

.sw-ow-stats {
	display: grid;
	grid-template-columns: repeat(4, auto);
	justify-content: start;
	gap: 26px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-ow-stats li { display: block; }

.sw-ow-stats__icon {
	display: block;
	margin-bottom: 8px;
	color: #9bc2e5;
}

.sw-ow-stats__value {
	display: block;
	margin-bottom: 2px;
	color: #fff;
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 22px;
	font-weight: 800;
	line-height: 1.1;
}

.sw-ow-stats__label {
	display: block;
	color: #7fa8c9;
	font-size: 11.5px;
	line-height: 1.4;
}

/* ---- projects + CSS-only filter ----------------------------------------- */

.sw-ow-projects {
	background: #f5f9fc;
	padding: 46px 0 56px;
}

/* Radios drive the filter; they sit before .sw-shell so the :checked ~ rules
   can reach both the pills and the grid. */
.sw-ow-radio {
	position: absolute;
	width: 1px;
	height: 1px;
	opacity: 0;
	pointer-events: none;
}

.sw-ow-filter {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	margin-bottom: 26px;
}

.sw-ow-filter__pill {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 10px 16px;
	background: #fff;
	border: 1px solid var(--sw-border-light);
	border-radius: 8px;
	color: var(--sw-slate);
	font-size: 13px;
	font-weight: 600;
	cursor: pointer;
	transition: border-color 0.2s var(--sw-ease), color 0.2s var(--sw-ease),
		background-color 0.2s var(--sw-ease);
}

.sw-ow-filter__pill:hover { border-color: rgba(8, 82, 150, 0.5); }

.sw-ow-filter__pill .sw-icon { color: #6a8299; }

/* Active pill — one rule per category. */
#sw-filter-all:checked ~ .sw-shell .sw-ow-filter__pill[for="sw-filter-all"],
#sw-filter-web:checked ~ .sw-shell .sw-ow-filter__pill[for="sw-filter-web"],
#sw-filter-ai:checked ~ .sw-shell .sw-ow-filter__pill[for="sw-filter-ai"],
#sw-filter-automation:checked ~ .sw-shell .sw-ow-filter__pill[for="sw-filter-automation"],
#sw-filter-software:checked ~ .sw-shell .sw-ow-filter__pill[for="sw-filter-software"],
#sw-filter-integrations:checked ~ .sw-shell .sw-ow-filter__pill[for="sw-filter-integrations"] {
	color: #fff;
	background: linear-gradient(90deg, #085296 0%, #5b9bd5 100%);
	border-color: transparent;
	box-shadow: 0 12px 26px -14px rgba(8, 82, 150, 0.9);
}

#sw-filter-all:checked ~ .sw-shell .sw-ow-filter__pill[for="sw-filter-all"] .sw-icon,
#sw-filter-web:checked ~ .sw-shell .sw-ow-filter__pill[for="sw-filter-web"] .sw-icon,
#sw-filter-ai:checked ~ .sw-shell .sw-ow-filter__pill[for="sw-filter-ai"] .sw-icon,
#sw-filter-automation:checked ~ .sw-shell .sw-ow-filter__pill[for="sw-filter-automation"] .sw-icon,
#sw-filter-software:checked ~ .sw-shell .sw-ow-filter__pill[for="sw-filter-software"] .sw-icon,
#sw-filter-integrations:checked ~ .sw-shell .sw-ow-filter__pill[for="sw-filter-integrations"] .sw-icon {
	color: #fff;
}

/* Keyboard focus is otherwise invisible, since the radio itself is hidden. */
.sw-ow-radio:focus-visible ~ .sw-shell .sw-ow-filter__pill[for] { outline: none; }
#sw-filter-all:focus-visible ~ .sw-shell .sw-ow-filter__pill[for="sw-filter-all"],
#sw-filter-web:focus-visible ~ .sw-shell .sw-ow-filter__pill[for="sw-filter-web"],
#sw-filter-ai:focus-visible ~ .sw-shell .sw-ow-filter__pill[for="sw-filter-ai"],
#sw-filter-automation:focus-visible ~ .sw-shell .sw-ow-filter__pill[for="sw-filter-automation"],
#sw-filter-software:focus-visible ~ .sw-shell .sw-ow-filter__pill[for="sw-filter-software"],
#sw-filter-integrations:focus-visible ~ .sw-shell .sw-ow-filter__pill[for="sw-filter-integrations"] {
	outline: 2px solid var(--sw-cyan-txt);
	outline-offset: 2px;
}

.sw-ow-grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 18px;
	align-items: stretch;
}

/* Hide cards outside the chosen category. */
#sw-filter-web:checked ~ .sw-shell .sw-ow-card:not(.cat--web),
#sw-filter-ai:checked ~ .sw-shell .sw-ow-card:not(.cat--ai),
#sw-filter-automation:checked ~ .sw-shell .sw-ow-card:not(.cat--automation),
#sw-filter-software:checked ~ .sw-shell .sw-ow-card:not(.cat--software),
#sw-filter-integrations:checked ~ .sw-shell .sw-ow-card:not(.cat--integrations) {
	display: none;
}

/* Fallback line, shown only when a filter matches nothing. */
.sw-ow-grid__empty {
	display: none;
	grid-column: 1 / -1;
	margin: 0;
	padding: 30px 0;
	text-align: center;
	font-size: 14px;
	color: var(--sw-muted);
}

.sw-ow-card {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	background: #fff;
	border: 1px solid var(--sw-border-light);
	border-radius: 14px;
	box-shadow: var(--sw-shadow-sm);
	transition: transform 0.3s var(--sw-ease), box-shadow 0.3s var(--sw-ease),
		border-color 0.3s var(--sw-ease);
}

.sw-ow-card:hover {
	transform: translateY(-4px);
	box-shadow: var(--sw-shadow-md);
	border-color: rgba(8, 82, 150, 0.35);
}

.sw-ow-card__media {
	position: relative;
	display: block;
	line-height: 0;
}

.sw-ow-card__media img {
	display: block;
	width: 100%;
	height: auto;
}

.sw-ow-card__badge {
	position: absolute;
	left: 12px;
	bottom: 12px;
	padding: 5px 11px;
	border-radius: 6px;
	background: rgba(255, 255, 255, 0.16);
	backdrop-filter: blur(6px);
	-webkit-backdrop-filter: blur(6px);
	color: #fff;
	font-family: Inter, Helvetica, Arial, sans-serif;
	font-size: 11px;
	font-weight: 700;
	line-height: 1.4;
}

.sw-ow-card__body {
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
	padding: 18px 18px 20px;
	--sw-accent: #085296;
}

.sw-ow-card__body h3 {
	margin: 0 0 8px;
	font-size: 16px;
	font-weight: 700;
	line-height: 1.3;
}

.sw-ow-card__body > p {
	margin: 0 0 12px;
	font-size: 12.5px;
	line-height: 1.65;
}

.sw-ow-card .sw-check-list { flex: 1 1 auto; margin-bottom: 14px; }
.sw-ow-card .sw-check-list li { font-size: 12.5px; margin-bottom: 7px; }

.sw-ow-more { margin: 28px 0 0; text-align: center; }
.sw-ow-more .sw-btn { display: inline-flex; }

/* ---- impact band -------------------------------------------------------- */

.sw-ow-impact {
	background: #041f38;
	padding: 46px 0;
}

.sw-ow-impact__grid {
	display: grid;
	grid-template-columns: 0.8fr 1.2fr;
	align-items: center;
	gap: 40px;
}

.sw-ow-impact__copy h2 {
	margin: 0;
	color: #fff;
	font-size: 27px;
	font-weight: 800;
	line-height: 1.28;
}

.sw-ow-impact__grid-items {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 18px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-ow-impact__grid-items li {
	padding-left: 18px;
	border-left: 1px solid rgba(255, 255, 255, 0.09);
}

.sw-ow-impact__grid-items li:first-child { border-left: 0; padding-left: 0; }

.sw-ow-impact__icon {
	display: block;
	margin-bottom: 10px;
	color: var(--sw-accent, #9bc2e5);
}

.sw-ow-impact__value {
	display: block;
	margin-bottom: 3px;
	color: #fff;
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 26px;
	font-weight: 800;
	line-height: 1.1;
}

.sw-ow-impact__grid-items strong {
	display: block;
	margin-bottom: 5px;
	color: #dce9f5;
	font-size: 13px;
	font-weight: 700;
}

.sw-ow-impact__note {
	display: block;
	color: #7fa8c9;
	font-size: 11.5px;
	line-height: 1.5;
}

/* ---- approach ----------------------------------------------------------- */

.sw-ow-process {
	background: #f2f7fb;
	padding: 62px 0 66px;
}

/* ---- closing CTA -------------------------------------------------------- */

.sw-ow-cta {
	background: #052846;
	padding: 42px 0;
}

.sw-ow-cta__grid {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 34px;
}

.sw-ow-cta h2 {
	margin: 0 0 8px;
	color: #fff;
	font-size: 25px;
	font-weight: 800;
	line-height: 1.25;
}

.sw-ow-cta p {
	max-width: 430px;
	margin: 0;
	color: #9bc2e5;
	font-size: 14.5px;
	line-height: 1.7;
}

/* ---- responsive --------------------------------------------------------- */

@media (max-width: 1100px) {
	.sw-ow-grid { grid-template-columns: repeat(2, 1fr); }

	.sw-ow-impact__grid {
		grid-template-columns: 1fr;
		gap: 28px;
	}

	.sw-ow-impact__grid-items { grid-template-columns: repeat(2, 1fr); row-gap: 24px; }
	.sw-ow-impact__grid-items li:nth-child(odd) { border-left: 0; padding-left: 0; }
}

@media (max-width: 980px) {
	.sw-ow-hero { padding: 42px 0 48px; }

	.sw-ow-hero__grid {
		grid-template-columns: 1fr;
		gap: 32px;
	}

	/* Prefixed to match the (0,2,0) of the base rule above. A media query adds
	   no specificity, so the bare selector lost to it and the headline stayed
	   42px at every width. */
	.sw-page .sw-ow-hero__title { font-size: 34px; }
	.sw-ow-hero__visual img { margin: 0 auto; max-width: 400px; }

	.sw-ow-cta__grid { flex-direction: column; align-items: flex-start; }
}

@media (max-width: 767px) {
	.sw-page .sw-ow-hero__title { font-size: 28px; }
	.sw-ow-stats { grid-template-columns: repeat(2, 1fr); gap: 20px; }
	.sw-ow-grid { grid-template-columns: 1fr; }
	.sw-ow-impact__grid-items { grid-template-columns: 1fr; }
	.sw-ow-impact__grid-items li { border-left: 0; padding-left: 0; }
	.sw-ow-impact__copy h2 { font-size: 23px; }
	.sw-ow-cta h2 { font-size: 22px; }
}

/* ===========================================================================
   21b. Our Work page — Divi builder layout
   ---------------------------------------------------------------------------
   The Our Work page is built from Divi modules stored in the page's own
   post_content, not from templates/page-our-work.php. Section 21 above still
   owns the visual design; nothing here restyles anything. This block only
   re-attaches that design to the DOM Divi emits — section > row > column >
   module — instead of the hand-written markup the PHP template produced.

   Three structural differences account for all of it:

   1. The filter radios end up nested inside a column, so section 21's
      `#sw-filter-x:checked ~ .sw-shell …` sibling selectors can no longer
      reach the pills or the cards. The :has() rules below do the same job
      scoped to the section instead, and keep the filter CSS-only — still no
      JavaScript. Where :has() is unsupported the grid degrades to showing
      every card, which is the same thing the page does with JS disabled.
   2. Project cards are et_pb_blurb modules, so the card internals are Divi's
      (.et_pb_blurb_content / .et_pb_module_header / .et_pb_blurb_description)
      rather than .sw-ow-card__media / .sw-ow-card__body.
   3. Divi columns float; several of these sections need them to align on a
      centre line, so those rows are switched to flex.

   The one deliberate visual change: the card badge sits top-left over the
   artwork rather than bottom-left. Divi renders the blurb image and the
   description as separate branches, so a badge in the description cannot be
   anchored to the bottom of an image whose height varies with column width.
   =========================================================================== */

/* ---- rows that need centred columns -------------------------------------- */

.sw-ow-hero .et_pb_row,
.sw-ow-impact .et_pb_row,
.sw-ow-cta .et_pb_row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
}

.sw-ow-hero .et_pb_row > .et_pb_column,
.sw-ow-impact .et_pb_row > .et_pb_column,
.sw-ow-cta .et_pb_row > .et_pb_column {
	float: none;
}

.sw-ow-hero .et_pb_module:last-child,
.sw-ow-impact .et_pb_module:last-child,
.sw-ow-cta .et_pb_module:last-child {
	margin-bottom: 0;
}

/* ---- hero ---------------------------------------------------------------- */

/* The art is right-aligned in the mockup. Divi wraps the img in
   .et_pb_image_wrap, so the `margin-left: auto` in section 21 has nothing to
   push against — align the wrapper instead and let section 21 cap the height. */
.sw-ow-hero__visual .et_pb_image {
	margin: 0;
	text-align: right;
}

.sw-ow-hero__visual .et_pb_image_wrap {
	display: inline-block;
	max-width: 100%;
}

/* ---- projects: filter ---------------------------------------------------- */

.sw-ow-projects .sw-ow-filter__row { padding-bottom: 0; }
.sw-ow-projects .sw-ow-filter__wrap { margin-bottom: 0; }
.sw-ow-projects .sw-ow-filter { margin-bottom: 0; }
.sw-ow-projects .sw-ow-grid__row { padding-top: 26px; }

/* Active pill. One rule per category, same as section 21 — :has() cannot take
   a variable, so the pairing still has to be written out. */
.sw-ow-projects:has(#sw-filter-all:checked) .sw-ow-filter__pill[for="sw-filter-all"],
.sw-ow-projects:has(#sw-filter-web:checked) .sw-ow-filter__pill[for="sw-filter-web"],
.sw-ow-projects:has(#sw-filter-ai:checked) .sw-ow-filter__pill[for="sw-filter-ai"],
.sw-ow-projects:has(#sw-filter-automation:checked) .sw-ow-filter__pill[for="sw-filter-automation"],
.sw-ow-projects:has(#sw-filter-software:checked) .sw-ow-filter__pill[for="sw-filter-software"],
.sw-ow-projects:has(#sw-filter-integrations:checked) .sw-ow-filter__pill[for="sw-filter-integrations"] {
	color: #fff;
	background: linear-gradient(90deg, #085296 0%, #5b9bd5 100%);
	border-color: transparent;
	box-shadow: 0 12px 26px -14px rgba(8, 82, 150, 0.9);
}

.sw-ow-projects:has(#sw-filter-all:checked) .sw-ow-filter__pill[for="sw-filter-all"] .sw-icon,
.sw-ow-projects:has(#sw-filter-web:checked) .sw-ow-filter__pill[for="sw-filter-web"] .sw-icon,
.sw-ow-projects:has(#sw-filter-ai:checked) .sw-ow-filter__pill[for="sw-filter-ai"] .sw-icon,
.sw-ow-projects:has(#sw-filter-automation:checked) .sw-ow-filter__pill[for="sw-filter-automation"] .sw-icon,
.sw-ow-projects:has(#sw-filter-software:checked) .sw-ow-filter__pill[for="sw-filter-software"] .sw-icon,
.sw-ow-projects:has(#sw-filter-integrations:checked) .sw-ow-filter__pill[for="sw-filter-integrations"] .sw-icon {
	color: #fff;
}

/* Keyboard focus, since the radio itself is off-screen. */
.sw-ow-projects:has(#sw-filter-all:focus-visible) .sw-ow-filter__pill[for="sw-filter-all"],
.sw-ow-projects:has(#sw-filter-web:focus-visible) .sw-ow-filter__pill[for="sw-filter-web"],
.sw-ow-projects:has(#sw-filter-ai:focus-visible) .sw-ow-filter__pill[for="sw-filter-ai"],
.sw-ow-projects:has(#sw-filter-automation:focus-visible) .sw-ow-filter__pill[for="sw-filter-automation"],
.sw-ow-projects:has(#sw-filter-software:focus-visible) .sw-ow-filter__pill[for="sw-filter-software"],
.sw-ow-projects:has(#sw-filter-integrations:focus-visible) .sw-ow-filter__pill[for="sw-filter-integrations"] {
	outline: 2px solid var(--sw-cyan-txt);
	outline-offset: 2px;
}

/* Hide cards outside the chosen category. */
.sw-ow-projects:has(#sw-filter-web:checked) .sw-ow-card:not(.cat--web),
.sw-ow-projects:has(#sw-filter-ai:checked) .sw-ow-card:not(.cat--ai),
.sw-ow-projects:has(#sw-filter-automation:checked) .sw-ow-card:not(.cat--automation),
.sw-ow-projects:has(#sw-filter-software:checked) .sw-ow-card:not(.cat--software),
.sw-ow-projects:has(#sw-filter-integrations:checked) .sw-ow-card:not(.cat--integrations) {
	display: none;
}

/* ---- projects: grid + blurb cards ---------------------------------------- */

/* The grid lives on the column so the four blurbs are its direct children and
   section 21's .sw-ow-grid rules — including the responsive step-downs — apply
   untouched. Divi floats columns, hence the reset. */
.et_pb_column.sw-ow-grid {
	float: none;
	display: grid;
}

.sw-ow-card.et_pb_blurb {
	position: relative;
	margin: 0;
	padding: 0;
	text-align: left;
}

.sw-ow-card .et_pb_blurb_content {
	display: flex;
	flex-direction: column;
	max-width: none;
	height: 100%;
	margin: 0;
}

.sw-ow-card .et_pb_main_blurb_image {
	display: block;
	margin: 0;
	line-height: 0;
	text-align: left;
}

.sw-ow-card .et_pb_main_blurb_image .et_pb_image_wrap { display: block; }

.sw-ow-card .et_pb_main_blurb_image img {
	display: block;
	width: 100%;
	height: auto;
}

/* Stands in for .sw-ow-card__body. */
.sw-ow-card .et_pb_blurb_container {
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
	padding: 18px 18px 20px;
	text-align: left;
	--sw-accent: #085296;
}

.sw-ow-card .et_pb_module_header {
	margin: 0 0 8px;
	padding: 0;
	font-size: 16px;
	font-weight: 700;
	line-height: 1.3;
}

.sw-ow-card .et_pb_module_header a {
	color: inherit;
	text-decoration: none;
}

.sw-ow-card .et_pb_blurb_description {
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
}

.sw-ow-card .et_pb_blurb_description > p {
	margin: 0 0 12px;
	font-size: 12.5px;
	line-height: 1.65;
}

/* Top-left rather than bottom-left — see the note at the head of this block. */
.sw-ow-card .sw-ow-card__badge {
	top: 12px;
	bottom: auto;
	z-index: 2;
}

.sw-ow-more .et_pb_button_module_wrapper { text-align: center; }

/* ---- approach ------------------------------------------------------------ */

.sw-ow-process .et_pb_column.sw-sec-head { float: none; }

/* ---- closing CTA --------------------------------------------------------- */

.sw-ow-cta .sw-btn-row .et_pb_button_module_wrapper { display: inline-block; margin: 0 0 0 12px; }
.sw-ow-cta .sw-btn-row { text-align: right; }

/* ---- responsive ---------------------------------------------------------- */

@media (max-width: 980px) {
	.sw-ow-hero__visual .et_pb_image { text-align: center; }

	.sw-ow-cta .sw-btn-row { text-align: left; }
	.sw-ow-cta .sw-btn-row .et_pb_button_module_wrapper { margin: 0 12px 0 0; }
}

/* ===========================================================================
   22. AI Solutions page (templates/page-ai-solutions.php)
   ---------------------------------------------------------------------------
   Built on the established design system rather than a mockup of its own, so
   most of it reuses existing components: .sw-shell, .sw-btn, .sw-sec-head,
   .sw-auto-grid / .sw-auto-tile (section 16), .sw-steps (16) and .sw-sol-chips
   (18). Only the hero, the capability grid, the trust band and the closing CTA
   are new.
   =========================================================================== */

/* ---- hero --------------------------------------------------------------- */

.sw-ai-hero {
	position: relative;
	overflow: hidden;
	background: #041f38;
	padding: 54px 0 62px;
}

.sw-ai-hero::before {
	content: "";
	position: absolute;
	top: -190px;
	right: -5%;
	width: 640px;
	height: 640px;
	border-radius: 50%;
	background: radial-gradient(circle, rgba(8, 82, 150, 0.28) 0%, rgba(8, 82, 150, 0) 68%);
	pointer-events: none;
}

.sw-ai-hero__grid {
	position: relative;
	z-index: 1;
	display: grid;
	grid-template-columns: 1fr 1fr;
	align-items: center;
	gap: 46px;
}

/* Prefixed with .sw-page to reach (0,2,0). The base rule
   `.sw-page h1, .sw-page h2, .sw-page h3 { color: var(--sw-slate) }` is
   (0,1,1), so a bare `.sw-sw-ai-hero__title` (0,1,0) lost to it and painted
   the headline near-black on a near-black hero. */
.sw-page .sw-ai-hero__title {
	margin: 0 0 18px;
	color: #fff;
	font-size: 44px;
	font-weight: 800;
	line-height: 1.15;
	letter-spacing: -1.2px;
}

.sw-ai-hero__lede {
	max-width: 480px;
	margin: 0 0 30px;
	color: var(--sw-muted-dark);
	font-size: 16px;
	line-height: 1.8;
}

.sw-ai-hero .sw-sol-chips { margin-top: 30px; }

/* Capped by height, not width — see .sw-ow-hero__visual img. A square image
   under a width cap sets the hero height on its own and leaves the copy column
   floating in dead space. */
.sw-ai-hero__visual img {
	display: block;
	width: auto;
	max-width: 100%;
	max-height: 400px;
	height: auto;
	margin-left: auto;
}

/* ---- capabilities -------------------------------------------------------- */

.sw-ai-caps {
	background: var(--sw-light);
	padding: 70px 0 66px;
}

.sw-ai-caps__grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 18px;
	align-items: stretch;
}

.sw-ai-cap {
	display: flex;
	flex-direction: column;
	padding: var(--sw-card-pad);
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-card-radius);
	box-shadow: var(--sw-card-shadow);
	transition: var(--sw-card-transition);
}

.sw-ai-cap:hover {
	transform: translateY(-4px);
	box-shadow: var(--sw-card-shadow-hover);
	border-color: var(--sw-accent);
}

.sw-ai-cap__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 52px;
	height: 52px;
	margin-bottom: 18px;
	border-radius: 50%;
	color: #fff;
	background: var(--sw-accent);
}

.sw-ai-cap h3 {
	margin: 0 0 10px;
	font-size: 18px;
	font-weight: 800;
	line-height: 1.3;
}

.sw-ai-cap > p {
	margin: 0;
	font-size: 13.5px;
	line-height: 1.75;
}


/* ---- tasks --------------------------------------------------- */

.sw-ai-tasks {
	background: var(--sw-light);
	padding: 0 0 72px;
}

/* ---- trust band ------------------------------------------------------- */

.sw-ai-trust {
	background: #041f38;
	padding: 58px 0;
}

.sw-ai-trust__grid {
	display: grid;
	grid-template-columns: 0.85fr 1.15fr;
	align-items: center;
	gap: 44px;
}

.sw-ai-trust__copy h2 {
	margin: 0 0 14px;
	color: #fff;
	font-size: 28px;
	font-weight: 800;
	line-height: 1.28;
}

.sw-ai-trust__copy p {
	margin: 0 0 16px;
	color: var(--sw-muted-dark);
	font-size: 15px;
	line-height: 1.8;
}

.sw-card-link--light { color: #9bc2e5; }

.sw-ai-trust__list {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 14px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-ai-trust__list li {
	display: flex;
	align-items: flex-start;
	gap: 12px;
	padding: 18px 18px;
	background: rgba(255, 255, 255, 0.035);
	border: 1px solid rgba(255, 255, 255, 0.09);
	border-radius: 12px;
	color: #7fa8c9;
	font-size: 12.5px;
	line-height: 1.6;
	transition: border-color 0.25s var(--sw-ease), background-color 0.25s var(--sw-ease);
}

.sw-ai-trust__list strong {
	display: block;
	margin-bottom: 4px;
	color: #fff;
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 14px;
	font-weight: 700;
	line-height: 1.35;
}

.sw-ai-trust__list li:hover {
	background: rgba(255, 255, 255, 0.06);
	border-color: rgba(8, 82, 150, 0.45);
}

.sw-ai-trust__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 32px;
	height: 32px;
	border-radius: 8px;
	color: #9bc2e5;
	background: rgba(8, 82, 150, 0.14);
}

/* ---- process ------------------------------------------------------------ */

.sw-ai-process {
	background: var(--sw-light-alt);
	padding: 68px 0 70px;
}

/* ---- featured work ------------------------------------------------------ */

.sw-ai-work {
	background: #fff;
	padding: 70px 0;
}

.sw-ai-work__grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 20px;
	align-items: stretch;
}

.sw-ai-proj {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	background: #fff;
	border: 1px solid var(--sw-border-light);
	border-radius: 16px;
	box-shadow: var(--sw-shadow-sm);
	transition: transform 0.3s var(--sw-ease), box-shadow 0.3s var(--sw-ease),
		border-color 0.3s var(--sw-ease);
}

.sw-ai-proj:hover {
	transform: translateY(-4px);
	box-shadow: var(--sw-shadow-md);
	border-color: rgba(8, 82, 150, 0.3);
}

.sw-ai-proj__media { display: block; line-height: 0; }

.sw-ai-proj__media img {
	display: block;
	width: 100%;
	height: auto;
}

.sw-ai-proj__body {
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
	padding: 22px 20px 24px;
}

.sw-ai-proj__body h3 {
	margin: 0 0 12px;
	font-size: 18px;
	font-weight: 800;
	line-height: 1.3;
}

.sw-ai-proj__label {
	margin: 12px 0 4px;
	color: var(--sw-muted);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 1.5px;
	text-transform: uppercase;
	opacity: 0.75;
}

.sw-ai-proj__body p {
	margin: 0;
	font-size: 13px;
	line-height: 1.7;
}

.sw-ai-proj__body .sw-card-link { margin-top: 16px; }

/* ---- closing CTA -------------------------------------------------------- */

.sw-ai-cta {
	background: #052846;
	padding: 52px 0;
}

.sw-ai-cta__grid {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 36px;
}

.sw-ai-cta h2 {
	margin: 0 0 10px;
	color: #fff;
	font-size: 28px;
	font-weight: 800;
	line-height: 1.25;
}

.sw-ai-cta p {
	max-width: 520px;
	margin: 0;
	color: #9bc2e5;
	font-size: 15px;
	line-height: 1.75;
}

/* ---- responsive --------------------------------------------------------- */

@media (max-width: 1100px) {
	.sw-ai-caps__grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 980px) {
	.sw-ai-hero { padding: 44px 0 52px; }

	.sw-ai-hero__grid,
	.sw-ai-trust__grid {
		grid-template-columns: 1fr;
		gap: 32px;
	}

	.sw-ai-hero__title { font-size: 36px; }
	.sw-ai-hero__visual img { margin: 0 auto; max-width: 420px; }

	.sw-ai-caps__grid { grid-template-columns: 1fr; }
	.sw-ai-trust__list { grid-template-columns: 1fr; }
	.sw-ai-work__grid { grid-template-columns: 1fr; }

	.sw-ai-cta__grid { flex-direction: column; align-items: flex-start; }
}

@media (max-width: 767px) {
	.sw-ai-hero__title { font-size: 29px; }
	.sw-ai-trust__list { grid-template-columns: repeat(2, 1fr); }
	.sw-ai-trust__copy h2 { font-size: 24px; }
	.sw-ai-cap h3 { font-size: 17px; }
	.sw-ai-cta h2 { font-size: 23px; }
}

/* ===========================================================================
   22b. AI Solutions page — Divi builder layout
   ---------------------------------------------------------------------------
   Companion to section 22 for when the page is built from Divi modules
   (SeriousWeb_AI_Solutions_Page.json) rather than templates/page-ai-solutions.php.
   Section 22 owns the design; this block only re-attaches it to Divi's DOM.

   The approach mirrors section 21b: each of the page's grids goes on a Divi
   COLUMN, so the modules inside become its direct grid children and section
   22's grid rules — including the responsive step-downs — apply unchanged.
   Each card is then an et_pb_blurb, so what remains is mapping Divi's blurb
   internals onto the class names section 22 expects:

     .et_pb_main_blurb_image  ->  .sw-ai-cap__icon / .sw-step-item__icon / media
     .et_pb_module_header     ->  the card's h3
     .et_pb_blurb_description ->  the card body

   Icon glyph, colour and size stay in the module settings — that is Divi's own
   icon system and the natural place for them. Only the chrome around the icon
   (the circle, its background) lives here.
   =========================================================================== */

/* ---- rows that need centred columns -------------------------------------- */

.sw-ai-hero .et_pb_row,
.sw-ai-trust .et_pb_row,
.sw-ai-cta .et_pb_row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
}

.sw-ai-hero .et_pb_row > .et_pb_column,
.sw-ai-trust .et_pb_row > .et_pb_column,
.sw-ai-cta .et_pb_row > .et_pb_column {
	float: none;
}

/* ---- hero ---------------------------------------------------------------- */

.sw-ai-hero__visual .et_pb_image {
	margin: 0;
	text-align: right;
}

.sw-ai-hero__visual .et_pb_image_wrap {
	display: inline-block;
	max-width: 100%;
}

/* The hero's two buttons sit in the copy column alongside the headline, so they
   cannot have a .sw-btn-row column of their own — lay the wrappers out inline
   instead. The closing CTA does get its own column, further down. */
.sw-ai-hero__copy .et_pb_button_module_wrapper {
	display: inline-block;
	margin: 0 12px 12px 0;
}

/* ---- grids on columns ---------------------------------------------------- */

.et_pb_column.sw-ai-caps__grid,
.et_pb_column.sw-auto-grid,
.et_pb_column.sw-ai-trust__list,
.et_pb_column.sw-steps,
.et_pb_column.sw-ai-work__grid {
	float: none;
	display: grid;
}

/* Divi spaces modules with a bottom margin; the grids above use gap. */
.sw-ai-caps__grid > .et_pb_module,
.sw-auto-grid > .et_pb_module,
.sw-ai-trust__list > .et_pb_module,
.sw-steps > .et_pb_module,
.sw-ai-work__grid > .et_pb_module {
	margin-bottom: 0;
}

.sw-ai-cap .et_pb_blurb_content,
.sw-auto-tile .et_pb_blurb_content,
.sw-ai-trust__list .et_pb_blurb_content,
.sw-step-item .et_pb_blurb_content,
.sw-ai-proj .et_pb_blurb_content {
	max-width: none;
	width: 100%;
	margin: 0;
}

/* ---- capability cards ---------------------------------------------------- */

.sw-ai-cap .et_pb_blurb_content {
	display: flex;
	flex-direction: column;
	height: 100%;
}

.sw-ai-cap .et_pb_main_blurb_image {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 52px;
	height: 52px;
	margin: 0 0 18px;
	border-radius: 50%;
	background: var(--sw-accent);
	line-height: 1;
}

.sw-ai-cap .et_pb_blurb_container { text-align: left; }

.sw-ai-cap .et_pb_module_header {
	margin: 0 0 10px;
	padding: 0;
	font-size: 18px;
	font-weight: 800;
	line-height: 1.3;
}

.sw-ai-cap .et_pb_blurb_description p {
	margin: 0;
	font-size: 13.5px;
	line-height: 1.75;
}

/* ---- task tiles ---------------------------------------------------------- */

.sw-auto-tile .et_pb_blurb_content {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 10px;
}

.sw-auto-tile .et_pb_main_blurb_image { margin: 0; line-height: 1; }
.sw-auto-tile .et_pb_blurb_container { text-align: center; }

.sw-auto-tile .et_pb_module_header {
	margin: 0;
	padding: 0;
	font-size: 11.5px;
	font-weight: 600;
	line-height: 1.4;
	color: var(--sw-slate);
	min-height: 2.8em;
}

/* ---- trust list ---------------------------------------------------------- */

/* Section 22 styles these as `li`; as blurbs they need the same chrome. */
.sw-ai-trust__list > .et_pb_blurb {
	padding: 18px;
	background: rgba(255, 255, 255, 0.035);
	border: 1px solid rgba(255, 255, 255, 0.09);
	border-radius: 12px;
	color: #7fa8c9;
	transition: background-color 0.3s var(--sw-ease), border-color 0.3s var(--sw-ease);
}

.sw-ai-trust__list > .et_pb_blurb:hover {
	background: rgba(255, 255, 255, 0.06);
	border-color: rgba(8, 82, 150, 0.45);
}

.sw-ai-trust__list .et_pb_blurb_content {
	display: flex;
	align-items: flex-start;
	gap: 12px;
}

.sw-ai-trust__list .et_pb_main_blurb_image {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 32px;
	height: 32px;
	margin: 0;
	border-radius: 8px;
	background: rgba(8, 82, 150, 0.28);
	line-height: 1;
}

.sw-ai-trust__list .et_pb_blurb_container { text-align: left; }

.sw-ai-trust__list .et_pb_module_header {
	margin: 0 0 4px;
	padding: 0;
	color: #dce9f5;
	font-size: 14px;
	font-weight: 700;
	line-height: 1.4;
}

.sw-ai-trust__list .et_pb_blurb_description p {
	margin: 0;
	font-size: 12.5px;
	line-height: 1.6;
}

/* ---- process steps ------------------------------------------------------- */

.sw-step-item .et_pb_main_blurb_image {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 62px;
	height: 62px;
	margin: 0 auto 14px;
	border-radius: 50%;
	background: var(--sw-accent);
	box-shadow: 0 16px 30px -16px var(--sw-accent);
	line-height: 1;
}

/* Divi renders the title before the description, but the step number belongs
   above the title — it rides in the description and is pulled back up here. */
.sw-step-item .et_pb_blurb_container {
	display: flex;
	flex-direction: column;
	text-align: center;
}

.sw-step-item .et_pb_module_header {
	margin: 0 0 6px;
	padding: 0;
	font-size: 17px;
	font-weight: 700;
}

.sw-step-item .et_pb_blurb_description { display: contents; }
.sw-step-item .sw-step-item__num { order: -1; }

/* ---- project cards ------------------------------------------------------- */

.sw-ai-proj .et_pb_blurb_content {
	display: flex;
	flex-direction: column;
	height: 100%;
}

.sw-ai-proj .et_pb_main_blurb_image {
	display: block;
	margin: 0;
	line-height: 0;
}

.sw-ai-proj .et_pb_main_blurb_image .et_pb_image_wrap { display: block; }

.sw-ai-proj .et_pb_main_blurb_image img {
	display: block;
	width: 100%;
	height: auto;
}

.sw-ai-proj .et_pb_blurb_container {
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
	padding: 22px 20px 24px;
	text-align: left;
}

.sw-ai-proj .et_pb_module_header {
	margin: 0 0 12px;
	padding: 0;
	font-size: 18px;
	font-weight: 800;
	line-height: 1.3;
}

.sw-ai-proj .et_pb_blurb_description {
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
}

/* ---- closing CTA --------------------------------------------------------- */

.sw-ai-cta .sw-btn-row .et_pb_button_module_wrapper { margin: 0; }

/* ===========================================================================
   27. Home page template — templates/page-home.php
   ---------------------------------------------------------------------------
   The homepage markup is Divi's own (section > row > column > module), so
   almost all of its styling already comes from the `sw-` rules earlier in this
   file — those were written against Divi's DOM and match unchanged.

   What is missing is the handful of values Divi stores per-module in the
   builder rather than in a class: section background, section padding, and row
   width. Those are reproduced below, taken from the builder layout so the
   template previews identically to the Theme Builder version and so the
   numbers survive the round-trip back into an importable JSON.

   Selectors are scoped under .sw-home (0-2-0) purely to out-rank Divi's own
   .et_pb_section / .et_pb_row defaults without resorting to !important.
   =========================================================================== */

/* Row: 90% wide, capped at 1240px — wider than Divi's 1080px default. */
.sw-divi .sw-row {
	width: 90%;
	max-width: 1240px;
	margin: 0 auto;
}

/* Section surfaces. Three tones carry the whole page rhythm: dark for the hero
   and the results band, white for the trust strip, light for everything in
   between. */
.sw-divi .sw-section--dark {
	background-color: var(--sw-ink);
}

.sw-divi .sw-section--white {
	background-color: var(--sw-white);
}

.sw-divi .sw-section--light {
	background-color: var(--sw-light);
}

/* Two sections take a tone of their own: the results band sits a step lighter
   than the hero, and the closing CTA a step cooler than the light sections, so
   the page does not end on the same surface it has been using throughout. */
.sw-home .sw-results {
	background-color: var(--sw-dark-alt);
}

.sw-home .sw-final-cta {
	background-color: var(--sw-light-alt);
}

/* Section padding, per section, matching the builder layout. */
.sw-home .sw-hero {
	padding: 140px 0 120px;
}

.sw-home .sw-trusted {
	padding: 52px 0;
}

.sw-home .sw-projects {
	padding: 96px 0;
}

/* These three run together as one light band, so the leading padding is
   reduced — the preceding section has already provided the breathing room. */
.sw-home .sw-automation,
.sw-home .sw-services,
.sw-home .sw-process {
	padding: 40px 0 96px;
}

.sw-home .sw-results {
	padding: 74px 0;
}

.sw-home .sw-final-cta {
	padding: 70px 0;
}

.sw-home .sw-home-content {
	padding: 72px 0;
}

/* Row spacing inside a section. Divi puts a bottom margin on every row; these
   are the deliberate exceptions from the layout. */
.sw-home .sw-projects .sw-row:first-child,
.sw-home .sw-automation .sw-row:first-child {
	padding-bottom: 46px;
}

.sw-home .sw-projects .sw-row:last-child {
	padding-top: 44px;
}

.sw-home .sw-automation .sw-row:last-child {
	padding-top: 36px;
}

.sw-home .sw-trusted .sw-row:first-child {
	padding-bottom: 0;
}

/* Divi's blurb icon box is sized and coloured by the rules in section 3; all
   this adds is centring the inline SVG the template puts inside it, since the
   original used an icon font glyph. */
.sw-home .et-pb-icon > .sw-icon {
	display: block;
}

/* ---- responsive --------------------------------------------------------- */

@media (max-width: 980px) {
	.sw-home .sw-hero {
		padding: 88px 0 76px;
	}

	.sw-home .sw-projects,
	.sw-home .sw-automation,
	.sw-home .sw-services,
	.sw-home .sw-process {
		padding: 64px 0;
	}

	.sw-home .sw-results,
	.sw-home .sw-final-cta {
		padding: 56px 0;
	}

	.sw-home .sw-projects .sw-row:first-child,
	.sw-home .sw-automation .sw-row:first-child {
		padding-bottom: 32px;
	}
}

@media (max-width: 767px) {
	.sw-home .sw-hero {
		padding: 64px 0 56px;
	}

	.sw-home .sw-projects,
	.sw-home .sw-automation,
	.sw-home .sw-services,
	.sw-home .sw-process,
	.sw-home .sw-results,
	.sw-home .sw-final-cta {
		padding: 48px 0;
	}
}

/* ---------------------------------------------------------------------------
   27b. What Divi's module settings used to supply
   ---------------------------------------------------------------------------
   On a builder page, Divi compiles each module's Design tab into per-module CSS
   (.et_pb_text_3_tb_body { … }) and writes it to wp-content/et-cache. A plain
   PHP template is not a builder page, so none of that is generated — and Divi
   does not even enqueue its column-width stylesheet. Without the rules below
   the template renders as unstyled stacked blocks.

   Every value here is taken from the corresponding module setting in the
   builder layout, with the colours moved onto the brand ramp. Keeping them in
   one block means the JSON conversion has an exact, ordered list of what to put
   back into each module's Design tab.

   All of it is scoped under .sw-divi so the Theme Builder homepage, which still
   gets these values from its own module settings, is untouched.
   --------------------------------------------------------------------------- */

/* ---- columns ------------------------------------------------------------
   Divi's grid, reproduced. Same class names and the same widths, so a column
   converts straight back to its Divi counterpart. Flex rather than Divi's
   floats, which also gives the card rows equal heights for free. */
.sw-divi .et_pb_row {
	display: flex;
	flex-wrap: wrap;
	align-items: stretch;
	position: relative;
}

/* The gutter is a right margin rather than `gap`, which is what Divi itself
   does — and it is the only version that fits. Column widths and a percentage
   `gap` resolve against the same width but round independently, so a row like
   58.75 + 2.5 + 38.75 lands a hair over 100% and the last column wraps. With
   the gutter as a margin the row sums to exactly 100%. */
.sw-divi .et_pb_column {
	margin-right: 2.5%;
	min-width: 0; /* Without this, long words stop columns from shrinking. */
}

.sw-divi .et_pb_column.et-last-child,
.sw-divi .et_pb_column:last-child {
	margin-right: 0;
}

.sw-divi .et_pb_column_4_4 { width: 100%; }
.sw-divi .et_pb_column_3_5 { width: 58.75%; }
.sw-divi .et_pb_column_2_5 { width: 38.75%; }
.sw-divi .et_pb_column_1_2 { width: 48.75%; }
.sw-divi .et_pb_column_1_3 { width: 31.666%; }
.sw-divi .et_pb_column_1_4 { width: 23.125%; }
.sw-divi .et_pb_column_1_5 { width: 18%; }
.sw-divi .et_pb_column_1_6 { width: 14.583%; }

/* Divi's tighter gutter setting, used by every card row on this page. */
.sw-divi .et_pb_gutters2 .et_pb_column { margin-right: 2%; }
.sw-divi .et_pb_gutters2 .et_pb_column.et-last-child,
.sw-divi .et_pb_gutters2 .et_pb_column:last-child { margin-right: 0; }
.sw-divi .et_pb_gutters2 .et_pb_column_1_3 { width: 32%; }
.sw-divi .et_pb_gutters2 .et_pb_column_1_4 { width: 23.5%; }
.sw-divi .et_pb_gutters2 .et_pb_column_1_5 { width: 18.4%; }
.sw-divi .et_pb_gutters2 .et_pb_column_1_6 { width: 15%; }

/* ---- module rhythm ------------------------------------------------------
   Divi gives every module a bottom margin; the last one in a column loses it. */
.sw-divi .et_pb_module {
	margin-bottom: 20px;
}

.sw-divi .et_pb_column > .et_pb_module:last-child {
	margin-bottom: 0;
}

.sw-divi .et_pb_text_inner > *:last-child {
	padding-bottom: 0;
	margin-bottom: 0;
}

/* ---- typography ---------------------------------------------------------- */

.sw-divi .sw-eyebrow p {
	font-family: Inter, Helvetica, Arial, sans-serif;
	font-size: 12px;
	font-weight: 700;
	letter-spacing: 1.4px;
	line-height: 1.6em;
	text-transform: uppercase;
}

/* The eyebrow takes its colour from the surface it sits on. */
.sw-divi .sw-section--dark .sw-eyebrow p {
	color: var(--sw-blue-200);
}

.sw-divi .sw-section--white .sw-eyebrow p,
.sw-divi .sw-section--light .sw-eyebrow p {
	color: var(--sw-blue-500);
}

.sw-divi h1 {
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 56px;
	font-weight: 800;
	line-height: 1.14em;
	letter-spacing: -1.4px;
	color: #fff;
	padding-bottom: 0;
}

.sw-divi h2 {
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 40px;
	font-weight: 800;
	line-height: 1.2em;
	letter-spacing: -0.8px;
	padding-bottom: 0;
}

.sw-divi .sw-section--light h2,
.sw-divi .sw-section--white h2 {
	color: var(--sw-slate);
}

.sw-divi .sw-section--dark h2 {
	color: #fff;
}

.sw-divi .sw-section--light p,
.sw-divi .sw-section--white p {
	font-family: Inter, Helvetica, Arial, sans-serif;
	font-size: 16px;
	line-height: 1.8em;
	color: var(--sw-muted);
}

.sw-divi .sw-section--dark p {
	font-family: Inter, Helvetica, Arial, sans-serif;
	font-size: 17px;
	line-height: 1.85em;
	color: var(--sw-muted-dark);
}

/* The intro paragraphs are measure-limited so they do not run the full column. */
.sw-divi .sw-hero-copy > .et_pb_text:nth-of-type(3) .et_pb_text_inner {
	max-width: 480px;
}

.sw-divi .sw-projects .sw-row:first-child p,
.sw-divi .sw-automation .sw-row:first-child p {
	max-width: 700px;
}

.sw-divi .sw-final-cta p {
	max-width: 460px;
}

.sw-divi .sw-project-body h3 {
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 20px;
	font-weight: 800;
	color: var(--sw-slate);
}

/* Centred heading blocks, as the layout has them. */
.sw-divi .sw-projects .sw-row:first-child,
.sw-divi .sw-automation .sw-row:first-child,
.sw-divi .sw-trusted .sw-row:first-child {
	text-align: center;
}

.sw-divi .sw-projects .sw-row:first-child p,
.sw-divi .sw-automation .sw-row:first-child p {
	margin-left: auto;
	margin-right: auto;
}

/* ---- buttons ------------------------------------------------------------
   Divi's .et_pb_button base is a transparent pill with a 2px border, so every
   button needs its fill stating explicitly. */
.sw-divi .sw-btn.et_pb_button {
	min-height: 52px;
	padding: 0 26px !important;
	border: 1px solid transparent !important;
	border-radius: 8px;
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 15px !important;
	font-weight: 700 !important;
	letter-spacing: 0;
}

.sw-divi .sw-btn.et_pb_button:after,
.sw-divi .sw-btn.et_pb_button:before {
	display: none !important;
}

.sw-divi .sw-btn--primary.et_pb_button {
	color: #fff !important;
	background-image: var(--sw-gradient);
	background-color: var(--sw-blue-600);
	border-color: transparent !important;
}

.sw-divi .sw-btn--primary.et_pb_button:hover {
	transform: translateY(-2px);
	box-shadow: 0 22px 46px -20px rgba(8, 82, 150, 0.95);
}

/* Outline button on a dark section. */
.sw-divi .sw-btn--ghost-dark.et_pb_button {
	color: #fff !important;
	background-color: rgba(255, 255, 255, 0.02);
	border-color: rgba(255, 255, 255, 0.3) !important;
}

/* Outline button on a light section. */
.sw-divi .sw-btn--ghost-light.et_pb_button {
	color: var(--sw-slate) !important;
	background-color: var(--sw-white);
	border-color: var(--sw-border-light) !important;
}

.sw-divi .sw-btn--sm.et_pb_button {
	min-height: 44px;
	padding: 0 20px !important;
	font-size: 14px !important;
}

.sw-divi .sw-btn--center.et_pb_button {
	display: flex;
	width: -moz-fit-content;
	width: fit-content;
	margin: 0 auto;
}

/* Trailing icon. The button is already inline-flex with a 0.5em gap, so this
   only has to stop the SVG being squashed and give the arrow somewhere to go
   on hover. Divi's own button icon is suppressed above — it renders from an
   icon font that a non-builder page never loads. */
.sw-divi .sw-btn__icon {
	flex: 0 0 auto;
	transition: transform 0.25s var(--sw-ease);
}

.sw-divi .sw-btn.et_pb_button:hover .sw-btn__icon {
	transform: translateX(3px);
}

@media (prefers-reduced-motion: reduce) {
	.sw-divi .sw-btn__icon {
		transition: none;
	}

	.sw-divi .sw-btn.et_pb_button:hover .sw-btn__icon {
		transform: none;
	}
}

/* Two buttons side by side in the hero and the closing CTA. */
.sw-divi .sw-cta-group {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 14px;
}

.sw-divi .sw-cta-group > .et_pb_text,
.sw-divi .sw-cta-group > .et_pb_image {
	flex: 0 0 100%;
}

.sw-divi .sw-cta-group > .et_pb_button {
	margin-bottom: 0;
}

.sw-divi .sw-cta-right {
	justify-content: flex-end;
	align-content: center;
}

/* ---- images -------------------------------------------------------------- */

.sw-divi .et_pb_image {
	display: block;
	max-width: 100%;
}

.sw-divi .et_pb_image .et_pb_image_wrap {
	display: block;
}

.sw-divi .et_pb_image img {
	display: block;
	width: 100%;
	height: auto;
}

.sw-divi .sw-hero-visual-col {
	display: flex;
	align-items: center;
}

/* ---- responsive ---------------------------------------------------------- */

@media (max-width: 980px) {
	/* Below the desktop breakpoint the gutter becomes a fixed gap, so the
	   fractional widths above are replaced wholesale rather than adjusted. */
	.sw-divi .et_pb_row {
		gap: 24px;
	}

	.sw-divi .et_pb_column,
	.sw-divi .et_pb_gutters2 .et_pb_column {
		margin-right: 0;
	}

	.sw-divi .et_pb_column_3_5,
	.sw-divi .et_pb_column_2_5,
	.sw-divi .et_pb_column_1_2,
	.sw-divi .et_pb_column_1_3,
	.sw-divi .et_pb_gutters2 .et_pb_column_1_3 {
		width: 100%;
	}

	.sw-divi .et_pb_column_1_4,
	.sw-divi .et_pb_gutters2 .et_pb_column_1_4,
	.sw-divi .et_pb_column_1_5,
	.sw-divi .et_pb_gutters2 .et_pb_column_1_5 {
		width: calc(50% - 12px);
	}

	.sw-divi .et_pb_column_1_6,
	.sw-divi .et_pb_gutters2 .et_pb_column_1_6 {
		width: calc(33.333% - 16px);
	}

	.sw-divi h1 { font-size: 40px; letter-spacing: -1px; }
	.sw-divi h2 { font-size: 30px; letter-spacing: -0.5px; }

	.sw-divi .sw-cta-right { justify-content: flex-start; }
}

@media (max-width: 767px) {
	.sw-divi .et_pb_row {
		gap: 18px;
	}

	.sw-divi .et_pb_column_1_4,
	.sw-divi .et_pb_gutters2 .et_pb_column_1_4,
	.sw-divi .et_pb_column_1_5,
	.sw-divi .et_pb_gutters2 .et_pb_column_1_5,
	.sw-divi .et_pb_column_1_6,
	.sw-divi .et_pb_gutters2 .et_pb_column_1_6 {
		width: calc(50% - 9px);
	}

	.sw-divi h1 { font-size: 32px; }
	.sw-divi h2 { font-size: 25px; }

	.sw-divi .sw-btn.et_pb_button,
	.sw-divi .sw-cta-group > .et_pb_button {
		width: 100%;
	}
}

/* ---------------------------------------------------------------------------
   27c. Home page — design pass
   ---------------------------------------------------------------------------
   Everything above reproduces the builder layout as it stands. This block is
   the deliberate improvement on top of it, and it is kept separate so it can be
   reviewed or reverted on its own.

   Four things were wrong with the page as laid out:

     1. Projects, Automation, Services and Process are all the same light
        surface, so 2,000px of page ran together as one undifferentiated band
        with no sense of where a section started or ended.
     2. The automation tiles and service cards had no surface at all — they were
        icons and labels floating on the background, which read as unfinished
        next to the project cards, which do have one.
     3. The Services and Process intro columns are 18% wide and carry a 40px
        heading, so "Solutions That Drive Efficiency." broke across four lines.
     4. Card content of differing lengths left the "Learn more" links at four
        different heights, so the row of cards had a ragged bottom edge.
   --------------------------------------------------------------------------- */

/* ---- 1. section rhythm ---------------------------------------------------
   Alternating the four light sections gives each one an edge. In Divi terms
   this is one background-colour setting per section. */
.sw-home .sw-automation,
.sw-home .sw-process {
	background-color: var(--sw-white);
}

/* ---- 2a. automation tiles ------------------------------------------------
   Given the same card treatment as the projects, so the twelve read as a grid
   of capabilities rather than loose labels. */
.sw-home .sw-chip.et_pb_blurb {
	height: 100%;
	padding: 20px 12px 18px !important;
	background: var(--sw-blue-25);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-radius);
	box-shadow: var(--sw-shadow-sm);
}

/* Hover deepens the tile rather than lightening it. The previous version went
   to white — on a white section that made the card vanish into the background
   at exactly the moment it was meant to respond. */
.sw-home .sw-chip.et_pb_blurb:hover {
	transform: translateY(-3px);
	background: var(--sw-blue-50);
	border-color: rgba(8, 82, 150, 0.35);
	box-shadow: var(--sw-shadow-md);
}

/* The icon gets a tile of its own, so it carries weight at 12 tiles wide. */
/* line-height:0 stops the inline SVG adding a phantom text line under itself,
   which was padding this block out beyond the tile it contains. */
.sw-home .sw-chip .et_pb_main_blurb_image {
	margin-bottom: 8px;
	line-height: 0;
}

.sw-home .sw-chip .et_pb_main_blurb_image .et-pb-icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 42px;
	height: 42px;
	margin: 0 auto;
	border-radius: 12px;
	background: var(--sw-blue-100);
	color: var(--sw-blue-600) !important;
	line-height: 1;
	transition: background-color 0.25s var(--sw-ease), color 0.25s var(--sw-ease);
}

/* The glyph is sized independently of the tile. At 26px it needs the tile back
   at 42px to keep any breathing room, so the block is taller than the tightest
   version — the 8px margin below still keeps it under where it started. */
.sw-home .sw-chip .et_pb_main_blurb_image .et-pb-icon > .sw-icon {
	width: 26px;
	height: 26px;
}

.sw-home .sw-chip.et_pb_blurb:hover .et_pb_main_blurb_image .et-pb-icon {
	background: var(--sw-blue-600);
	color: #fff !important;
}

/* Two rules in section 3 tint every 2nd and 3rd tile's icon a different colour:

     .sw-row--chips > .et_pb_column:nth-child(2n) .sw-chip .et-pb-icon
       { color: var(--sw-blue) !important; }

   That was variety when the palette was blue-and-violet. On a single blue ramp
   it only makes three of the twelve look wrong — and because the selector is
   (0,5,0) it outranked the two rules above, so tiles 2 and 4 kept a #085296
   icon that vanished into the #085296 tile the moment you hovered.

   Matching their shape and going one class higher is what it takes to win.
   The rules themselves are left alone because they also serve the Theme Builder
   homepage, which is outside this template's scope. */
.sw-home .sw-row--chips > .et_pb_column:nth-child(2n) .sw-chip .et-pb-icon,
.sw-home .sw-row--chips > .et_pb_column:nth-child(3n) .sw-chip .et-pb-icon {
	color: var(--sw-blue-600) !important;
}

.sw-home .sw-row--chips > .et_pb_column:nth-child(2n) .sw-chip.et_pb_blurb:hover .et-pb-icon,
.sw-home .sw-row--chips > .et_pb_column:nth-child(3n) .sw-chip.et_pb_blurb:hover .et-pb-icon {
	color: #fff !important;
}

.sw-home .sw-chip .et_pb_module_header {
	color: #000;
}

/* Both tile rows sit in one section, so they need the same gap between them
   that they have between columns. */
.sw-home .sw-automation .sw-row--chips + .sw-row--chips {
	padding-top: 20px;
}

/* ---- 2b. service cards --------------------------------------------------- */
.sw-home .sw-card--service.et_pb_blurb {
	height: 100%;
	padding: 26px 20px 24px !important;
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-radius);
	box-shadow: var(--sw-shadow-sm);
	display: flex;
}

.sw-home .sw-card--service.et_pb_blurb:hover {
	transform: translateY(-4px);
	border-color: rgba(8, 82, 150, 0.3);
	box-shadow: var(--sw-shadow-md);
}

/* Push the "Learn more" line to the bottom of every card, whatever the blurb
   length, so the four line up. */
.sw-home .sw-card--service.et_pb_blurb .et_pb_blurb_content,
.sw-home .sw-card--service.et_pb_blurb .et_pb_blurb_container,
.sw-home .sw-card--service.et_pb_blurb .et_pb_blurb_description {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	width: 100%;
}

.sw-home .sw-card--service .sw-card-more {
	margin-top: auto;
	padding-top: 14px;
}

.sw-home .sw-card--service .et_pb_module_header {
	color: #000;
}

/* ---- 2c. process steps ---------------------------------------------------
   Kept surface-free on purpose: the numbered circles already carry the
   sequence, and boxing them would compete with the service cards directly
   above. They only need to sit on a common baseline. */
.sw-home .sw-step.et_pb_blurb {
	height: 100%;
	padding: 8px 6px 0 !important;
}

.sw-home .sw-step .et_pb_module_header {
	color: #000;
}

/* ---- 3. intro columns ----------------------------------------------------
   At 18% of a 1240px row these columns are ~215px wide. A 40px heading cannot
   sit in that, so it steps down — and the eyebrow, heading and lead get a
   tighter rhythm to match the narrower measure. */
.sw-home .sw-svc-intro h2,
.sw-home .sw-process-intro h2,
.sw-home .sw-results-intro h2 {
	font-size: 30px;
	line-height: 1.22em;
	letter-spacing: -0.4px;
}

.sw-home .sw-svc-intro .et_pb_module,
.sw-home .sw-process-intro .et_pb_module {
	margin-bottom: 14px;
}

.sw-home .sw-svc-intro p,
.sw-home .sw-process-intro p {
	font-size: 15px;
	line-height: 1.7em;
}

/* ---- 4. project cards ---------------------------------------------------- */

/* One aspect ratio across all four, so the row has a straight top edge even
   though the placeholder art is different sizes. */
.sw-home .sw-project-img img {
	aspect-ratio: 16 / 9;
	object-fit: cover;
}

.sw-home .sw-project-body {
	display: flex;
	flex-direction: column;
}

.sw-home .sw-project-body .et_pb_text_inner {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
}

.sw-home .sw-project-body .sw-card-more {
	margin-top: auto;
	padding-top: 14px;
}

/* Card titles run to two lines on the narrower cards; reserving the second
   line keeps the blurbs starting together. */
.sw-home .sw-project-body h3 {
	min-height: 2.4em;
	margin-bottom: 6px;
}

/* ---- 5. hero -------------------------------------------------------------
   The chips were sitting hard under the buttons with the same 14px gap that
   separates the buttons from each other, so they read as a third button row. */
.sw-home .sw-hero-chip-wrap {
	flex: 0 0 100%;
	margin-top: 12px;
}

/* The heading carries its own <br>, so the column width is the only measure it
   needs — a ch-based cap on top of that just forced a fourth line. */

/* ---- 6. trusted strip ----------------------------------------------------
   A quiet band between two loud ones. Consistent logo heights and a hairline
   underneath so it reads as a divider rather than an empty gap. */
.sw-home .sw-trusted {
	border-bottom: 1px solid var(--sw-border-light);
}

/* The base rule greys these to 55%, which on light placeholder art leaves them
   almost invisible. Quiet is right for this band; illegible is not. */
.sw-home .sw-client-logo img {
	max-height: 32px;
	margin: 0 auto;
	width: auto;
	opacity: 0.85;
}

.sw-home .sw-client-logo img:hover {
	opacity: 1;
}

/* ---- responsive ---------------------------------------------------------- */

@media (max-width: 980px) {
	.sw-home .sw-svc-intro h2,
	.sw-home .sw-process-intro h2,
	.sw-home .sw-results-intro h2 {
		font-size: 28px;
	}

	.sw-home .sw-project-body h3 {
		min-height: 0;
	}

}

/* ---- 7. success stories band ---------------------------------------------
   Filling this band with sample values instead of "##" exposed that its layout
   only ever held together because Divi's module settings were propping it up:

     - the avatar had no size of its own, so a 160px placeholder stretched to
       the full 390px column and became the loudest thing on the page;
     - the intro column stretches its children, so the button ran its whole
       width instead of sitting at its own size;
     - the three columns each aligned differently, so nothing shared a baseline.
   --------------------------------------------------------------------------- */

.sw-home .sw-results .et_pb_row {
	align-items: center;
}

/* The portrait is supporting evidence for the quote, not a hero image. */
.sw-home .sw-quote-avatar {
	margin-bottom: 14px !important;
}

.sw-home .sw-quote-avatar img {
	width: 64px;
	height: 64px;
	object-fit: cover;
}

.sw-home .sw-quote {
	display: flex;
	flex-direction: column;
	justify-content: center;
}

.sw-home .sw-quote-mark {
	/* --sw-blue is the dark end of the ramp and all but vanished on this
	   surface; the quote mark should read as a light accent. */
	color: var(--sw-blue-300);
}

.sw-home .sw-quote-by {
	margin-top: 10px;
	font-size: 14px !important;
	color: var(--sw-blue-300) !important;
}

/* Stop the intro column stretching the button to full width. */
.sw-home .sw-results-intro {
	align-items: flex-start;
}

.sw-home .sw-results-intro > .et_pb_text {
	width: 100%;
}

.sw-home .sw-results-intro > .et_pb_button {
	width: auto;
	margin-top: 6px;
}

/* Three figures across a third of the row is tight; this gives each one its own
   line-length and keeps the labels off two lines. */
.sw-home .sw-stats {
	gap: 18px 20px;
}

.sw-home .sw-stats li {
	flex: 1 1 100px;
	text-align: left;
}

.sw-home .sw-stats li span {
	font-size: 30px;
	margin-bottom: 2px;
}

@media (max-width: 980px) {
	.sw-home .sw-results .et_pb_row {
		align-items: stretch;
	}

	.sw-home .sw-stats li {
		flex: 1 1 120px;
	}
}

/* ===========================================================================
   28. Contact page template — templates/page-contact.php
   ---------------------------------------------------------------------------
   The page reuses the shared Divi-module layer in section 27b (.sw-divi), so
   only what is specific to this page lives here: the two panels and the form.

   The form is styled from scratch rather than inheriting Divi's input styles,
   because Divi only ships those with its own contact module — which a plain
   template never loads. When this page becomes a Divi layout the markup is
   replaced by et_pb_contact_form and most of the .sw-form rules stop applying;
   the panel and card rules keep working, because they only wrap it.
   =========================================================================== */

.sw-contact .sw-contact-hero {
	padding: 96px 0 84px;
}

.sw-contact .sw-contact-hero .et_pb_text_inner {
	max-width: 760px;
}

.sw-contact .sw-contact-body {
	padding: 72px 0 88px;
}

/* Form and details sit top-aligned: the form is much taller than the cards
   beside it, and centring would float the addresses in empty space. */
.sw-contact .sw-row--contact {
	align-items: flex-start;
}

/* ---- panels -------------------------------------------------------------- */

.sw-contact .sw-contact-panel {
	padding: 32px 30px 34px;
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-radius);
	box-shadow: var(--sw-shadow-sm);
}

.sw-contact .sw-contact-panel__title {
	margin: 0 0 20px;
	padding: 0;
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 24px;
	font-weight: 800;
	line-height: 1.25;
	color: var(--sw-slate);
}

.sw-contact .sw-contact-card {
	padding: 24px 24px 26px;
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-radius);
	box-shadow: var(--sw-shadow-sm);
}

.sw-contact .sw-contact-card + .sw-contact-card {
	margin-top: 18px;
}

.sw-contact .sw-contact-card__title {
	margin: 0 0 12px;
	padding: 0;
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 17px;
	font-weight: 800;
	line-height: 1.3;
	color: var(--sw-slate);
}

/* <address> is italic by default in every browser, which reads as emphasis
   these are not asking for. */
.sw-contact .sw-contact-address {
	font-style: normal;
	font-family: Inter, Helvetica, Arial, sans-serif;
	font-size: 15px;
	line-height: 1.75;
	color: var(--sw-muted);
}

.sw-contact .sw-contact-list {
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-contact .sw-contact-list li {
	padding: 10px 0;
	font-family: Inter, Helvetica, Arial, sans-serif;
	font-size: 15px;
	line-height: 1.6;
	color: var(--sw-muted);
	border-bottom: 1px solid var(--sw-border-light);
}

.sw-contact .sw-contact-list li:last-child {
	border-bottom: 0;
	padding-bottom: 0;
}

.sw-contact .sw-contact-list__label {
	display: block;
	margin-bottom: 2px;
	font-size: 12px;
	font-weight: 700;
	letter-spacing: 1px;
	text-transform: uppercase;
	color: var(--sw-blue-500);
}

.sw-contact .sw-contact-list a {
	color: var(--sw-blue-600);
	font-weight: 600;
	text-decoration: none;
	overflow-wrap: anywhere; /* Long addresses must not widen the column. */
}

.sw-contact .sw-contact-list a:hover {
	text-decoration: underline;
}

.sw-contact .sw-contact-pref {
	margin: 16px 0 0;
	padding: 12px 14px;
	background: var(--sw-blue-25);
	border-radius: 10px;
	font-family: Inter, Helvetica, Arial, sans-serif;
	font-size: 14px;
	line-height: 1.6;
	color: var(--sw-muted);
}

/* ---- form ---------------------------------------------------------------- */

.sw-contact .sw-form__row {
	display: flex;
	flex-wrap: wrap;
	gap: 0 18px;
}

.sw-contact .sw-form__row > .sw-form__field {
	flex: 1 1 200px;
}

.sw-contact .sw-form__field {
	margin-bottom: 18px;
}

.sw-contact .sw-form label {
	display: block;
	margin-bottom: 7px;
	font-family: Inter, Helvetica, Arial, sans-serif;
	font-size: 14px;
	font-weight: 600;
	color: var(--sw-slate);
}

.sw-contact .sw-form__req {
	color: var(--sw-blue-500);
}

.sw-contact .sw-form__opt {
	font-weight: 400;
	color: var(--sw-muted);
}

.sw-contact .sw-form input[type="text"],
.sw-contact .sw-form input[type="email"],
.sw-contact .sw-form textarea {
	display: block;
	width: 100%;
	padding: 13px 15px;
	background: var(--sw-blue-25);
	border: 1px solid var(--sw-border-light);
	border-radius: 10px;
	font-family: Inter, Helvetica, Arial, sans-serif;
	font-size: 15px;
	line-height: 1.55;
	color: var(--sw-slate);
	transition: border-color 0.2s var(--sw-ease), box-shadow 0.2s var(--sw-ease),
		background-color 0.2s var(--sw-ease);
}

.sw-contact .sw-form textarea {
	resize: vertical;
	min-height: 150px;
}

.sw-contact .sw-form input::placeholder,
.sw-contact .sw-form textarea::placeholder {
	color: var(--sw-blue-300);
}

.sw-contact .sw-form input:focus,
.sw-contact .sw-form textarea:focus {
	outline: none;
	background: var(--sw-white);
	border-color: var(--sw-blue-400);
	box-shadow: 0 0 0 3px rgba(91, 155, 213, 0.28);
}

/* Keyboard users still get the theme's ring; the glow above is the resting
   focus style for pointer users who click straight in. */
.sw-contact .sw-form input:focus-visible,
.sw-contact .sw-form textarea:focus-visible,
.sw-contact .sw-form button:focus-visible {
	outline: 2px solid var(--sw-blue-500);
	outline-offset: 2px;
}

.sw-contact .sw-form__note {
	margin: 0 0 18px;
	padding: 0;
	font-family: Inter, Helvetica, Arial, sans-serif;
	font-size: 13px;
	line-height: 1.6;
	color: var(--sw-muted);
}

/* Honeypot. Off-canvas rather than display:none, because some bots skip fields
   that are explicitly hidden. */
.sw-contact .sw-form__trap {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

/* The submit control is a <button>, so it needs the button styling that
   section 27b applies to .sw-btn anchors. */
.sw-contact .sw-form button.sw-btn {
	cursor: pointer;
	border: 1px solid transparent !important;
}

/* ---- status message ------------------------------------------------------ */

.sw-contact .sw-form-notice {
	margin: 0 0 20px;
	padding: 13px 16px;
	border-radius: 10px;
	border: 1px solid transparent;
	font-family: Inter, Helvetica, Arial, sans-serif;
	font-size: 14px;
	line-height: 1.6;
}

.sw-contact .sw-form-notice--success {
	background: var(--sw-blue-50);
	border-color: var(--sw-blue-200);
	color: var(--sw-blue-600);
}

/* The palette has no red in it. Rather than introduce one colour that belongs
   to no part of the system, an error is marked by weight and a solid bar. */
.sw-contact .sw-form-notice--error {
	background: var(--sw-blue-25);
	border-color: var(--sw-blue-300);
	border-left: 4px solid var(--sw-blue-600);
	color: var(--sw-navy-900);
	font-weight: 600;
}

/* ---- responsive ---------------------------------------------------------- */

@media (max-width: 980px) {
	.sw-contact .sw-contact-hero {
		padding: 64px 0 56px;
	}

	.sw-contact .sw-contact-body {
		padding: 48px 0 64px;
	}

	/* The details column follows the form on a phone, which matches the reading
	   order the intro describes. */
	.sw-contact .sw-contact-aside {
		margin-top: 24px;
	}
}

@media (max-width: 767px) {
	.sw-contact .sw-contact-panel {
		padding: 24px 20px 26px;
	}

	.sw-contact .sw-contact-panel__title {
		font-size: 21px;
	}

	.sw-contact .sw-form__row {
		gap: 0;
	}
}

/* ===========================================================================
   28b. Contact page — redesign
   ---------------------------------------------------------------------------
   Laid out from the contact mockup. Section 28 above still owns the form
   controls, the panel and the notice; this block adds what the redesign
   introduces and overrides only where the mockup departs from it:

     - a two-column hero with reassurance points beside the illustration
     - icons sitting inside the name / email / company / phone inputs
     - a contact-details list of icon tile + label + value + note
     - the dark booking card
     - the four-step "what happens next" band

   Colours are ramp steps, not new values: hero --sw-navy-950, body --sw-light,
   booking card --sw-navy-900, steps band --sw-light-alt.
   =========================================================================== */

/* ---- hero ---------------------------------------------------------------- */

.sw-contact-hero {
	position: relative;
	overflow: hidden;
	background: #03182c;
	padding: 46px 0 54px;
}

.sw-contact-hero::before {
	content: "";
	position: absolute;
	top: -200px;
	right: -6%;
	width: 640px;
	height: 640px;
	border-radius: 50%;
	background: radial-gradient(circle, rgba(8, 82, 150, 0.26) 0%, rgba(8, 82, 150, 0) 68%);
	pointer-events: none;
}

.sw-contact-hero__row {
	position: relative;
	z-index: 1;
	align-items: center;
}

/* Prefixed to reach (0,2,0), the same trick the other hero titles use: the base
   `.sw-page h1, .sw-page h2, .sw-page h3 { color: var(--sw-slate) }` is (0,1,1)
   and would otherwise paint the headline near-black on a near-black hero. */
.sw-divi .sw-contact-hero__title,
.sw-page .sw-contact-hero__title {
	margin: 0 0 16px;
	color: #fff;
	font-size: 44px;
	font-weight: 800;
	line-height: 1.14;
	letter-spacing: -1.2px;
}

.sw-contact-hero__lede {
	max-width: 470px;
	margin: 0 0 28px;
	color: var(--sw-muted-dark);
	font-size: 16px;
	line-height: 1.8;
}

.sw-contact-hero__visual img {
	display: block;
	width: auto;
	max-width: 100%;
	max-height: 340px;
	height: auto;
	margin-left: auto;
}

.sw-contact-trust {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 18px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-contact-trust li {
	display: flex;
	align-items: flex-start;
	gap: 10px;
}

.sw-contact-trust__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 34px;
	height: 34px;
	border-radius: 50%;
	color: #9bc2e5;
	background: rgba(8, 82, 150, 0.3);
}

.sw-contact-trust strong {
	display: block;
	margin-bottom: 2px;
	color: #dce9f5;
	font-size: 13.5px;
	font-weight: 700;
}

.sw-contact-trust li > span:last-child {
	color: #7fa8c9;
	font-size: 12.5px;
	line-height: 1.5;
}

/* ---- form panel ---------------------------------------------------------- */

.sw-contact-panel__sub {
	margin: -8px 0 22px;
	color: var(--sw-muted);
	font-size: 14.5px;
	line-height: 1.7;
}

/* Icon inside the control. The input keeps its own left padding so the text
   never runs under the glyph, and the icon is inert so a click still lands on
   the field. */
.sw-form__field--icon { position: relative; }

.sw-form__field--icon .sw-form__icon {
	position: absolute;
	left: 14px;
	bottom: 15px;
	display: flex;
	color: #6a8299;
	pointer-events: none;
}

.sw-form__field--icon input { padding-left: 40px; }

.sw-form select {
	width: 100%;
	padding: 13px 40px 13px 14px;
	background-color: #fff;
	border: 1px solid var(--sw-border-light);
	border-radius: 10px;
	color: var(--sw-slate);
	font-family: inherit;
	font-size: 14.5px;
	line-height: 1.4;
	appearance: none;
	-webkit-appearance: none;
	background-repeat: no-repeat;
	background-position: right 14px center;
	/* Chevron as a background image so the control needs no wrapper element. */
	background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%236a8299' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
}

.sw-form select:focus-visible {
	outline: 2px solid var(--sw-cyan-txt);
	outline-offset: 1px;
}

.sw-btn--block.et_pb_button,
body #page-container .et_pb_section .sw-btn--block.et_pb_button {
	display: flex;
	width: 100%;
	justify-content: center;
}

.sw-form__note {
	display: flex;
	align-items: flex-start;
	gap: 8px;
	margin-top: 14px;
}

.sw-form__note-icon {
	display: flex;
	flex: 0 0 auto;
	margin-top: 2px;
	color: #6a8299;
}

/* ---- contact details ----------------------------------------------------- */

.sw-contact-card__sub {
	margin: -6px 0 18px;
	color: var(--sw-muted);
	font-size: 13.5px;
}

.sw-contact-info {
	display: grid;
	gap: 18px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-contact-info li {
	display: flex;
	align-items: flex-start;
	gap: 14px;
}

.sw-contact-info__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 44px;
	height: 44px;
	border-radius: 12px;
	color: var(--sw-blue-600);
	background: var(--sw-blue-50);
}

.sw-contact-info__body { min-width: 0; }

.sw-contact-info strong {
	display: block;
	margin-bottom: 3px;
	color: var(--sw-blue-600);
	font-size: 14px;
	font-weight: 700;
}

.sw-contact-info__value {
	display: block;
	color: var(--sw-slate);
	font-size: 14px;
	text-decoration: none;
	overflow-wrap: anywhere;
}

a.sw-contact-info__value:hover { text-decoration: underline; }

.sw-contact-info__note {
	display: block;
	margin-top: 2px;
	color: var(--sw-muted);
	font-size: 12.5px;
	line-height: 1.55;
}

/* ---- booking card -------------------------------------------------------- */

.sw-contact-consult {
	display: flex;
	align-items: flex-start;
	gap: 16px;
	margin-top: 18px;
	padding: 22px 20px 24px;
	background: #041f38;
	border-radius: var(--sw-card-radius);
	box-shadow: var(--sw-shadow-md);
}

.sw-contact-consult__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 54px;
	height: 54px;
	border-radius: 14px;
	color: #9bc2e5;
	background: rgba(8, 82, 150, 0.32);
}

.sw-divi .sw-contact-consult__title,
.sw-page .sw-contact-consult__title {
	margin: 0 0 6px;
	color: #fff;
	font-size: 17px;
	font-weight: 800;
	line-height: 1.3;
}

.sw-contact-consult p {
	margin: 0 0 14px;
	color: #9bc2e5;
	font-size: 13px;
	line-height: 1.65;
}

/* ---- what happens next --------------------------------------------------- */

.sw-contact-steps {
	background: var(--sw-light-alt);
	padding: 62px 0 66px;
}

.sw-contact-steps__grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 24px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-contact-step {
	position: relative;
	padding: 0 12px;
	text-align: center;
}

/* Hairline between steps, mirroring the mockup. Drawn on the following element
   rather than as a border, so the last one needs no exception. */
.sw-contact-step + .sw-contact-step::before {
	content: "";
	position: absolute;
	left: 0;
	top: 10%;
	height: 80%;
	border-left: 1px solid rgba(8, 82, 150, 0.14);
}

.sw-contact-step__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 52px;
	height: 52px;
	margin-bottom: 12px;
	border-radius: 50%;
	color: var(--sw-blue-600);
	background: #fff;
	box-shadow: var(--sw-shadow-sm);
}

.sw-contact-step h3 {
	margin: 0 0 6px;
	font-size: 15.5px;
	font-weight: 700;
}

.sw-contact-step p {
	margin: 0;
	color: var(--sw-muted);
	font-size: 13px;
	line-height: 1.6;
}

/* ---- responsive ---------------------------------------------------------- */

@media (max-width: 1100px) {
	.sw-contact-steps__grid { grid-template-columns: repeat(2, 1fr); row-gap: 32px; }
	.sw-contact-step:nth-child(odd)::before { display: none; }
}

@media (max-width: 980px) {
	.sw-contact-hero__visual img { margin: 0 auto; max-width: 320px; }
	.sw-contact-trust { grid-template-columns: 1fr; gap: 14px; }

	.sw-divi .sw-contact-hero__title,
	.sw-page .sw-contact-hero__title { font-size: 34px; }
}

@media (max-width: 767px) {
	.sw-divi .sw-contact-hero__title,
	.sw-page .sw-contact-hero__title { font-size: 28px; }

	.sw-contact-steps__grid { grid-template-columns: 1fr; }
	.sw-contact-step::before { display: none !important; }
	.sw-contact-consult { flex-direction: column; }
}

/* The PHP template writes this card as h2 + p; the Divi layout writes it as
   spans inside one text module. Both shapes get the same treatment. */
.sw-contact-consult__body { display: block; }
.sw-contact-consult__title { display: block; }

.sw-contact-consult__copy {
	display: block;
	margin: 0 0 14px;
	color: #9bc2e5;
	font-size: 13px;
	line-height: 1.65;
}

/* ===========================================================================
   17b. Services page — Divi builder layout
   ---------------------------------------------------------------------------
   Companion to the Services rules above for when the page is built from Divi
   modules (templates/jsonimports/SeriousWeb_Services_Page.json) rather than
   templates/page-services.php. Those rules own the design; this block only
   re-attaches it to Divi's DOM, exactly as 20b, 21b and 22b do elsewhere.

   Each grid goes on a Divi COLUMN so its modules become direct grid children
   and the existing grid rules — including their responsive step-downs — apply
   unchanged. Cards, tiles and steps are all et_pb_blurb, so the rest is mapping
   Divi's blurb internals onto the class names the design expects:

     .et_pb_main_blurb_image  ->  .sw-svc-card__icon / .sw-auto-tile__icon
                                  / .sw-step-item__icon
     .et_pb_module_header     ->  the card's h3
     .et_pb_blurb_description ->  the card body

   Embedded verbatim in the exported JSON's code module, so the layout imports
   correctly onto a host that has not had this stylesheet deployed. Keep the
   two copies in step.
   =========================================================================== */

.sw-svc-styles { display: none; }

/* ---- rows that need side-by-side columns --------------------------------- */

.sw-svc-hero .et_pb_row,
.sw-svc-cta .et_pb_row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
}

.sw-svc-hero .et_pb_row > .et_pb_column,
.sw-svc-cta .et_pb_row > .et_pb_column {
	float: none;
}

/* ---- hero ---------------------------------------------------------------- */

.sw-svc-hero__visual .et_pb_image {
	margin: 0;
	text-align: right;
}

.sw-svc-hero__visual .et_pb_image_wrap {
	display: inline-block;
	max-width: 100%;
}

.sw-svc-hero__copy .et_pb_button_module_wrapper {
	display: inline-block;
	margin: 0 12px 12px 0;
}

/* ---- grids on columns ---------------------------------------------------- */

.et_pb_column.sw-svc-grid,
.et_pb_column.sw-auto-grid,
.et_pb_column.sw-steps {
	float: none;
	display: grid;
}

.sw-svc-grid > .et_pb_module,
.sw-auto-grid > .et_pb_module,
.sw-steps > .et_pb_module {
	margin-bottom: 0;
}

.sw-svc-card .et_pb_blurb_content,
.sw-auto-tile .et_pb_blurb_content,
.sw-step-item .et_pb_blurb_content {
	max-width: none;
	width: 100%;
	margin: 0;
}

.et_pb_column.sw-sec-head { float: none; }

/* Divi's default for a top-placed blurb icon is
   `.et_pb_blurb_position_top .et-pb-icon { font-size: 96px }` (0-2-0), and the
   icon_font_size set on each module produces no rule at all — Divi emits the
   icon's colour and font-family but not its size. Without these the icons
   render at 96px: they burst the 12-column tile grid and swallow the circular
   backgrounds whole. Same 0-3-0 fix the .sw-chip rules use in section 3. */
.sw-svc-card .et_pb_main_blurb_image .et-pb-icon,
.sw-step-item .et_pb_main_blurb_image .et-pb-icon {
	font-size: 26px;
	line-height: 1;
}

.sw-auto-tile .et_pb_main_blurb_image .et-pb-icon {
	font-size: 22px;
	line-height: 1;
	color: var(--sw-indigo);
}

.sw-svc-card .et_pb_main_blurb_image .et_pb_image_wrap,
.sw-auto-tile .et_pb_main_blurb_image .et_pb_image_wrap,
.sw-step-item .et_pb_main_blurb_image .et_pb_image_wrap {
	display: flex;
	line-height: 1;
}

/* ---- service cards ------------------------------------------------------- */

.sw-svc-card.et_pb_blurb { margin: 0; text-align: left; }

.sw-svc-card .et_pb_blurb_content {
	display: flex;
	flex-direction: column;
	height: 100%;
}

.sw-svc-card .et_pb_main_blurb_image {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 50px;
	height: 50px;
	margin: 0 0 18px;
	border-radius: 50%;
	background: var(--sw-accent);
	line-height: 1;
}

.sw-svc-card .et_pb_blurb_container {
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
	text-align: left;
}

.sw-svc-card .et_pb_module_header {
	margin: 0 0 10px;
	padding: 0;
	font-size: 19px;
	font-weight: 800;
	line-height: 1.3;
}

.sw-svc-card .et_pb_blurb_description {
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
}

.sw-svc-card .et_pb_blurb_description > p {
	margin: 0 0 16px;
	font-size: 14px;
	line-height: 1.7;
}

/* ---- automation tiles ---------------------------------------------------- */

.sw-auto-tile.et_pb_blurb { margin: 0; }

.sw-auto-tile .et_pb_blurb_content {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 10px;
}

.sw-auto-tile .et_pb_main_blurb_image { margin: 0; line-height: 1; }
.sw-auto-tile .et_pb_blurb_container { text-align: center; }

.sw-auto-tile .et_pb_module_header {
	margin: 0;
	padding: 0;
	font-size: 11.5px;
	font-weight: 600;
	line-height: 1.4;
	color: var(--sw-slate);
	min-height: 2.8em;
}

/* ---- process steps ------------------------------------------------------- */

.sw-step-item.et_pb_blurb { margin: 0; }

.sw-step-item .et_pb_main_blurb_image {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 62px;
	height: 62px;
	margin: 0 auto 14px;
	border-radius: 50%;
	background: var(--sw-accent);
	box-shadow: 0 16px 30px -16px var(--sw-accent);
	line-height: 1;
}

/* The step number sits above the title. Divi always renders its own title
   before the description, so rather than reordering with display:contents and
   a negative `order` — which depends on the description collapsing into the
   flex container and silently did nothing — the blurb ships no title at all
   and the description carries the number, the h3 and the copy in the order
   they should appear. Section 19 already styles `.sw-step-item h3`. */
.sw-step-item .et_pb_blurb_container { text-align: center; }

/* ---- closing CTA --------------------------------------------------------- */

.sw-svc-cta .sw-btn-row .et_pb_button_module_wrapper { display: inline-block; margin: 0 0 0 12px; }
.sw-svc-cta .sw-btn-row { text-align: right; }

@media (max-width: 980px) {
	.sw-svc-hero__visual .et_pb_image { text-align: center; }
	.sw-svc-cta .sw-btn-row { text-align: left; }
	.sw-svc-cta .sw-btn-row .et_pb_button_module_wrapper { margin: 0 12px 0 0; }
}

/* ===========================================================================
   29. AI Invoice Processing page (templates/page-ai-invoice-processing.php)
   ---------------------------------------------------------------------------
   Built to the invoice mockup. Reuses the shared shell, buttons and section
   headings from section 16, the check-list from section 16, and the accent and
   tint variables from section 1 — so only this page's own blocks live here:

     hero with four inline proof points · four benefit cards · a five-step flow
     with connectors · the extraction card · the case-study / fit pair · the
     technology pills · the closing CTA.

   Section rhythm follows the mockup; the colours are ramp steps — hero
   --sw-navy-950, benefits and flow --sw-light, extraction --sw-light-alt,
   closing CTA --sw-navy-850.
   =========================================================================== */

/* ---- hero ---------------------------------------------------------------- */

.sw-inv-hero {
	position: relative;
	overflow: hidden;
	background: #03182c;
	padding: 44px 0 52px;
}

.sw-inv-hero::before {
	content: "";
	position: absolute;
	top: -220px;
	right: -8%;
	width: 720px;
	height: 720px;
	border-radius: 50%;
	background: radial-gradient(circle, rgba(8, 82, 150, 0.28) 0%, rgba(8, 82, 150, 0) 68%);
	pointer-events: none;
}

.sw-inv-hero__grid {
	position: relative;
	z-index: 1;
	display: grid;
	grid-template-columns: 1fr 1.1fr;
	align-items: center;
	gap: 46px;
}

/* Prefixed to reach (0,2,0). The base `.sw-page h1, .sw-page h2, .sw-page h3
   { color: var(--sw-slate) }` is (0,1,1) and would paint the headline
   near-black on a near-black hero. Same trick as the other hero titles. */
.sw-page .sw-inv-hero__title {
	margin: 0 0 16px;
	color: #fff;
	font-size: 42px;
	font-weight: 800;
	line-height: 1.16;
	letter-spacing: -1.2px;
}

.sw-inv-hero__lede {
	max-width: 460px;
	margin: 0 0 26px;
	color: var(--sw-muted-dark);
	font-size: 15.5px;
	line-height: 1.8;
}

.sw-inv-hero__visual img {
	display: block;
	width: auto;
	max-width: 100%;
	max-height: 380px;
	height: auto;
	margin-left: auto;
}

/* Four proof points on one line under the lede. auto-fit rather than a fixed
   four columns, so they reflow instead of crushing when the copy is longer. */
.sw-inv-points {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
	gap: 16px 18px;
	list-style: none;
	margin: 0 0 28px;
	padding: 0;
}

.sw-inv-points li {
	display: flex;
	align-items: flex-start;
	gap: 9px;
}

.sw-inv-points__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 30px;
	height: 30px;
	border-radius: 9px;
	color: #9bc2e5;
	background: rgba(8, 82, 150, 0.32);
}

.sw-inv-points strong {
	display: block;
	margin-bottom: 1px;
	color: #dce9f5;
	font-size: 12.5px;
	font-weight: 700;
	line-height: 1.35;
}

.sw-inv-points li > span:last-child {
	color: #7fa8c9;
	font-size: 11.5px;
	line-height: 1.45;
}

/* ---- benefits ------------------------------------------------------------ */

.sw-inv-benefits {
	background: var(--sw-light);
	padding: 66px 0 62px;
}

.sw-inv-benefit-grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 18px;
	list-style: none;
	margin: 0;
	padding: 0;
	align-items: stretch;
}

.sw-inv-benefit {
	display: flex;
	align-items: flex-start;
	gap: 14px;
	padding: var(--sw-card-pad);
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-card-radius);
	box-shadow: var(--sw-card-shadow);
	transition: var(--sw-card-transition);
}

.sw-inv-benefit:hover {
	transform: translateY(-4px);
	box-shadow: var(--sw-card-shadow-hover);
	border-color: var(--sw-accent);
}

/* --sw-tint, not --sw-accent-soft — the cards carry .sw-tint--*, which does not
   define --sw-accent-soft, and there is no :root fallback. See .sw-ab-pillar__icon. */
.sw-inv-benefit__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 46px;
	height: 46px;
	border-radius: 50%;
	color: var(--sw-accent);
	background: var(--sw-tint);
}

.sw-inv-benefit strong {
	display: block;
	margin-bottom: 5px;
	font-size: 15px;
	font-weight: 700;
	line-height: 1.3;
	color: var(--sw-slate);
}

.sw-inv-benefit span > span {
	display: block;
	color: var(--sw-muted);
	font-size: 12.5px;
	line-height: 1.6;
}

/* ---- how it works -------------------------------------------------------- */

.sw-inv-how {
	background: var(--sw-light);
	padding: 0 0 68px;
}

.sw-inv-flow {
	display: grid;
	grid-template-columns: repeat(5, 1fr);
	gap: 18px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-inv-step {
	position: relative;
	text-align: center;
	padding: 0 6px;
}

/* Dashed connector between steps, drawn on the following item so the last one
   needs no exception. Hidden once the row wraps, where it would point at a
   step on the line above. */
.sw-inv-step + .sw-inv-step::before {
	content: "";
	position: absolute;
	top: 30px;
	left: -9px;
	width: 18px;
	border-top: 2px dashed rgba(8, 82, 150, 0.3);
}

.sw-inv-step__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 60px;
	height: 60px;
	margin-bottom: 12px;
	border-radius: 50%;
	color: #fff;
	background: var(--sw-accent);
	box-shadow: 0 16px 30px -16px var(--sw-accent);
}

.sw-inv-step__num {
	display: block;
	margin-bottom: 4px;
	color: var(--sw-accent);
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 17px;
	font-weight: 800;
}

.sw-inv-step h3 {
	margin: 0 0 6px;
	font-size: 15px;
	font-weight: 700;
	line-height: 1.3;
}

.sw-inv-step p {
	margin: 0;
	color: var(--sw-muted);
	font-size: 12.5px;
	line-height: 1.6;
}

/* ---- what we extract ----------------------------------------------------- */

.sw-inv-extract {
	background: var(--sw-light);
	padding: 0 0 66px;
}

.sw-inv-extract__card {
	padding: var(--sw-card-pad);
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-card-radius);
	box-shadow: var(--sw-card-shadow);
}

.sw-sec-head--tight { margin-bottom: 26px; }

.sw-inv-fields {
	display: grid;
	grid-template-columns: repeat(6, 1fr);
	gap: 18px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-inv-fields li {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	padding-left: 16px;
	border-left: 1px solid var(--sw-border-light);
}

.sw-inv-fields li:first-child { border-left: 0; padding-left: 0; }

.sw-inv-fields__icon {
	display: flex;
	flex: 0 0 auto;
	color: var(--sw-blue-500);
}

.sw-inv-fields strong {
	display: block;
	margin-bottom: 2px;
	font-size: 12.5px;
	font-weight: 700;
	line-height: 1.35;
	color: var(--sw-slate);
}

.sw-inv-fields span > span {
	display: block;
	color: var(--sw-muted);
	font-size: 11.5px;
	line-height: 1.45;
}

/* ---- case study + fit ---------------------------------------------------- */

.sw-inv-case {
	background: var(--sw-light);
	padding: 0 0 70px;
}

/* Equal columns: with no screenshot in the case-study card, the two panels
   carry the same amount of copy and a 3:2 split just left the white one
   half-empty. */
.sw-inv-case__grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 18px;
	align-items: stretch;
}

.sw-inv-case__card {
	overflow: hidden;
	background: #fff;
	border: 1px solid var(--sw-border-light);
	border-radius: 18px;
	box-shadow: var(--sw-shadow-sm);
}

.sw-inv-case__copy {
	display: flex;
	flex-direction: column;
	padding: 28px 26px 30px;
	--sw-accent: #085296;
}

.sw-page .sw-inv-case__copy h2 {
	margin: 0 0 12px;
	font-size: 21px;
	font-weight: 800;
	line-height: 1.3;
}

.sw-inv-case__copy > p {
	margin: 0 0 16px;
	color: var(--sw-muted);
	font-size: 13.5px;
	line-height: 1.7;
}

.sw-inv-case__copy .sw-check-list li { font-size: 13px; }

.sw-inv-fit {
	padding: 28px 26px 30px;
	background: #041f38;
	border-radius: var(--sw-card-radius);
	box-shadow: var(--sw-shadow-md);
	--sw-accent: #5b9bd5;
}

.sw-page .sw-inv-fit h2 {
	margin: 0 0 10px;
	color: #fff;
	font-size: 20px;
	font-weight: 800;
	line-height: 1.3;
}

.sw-inv-fit > p {
	margin: 0 0 16px;
	color: #9bc2e5;
	font-size: 13.5px;
	line-height: 1.7;
}

/* The shared check-list is written for light surfaces; on the dark card the
   text has to lift or it drops to near-invisible on navy. */
.sw-page .sw-inv-fit .sw-check-list li {
	color: #dce9f5;
	font-size: 13px;
}

/* ---- technologies -------------------------------------------------------- */

.sw-inv-stack {
	background: var(--sw-light);
	padding: 0 0 62px;
	text-align: center;
}

.sw-page .sw-inv-stack .sw-eyebrow { margin-bottom: 18px; }

.sw-inv-stack__list {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 12px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-inv-stack__list li {
	padding: 12px 20px;
	background: #fff;
	border: 1px solid var(--sw-border-light);
	border-radius: 10px;
	box-shadow: var(--sw-shadow-sm);
	color: var(--sw-slate);
	font-size: 13.5px;
	font-weight: 700;
}

/* ---- closing CTA --------------------------------------------------------- */

.sw-inv-cta {
	background: #052846;
	padding: 46px 0;
}

.sw-inv-cta__grid {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 34px;
}

.sw-page .sw-inv-cta h2 {
	margin: 0 0 8px;
	color: #fff;
	font-size: 26px;
	font-weight: 800;
	line-height: 1.25;
}

.sw-inv-cta p {
	max-width: 430px;
	margin: 0;
	color: #9bc2e5;
	font-size: 14.5px;
	line-height: 1.7;
}

/* ---- responsive ---------------------------------------------------------- */

@media (max-width: 1100px) {
	.sw-inv-benefit-grid { grid-template-columns: repeat(2, 1fr); }
	.sw-inv-flow { grid-template-columns: repeat(3, 1fr); row-gap: 30px; }
	.sw-inv-step::before { display: none; }
	.sw-inv-fields { grid-template-columns: repeat(3, 1fr); row-gap: 22px; }
	.sw-inv-fields li:nth-child(3n + 1) { border-left: 0; padding-left: 0; }

	.sw-inv-case__grid { grid-template-columns: 1fr; }
}

@media (max-width: 980px) {
	.sw-inv-hero__grid { grid-template-columns: 1fr; gap: 32px; }
	.sw-page .sw-inv-hero__title { font-size: 33px; }
	.sw-inv-hero__visual img { margin: 0 auto; max-width: 420px; }

	.sw-inv-cta__grid { flex-direction: column; align-items: flex-start; }
}

@media (max-width: 767px) {
	.sw-page .sw-inv-hero__title { font-size: 27px; }
	.sw-inv-benefit-grid { grid-template-columns: 1fr; }
	.sw-inv-flow { grid-template-columns: 1fr; }
	.sw-inv-fields { grid-template-columns: 1fr; }
	.sw-inv-fields li { border-left: 0; padding-left: 0; }
	.sw-page .sw-inv-cta h2 { font-size: 22px; }
}

/* ===========================================================================
   29b. AI Invoice Processing — Divi builder layout
   ---------------------------------------------------------------------------
   Companion to section 29 for when the page is built from Divi modules
   (templates/jsonimports/SeriousWeb_AI_Invoice_Processing_Page.json) rather
   than templates/page-ai-invoice-processing.php.

   Deliberately much smaller than 20b/21b/22b/17b. Those pages rebuilt their
   cards as et_pb_blurb, which then needed Divi's blurb internals mapped back
   onto the design — the source of the 96px icon and missing-tick bugs. Here
   every icon-bearing block keeps the template's own markup inside a text
   module, so section 29 matches verbatim and there is nothing to map. Only the
   outer grids differ, because Divi supplies those as rows and columns.

   Embedded verbatim in the exported JSON's code module, so the layout imports
   correctly onto a host without this stylesheet. Keep the two copies in step.
   =========================================================================== */

.sw-inv-styles { display: none; }

.sw-inv-hero .et_pb_row,
.sw-inv-cta .et_pb_row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
}

.sw-inv-hero .et_pb_row > .et_pb_column,
.sw-inv-cta .et_pb_row > .et_pb_column {
	float: none;
}

.et_pb_column.sw-sec-head { float: none; }

/* Divi wraps the img in .et_pb_image_wrap, so section 29's `margin-left: auto`
   has nothing to push against — align the wrapper and let 29 cap the height. */
.sw-inv-hero__visual .et_pb_image {
	margin: 0;
	text-align: right;
}

.sw-inv-hero__visual .et_pb_image_wrap {
	display: inline-block;
	max-width: 100%;
}

/* The hero's two buttons share the copy column with the headline, so they
   cannot have a .sw-btn-row column of their own. The closing CTA does. */
.sw-inv-hero__copy .et_pb_button_module_wrapper {
	display: inline-block;
	margin: 0 12px 12px 0;
}

.sw-inv-cta .sw-btn-row .et_pb_button_module_wrapper { display: inline-block; margin: 0 0 0 12px; }
.sw-inv-cta .sw-btn-row { text-align: right; }

@media (max-width: 980px) {
	.sw-inv-hero__visual .et_pb_image { text-align: center; }
	.sw-inv-cta .sw-btn-row { text-align: left; }
	.sw-inv-cta .sw-btn-row .et_pb_button_module_wrapper { margin: 0 12px 0 0; }
}

/* ===========================================================================
   30. Business Process Automation page
       (templates/page-business-process-automation.php)
   ---------------------------------------------------------------------------
   Built to the automation mockup. Reuses the shared shell, buttons, section
   heads and the accent/tint variables, so only this page's own blocks live
   here: hero with four proof points · five benefit cards · a five-step flow
   with connectors · the process card · tool pills · closing CTA.

   Deliberately kept self-contained rather than sharing selectors with section
   29 (AI Invoice Processing), which is laid out the same way. The two pages
   are exported as separate importable layouts that each embed their own CSS by
   line range, so a shared block would have to be embedded in both and would
   couple two pages that may well diverge. The duplication is the cheaper
   trade; if a third page of this shape appears, factor all three out instead.

   Section rhythm follows the mockup; colours are ramp steps — hero
   --sw-navy-950, body --sw-light, closing CTA --sw-navy-850.
   =========================================================================== */

/* ---- hero ---------------------------------------------------------------- */

.sw-bpa-hero {
	position: relative;
	overflow: hidden;
	background: #03182c;
	padding: 44px 0 52px;
}

.sw-bpa-hero::before {
	content: "";
	position: absolute;
	top: -220px;
	right: -8%;
	width: 720px;
	height: 720px;
	border-radius: 50%;
	background: radial-gradient(circle, rgba(8, 82, 150, 0.28) 0%, rgba(8, 82, 150, 0) 68%);
	pointer-events: none;
}

.sw-bpa-hero__grid {
	position: relative;
	z-index: 1;
	display: grid;
	grid-template-columns: 1fr 1.15fr;
	align-items: center;
	gap: 44px;
}

/* Prefixed to reach (0,2,0). The base `.sw-page h1, .sw-page h2, .sw-page h3
   { color: var(--sw-slate) }` is (0,1,1) and would paint the headline
   near-black on a near-black hero. Same trick as the other hero titles. */
.sw-page .sw-bpa-hero__title {
	margin: 0 0 16px;
	color: #fff;
	font-size: 42px;
	font-weight: 800;
	line-height: 1.16;
	letter-spacing: -1.2px;
}

.sw-bpa-hero__lede {
	max-width: 470px;
	margin: 0 0 26px;
	color: var(--sw-muted-dark);
	font-size: 15.5px;
	line-height: 1.8;
}

.sw-bpa-hero__visual img {
	display: block;
	width: auto;
	max-width: 100%;
	max-height: 380px;
	height: auto;
	margin-left: auto;
}

/* Four proof points in one band under the lede. The icon sits on its own line
   above the label, so each column stays narrow enough for four across. */
.sw-bpa-points {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
	gap: 18px;
	list-style: none;
	margin: 0 0 28px;
	padding: 0;
}

.sw-bpa-points li {
	padding-left: 14px;
	border-left: 1px solid rgba(255, 255, 255, 0.09);
}

.sw-bpa-points li:first-child { border-left: 0; padding-left: 0; }

.sw-bpa-points__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 30px;
	height: 30px;
	margin-bottom: 8px;
	border-radius: 50%;
	color: #9bc2e5;
	background: rgba(8, 82, 150, 0.32);
}

.sw-bpa-points strong {
	display: block;
	margin-bottom: 3px;
	color: #dce9f5;
	font-size: 12.5px;
	font-weight: 700;
	line-height: 1.35;
}

.sw-bpa-points li > span:last-child {
	display: block;
	color: #7fa8c9;
	font-size: 11.5px;
	line-height: 1.5;
}

/* ---- benefits ------------------------------------------------------------ */

.sw-bpa-benefits {
	background: var(--sw-light);
	padding: 62px 0 58px;
}

.sw-bpa-benefit-grid {
	display: grid;
	grid-template-columns: repeat(5, 1fr);
	gap: 16px;
	list-style: none;
	margin: 0;
	padding: 0;
	align-items: stretch;
}

.sw-bpa-benefit {
	padding: var(--sw-card-pad);
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-card-radius);
	box-shadow: var(--sw-card-shadow);
	text-align: center;
	transition: var(--sw-card-transition);
}

.sw-bpa-benefit:hover {
	transform: translateY(-4px);
	box-shadow: var(--sw-card-shadow-hover);
	border-color: var(--sw-accent);
}

/* --sw-tint, not --sw-accent-soft: the cards carry .sw-tint--*, which defines
   --sw-tint and --sw-accent only. --sw-accent-soft is set exclusively by the
   .sw-accent--* classes and has no :root fallback, so referencing it here left
   the icon disc with no background at all. */
.sw-bpa-benefit__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 52px;
	height: 52px;
	margin-bottom: 14px;
	border-radius: 50%;
	color: var(--sw-accent);
	background: var(--sw-tint);
}

.sw-bpa-benefit h3 {
	margin: 0 0 8px;
	font-size: 15px;
	font-weight: 700;
	line-height: 1.3;
}

.sw-bpa-benefit p {
	margin: 0;
	color: var(--sw-muted);
	font-size: 12.5px;
	line-height: 1.65;
}

/* ---- how it works -------------------------------------------------------- */

.sw-bpa-how {
	background: var(--sw-light);
	padding: 0 0 62px;
}

.sw-bpa-flow {
	display: grid;
	grid-template-columns: repeat(5, 1fr);
	gap: 18px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-bpa-step {
	position: relative;
	padding: 0 6px;
	text-align: center;
}

/* Dashed connector between steps, drawn on the following item so the last one
   needs no exception. Hidden once the row wraps, where it would point at a
   step on the line above. */
.sw-bpa-step + .sw-bpa-step::before {
	content: "";
	position: absolute;
	top: 30px;
	left: -9px;
	width: 18px;
	border-top: 2px dashed rgba(8, 82, 150, 0.3);
}

.sw-bpa-step__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 60px;
	height: 60px;
	margin-bottom: 12px;
	border-radius: 50%;
	color: #fff;
	background: var(--sw-accent);
	box-shadow: 0 16px 30px -16px var(--sw-accent);
}

.sw-bpa-step__num {
	display: block;
	margin-bottom: 4px;
	color: var(--sw-accent);
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 17px;
	font-weight: 800;
}

.sw-bpa-step h3 {
	margin: 0 0 6px;
	font-size: 15px;
	font-weight: 700;
	line-height: 1.3;
}

.sw-bpa-step p {
	margin: 0;
	color: var(--sw-muted);
	font-size: 12.5px;
	line-height: 1.6;
}

/* ---- where we automate --------------------------------------------------- */

.sw-bpa-where {
	background: var(--sw-light);
	padding: 0 0 62px;
}

.sw-bpa-where__card {
	padding: var(--sw-card-pad);
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-card-radius);
	box-shadow: var(--sw-card-shadow);
}

.sw-bpa-processes {
	display: grid;
	grid-template-columns: repeat(6, 1fr);
	gap: 20px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-bpa-processes li {
	padding-left: 18px;
	border-left: 1px solid var(--sw-border-light);
}

.sw-bpa-processes li:first-child { border-left: 0; padding-left: 0; }

.sw-bpa-processes__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 42px;
	height: 42px;
	margin-bottom: 12px;
	border-radius: 12px;
	color: var(--sw-blue-600);
	background: var(--sw-blue-50);
}

.sw-bpa-processes strong {
	display: block;
	margin-bottom: 4px;
	font-size: 13.5px;
	font-weight: 700;
	line-height: 1.35;
	color: var(--sw-slate);
}

.sw-bpa-processes li > span:last-child {
	display: block;
	color: var(--sw-muted);
	font-size: 12px;
	line-height: 1.55;
}

/* ---- tools --------------------------------------------------------------- */

.sw-bpa-tools {
	background: var(--sw-light);
	padding: 0 0 58px;
	text-align: center;
}

.sw-page .sw-bpa-tools .sw-eyebrow { margin-bottom: 18px; }

.sw-bpa-tools__list {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 12px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-bpa-tools__list li {
	padding: 12px 20px;
	background: #fff;
	border: 1px solid var(--sw-border-light);
	border-radius: 10px;
	box-shadow: var(--sw-shadow-sm);
	color: var(--sw-slate);
	font-size: 13.5px;
	font-weight: 700;
}

/* ---- closing CTA --------------------------------------------------------- */

.sw-bpa-cta {
	background: #052846;
	padding: 44px 0;
}

.sw-bpa-cta__grid {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 34px;
}

.sw-page .sw-bpa-cta h2 {
	margin: 0 0 8px;
	color: #fff;
	font-size: 26px;
	font-weight: 800;
	line-height: 1.25;
}

.sw-bpa-cta p {
	max-width: 460px;
	margin: 0;
	color: #9bc2e5;
	font-size: 14.5px;
	line-height: 1.7;
}

/* ---- responsive ---------------------------------------------------------- */

@media (max-width: 1100px) {
	.sw-bpa-benefit-grid { grid-template-columns: repeat(3, 1fr); }
	.sw-bpa-flow { grid-template-columns: repeat(3, 1fr); row-gap: 30px; }
	.sw-bpa-step::before { display: none; }
	.sw-bpa-processes { grid-template-columns: repeat(3, 1fr); row-gap: 24px; }
	.sw-bpa-processes li:nth-child(3n + 1) { border-left: 0; padding-left: 0; }
}

@media (max-width: 980px) {
	.sw-bpa-hero__grid { grid-template-columns: 1fr; gap: 32px; }
	.sw-page .sw-bpa-hero__title { font-size: 33px; }
	.sw-bpa-hero__visual img { margin: 0 auto; max-width: 420px; }
	.sw-bpa-cta__grid { flex-direction: column; align-items: flex-start; }
}

@media (max-width: 767px) {
	.sw-page .sw-bpa-hero__title { font-size: 27px; }
	.sw-bpa-points { grid-template-columns: repeat(2, 1fr); }
	.sw-bpa-points li { border-left: 0; padding-left: 0; }
	.sw-bpa-benefit-grid { grid-template-columns: 1fr; }
	.sw-bpa-flow { grid-template-columns: 1fr; }
	.sw-bpa-processes { grid-template-columns: 1fr; }
	.sw-bpa-processes li { border-left: 0; padding-left: 0; }
	.sw-page .sw-bpa-cta h2 { font-size: 22px; }
}

/* ===========================================================================
   30b. Business Process Automation — Divi builder layout
   ---------------------------------------------------------------------------
   Companion to section 30 for when the page is built from Divi modules
   (templates/jsonimports/SeriousWeb_Business_Process_Automation_Page.json)
   rather than templates/page-business-process-automation.php.

   Small, like 29b and for the same reason: every icon-bearing block keeps the
   template's own markup inside a text module, so section 30 matches verbatim
   and none of Divi's blurb internals have to be mapped. Only the outer grids
   differ, because Divi supplies those as rows and columns.

   The export embeds sections 30 AND 30b — not just this one. Section 30 is new,
   so a server that has not had this stylesheet deployed has no styling for the
   page at all; embedding only the bridge is what left the invoice page
   unstyled on import. Keep the embedded copy in step with both.
   =========================================================================== */

.sw-bpa-styles { display: none; }

.sw-bpa-hero .et_pb_row,
.sw-bpa-cta .et_pb_row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
}

.sw-bpa-hero .et_pb_row > .et_pb_column,
.sw-bpa-cta .et_pb_row > .et_pb_column {
	float: none;
}

.et_pb_column.sw-sec-head { float: none; }

/* Divi wraps the img in .et_pb_image_wrap, so section 30's `margin-left: auto`
   has nothing to push against — align the wrapper and let 30 cap the height. */
.sw-bpa-hero__visual .et_pb_image {
	margin: 0;
	text-align: right;
}

.sw-bpa-hero__visual .et_pb_image_wrap {
	display: inline-block;
	max-width: 100%;
}

/* The hero's two buttons share the copy column with the headline, so they
   cannot have a .sw-btn-row column of their own. The closing CTA does. */
.sw-bpa-hero__copy .et_pb_button_module_wrapper {
	display: inline-block;
	margin: 0 12px 12px 0;
}

.sw-bpa-cta .sw-btn-row .et_pb_button_module_wrapper { display: inline-block; margin: 0 0 0 12px; }
.sw-bpa-cta .sw-btn-row { text-align: right; }

@media (max-width: 980px) {
	.sw-bpa-hero__visual .et_pb_image { text-align: center; }
	.sw-bpa-cta .sw-btn-row { text-align: left; }
	.sw-bpa-cta .sw-btn-row .et_pb_button_module_wrapper { margin: 0 12px 0 0; }
}

/* ===========================================================================
   31. Custom Business Software page
       (templates/page-custom-business-software.php)
   ---------------------------------------------------------------------------
   Reuses the shared shell, buttons, section heads and check-list from section
   16, and the accent/tint tokens from section 1. Only this page's own blocks
   live here.

   Laid out to read differently from sections 29 and 30, which share a shape:
   seven alternating surfaces instead of one long light band, an asymmetric
   card grid whose lead card spans two columns, and a vertical build timeline
   instead of a horizontal step flow.

   Surfaces run dark → white → light → dark → light → white → dark:
   --sw-navy-950, #fff, --sw-light, --sw-navy-900, --sw-light, #fff,
   --sw-navy-850.

   NOTE ON TINTS: cards carry .sw-tint--*, which defines --sw-tint and
   --sw-accent only. --sw-accent-soft belongs to the .sw-accent--* classes and
   has no :root fallback, so an icon disc on a tinted card must use
   var(--sw-tint). See .sw-ab-pillar__icon, which got this right first.
   =========================================================================== */

/* ---- hero ---------------------------------------------------------------- */

.sw-cs-hero {
	position: relative;
	overflow: hidden;
	background: #03182c;
	padding: 44px 0 52px;
}

.sw-cs-hero::before {
	content: "";
	position: absolute;
	top: -220px;
	right: -8%;
	width: 720px;
	height: 720px;
	border-radius: 50%;
	background: radial-gradient(circle, rgba(8, 82, 150, 0.28) 0%, rgba(8, 82, 150, 0) 68%);
	pointer-events: none;
}

.sw-cs-hero__grid {
	position: relative;
	z-index: 1;
	display: grid;
	grid-template-columns: 1fr 1.1fr;
	align-items: center;
	gap: 44px;
}

/* Prefixed to reach (0,2,0). The base `.sw-page h1, .sw-page h2, .sw-page h3
   { color: var(--sw-slate) }` is (0,1,1) and would paint the headline
   near-black on a near-black hero. */
.sw-page .sw-cs-hero__title {
	margin: 0 0 16px;
	color: #fff;
	font-size: 42px;
	font-weight: 800;
	line-height: 1.16;
	letter-spacing: -1.2px;
}

.sw-cs-hero__lede {
	max-width: 480px;
	margin: 0 0 24px;
	color: var(--sw-muted-dark);
	font-size: 15.5px;
	line-height: 1.8;
}

.sw-cs-hero__visual img {
	display: block;
	width: auto;
	max-width: 100%;
	max-height: 380px;
	height: auto;
	margin-left: auto;
}

/* The shared check-list is written for light surfaces. On the hero the text
   has to lift, or it drops to near-invisible on navy. */
.sw-page .sw-cs-hero .sw-check-list { margin-bottom: 28px; }
.sw-page .sw-cs-hero .sw-check-list li { color: #c3dbef; font-size: 14px; }
.sw-page .sw-cs-hero .sw-check { background: var(--sw-blue-400); }

/* ---- what we build ------------------------------------------------------- */

.sw-cs-build {
	background: #fff;
	padding: 66px 0 62px;
}

/* Asymmetric on purpose: the lead card spans two columns, so the row reads
   1 wide + 1, then 3 — rather than five identical tiles. */
.sw-cs-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 18px;
	list-style: none;
	margin: 0;
	padding: 0;
	align-items: stretch;
}

.sw-cs-card--lead { grid-column: span 2; }

.sw-cs-card {
	padding: var(--sw-card-pad);
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-card-radius);
	box-shadow: var(--sw-card-shadow);
	transition: var(--sw-card-transition);
}

.sw-cs-card:hover {
	transform: translateY(-4px);
	box-shadow: var(--sw-card-shadow-hover);
	border-color: var(--sw-accent);
}

.sw-cs-card__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	margin-bottom: 14px;
	border-radius: 50%;
	color: var(--sw-accent);
	background: var(--sw-tint);
}

.sw-cs-card h3 {
	margin: 0 0 8px;
	font-size: 16px;
	font-weight: 700;
	line-height: 1.3;
}

.sw-cs-card--lead h3 { font-size: 19px; }

.sw-cs-card p {
	margin: 0;
	color: var(--sw-muted);
	font-size: 13px;
	line-height: 1.7;
}

/* ---- how we build -------------------------------------------------------- */

.sw-cs-how {
	background: var(--sw-light);
	padding: 62px 0;
}

/* Vertical rather than the horizontal step rows on sections 29 and 30: each
   phase carries a deliverable line, which needs more width than a fifth of a
   row allows. The rail is drawn on the list so no phase owns it. */
.sw-cs-timeline {
	position: relative;
	max-width: 720px;
	margin: 0 auto;
	padding: 0 0 0 40px;
	list-style: none;
}

.sw-cs-timeline::before {
	content: "";
	position: absolute;
	left: 15px;
	top: 10px;
	bottom: 10px;
	border-left: 2px dashed rgba(8, 82, 150, 0.28);
}

.sw-cs-phase {
	position: relative;
	padding-bottom: 30px;
}

.sw-cs-phase:last-child { padding-bottom: 0; }

.sw-cs-phase__marker {
	position: absolute;
	left: -40px;
	top: 2px;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	border-radius: 50%;
	color: #fff;
	background: var(--sw-accent);
	box-shadow: 0 10px 20px -12px var(--sw-accent);
}

.sw-cs-phase__num {
	display: block;
	margin-bottom: 2px;
	color: var(--sw-accent);
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 13px;
	font-weight: 800;
	letter-spacing: 1px;
}

.sw-cs-phase h3 {
	margin: 0 0 6px;
	font-size: 18px;
	font-weight: 700;
	line-height: 1.3;
}

.sw-cs-phase p {
	margin: 0;
	color: var(--sw-muted);
	font-size: 13.5px;
	line-height: 1.7;
}

.sw-cs-phase__deliver {
	margin-top: 8px !important;
	color: var(--sw-blue-600);
	font-size: 12.5px;
	font-weight: 700;
}

/* ---- ownership ----------------------------------------------------------- */

.sw-cs-own {
	background: #041f38;
	padding: 56px 0;
}

.sw-cs-own__grid {
	display: grid;
	grid-template-columns: 2fr 3fr;
	align-items: center;
	gap: 40px;
}

.sw-page .sw-cs-own__copy h2 {
	margin: 0 0 12px;
	color: #fff;
	font-size: 27px;
	font-weight: 800;
	line-height: 1.28;
}

.sw-cs-own__copy p {
	margin: 0;
	color: var(--sw-muted-dark);
	font-size: 14.5px;
	line-height: 1.8;
}

.sw-cs-own__panel {
	padding: 26px 26px 22px;
	background: rgba(255, 255, 255, 0.035);
	border: 1px solid rgba(255, 255, 255, 0.09);
	border-radius: 16px;
	--sw-accent: #5b9bd5;
}

.sw-page .sw-cs-own__panel .sw-check-list { margin: 0; }
.sw-page .sw-cs-own__panel .sw-check-list li { color: #dce9f5; font-size: 13.5px; }

/* ---- technology ---------------------------------------------------------- */

.sw-cs-stack {
	background: var(--sw-light);
	padding: 58px 0;
}

.sw-cs-stack__grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 18px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-cs-group {
	padding: var(--sw-card-pad);
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-card-radius);
	box-shadow: var(--sw-card-shadow);
}

.sw-cs-group h3 {
	margin: 0 0 12px;
	padding-bottom: 10px;
	border-bottom: 1px solid var(--sw-border-light);
	color: var(--sw-blue-600);
	font-size: 12px;
	font-weight: 700;
	letter-spacing: 1.4px;
	text-transform: uppercase;
}

.sw-cs-group ul {
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-cs-group li {
	margin-bottom: 6px;
	color: var(--sw-slate);
	font-size: 13.5px;
	font-weight: 600;
}

.sw-cs-group li:last-child { margin-bottom: 0; }

/* ---- FAQ ----------------------------------------------------------------- */

.sw-cs-faq {
	background: #fff;
	padding: 62px 0 66px;
}

.sw-cs-faq__list {
	max-width: 780px;
	margin: 0 auto;
}

/* <details>/<summary> rather than a scripted accordion: keyboard accessible,
   findable by browser search, and it works with JavaScript disabled. */
.sw-cs-faq__item {
	margin-bottom: 10px;
	padding: 0 20px;
	background: #fff;
	border: 1px solid var(--sw-border-light);
	border-radius: 12px;
	box-shadow: var(--sw-shadow-sm);
}

.sw-cs-faq__item[open] { background: var(--sw-blue-25); }

.sw-cs-faq__item summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding: 17px 0;
	color: var(--sw-slate);
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 15.5px;
	font-weight: 700;
	line-height: 1.4;
	cursor: pointer;
	list-style: none;
}

/* Both spellings — WebKit still uses the pseudo-element for the marker. */
.sw-cs-faq__item summary::-webkit-details-marker { display: none; }
.sw-cs-faq__item summary::marker { content: ""; }

.sw-cs-faq__item summary:focus-visible {
	outline: 2px solid var(--sw-cyan-txt);
	outline-offset: 3px;
}

.sw-cs-faq__chev {
	flex: 0 0 auto;
	width: 10px;
	height: 10px;
	border-right: 2px solid var(--sw-blue-500);
	border-bottom: 2px solid var(--sw-blue-500);
	transform: rotate(45deg) translate(-2px, -2px);
	transition: transform 0.25s var(--sw-ease);
}

.sw-cs-faq__item[open] .sw-cs-faq__chev {
	transform: rotate(-135deg) translate(-2px, -2px);
}

.sw-cs-faq__body {
	padding: 0 0 18px;
	border-top: 1px solid var(--sw-border-light);
}

.sw-cs-faq__body p {
	margin: 14px 0 0;
	color: var(--sw-muted);
	font-size: 14px;
	line-height: 1.75;
}

/* ---- closing CTA --------------------------------------------------------- */

.sw-cs-cta {
	background: #052846;
	padding: 44px 0;
}

.sw-cs-cta__grid {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 34px;
}

.sw-page .sw-cs-cta h2 {
	margin: 0 0 8px;
	color: #fff;
	font-size: 25px;
	font-weight: 800;
	line-height: 1.25;
}

.sw-cs-cta p {
	max-width: 470px;
	margin: 0;
	color: #9bc2e5;
	font-size: 14.5px;
	line-height: 1.7;
}

/* ---- responsive ---------------------------------------------------------- */

@media (max-width: 1100px) {
	.sw-cs-grid { grid-template-columns: repeat(2, 1fr); }
	.sw-cs-card--lead { grid-column: span 2; }
	.sw-cs-stack__grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 980px) {
	.sw-cs-hero__grid { grid-template-columns: 1fr; gap: 32px; }
	.sw-page .sw-cs-hero__title { font-size: 33px; }
	.sw-cs-hero__visual img { margin: 0 auto; max-width: 420px; }

	.sw-cs-own__grid { grid-template-columns: 1fr; gap: 28px; }
	.sw-cs-cta__grid { flex-direction: column; align-items: flex-start; }
}

@media (max-width: 767px) {
	.sw-page .sw-cs-hero__title { font-size: 27px; }

	.sw-cs-grid { grid-template-columns: 1fr; }
	.sw-cs-card--lead { grid-column: span 1; }
	.sw-cs-card--lead h3 { font-size: 17px; }

	.sw-cs-timeline { padding-left: 32px; }
	.sw-cs-timeline::before { left: 12px; }
	.sw-cs-phase__marker { left: -32px; width: 26px; height: 26px; }

	.sw-cs-stack__grid { grid-template-columns: 1fr; }
	.sw-cs-faq__item { padding: 0 16px; }
	.sw-page .sw-cs-cta h2 { font-size: 22px; }
}

/* ===========================================================================
   31b. Custom Business Software — Divi builder layout
   ---------------------------------------------------------------------------
   Companion to section 31 for when the page is built from Divi modules
   (templates/jsonimports/SeriousWeb_Custom_Business_Software_Page.json) rather
   than templates/page-custom-business-software.php.

   Small, like 29b and 30b: every icon-bearing block keeps the template's own
   markup inside a text module, so section 31 matches verbatim and none of
   Divi's blurb internals have to be mapped. Only the outer grids differ,
   because Divi supplies those as rows and columns — which also means section
   31's .sw-cs-hero__grid, .sw-cs-own__grid and .sw-cs-cta__grid rules are inert
   in the builder layout, and the row rules below stand in for them.

   The export embeds sections 31 AND 31b. Section 31 is new, so a server that
   has not had this stylesheet deployed has no styling for the page at all.
   Keep the embedded copy in step with both.
   =========================================================================== */

.sw-cs-styles { display: none; }

.sw-cs-hero .et_pb_row,
.sw-cs-own .et_pb_row,
.sw-cs-cta .et_pb_row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
}

.sw-cs-hero .et_pb_row > .et_pb_column,
.sw-cs-own .et_pb_row > .et_pb_column,
.sw-cs-cta .et_pb_row > .et_pb_column {
	float: none;
}

.et_pb_column.sw-sec-head { float: none; }
.et_pb_column.sw-cs-own__copy { float: none; }

/* Divi wraps the img in .et_pb_image_wrap, so section 31's `margin-left: auto`
   has nothing to push against — align the wrapper and let 31 cap the height. */
.sw-cs-hero__visual .et_pb_image {
	margin: 0;
	text-align: right;
}

.sw-cs-hero__visual .et_pb_image_wrap {
	display: inline-block;
	max-width: 100%;
}

/* The hero's two buttons share the copy column with the headline, so they
   cannot have a .sw-btn-row column of their own. The closing CTA does. */
.sw-cs-hero__copy .et_pb_button_module_wrapper {
	display: inline-block;
	margin: 0 12px 12px 0;
}

.sw-cs-cta .sw-btn-row .et_pb_button_module_wrapper { display: inline-block; margin: 0 0 0 12px; }
.sw-cs-cta .sw-btn-row { text-align: right; }

@media (max-width: 980px) {
	.sw-cs-hero__visual .et_pb_image { text-align: center; }
	.sw-cs-cta .sw-btn-row { text-align: left; }
	.sw-cs-cta .sw-btn-row .et_pb_button_module_wrapper { margin: 0 12px 0 0; }
}

/* ===========================================================================
   32. Websites & Web Development v2 (templates/page-websites-development.php)
   ---------------------------------------------------------------------------
   Replacement for section 19, which styles the older page-websites.php. Both
   are present while the new page is reviewed; retire 19 with that template.

   Deliberately lean. The process band reuses .sw-steps / .sw-step-item from
   section 16 wholesale, the panels reuse .sw-check-list, and the section heads
   reuse .sw-sec-head — so only this page's own blocks are here: the centred
   hero, the overlapping outcome strip, the four type rows, the build-standard
   definition list and the two platform panels.

   Two rules applied up front, both learned the hard way elsewhere in this file:

   1. Icon discs on tinted cards use var(--sw-tint). The .sw-tint--* classes
      define --sw-tint and --sw-accent only; --sw-accent-soft belongs to the
      .sw-accent--* classes and has no :root fallback, so referencing it leaves
      the disc with no background. See .sw-ab-pillar__icon.
   2. Anything that would read `.sw-page .sw-wd-<section>` is written compound —
      `.sw-page.sw-wd-hero` — because a Divi export puts both classes on the
      same section element, where a descendant combinator cannot match.

   Surfaces run dark → light → white → light-alt → dark → navy-850.
   =========================================================================== */

/* ---- hero ---------------------------------------------------------------- */

.sw-wd-hero {
	position: relative;
	overflow: hidden;
	background: #03182c;
	padding: 56px 0 0;
}

/* Centred glow rather than the right-offset one the split heroes use — there
   is no art column here for it to sit behind. */
.sw-wd-hero::before {
	content: "";
	position: absolute;
	top: -320px;
	left: 50%;
	width: 900px;
	height: 900px;
	margin-left: -450px;
	border-radius: 50%;
	background: radial-gradient(circle, rgba(8, 82, 150, 0.26) 0%, rgba(8, 82, 150, 0) 68%);
	pointer-events: none;
}

.sw-wd-hero__copy {
	position: relative;
	z-index: 1;
	max-width: 760px;
	margin: 0 auto;
	text-align: center;
}

.sw-wd-hero .sw-crumbs { justify-content: center; display: flex; gap: 8px; }

/* Compound, not descendant: both classes land on one element in a Divi export.
   Still (0,2,0), so it out-ranks `.sw-page h1 { color: var(--sw-slate) }`. */
.sw-page .sw-wd-hero__title,
.sw-page.sw-wd-hero .sw-wd-hero__title {
	margin: 0 0 18px;
	color: #fff;
	font-size: 44px;
	font-weight: 800;
	line-height: 1.14;
	letter-spacing: -1.3px;
}

.sw-wd-hero__lede {
	max-width: 620px;
	margin: 0 auto 28px;
	color: var(--sw-muted-dark);
	font-size: 16px;
	line-height: 1.8;
}

.sw-btn-row--center { justify-content: center; }

/* ---- outcome strip ------------------------------------------------------- */

/* Overlaps the band below, the same way .sw-ab-stats-wrap does: the transform
   moves it down without the section's own padding growing to match. */
.sw-wd-strip__wrap {
	position: relative;
	z-index: 2;
	margin-bottom: -44px;
	transform: translateY(44px);
}

.sw-wd-strip {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	list-style: none;
	margin: 0;
	padding: 0;
	background: #fff;
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-card-radius);
	box-shadow: var(--sw-shadow-md);
	overflow: hidden;
}

.sw-wd-strip li {
	padding: 20px 18px 22px;
	border-left: 1px solid var(--sw-border-light);
}

.sw-wd-strip li:first-child { border-left: 0; }

.sw-wd-strip__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 34px;
	height: 34px;
	margin-bottom: 10px;
	border-radius: 9px;
	color: var(--sw-blue-600);
	background: var(--sw-blue-50);
}

.sw-wd-strip strong {
	display: block;
	margin-bottom: 3px;
	color: var(--sw-slate);
	font-size: 13.5px;
	font-weight: 700;
	line-height: 1.35;
}

.sw-wd-strip li > span:last-child {
	display: block;
	color: var(--sw-muted);
	font-size: 12px;
	line-height: 1.5;
}

/* ---- what we build ------------------------------------------------------- */

/* Top padding absorbs the strip's 44px overlap. */
.sw-wd-build {
	background: var(--sw-light);
	padding: 96px 0 62px;
}

.sw-wd-types {
	display: grid;
	gap: 14px;
	list-style: none;
	margin: 0;
	padding: 0;
}

/* Rows, not cards: icon, copy, and the qualifying line in its own column. */
.sw-wd-type {
	display: grid;
	grid-template-columns: auto 1fr 240px;
	align-items: center;
	gap: 22px;
	padding: 22px 24px;
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-card-radius);
	box-shadow: var(--sw-card-shadow);
	transition: var(--sw-card-transition);
}

.sw-wd-type:hover {
	transform: translateY(-3px);
	box-shadow: var(--sw-card-shadow-hover);
	border-color: var(--sw-accent);
}

.sw-wd-type__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 50px;
	height: 50px;
	border-radius: 50%;
	color: var(--sw-accent);
	background: var(--sw-tint);
}

.sw-wd-type h3 {
	margin: 0 0 6px;
	font-size: 17px;
	font-weight: 700;
	line-height: 1.3;
}

.sw-wd-type__body p {
	margin: 0;
	color: var(--sw-muted);
	font-size: 13.5px;
	line-height: 1.7;
}

.sw-wd-type__for {
	margin: 0;
	padding-left: 22px;
	border-left: 1px solid var(--sw-border-light);
	color: var(--sw-muted);
	font-size: 12.5px;
	line-height: 1.6;
}

.sw-wd-type__for strong {
	display: block;
	margin-bottom: 3px;
	color: var(--sw-blue-600);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 1.2px;
	text-transform: uppercase;
}

/* ---- what "done" means --------------------------------------------------- */

.sw-wd-standard {
	background: #fff;
	padding: 66px 0;
}

.sw-wd-standard__list {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 0 44px;
	margin: 0;
}

.sw-wd-standard__row {
	display: grid;
	grid-template-columns: 150px 1fr;
	gap: 18px;
	padding: 15px 0;
	border-top: 1px solid var(--sw-border-light);
}

.sw-wd-standard__row dt {
	color: var(--sw-blue-600);
	font-family: Manrope, Helvetica, Arial, sans-serif;
	font-size: 13.5px;
	font-weight: 800;
	line-height: 1.4;
}

.sw-wd-standard__row dd {
	margin: 0;
	color: var(--sw-muted);
	font-size: 13.5px;
	line-height: 1.7;
}

/* ---- process ------------------------------------------------------------- */

/* .sw-steps and .sw-step-item come from section 16 untouched — this band adds
   nothing but its surface. */
.sw-wd-process {
	background: var(--sw-light-alt);
	padding: 62px 0 66px;
}

/* ---- choosing the platform ----------------------------------------------- */

.sw-wd-platform {
	background: #041f38;
	padding: 58px 0 62px;
}

.sw-page .sw-wd-platform h2,
.sw-page.sw-wd-platform h2 {
	color: #fff;
}

.sw-page .sw-wd-platform .sw-sec-head__sub,
.sw-page.sw-wd-platform .sw-sec-head__sub {
	color: var(--sw-muted-dark);
}

.sw-wd-platform__grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 18px;
	align-items: stretch;
}

.sw-wd-panel {
	padding: 26px 24px 24px;
	border-radius: 16px;
	--sw-accent: #5b9bd5;
}

.sw-wd-panel--yes {
	background: rgba(255, 255, 255, 0.045);
	border: 1px solid rgba(255, 255, 255, 0.1);
}

.sw-wd-panel--no {
	background: rgba(255, 255, 255, 0.02);
	border: 1px solid rgba(255, 255, 255, 0.07);
}

.sw-page .sw-wd-panel h3,
.sw-page.sw-wd-platform .sw-wd-panel h3 {
	margin: 0 0 14px;
	color: #fff;
	font-size: 16px;
	font-weight: 800;
	line-height: 1.35;
}

/* The shared check-list is written for light surfaces; lift it on navy. */
.sw-page .sw-wd-panel .sw-check-list { margin: 0; }
.sw-page .sw-wd-panel .sw-check-list li { color: #dce9f5; font-size: 13.5px; }

/* The second panel lists what we will not sell you, so its ticks should not
   read as endorsements — muted, and squared off. */
.sw-wd-panel--no .sw-check {
	background: rgba(255, 255, 255, 0.16);
	border-radius: 5px;
}

/* ---- closing CTA --------------------------------------------------------- */

.sw-wd-cta {
	background: #052846;
	padding: 44px 0;
}

.sw-wd-cta__grid {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 34px;
}

.sw-page .sw-wd-cta h2,
.sw-page.sw-wd-cta h2 {
	margin: 0 0 8px;
	color: #fff;
	font-size: 25px;
	font-weight: 800;
	line-height: 1.25;
}

.sw-page .sw-wd-cta p,
.sw-page.sw-wd-cta p {
	max-width: 470px;
	margin: 0;
	color: #9bc2e5;
	font-size: 14.5px;
	line-height: 1.7;
}

/* ---- responsive ---------------------------------------------------------- */

@media (max-width: 1100px) {
	.sw-wd-strip { grid-template-columns: repeat(2, 1fr); }
	.sw-wd-strip li:nth-child(odd) { border-left: 0; }
	.sw-wd-strip li:nth-child(n + 3) { border-top: 1px solid var(--sw-border-light); }

	.sw-wd-type { grid-template-columns: auto 1fr; }

	/* The qualifying line moves under the copy, so its rule turns horizontal. */
	.sw-wd-type__for {
		grid-column: 1 / -1;
		padding: 14px 0 0;
		border-left: 0;
		border-top: 1px solid var(--sw-border-light);
	}

	.sw-wd-standard__list { grid-template-columns: 1fr; }
}

@media (max-width: 980px) {
	.sw-page .sw-wd-hero__title,
	.sw-page.sw-wd-hero .sw-wd-hero__title { font-size: 34px; }

	.sw-wd-platform__grid { grid-template-columns: 1fr; }
	.sw-wd-cta__grid { flex-direction: column; align-items: flex-start; }
}

@media (max-width: 767px) {
	.sw-wd-hero { padding: 40px 0 0; }

	.sw-page .sw-wd-hero__title,
	.sw-page.sw-wd-hero .sw-wd-hero__title { font-size: 28px; }

	/* An overlapping card just crowds the heading on a phone. */
	.sw-wd-strip__wrap { margin-bottom: 0; transform: none; }
	.sw-wd-strip { grid-template-columns: 1fr; }
	.sw-wd-strip li { border-left: 0; }
	.sw-wd-strip li + li { border-top: 1px solid var(--sw-border-light); }

	.sw-wd-build { padding: 52px 0 46px; }

	.sw-wd-type {
		grid-template-columns: 1fr;
		gap: 14px;
		text-align: left;
	}

	.sw-wd-standard__row { grid-template-columns: 1fr; gap: 4px; }
	.sw-page .sw-wd-cta h2,
	.sw-page.sw-wd-cta h2 { font-size: 22px; }
}

/* ===========================================================================
   32b. Websites & Web Development — Divi module layout
   ---------------------------------------------------------------------------
   For the Divi 5 export, where each content item is its own module in its own
   column rather than a child of one of section 32's CSS grids. Divi's columns
   then do the across-the-row layout, so the items need the spacing the grid
   `gap` used to give them, and have to stand up on their own.

   Embedded in the export alongside section 32. Not used by the PHP template,
   which keeps its grids.
   =========================================================================== */

.sw-wd-type--solo { margin-bottom: 14px; }
.sw-wd-type--solo:last-child { margin-bottom: 0; }

/* A step out of .sw-steps has no grid to centre it. */
.sw-step-item--solo { text-align: center; padding: 0 6px; }

/* Panels and standard columns are self-contained; they only need their gap
   back when Divi stacks the columns below 980px. */
@media (max-width: 980px) {
	.sw-wd-panel { margin-bottom: 18px; }
	.sw-wd-panel:last-child { margin-bottom: 0; }
	.sw-wd-standard__col + .sw-wd-standard__col { margin-top: 0; }
}

/* ---- 32b, continued: surviving wpautop ----------------------------------
   Divi runs module content through wpautop, which injects a stray closing </p>
   after an inline element that is followed by a block one — every icon span in
   this page. The browser resolves that into an empty <p>, which becomes an
   extra grid child and shifts every real one along by a column. The card grid
   was laid out by implicit order, so the body landed in the 240px column meant
   for the qualifying line.

   Two defences, because either alone is fragile:
     1. place the real children explicitly, so a phantom child cannot displace
        them whatever order it arrives in;
     2. hide empty paragraphs inside these blocks. */

.sw-wd-type > p:empty,
.sw-wd-strip li > p:empty,
.sw-step-item > p:empty,
.sw-wd-panel > p:empty { display: none; }

.sw-wd-type > .sw-wd-type__icon { grid-column: 1; grid-row: 1; }
.sw-wd-type > .sw-wd-type__body { grid-column: 2; grid-row: 1; }
.sw-wd-type > .sw-wd-type__for  { grid-column: 3; grid-row: 1; }

/* The list sits inside a half-width Divi column, so it must be single-column —
   without this each half runs the two-column grid and the page shows four. */
.sw-wd-standard__list--single { grid-template-columns: 1fr !important; }

@media (max-width: 1100px) {
	.sw-wd-type > .sw-wd-type__body { grid-column: 2; }
	.sw-wd-type > .sw-wd-type__for  { grid-column: 1 / -1; grid-row: 2; }
}

@media (max-width: 767px) {
	.sw-wd-type > .sw-wd-type__icon,
	.sw-wd-type > .sw-wd-type__body,
	.sw-wd-type > .sw-wd-type__for { grid-column: 1; grid-row: auto; }
}


/* ===========================================================================
   33. n8n Automation page (templates/page-n8n-automation.php)
   ---------------------------------------------------------------------------
   Built from a dark-neon mockup, recoloured onto the brand blue ramp — the
   rule stated in section 16: colours come from :root, never from the mockups.
   The mockup's structure, item counts and spacing rhythm are reproduced as
   drawn; only the palette and the fabricated dashboard numbers are not.

   Deliberately lean. The process band reuses .sw-steps / .sw-step-item and the
   tool tiles reuse .sw-auto-grid / .sw-auto-tile, both from section 16, and
   every section head is .sw-sec-head. Only this page's own blocks are here:
   the split hero, its CSS node diagram, the benefit cards, the six-across use
   case grid and the gradient CTA panel.

   Three conventions carried over from section 32, each learned the hard way:

   1. Section selectors are written BARE (`.sw-n8n-hero`), because the PHP
      template puts .sw-page on <main> and the section class on a child, while
      a Divi export puts both on the same element. A bare class matches either.
      Where a rule must reach (0,2,0) to beat a later media query, both forms
      are listed — see .sw-n8n-hero__title.
   2. Icon discs on tinted cards use var(--sw-tint). The .sw-tint--* classes
      define --sw-tint and --sw-accent only; --sw-accent-soft belongs to the
      .sw-accent--* classes and has no :root fallback, so referencing it here
      would leave the disc with no background.
   3. Every hover transform is suppressed by section 14's reduced-motion block.

   Surfaces run dark → light → white → light-alt → white → navy-850.
   =========================================================================== */

/* .sw-accent--violet is defined per-page at (0,2,0) for solutions and websites;
   this (0,1,0) fallback gives step 05 its colour here without touching either. */
.sw-accent--violet { --sw-accent: var(--sw-blue-400); }

/* ---- hero ---------------------------------------------------------------- */

.sw-n8n-hero {
	position: relative;
	background: var(--sw-navy-900);
	padding: 96px 0 104px;
	overflow: hidden;
}

/* A single soft bloom behind the diagram, standing in for the mockup's neon
   glow without introducing a second hue. */
.sw-n8n-hero::before {
	content: "";
	position: absolute;
	top: -18%;
	right: -10%;
	width: 620px;
	height: 620px;
	background: radial-gradient(circle, rgba(91, 155, 213, 0.16) 0%, rgba(91, 155, 213, 0) 68%);
	pointer-events: none;
}

.sw-n8n-hero__grid {
	position: relative;
	display: grid;
	grid-template-columns: 1.15fr 1fr;
	gap: 56px;
	align-items: center;
}

.sw-n8n-hero .sw-crumbs { margin-bottom: 22px; }

.sw-page .sw-n8n-hero__title,
.sw-page.sw-n8n-hero .sw-n8n-hero__title {
	margin: 0 0 20px;
	font-size: 52px;
	font-weight: 800;
	line-height: 1.1;
	letter-spacing: -1.2px;
	color: var(--sw-white);
}

.sw-n8n-hero__lede {
	max-width: 34em;
	margin: 0 0 32px;
	font-size: 17px;
	line-height: 1.75;
	color: var(--sw-muted-dark);
}

/* ---- hero feature list --------------------------------------------------- */

.sw-n8n-hero__features {
	list-style: none;
	margin: 0 0 34px;
	padding: 0;
	display: grid;
	gap: 18px;
}

.sw-n8n-hero__features li {
	display: grid;
	grid-template-columns: 40px 1fr;
	gap: 14px;
	align-items: start;
}

.sw-n8n-hero__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	border-radius: 50%;
	background: rgba(91, 155, 213, 0.14);
	border: 1px solid var(--sw-border-dark);
	color: var(--sw-blue-200);
}

.sw-n8n-hero__features strong {
	display: block;
	font-size: 15.5px;
	font-weight: 700;
	line-height: 1.4;
	color: var(--sw-white);
}

.sw-n8n-hero__features span:not(.sw-n8n-hero__icon) {
	display: block;
	margin-top: 3px;
	font-size: 14px;
	line-height: 1.6;
	color: var(--sw-muted-dark);
}

/* ---- hero diagram --------------------------------------------------------
   The mockup's screenshot of an n8n canvas, rebuilt in CSS: no asset to
   commission, it scales, and it carries no invented run data. Node types only. */

.sw-n8n-flow {
	background: var(--sw-navy-800);
	border: 1px solid var(--sw-border-dark);
	border-radius: var(--sw-card-radius);
	padding: 26px 24px 22px;
	box-shadow: var(--sw-shadow-md);
}

.sw-n8n-flow__title {
	margin: 0 0 20px;
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 1.4px;
	text-transform: uppercase;
	color: var(--sw-blue-300);
}

.sw-n8n-flow__nodes {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	grid-template-rows: auto auto;
	gap: 14px 24px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-n8n-node {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 7px;
	padding: 13px 8px;
	background: var(--sw-navy-850);
	border: 1px solid var(--sw-border-dark);
	border-radius: 11px;
	text-align: center;
}

/* The three sequential nodes span both rows so they centre against the pair of
   branches to their right; the branches take one row each in the last column. */
.sw-n8n-node--step:nth-child(1) { grid-column: 1; grid-row: 1 / span 2; }
.sw-n8n-node--step:nth-child(2) { grid-column: 2; grid-row: 1 / span 2; }
.sw-n8n-node--step:nth-child(3) { grid-column: 3; grid-row: 1 / span 2; }
.sw-n8n-node--out:nth-child(4)  { grid-column: 4; grid-row: 1; }
.sw-n8n-node--out:nth-child(5)  { grid-column: 4; grid-row: 2; }

.sw-n8n-node__icon { color: var(--sw-blue-300); line-height: 1; }

.sw-n8n-node__label {
	font-size: 11.5px;
	font-weight: 600;
	line-height: 1.35;
	color: var(--sw-blue-100);
}

/* Connectors. Drawn into the grid gap rather than between elements, so they
   cannot fall out of step with the layout. */
.sw-n8n-node--step:nth-child(1)::after,
.sw-n8n-node--step:nth-child(2)::after,
.sw-n8n-node--out::before {
	content: "";
	position: absolute;
	top: 50%;
	width: 24px;
	border-top: 1px dashed rgba(155, 194, 229, 0.42);
}

.sw-n8n-node--step:nth-child(1)::after,
.sw-n8n-node--step:nth-child(2)::after { left: 100%; }
.sw-n8n-node--out::before { right: 100%; }

/* The decision node's two branches: a short vertical spine in the gap, joined
   to each branch by the horizontal dash above. */
.sw-n8n-node--out:nth-child(4)::after {
	content: "";
	position: absolute;
	right: 100%;
	top: 50%;
	width: 0;
	height: calc(100% + 14px);
	border-left: 1px dashed rgba(155, 194, 229, 0.42);
	margin-right: 12px;
}

.sw-n8n-flow__caption {
	margin: 20px 0 0;
	font-size: 12.5px;
	line-height: 1.65;
	color: var(--sw-muted-dark);
}

/* ---- why: benefit cards -------------------------------------------------- */

.sw-n8n-why {
	background: var(--sw-light);
	padding: 88px 0;
}

.sw-n8n-cards {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 22px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-n8n-card {
	display: flex;
	flex-direction: column;
	padding: 30px 26px 28px;
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-radius);
	text-align: center;
	transition: transform 0.25s var(--sw-ease), box-shadow 0.25s var(--sw-ease),
		border-color 0.25s var(--sw-ease);
}

.sw-n8n-card:hover {
	transform: translateY(-3px);
	box-shadow: var(--sw-shadow-md);
	border-color: var(--sw-accent);
}

/* var(--sw-tint), not --sw-accent-soft. See note 2 in this section's header. */
.sw-n8n-card__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 54px;
	height: 54px;
	margin: 0 auto 18px;
	border-radius: 50%;
	background: var(--sw-tint);
	color: var(--sw-accent);
}

.sw-n8n-card h3 {
	margin: 0 0 10px;
	font-size: 17px;
	font-weight: 700;
	line-height: 1.35;
	color: var(--sw-slate);
}

.sw-n8n-card p {
	margin: 0;
	font-size: 14.5px;
	line-height: 1.7;
	color: var(--sw-muted);
}

/* ---- use cases ----------------------------------------------------------- */

.sw-n8n-cases {
	background: var(--sw-white);
	padding: 88px 0;
}

/* Six across, as drawn. Card copy is set tighter to suit ~175px columns; if the
   copy grows, this one value going to repeat(3, 1fr) is the whole change. */
.sw-n8n-case-grid {
	display: grid;
	grid-template-columns: repeat(6, 1fr);
	gap: 16px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.sw-n8n-case {
	display: flex;
	flex-direction: column;
	padding: 24px 16px 22px;
	background: var(--sw-blue-25);
	border: 1px solid var(--sw-border-light);
	border-radius: 12px;
	text-align: center;
	transition: transform 0.25s var(--sw-ease), box-shadow 0.25s var(--sw-ease),
		border-color 0.25s var(--sw-ease);
}

.sw-n8n-case:hover {
	transform: translateY(-3px);
	box-shadow: var(--sw-shadow-md);
	border-color: var(--sw-blue-400);
}

.sw-n8n-case__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 46px;
	height: 46px;
	margin: 0 auto 14px;
	border-radius: 12px;
	background: var(--sw-blue-100);
	color: var(--sw-blue-600);
}

.sw-n8n-case h3 {
	margin: 0 0 8px;
	font-size: 14.5px;
	font-weight: 700;
	line-height: 1.35;
	color: var(--sw-slate);
}

.sw-n8n-case p {
	margin: 0;
	font-size: 13px;
	line-height: 1.6;
	color: var(--sw-muted);
}

/* ---- process ------------------------------------------------------------- */

.sw-n8n-process {
	background: var(--sw-light-alt);
	padding: 88px 0;
}

/* ---- tools --------------------------------------------------------------- */

.sw-n8n-tools {
	background: var(--sw-white);
	padding: 76px 0 88px;
}

/* .sw-auto-grid is repeat(12, 1fr) for the twelve-tile automation strip; this
   page shows nine. */
.sw-auto-grid--nine { grid-template-columns: repeat(9, 1fr); }

/* ---- closing CTA --------------------------------------------------------- */

.sw-n8n-cta {
	background: var(--sw-navy-850);
	padding: 76px 0;
}

.sw-n8n-cta__panel {
	display: grid;
	grid-template-columns: 1.1fr auto;
	gap: 40px;
	align-items: center;
	padding: 52px 56px;
	background: var(--sw-gradient);
	border-radius: 20px;
}

.sw-n8n-cta__copy h2 {
	margin: 0 0 12px;
	font-size: 32px;
	font-weight: 800;
	line-height: 1.2;
	letter-spacing: -0.8px;
	color: var(--sw-white);
}

.sw-n8n-cta__copy p {
	margin: 0;
	max-width: 46em;
	font-size: 15.5px;
	line-height: 1.7;
	color: rgba(255, 255, 255, 0.9);
}

/* The primary button sits on the gradient, so it inverts: white ground, brand
   ink. .sw-btn--primary would be a blue gradient on a blue gradient.

   Written .sw-page .sw-btn--on-grad, not .sw-btn--on-grad: the base rule
   `.sw-page .sw-btn` sets `border: 1px solid transparent` at (0,2,0), which
   beats a bare class and would swallow the border. The secondary button beside
   it is .sw-btn--outline-dark, which the shared shell already defines for
   exactly this case — white text on a translucent white border. */
.sw-page .sw-btn--on-grad {
	background: var(--sw-white);
	border-color: var(--sw-white);
	color: var(--sw-blue-600);
}

.sw-page .sw-btn--on-grad:hover,
.sw-page .sw-btn--on-grad:focus-visible {
	background: var(--sw-blue-50);
	border-color: var(--sw-blue-50);
	color: var(--sw-blue-600);
}

.sw-n8n-cta__panel .sw-btn:focus-visible {
	outline: 2px solid var(--sw-white);
	outline-offset: 2px;
}

/* ---- responsive ---------------------------------------------------------- */

@media (max-width: 1100px) {
	.sw-n8n-hero__grid { gap: 36px; }
	.sw-n8n-case-grid { grid-template-columns: repeat(3, 1fr); }
	.sw-auto-grid--nine { grid-template-columns: repeat(5, 1fr); }
}

@media (max-width: 980px) {
	.sw-n8n-hero { padding: 72px 0 76px; }

	/* Copy leads when the hero stacks; the diagram is supporting material. */
	.sw-n8n-hero__grid { grid-template-columns: 1fr; }
	.sw-n8n-hero__visual { max-width: 520px; margin: 0 auto; }

	.sw-page .sw-n8n-hero__title,
	.sw-page.sw-n8n-hero .sw-n8n-hero__title { font-size: 40px; letter-spacing: -1px; }

	.sw-n8n-why,
	.sw-n8n-cases,
	.sw-n8n-process { padding: 64px 0; }

	.sw-n8n-cards { grid-template-columns: repeat(2, 1fr); }
	.sw-n8n-tools { padding: 56px 0 64px; }

	.sw-n8n-cta { padding: 60px 0; }
	.sw-n8n-cta__panel { grid-template-columns: 1fr; gap: 28px; text-align: center; padding: 44px 36px; }
	.sw-n8n-cta__copy p { margin-inline: auto; }
	.sw-n8n-cta__panel .sw-btn-row { justify-content: center; }
}

@media (max-width: 767px) {
	.sw-n8n-hero { padding: 56px 0 60px; }

	.sw-page .sw-n8n-hero__title,
	.sw-page.sw-n8n-hero .sw-n8n-hero__title { font-size: 32px; letter-spacing: -0.6px; }

	.sw-n8n-hero__lede { font-size: 16px; }

	.sw-n8n-why,
	.sw-n8n-cases,
	.sw-n8n-process { padding: 52px 0; }

	.sw-n8n-cards { grid-template-columns: 1fr; }
	.sw-n8n-case-grid { grid-template-columns: repeat(2, 1fr); }
	.sw-auto-grid--nine { grid-template-columns: repeat(3, 1fr); }

	.sw-n8n-tools { padding: 44px 0 52px; }
	.sw-n8n-cta { padding: 48px 0; }
	.sw-n8n-cta__panel { padding: 36px 24px; }
	.sw-n8n-cta__copy h2 { font-size: 26px; }
}

/* Below 480px the diagram is four columns of unreadable 11px labels. It is
   decorative and captioned in the copy above, so it goes rather than shrinks. */
@media (max-width: 479px) {
	.sw-n8n-hero__visual { display: none; }
}


/* ===========================================================================
   33b. n8n Automation — Divi module layout
   ---------------------------------------------------------------------------
   For the Divi 5 export, where the benefit cards, use cases and process steps
   are each their own module in their own Divi column rather than children of
   section 33's CSS grids. Divi's columns then do the across-the-row layout.

   Embedded in the export alongside section 33. Not used by the PHP template,
   which keeps its grids.
   =========================================================================== */

/* ---- surviving wpautop ---------------------------------------------------
   Divi runs module content through wpautop, which injects a stray closing </p>
   after an inline element followed by a block one — every icon span on this
   page. The browser resolves that into an empty <p>: an extra flex/grid child
   that pushes every real one along. Hiding it is the whole fix here, because
   these cards are flex columns rather than placed grid children. */

.sw-n8n-card > p:empty,
.sw-n8n-case > p:empty,
.sw-n8n-node > p:empty,
.sw-step-item > p:empty,
.sw-auto-tile > p:empty,
.sw-n8n-hero__features li > p:empty { display: none; }

/* Second defence, for the one grid whose children come from module content.
   Hiding the phantom is not enough on its own: the feature rows are placed by
   implicit order, so an extra child arriving before them shifts the icon and
   the body along a column. Placing the real children explicitly means a
   phantom cannot move them wherever it lands. */
.sw-n8n-hero__features li > .sw-n8n-hero__icon { grid-column: 1; grid-row: 1; }
.sw-n8n-hero__features li > div { grid-column: 2; grid-row: 1; }

/* ---- items standing alone in a Divi column ------------------------------- */

/* A card out of .sw-n8n-cards has no grid gap; it gets its own bottom margin
   for when Divi stacks, and full height so a row of them stays level. */
.sw-n8n-card--solo,
.sw-n8n-case--solo { height: 100%; }

/* A step out of .sw-steps has no grid to centre it. */
.sw-step-item--solo { text-align: center; padding: 0 6px; }

/* ---- Divi column stacking ------------------------------------------------
   Divi collapses every column to full width below 980px, which would take the
   six use cases and five steps straight from one row to a single stack. Making
   the ROW a grid overrides the column widths whether Divi laid them out with
   floats (4) or flex (5), so one rule covers both builders. */

@media (max-width: 980px) {
	/* Keyed off .sw-n8n-row, a class the export puts on the ITEM rows only —
	   not off :first-child, which assumes Divi wraps rows in a way it may not.
	   The heading rows carry no class and are left alone. */
	.et_pb_row.sw-n8n-row {
		display: grid;
		gap: 18px;
	}

	.et_pb_row.sw-n8n-row > .et_pb_column {
		width: auto !important;
		max-width: none !important;
		margin: 0 !important;
		float: none !important;
	}

	.sw-n8n-why .et_pb_row.sw-n8n-row { grid-template-columns: repeat(2, 1fr); }
	.sw-n8n-cases .et_pb_row.sw-n8n-row { grid-template-columns: repeat(3, 1fr); }
	.sw-n8n-process .et_pb_row.sw-n8n-row { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 767px) {
	.sw-n8n-why .et_pb_row.sw-n8n-row { grid-template-columns: 1fr; }
	.sw-n8n-cases .et_pb_row.sw-n8n-row { grid-template-columns: repeat(2, 1fr); }
	.sw-n8n-process .et_pb_row.sw-n8n-row { grid-template-columns: 1fr; }
}

/* In the export the CTA panel is the ROW, not a div inside a column, so Divi's
   own two columns give the mockup's side-by-side split. Section 33 makes the
   panel a CSS grid for the PHP template; here that would fight Divi's flex row,
   so flex wins back at (0,2,0) and the columns do the work. */
.et_pb_row.sw-n8n-cta__panel {
	display: flex;
	align-items: center;
}

@media (max-width: 980px) {
	.et_pb_row.sw-n8n-cta__panel { display: block; text-align: center; }
	.et_pb_row.sw-n8n-cta__panel .sw-btn-row { justify-content: center; margin-top: 24px; }
}

/* ===========================================================================
   35. Homepage v2  —  templates/page-home-v2.php
   ---------------------------------------------------------------------------
   Built from the August 2026 mockup. Structure, hierarchy, item counts and
   spacing rhythm are the mockup's; colour and type come from the tokens in
   :root throughout — including the final CTA panel, which briefly carried the
   mockup's blue-to-violet gradient and now uses the two brand values
   (see --sw-cta-grad-* below). Nothing on this page introduces a colour the
   brand palette does not already define.

   Selectors are written BARE (.sw-h2-caps, not .sw-divi .sw-h2-caps) because
   the same rules have to serve two different DOMs: in the PHP template the
   section class sits on a child of the .sw-divi wrapper, but in a Divi export
   it sits on the same element as .et_pb_section. Only rules that must out-rank
   something later list both forms.

   What this section does NOT redefine: Divi's grid, gutters, module rhythm and
   button fills all come from section 27 via the .sw-divi wrapper.
   =========================================================================== */

:root {
	/* Final-CTA gradient.
	   Was #00309f -> #4421d8, sampled straight from the mockup, which put the
	   only violet on the site into this one panel — and left the homepage as
	   the one CTA whose fill matched nothing else. Every other CTA panel is
	   #052846, and the one other gradient panel (.sw-n8n-cta__panel) is
	   var(--sw-gradient).

	   Now the two brand values from the block at the top of :root. The stop
	   positions are kept from the mockup: solid to 42%, then a ramp, which is
	   what holds the copy column on the dark end where white text has the
	   contrast it needs. */
	--sw-cta-grad-start: var(--seriousweb-dark-blue);
	--sw-cta-grad-end: var(--seriousweb-blue);
}

/* ---- section surfaces and rhythm ---------------------------------------- */
.sw-h2-hero { background-color: var(--sw-navy-900); }
.sw-h2-caps,
.sw-h2-proc,
.sw-h2-why,
.sw-h2-results,
.sw-h2-cta { background-color: var(--sw-white); }
.sw-h2-sols { background-color: var(--sw-light); }
.sw-h2-domain { background-color: var(--sw-blue-50); }

/* One band rhythm, three breakpoints: 96 / 72 / 56, with the hero a step larger
   at 128 / 92 / 68. Every band is symmetric. The two panel sections carry no
   top padding on purpose — the preceding section's bottom padding is the gap,
   so the spacing between panels stays the same 96 as everywhere else. */
.sw-h2-hero { padding: 128px 0; }
.sw-h2-domain { padding: 16px 0; }
.sw-h2-caps { padding: 96px 0; }
.sw-h2-sols { padding: 96px 0; }
.sw-h2-proc { padding: 96px 0; }
/* The mockup runs sections 5 and 6 on the same white surface. Built and looked
   at, the middle of the page reads as one undifferentiated white slab roughly
   1400px tall, so this takes the faintest step on the ramp — enough to separate
   the two bands without introducing a colour the site does not already have. */
.sw-h2-why { padding: 96px 0; background-color: var(--sw-blue-25); }
.sw-h2-results { padding: 0 0 96px; }
.sw-h2-cta { padding: 0 0 96px; }

/* Heading block above each card grid. */
.sw-h2-head { max-width: 760px !important; text-align: center; margin-bottom: 46px !important; }
.sw-h2-head .et_pb_module { margin-bottom: 12px; }
.sw-h2-head h2 {
	margin: 0;
	padding: 0;
	font-size: 36px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.8px;
	color: var(--sw-slate);
	/* Evens the two lines instead of leaving "efficiently" alone on the second.
	   Unsupported browsers just get the normal greedy break. */
	text-wrap: balance;
}
.sw-h2-caps .sw-eyebrow p,
.sw-h2-sols .sw-eyebrow p,
.sw-h2-proc .sw-eyebrow p,
.sw-h2-why .sw-eyebrow p {
	font-size: 13px;
	letter-spacing: 1.6px;
	color: var(--sw-blue-500);
}

/* ---- 1. hero ------------------------------------------------------------- */
/* ---- 1. hero --------------------------------------------------------------
   Centred, not the mockup's left-aligned two-column split. That split existed
   to balance the copy against the isometric artwork; with the artwork removed,
   keeping it leaves half the hero empty and reads as a missing image rather
   than as a decision. Centring also matches every section heading further down
   the page, so the hero stops being the one band with its own alignment.

   The measure is capped at 860px: across the full 1240px row a 56px headline
   runs as one long line and the intro reaches an unreadable line length. */
.sw-h2-hero-row { align-items: center; }

/* The column stays full width and the measure is capped on the content instead.
   Centring the column itself does not work: auto margins have to beat
   `.sw-divi .et_pb_column.et-last-child { margin-right: 0 }` at (0,3,0), so
   only margin-left resolves to auto and the whole hero lands ~190px right of
   centre. Constraining the children needs no specificity fight and does not
   depend on Divi still emitting et-last-child in an export. */
.sw-h2-hero-copy {
	display: block;
	text-align: center;
}

/* The base .sw-hero glows sit hard right, where the artwork used to be. These
   re-centre them behind the headline. Same (0,1,0) specificity as the base
   rules, and section 35 is last in the file, so these win without !important
   and without touching the v1 homepage that still has its artwork. */
.sw-h2-hero::before {
	top: -260px;
	right: auto;
	left: 50%;
	width: 900px;
	height: 720px;
	transform: translateX(-50%);
	background: radial-gradient(circle, rgba(8, 82, 150, 0.38) 0%, rgba(8, 82, 150, 0) 66%);
}

.sw-h2-hero::after {
	bottom: -320px;
	right: auto;
	left: 50%;
	width: 760px;
	height: 620px;
	transform: translateX(-50%);
	background: radial-gradient(circle, rgba(91, 155, 213, 0.22) 0%, rgba(91, 155, 213, 0) 68%);
}

.sw-h2-hero .sw-eyebrow p {
	font-size: 13px;
	letter-spacing: 1.6px;
	color: var(--sw-blue-200);
}
.sw-h2-hero .sw-eyebrow { margin-bottom: 16px !important; }
.sw-h2-hero-title h1 {
	max-width: 860px;
	margin: 0 auto;
	padding: 0;
	font-size: 58px;
	font-weight: 700;
	line-height: 1.1;
	letter-spacing: -1.6px;
	color: var(--sw-white);
}
.sw-h2-hero-title { margin-bottom: 24px !important; }
.sw-h2-hero-intro p {
	max-width: 620px;
	margin: 0 auto;
	font-size: 18px;
	line-height: 1.7;
	color: var(--sw-muted-dark);
}
.sw-h2-hero-intro { margin-bottom: 32px !important; }

/* Sits outside a module so the two buttons stay on one line — .sw-hero-copy is
   normal block flow, and a flex column would put each on its own row. */
.sw-h2-hero-btns {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 12px;
	margin-bottom: 32px;
}
.sw-h2-hero-btns .et_pb_button { margin-bottom: 0; }

.sw-h2-trust { margin-bottom: 0 !important; }
.sw-trust__line { margin: 0; font-size: 14px; color: var(--sw-blue-200); }
.sw-trust__line strong { color: var(--sw-white); font-weight: 700; }

/* ---- 2. domain notice ---------------------------------------------------- */
.sw-h2-domain p { margin: 0; text-align: center; font-size: 14px; color: var(--sw-slate); }
.sw-domain-bar__icon { display: inline-flex; vertical-align: -4px; margin-right: 8px; color: var(--sw-blue-600); }
.sw-domain-bar__muted { color: var(--sw-muted); }

/* ---- grids --------------------------------------------------------------
   The grid goes on the COLUMN and the modules inside become its direct grid
   children — Divi has no nested rows, and this keeps the responsive step-downs
   in one place instead of in Divi's gutter maths. */
.sw-fgrid, .sw-sgrid, .sw-pgrid {
	float: none;
	display: grid;
	gap: 24px;
}
/* minmax(0, 1fr), not 1fr: an auto min-size lets a long unbreakable word push a
   track wider than its share and overflow the row. */
.sw-fgrid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.sw-sgrid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
/* Tighter than the card grids by intent, not by drift: five tracks instead of
   four, and the dashed connectors read better across a short gap. */
.sw-pgrid { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 12px; }

/* The grid gap owns the spacing now, so Divi's per-module bottom margin goes. */
.sw-fgrid > .et_pb_module,
.sw-sgrid > .et_pb_module,
.sw-pgrid > .et_pb_module { margin-bottom: 0 !important; }

/* Each module is a grid item, so its inner wrapper has to fill it or the cards
   in a row stop matching heights. */
.sw-fgrid > .et_pb_module,
.sw-sgrid > .et_pb_module,
.sw-fgrid > .et_pb_module > .et_pb_text_inner,
.sw-sgrid > .et_pb_module > .et_pb_text_inner { height: 100%; }

/* Restores the cards' bottom padding.

   Section 27 carries `.sw-divi .et_pb_text_inner > *:last-child {
   padding-bottom: 0 }` at (0,3,0) to kill the trailing margin on a stray <p>
   inside a Text module. Every card here is the only child of its Text module,
   so that rule silently flattened 28px of bottom padding down to whatever the
   last line box happened to leave — measured at 7px against a 26px top, which
   is what made the cards look bottom-cropped.

   (0,3,0) and later in the file, so it wins without !important. The bare form
   covers the exported DOM, where no .sw-divi wrapper exists and nothing zeroes
   the padding in the first place. */
.sw-divi .et_pb_text_inner > .sw-fcard,
.sw-divi .et_pb_text_inner > .sw-scard,
.et_pb_text_inner > .sw-fcard,
.et_pb_text_inner > .sw-scard {
	padding-bottom: 28px;
}

/* ---- feature card (sections 3 and 6) -------------------------------------
   Shared by "How we support your business" and "Why businesses choose
   SeriousWeb", so changes here land on both — which is the point: they are the
   same component and should not drift apart. */
.sw-fcard {
	position: relative;
	height: 100%;
	padding: var(--sw-card-pad);
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-card-radius);
	/* Two shadows, not var(--sw-shadow-sm): these cards sit on white, where a
	   1px hairline and a 3px shadow leave them reading as faint outlines rather
	   than as raised surfaces. A tight contact shadow plus a wide soft one give
	   them an edge without darkening the section. */
	box-shadow: var(--sw-card-shadow);
	transition: var(--sw-card-transition);
}
.sw-fcard:hover {
	transform: translateY(-4px);
	border-color: var(--sw-blue-200);
	box-shadow: var(--sw-card-shadow-hover);
}

/* min-height reserves two lines of title. Without it a card whose title wraps
   — "Web Design & Development" — starts its description ~40px below its
   neighbours', and the row loses its shared baseline. */
.sw-fcard__head {
	display: flex;
	align-items: center;
	gap: 12px;
	min-height: 52px;
	margin-bottom: 12px;
}
.sw-fcard__icon {
	flex: 0 0 auto;
	display: grid;
	place-items: center;
	width: 42px;
	height: 42px;
	border-radius: 12px;
	background: rgba(8, 82, 150, 0.09);
	color: var(--sw-blue-600);
	transition: background-color 0.25s var(--sw-ease), color 0.25s var(--sw-ease);
}
/* The tile fills on hover, so the whole card has one clear focal response
   rather than just drifting upward. */
.sw-fcard:hover .sw-fcard__icon {
	background: var(--sw-blue-600);
	color: var(--sw-white);
}
.sw-fcard__title {
	margin: 0;
	padding: 0;
	font-size: 17px;
	font-weight: 700;
	line-height: 1.3;
	letter-spacing: -0.2px;
	color: var(--sw-slate);
	text-wrap: balance;
}
.sw-fcard__text { margin: 0; font-size: 15px; line-height: 1.7; color: var(--sw-muted); }

/* ---- solution card (section 4) -------------------------------------------
   Shares the feature card's shadow, radius, icon-tile size and hover response
   on purpose: they are two cards on one page and were visibly drifting apart —
   this one still had the old single-layer shadow and its own padding. */
.sw-scard {
	position: relative;
	display: flex;
	flex-direction: column;
	height: 100%;
	padding: var(--sw-card-pad);
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-card-radius);
	box-shadow: var(--sw-card-shadow);
	transition: var(--sw-card-transition);
}
.sw-scard:hover {
	transform: translateY(-4px);
	border-color: var(--sw-blue-200);
	box-shadow: var(--sw-card-shadow-hover);
}

/* The whole card becomes the click target by stretching the existing link over
   it — no extra markup, and the anchor stays the one focusable element rather
   than the card growing a second tab stop. */
.sw-scard .sw-card-more a::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: var(--sw-radius);
}

/* 42px, matching .sw-fcard__icon. The two were 44 and 42 — two pixels apart for
   no reason, which is the drift the lint exists to catch. */
.sw-scard__mark {
	display: grid;
	place-items: center;
	width: 42px;
	height: 42px;
	margin-bottom: 14px;
	border-radius: 12px;
	background: rgba(8, 82, 150, 0.09);
	color: var(--sw-blue-600);
	transition: background-color 0.25s var(--sw-ease), color 0.25s var(--sw-ease);
}
.sw-scard:hover .sw-scard__mark {
	background: var(--sw-blue-600);
	color: var(--sw-white);
}
/* The mockup gives these cards green and coral marks. One hue, four steps —
   distinguishable without introducing a second palette. Same approach as
   .sw-step--1..4 in section 8. */
.sw-sgrid > .et_pb_module:nth-child(2) .sw-scard__mark { color: var(--sw-blue-500); }
.sw-sgrid > .et_pb_module:nth-child(3) .sw-scard__mark { color: var(--sw-blue-400); }
.sw-scard__title {
	margin: 0 0 8px;
	padding: 0;
	font-size: 18px;
	font-weight: 700;
	line-height: 1.3;
	letter-spacing: -0.2px;
	color: var(--sw-slate);
	text-wrap: balance;
}
/* padding-bottom:0 is doing real work. A global `p { padding-bottom: 1em }`
   applies here, and the `p:last-of-type` rule that normally cancels it does not
   match — the last <p> in this card is .sw-card-more, not the description. That
   left 15px of dead space inside every card, which is most of why they stood
   taller than they needed to. */
.sw-scard__text {
	margin: 0 0 auto;
	padding-bottom: 0;
	font-size: 15px;
	line-height: 1.7;
	color: var(--sw-muted);
}

/* Descriptions vary in length, so `margin-bottom: auto` above leaves a gap of
   whatever is left over before the link. A hairline turns that leftover space
   into a deliberate footer rule, and gives every card the same anchor line
   regardless of how much copy it carries. */
.sw-scard .sw-card-more {
	margin: 18px 0 0 !important;
	padding-top: 14px;
	border-top: 1px solid var(--sw-border-light);
}
.sw-scard .sw-card-more a { border-bottom: 0; }

/* The arrow is part of the link text, so it moves with a transform on the
   anchor's inline box rather than needing its own element. */
.sw-scard .sw-card-more a { display: inline-flex; gap: 6px; transition: gap 0.25s var(--sw-ease); }
.sw-scard:hover .sw-card-more a { gap: 12px; }

.sw-scard--featured {
	/* A flat fill made "featured" read as "this one is a different colour".
	   The wash lifts the top-left corner behind the mark and title, so the card
	   has its own light source and looks intentional next to three white ones. */
	background:
		radial-gradient(120% 90% at 0% 0%, rgba(91, 155, 213, 0.22) 0%, rgba(91, 155, 213, 0) 58%),
		var(--sw-navy-850);
	border-color: transparent;
	box-shadow: 0 1px 2px rgba(4, 31, 56, 0.08), 0 16px 34px -20px rgba(4, 31, 56, 0.55);
}
.sw-scard--featured:hover {
	border-color: transparent;
	box-shadow: 0 2px 4px rgba(4, 31, 56, 0.1), 0 26px 52px -22px rgba(4, 31, 56, 0.65);
}
.sw-scard--featured .sw-scard__mark { background: rgba(155, 194, 229, 0.16); color: var(--sw-blue-200); }
.sw-scard--featured:hover .sw-scard__mark { background: var(--sw-blue-200); color: var(--sw-navy-850); }
.sw-scard--featured .sw-scard__title { color: var(--sw-white); }
.sw-scard--featured .sw-scard__text { color: var(--sw-blue-200); }
.sw-scard--featured .sw-card-more { border-top-color: var(--sw-border-dark); }
.sw-scard--featured .sw-card-more a { color: var(--sw-blue-200); }

/* SLICE:pstep:start — export strip boundary, do not remove.
   Exports embed this block, and the slices sidecar located it by searching for
   the rule text below. That string matches FOUR places in this file (here, and
   the .sw-s2-proc / .sw-w3-proc / .sw-ow2-proc overrides), and worked only
   because indexOf happens to find this one first. Anchor on this sentinel. */

/* ---- process step (section 5) --------------------------------------------
   Text modules, not blurbs: the number sits above the title, and Divi renders a
   blurb's title before its description, always. Building the order into the
   markup beats reordering it with display:contents afterwards. */
.sw-pstep { position: relative; padding: 0 8px; text-align: center; }
.sw-pstep__badge {
	position: relative;
	z-index: 1;
	display: grid;
	place-items: center;
	width: 62px;
	height: 62px;
	margin: 0 auto 16px;
	border: 1px solid var(--sw-blue-100);
	border-radius: 50%;
	background: var(--sw-white);
	color: var(--sw-blue-600);
}
/* Dashed connector, drawn behind the badge and only between items. */
.sw-pgrid > .et_pb_module:not(:first-child) .sw-pstep::before {
	content: "";
	position: absolute;
	top: 31px;
	right: 50%;
	left: -50%;
	z-index: 0;
	border-top: 2px dashed var(--sw-blue-100);
}
.sw-pstep__num {
	margin: 0 0 2px;
	font-size: 13px;
	font-weight: 800;
	letter-spacing: 1px;
	color: var(--sw-blue-400);
}
.sw-pstep__title {
	margin: 0 0 8px;
	padding: 0;
	font-size: 17px;
	font-weight: 700;
	line-height: 1.3;
	letter-spacing: -0.2px;
	color: var(--sw-slate);
	text-wrap: balance;
}
.sw-pstep__text { margin: 0; font-size: 15px; line-height: 1.7; color: var(--sw-muted); }

/* ---- panels (sections 7 and 8) -------------------------------------------
   The panel is the ROW: background, radius and padding are all things a Divi
   row carries natively, so there is no wrapper div to convert. */
.sw-h2-panel {
	align-items: center;
	border-radius: 22px;
	padding: 52px 48px;
	width: 90%;
	max-width: 1240px;
}
.sw-h2-panel--dark { background-color: var(--sw-navy-850); }
.sw-h2-panel--grad {
	background-image: linear-gradient(
		90deg,
		var(--sw-cta-grad-start) 0%,
		var(--sw-cta-grad-start) 42%,
		var(--sw-cta-grad-end) 100%
	);
}

/* The row's own padding eats into the column widths, so the two halves are
   recomputed against the padded box rather than inheriting section 27's. */
.sw-h2-panel > .et_pb_column_1_2 { width: 47.5%; margin-right: 5%; }
.sw-h2-panel > .et_pb_column_3_5 { width: 57.5%; margin-right: 5%; }
.sw-h2-panel > .et_pb_column_2_5 { width: 37.5%; margin-right: 0; }
.sw-h2-panel > .et_pb_column.et-last-child { margin-right: 0; }

/* ---- 7. results ---------------------------------------------------------- */
/* Same size as the CTA panel heading below — the two panels are the same width,
   the same radius and adjacent, so a 26 here against a 32 there read as a
   mistake rather than a hierarchy. */
.sw-h2-results-title h2 {
	margin: 0;
	padding: 0;
	font-size: 30px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.6px;
	color: var(--sw-white);
	text-wrap: balance;
}
.sw-h2-results-title { margin-bottom: 32px !important; }

.sw-statgrid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 24px 16px; }
.sw-stat { display: flex; flex-direction: column; gap: 8px; }
.sw-stat__icon {
	display: grid;
	place-items: center;
	width: 42px;
	height: 42px;
	border-radius: 12px;
	background: rgba(155, 194, 229, 0.14);
	color: var(--sw-blue-200);
}
.sw-stat__num { font-size: 30px; font-weight: 800; line-height: 1.1; color: var(--sw-white); }
.sw-stat__label { font-size: 13px; color: var(--sw-blue-200); }

.sw-h2-quote-col { border-left: 1px solid var(--sw-border-dark); padding-left: 40px; }
.sw-quote2 { margin: 0; border: 0; padding: 0; }
.sw-quote2__text { margin: 0 0 16px; font-size: 19px; line-height: 1.7; color: var(--sw-white); }
.sw-quote2__by { margin: 0; font-size: 14px; color: var(--sw-blue-200); }

/* ---- 8. final CTA -------------------------------------------------------- */
.sw-h2-cta-copy h2 {
	margin: 0;
	padding: 0;
	font-size: 30px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.6px;
	color: var(--sw-white);
	text-wrap: balance;
}
.sw-h2-cta-copy p { margin: 0; max-width: 480px; font-size: 16px; line-height: 1.7; color: rgba(255, 255, 255, 0.86); }
.sw-h2-cta-copy .et_pb_module:last-child { margin-bottom: 0; }
/* align-items:center is load-bearing, not cosmetic. The column is a flex item
   of the row and stretches to full panel height; without this the buttons —
   being flex items themselves — stretch with it and render as two 140px-tall
   slabs. */
.sw-h2-cta-btns {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: flex-end;
	gap: 12px;
}
.sw-h2-cta-btns .et_pb_button { margin-bottom: 0; }

/* White button on the gradient. Listed in both forms so it out-ranks
   `.sw-divi .sw-btn.et_pb_button` (0-2-0) in the PHP template and stands alone
   in the export. The shadow is tinted toward the violet end, not the site navy. */
.sw-btn--on-grad.et_pb_button,
.sw-divi .sw-btn--on-grad.et_pb_button {
	color: var(--sw-cta-grad-start) !important;
	background-color: var(--sw-white);
	background-image: none;
	border-color: transparent !important;
	box-shadow: 0 16px 34px -18px rgba(4, 31, 56, 0.55);
}
.sw-btn--on-grad.et_pb_button:hover,
.sw-divi .sw-btn--on-grad.et_pb_button:hover {
	box-shadow: 0 22px 46px -20px rgba(4, 31, 56, 0.68);
}

/* The outline button sits at 85-97% across the panel, which on the brand ramp
   is #4588C5 to #5696D1 — white label contrast there measures 3.8:1 and 3.1:1,
   under AA for a 14px bold label. The violet end this replaced was far darker,
   so the fix belongs with the colour change rather than being left as a
   pre-existing quirk. A navy scrim under the button lifts it back to 5.1:1
   without touching the brand gradient. Matches .sw-divi .sw-btn--ghost-dark at
   (0,2,0) and sits later in the file. */
.sw-h2-cta-btns .sw-btn--ghost-dark,
.sw-divi .sw-h2-cta-btns .sw-btn--ghost-dark.et_pb_button {
	background-color: rgba(4, 31, 56, 0.22);
	border-color: rgba(255, 255, 255, 0.55) !important;
}

/* ---- responsive ---------------------------------------------------------- */
@media (max-width: 980px) {
	.sw-h2-hero { padding: 92px 0; }
	.sw-h2-caps, .sw-h2-sols, .sw-h2-proc, .sw-h2-why { padding: 72px 0; }
	.sw-h2-results, .sw-h2-cta { padding: 0 0 72px; }

	.sw-h2-hero-title h1 { font-size: 44px; letter-spacing: -1.2px; }
	.sw-h2-hero-intro p { font-size: 17px; }
	.sw-h2-head h2 { font-size: 32px; }
	.sw-h2-results-title h2, .sw-h2-cta-copy h2 { font-size: 26px; }
	.sw-h2-head { margin-bottom: 40px !important; }

	.sw-fgrid, .sw-sgrid { grid-template-columns: repeat(2, 1fr); }
	.sw-pgrid { grid-template-columns: repeat(3, 1fr); gap: 28px 12px; }
	/* At 3-across the line between items 3 and 4 would run backwards across the
	   wrap, so the connectors come off entirely. */
	.sw-pgrid > .et_pb_module:not(:first-child) .sw-pstep::before { display: none; }

	.sw-h2-panel { padding: 40px 32px; }
	.sw-h2-panel > .et_pb_column_1_2,
	.sw-h2-panel > .et_pb_column_3_5,
	.sw-h2-panel > .et_pb_column_2_5 { width: 100%; margin-right: 0; }
	.sw-h2-quote-col {
		border-left: 0;
		border-top: 1px solid var(--sw-border-dark);
		padding-left: 0;
		padding-top: 32px;
		margin-top: 32px;
	}
	.sw-h2-cta-btns { justify-content: flex-start; margin-top: 26px; }
}

@media (max-width: 767px) {
	.sw-h2-hero { padding: 68px 0; }
	.sw-h2-caps, .sw-h2-sols, .sw-h2-proc, .sw-h2-why { padding: 56px 0; }
	.sw-h2-results, .sw-h2-cta { padding: 0 0 56px; }

	.sw-h2-hero-title h1 { font-size: 34px; letter-spacing: -0.8px; }
	.sw-h2-hero-intro p { font-size: 16px; }
	.sw-h2-head h2 { font-size: 26px; }
	.sw-h2-head { margin-bottom: 32px !important; }

	.sw-h2-hero-btns { gap: 12px; }
	.sw-h2-hero-btns .et_pb_button,
	.sw-h2-cta-btns .et_pb_button { width: 100%; }

	.sw-fgrid, .sw-sgrid, .sw-pgrid { grid-template-columns: 1fr; }
	.sw-statgrid { grid-template-columns: repeat(2, 1fr); }
	.sw-h2-panel { padding: 32px 24px; }
	.sw-h2-results-title h2, .sw-h2-cta-copy h2 { font-size: 24px; }
	.sw-quote2__text { font-size: 17px; }
}

/* ===========================================================================
   36. Services v2  —  templates/page-services-v2.php
   ---------------------------------------------------------------------------
   Only this page's own blocks. Everything shared is reused rather than
   restated: .sw-svc-grid / .sw-svc-card / .sw-svc-card__icon (§16),
   .sw-check-list (§16, needs the .sw-page ancestor each section carries),
   .sw-pstep* and .sw-statgrid / .sw-stat* (§35), .sw-btn* (§2, §27),
   .sw-eyebrow, .sw-grad-text, .sw-card-more.

   Section classes are new (sw-s2-*) rather than reusing v1's .sw-svc-hero etc.
   so that restyling this page cannot change the live /services/ page, which is
   still on page-services.php.

   Bare selectors, so the same rules serve the PHP template and an export.
   =========================================================================== */

/* ---- section surfaces and rhythm ----------------------------------------
   Compound `.et_pb_section.sw-s2-*`, not the bare class. Divi's own
   `.et_pb_section { padding: 54px 0 }` is also (0,1,0) and loads after the
   child stylesheet, so a bare `.sw-s2-cta` loses the tie and the band renders
   with Divi's default padding instead. The compound form is (0,2,0) and wins
   outright — and it still matches in an export, where both classes land on the
   same element. */
/* Symmetric, so the copy sits on the band's true centre. It was 112/104, which
   pushed it 8px high — invisible until measured, but there is no reason for it
   now that the hero is a single centred column rather than a split. */
.et_pb_section.sw-s2-hero { background-color: var(--sw-navy-900); padding: 112px 0; }
.et_pb_section.sw-s2-core { background-color: var(--sw-white); padding: 96px 0; }
.et_pb_section.sw-s2-auto { background-color: var(--sw-light); padding: 96px 0; }
/* A half-step lighter than the band above, so two adjacent tinted sections do
   not read as one slab. */
.et_pb_section.sw-s2-proc { background-color: var(--sw-blue-25); padding: 96px 0; }
.et_pb_section.sw-s2-why  { background-color: var(--sw-navy-900); padding: 96px 0; }
.et_pb_section.sw-s2-cta  { background-color: var(--sw-white); padding: 0 0 96px; }

.sw-s2-head { max-width: 720px !important; text-align: center; margin-bottom: 48px !important; }
.sw-s2-head .et_pb_module { margin-bottom: 12px; }
.sw-s2-head h2 {
	margin: 0;
	padding: 0;
	font-size: 36px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.8px;
	color: var(--sw-slate);
	text-wrap: balance;
}
.sw-s2-head__sub p { margin: 0; font-size: 16px; line-height: 1.7; color: var(--sw-muted); }
.sw-s2-core .sw-eyebrow p,
.sw-s2-auto .sw-eyebrow p,
.sw-s2-proc .sw-eyebrow p { font-size: 13px; letter-spacing: 1.6px; color: var(--sw-blue-500); }

/* ---- 1. hero --------------------------------------------------------------
   Centred, not the mockup's left-aligned two-column split. That split existed
   to balance the copy against the isometric artwork; with the artwork removed,
   keeping it leaves half the band empty and reads as a missing image. Centring
   also matches every section heading further down this page. */
.et_pb_section.sw-s2-hero { position: relative; overflow: hidden; }

/* Two soft light sources, so the band is not a flat navy rectangle now that
   nothing else occupies it. Same idea as .sw-hero on the homepage, but centred
   and defined here so the two pages stay independent. */
.sw-s2-hero::before,
.sw-s2-hero::after {
	content: "";
	position: absolute;
	left: 50%;
	border-radius: 50%;
	pointer-events: none;
	z-index: 0;
	transform: translateX(-50%);
}
.sw-s2-hero::before {
	top: -240px;
	width: 900px;
	height: 700px;
	background: radial-gradient(circle, rgba(8, 82, 150, 0.36) 0%, rgba(8, 82, 150, 0) 66%);
}
.sw-s2-hero::after {
	bottom: -300px;
	width: 740px;
	height: 600px;
	background: radial-gradient(circle, rgba(91, 155, 213, 0.2) 0%, rgba(91, 155, 213, 0) 68%);
}
.sw-s2-hero .et_pb_row { position: relative; z-index: 1; }

.sw-s2-hero__row { align-items: center; }
.sw-s2-hero__copy { text-align: center; }
/* In an export Divi puts .et_pb_text_align_left on every module at (0,2,0),
   which beats centring inherited from the column. Win it back here so the
   layout and the export agree. */
.sw-s2-hero__copy .et_pb_text.et_pb_module { text-align: center; }
.sw-s2-hero .sw-eyebrow p { font-size: 13px; letter-spacing: 1.6px; color: var(--sw-blue-200); }
.sw-s2-hero__title h1 {
	max-width: 860px;
	margin: 0 auto;
	padding: 0;
	font-size: 52px;
	font-weight: 700;
	line-height: 1.12;
	letter-spacing: -1.2px;
	color: var(--sw-white);
}
.sw-s2-hero__title { margin-bottom: 20px !important; }
.sw-s2-hero__lede p {
	max-width: 620px;
	margin: 0 auto;
	font-size: 18px;
	line-height: 1.7;
	color: var(--sw-muted-dark);
}
.sw-s2-hero__lede { margin-bottom: 32px !important; }
/* Outside a module so the two buttons stay on one line — the column is normal
   block flow, and a flex column would put each on its own row. */
.sw-s2-hero__btns {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 12px;
}
.sw-s2-hero__btns .et_pb_button { margin-bottom: 0; }

/* ---- restores the bottom padding on this page's cards --------------------
   Section 27 carries `.sw-divi .et_pb_text_inner > *:last-child {
   padding-bottom: 0 }` at (0,3,0) to kill the trailing margin on a stray <p>
   inside a Text module. Every card on this page is the ONLY child of its Text
   module, so that rule matched and flattened their bottom padding to zero —
   the cards rendered 26px at the top and nothing at the bottom.

   Same defect the homepage cards had. Listed at (0,3,0) and later in the file
   so it wins without !important, each component restoring its own value. The
   bare forms cover the exported DOM, where no .sw-divi wrapper exists and
   nothing zeroes the padding in the first place.

   v1 /services/ is unaffected either way: its cards sit directly in the
   section, not inside an .et_pb_text_inner. */
/* The core-service cards are blurbs now, so they are the grid item themselves
   rather than the only child of a Text module — the :last-child rule above
   cannot reach them and no exemption is needed. Kept for the auto tiles only. */
/* The auto tiles are blurbs too now, so they are the grid item rather than the
   only child of a Text module — the :last-child rule cannot reach them and the
   exemption that used to be here is no longer needed. */

/* ---- 2. core services ----------------------------------------------------
   Everything here is scoped to .sw-s2-core so the live /services/ page, which
   shares .sw-svc-card, is not affected. */
.sw-s2-core .sw-svc-grid > .et_pb_module { margin-bottom: 0 !important; height: 100%; }

/* ---- mapping the card design onto Divi's blurb DOM -----------------------
   The blurb IS the card now, so its internals have to behave like the flex
   column the design assumes:

       .et_pb_blurb                 the card    (padding, border, shadow)
         .et_pb_blurb_content       flex column (so the link can sit at the end)
           .et_pb_main_blurb_image  the icon tile
           .et_pb_blurb_container   title + description, filling the rest
             .et_pb_module_header   the title
             .et_pb_blurb_description  copy, checklist, Learn more

   Three Divi defaults have to be undone or the card is unrecognisable:
   max-width 550px on the content, centred text, and a 96px icon. */
.sw-s2-core .sw-svc-card.et_pb_blurb { height: 100%; }
.sw-s2-core .sw-svc-card .et_pb_blurb_content {
	display: flex;
	flex-direction: column;
	max-width: none;      /* Divi caps blurb content at 550px */
	height: 100%;
	text-align: left;     /* Divi centres blurb text */
}
.sw-s2-core .sw-svc-card .et_pb_blurb_container {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
}
.sw-s2-core .sw-svc-card .et_pb_blurb_description {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
}
/* Divi sizes a top-placed blurb icon at 96px from (0,2,0). The glyph here is an
   inline SVG so font-size does not drive it, but the wrapper still needs to
   stop reserving that much room. */
/* §16 paints .sw-svc-card .et_pb_main_blurb_image as a 50px navy disc at
   (0,2,0) — left over from an older blurb-based version of this card. The tile
   is the span inside it now, so the wrapper has to stop being a shape or both
   paint and a dark semicircle bleeds out from behind the tinted square. */
.sw-s2-core .sw-svc-card .et_pb_main_blurb_image {
	width: auto;
	height: auto;
	margin-bottom: 0;
	background: none;
	border-radius: 0;
	line-height: 1;
	font-size: 0;
	/* Divi centres a top-placed blurb icon; this card is left-aligned. */
	text-align: left;
}
/* The glyph is TEXT from Divi's icon font, so the tile needs a real font-size —
   the wrapper above keeps font-size:0 only to kill inline-block whitespace. */
.sw-s2-core .sw-svc-card .et_pb_main_blurb_image .et-pb-icon {
	font-family: ETmodules;
	font-size: 22px;
	font-weight: 400;
	font-style: normal;
	font-variant: normal;
	line-height: 1;
	text-transform: none;
	speak: never;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}

/* Two lines of title reserved, so every description starts on the same
   baseline whatever the heading does. "Websites & Digital Experiences" wraps
   and the other three do not. */
.sw-s2-core .sw-svc-card__title {
	min-height: 44px;
	margin: 0 0 12px;
	padding: 0;
	font-size: 17px;
	font-weight: 700;
	line-height: 1.3;
	letter-spacing: -0.2px;
	color: var(--sw-slate);
	text-wrap: balance;
}

/* A tinted rounded square with a blue glyph, matching the mockup and the card
   icons everywhere else on the site. §16's shared .sw-svc-card__icon is a solid
   navy disc, which reads far heavier than the mockup and is the only icon of
   that shape on the page. Overridden here rather than changed at source, so v1
   keeps its own look. */
.sw-s2-core .sw-svc-card__icon {
	display: grid;
	place-items: center;
	width: 46px;
	height: 46px;
	margin-bottom: 20px;
	border-radius: 12px;
	background: rgba(8, 82, 150, 0.09);
	color: var(--sw-blue-600);
	transition: background-color 0.25s var(--sw-ease), color 0.25s var(--sw-ease);
}
.sw-s2-core .sw-svc-card:hover .sw-svc-card__icon {
	background: var(--sw-blue-600);
	color: var(--sw-white);
}

.sw-s2-core .sw-svc-card__text { margin: 0 0 16px; font-size: 15px; line-height: 1.7; color: var(--sw-muted); }
.sw-s2-core .sw-svc-card .sw-check-list { margin: 0 0 auto; }
.sw-s2-core .sw-svc-card .sw-card-more {
	margin: 20px 0 0 !important;
	padding-top: 16px;
	border-top: 1px solid var(--sw-border-light);
}

/* ---- 3. automation tiles -------------------------------------------------
   Twelve items is above Divi's 1_6 ceiling, so this band is a CSS grid whatever
   else the page does. */
.sw-s2-auto__grid {
	float: none;
	display: grid;
	/* Six across, so the twelve tiles fall into two rows.
	   One grid rather than two Divi rows on purpose: two rows equalise their
	   heights independently, which is the problem the homepage's chip band had
	   to compensate for with a min-height. A single grid equalises all twelve
	   together, and six is Divi's column ceiling anyway (1_6), so nothing is
	   lost structurally. */
	grid-template-columns: repeat(6, minmax(0, 1fr));
	gap: 12px;
}
.sw-s2-auto__grid > .et_pb_module { margin-bottom: 0 !important; height: 100%; }

/* The tile is a Blurb now, so it IS the grid item. Divi's blurb defaults have
   to be undone the same way as the service cards: a 550px content cap, and a
   96px top-placed icon. Centred text is already what this tile wants. */
.sw-auto-tile.et_pb_blurb .et_pb_blurb_content { max-width: none; }
.sw-auto-tile .et_pb_main_blurb_image { margin-bottom: 0; line-height: 1; font-size: 0; }
.sw-auto-tile .et_pb_module_header {
	margin: 0;
	padding: 0;
	font-size: 12px;
	line-height: 1.3;
	font-weight: 700;
	color: var(--sw-slate);
}
.sw-auto-tile {
	position: relative;
	height: 100%;
	padding: 16px 8px;
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-card-radius);
	box-shadow: var(--sw-card-shadow);
	text-align: center;
	transition: var(--sw-card-transition);
}
.sw-auto-tile:hover {
	transform: translateY(-3px);
	border-color: var(--sw-blue-200);
	box-shadow: var(--sw-card-shadow-hover);
}
.sw-auto-tile__icon {
	display: grid;
	place-items: center;
	width: 34px;
	height: 34px;
	margin: 0 auto 8px;
	border-radius: 12px;
	background: rgba(8, 82, 150, 0.09);
	color: var(--sw-blue-600);
	/* Divi icon-font glyph, so the tile needs a real font-size — the wrapper
	   above keeps font-size:0 only to kill inline-block whitespace. */
	font-family: ETmodules;
	font-size: 17px;
	font-weight: 400;
	font-style: normal;
	line-height: 1;
	text-transform: none;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}
/* Chevron between tiles. Excluded on every 6th item as well as the last, or a
   chevron at the end of row one points into the margin.

   Written as `> .sw-auto-tile`, not `> .et_pb_module .sw-auto-tile`: the tile
   IS the module now that it is a blurb, and a descendant combinator cannot
   match an element against itself — which silently removed every chevron. */
.sw-s2-auto__grid > .sw-auto-tile:not(:last-child):not(:nth-child(6n))::after {
	content: "";
	position: absolute;
	top: 50%;
	right: -8px;
	width: 6px;
	height: 6px;
	border-top: 2px solid var(--sw-blue-150);
	border-right: 2px solid var(--sw-blue-150);
	transform: translateY(-50%) rotate(45deg);
}
/* §27's `.sw-divi .sw-btn--center.et_pb_button { margin: 0 auto }` is (0,3,0)
   and was overriding a (0,2,0) margin-top, so the button sat hard against the
   tiles with no gap at all. Both forms listed: the first wins in the PHP
   preview, the second in an export, where there is no .sw-divi wrapper. */
.sw-divi .sw-s2-auto .sw-btn--center.et_pb_button,
.sw-s2-auto .sw-btn--center.et_pb_button {
	margin-top: 40px;
}

/* ---- 4. approach ----------------------------------------------------------
   Four real 1_4 columns now, so .sw-pstep is the COLUMN rather than a div
   inside a Text module. §35's .sw-pstep* rules still apply — they were written
   against the class, not the element. */
.sw-s2-proc .sw-pstep { position: relative; text-align: center; }
.sw-s2-proc .sw-pstep > .et_pb_module { margin-bottom: 0; }

/* The icon module is the circle. §35 styles .sw-pstep__badge as a grid box, so
   only the glyph font and centring are needed here. */
.sw-s2-proc .sw-pstep__badge {
	position: relative;
	z-index: 1;
	display: grid;
	place-items: center;
	width: 62px;
	height: 62px;
	margin: 0 auto 16px;
	border: 1px solid var(--sw-blue-100);
	border-radius: 50%;
	background: var(--sw-white);
	color: var(--sw-blue-600);
}
.sw-s2-proc .sw-pstep__badge .et-pb-icon {
	font-family: ETmodules;
	font-size: 24px;
	font-weight: 400;
	font-style: normal;
	line-height: 1;
	text-transform: none;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}

/* The connector Divider modules. Each sits inside the column to its right and
   is pulled back across the gutter to meet the previous circle — Divi cannot
   place a module between two columns, and 4 steps + 3 dividers would need
   seven columns against a ceiling of six. */
.sw-s2-proc .sw-pstep__link {
	position: absolute;
	top: 31px;
	left: -50%;
	width: 100%;
	margin: 0 !important;
	padding: 0 !important;
	z-index: 0;
}
.sw-s2-proc .sw-pstep__link .et_pb_divider_internal {
	border-top: 2px dashed var(--sw-blue-100);
}
.sw-s2-proc .sw-pstep__head { margin-bottom: 0; }

/* ---- 5. why us ----------------------------------------------------------- */
.sw-s2-why__head { margin-bottom: 40px !important; }
.sw-s2-why .sw-eyebrow p { font-size: 13px; letter-spacing: 1.6px; color: var(--sw-blue-200); }
.sw-s2-why__title h2 {
	margin: 0;
	padding: 0;
	font-size: 34px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.8px;
	color: var(--sw-white);
}
.sw-s2-why__row { align-items: stretch; }
.sw-why-grid {
	float: none;
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 24px;
	align-content: start;
}
.sw-why-grid > .et_pb_module { margin-bottom: 0 !important; }

/* ---- benefits: Blurb modules, icon beside the title ----------------------
   et_pb_blurb_position_left puts the icon in a row with the text, which is the
   layout this card wants. The usual three Divi defaults still need undoing:
   the 550px content cap, centred text, and the 96px icon. */
.sw-why-item.et_pb_blurb .et_pb_blurb_content {
	display: flex;
	align-items: flex-start;
	gap: 12px;
	max-width: none;
	text-align: left;
}
.sw-why-item .et_pb_main_blurb_image { flex: 0 0 auto; margin: 0; line-height: 1; font-size: 0; }
.sw-why-item .et_pb_blurb_container { flex: 1 1 auto; }
.sw-why-item .et_pb_module_header {
	margin: 0 0 6px;
	padding: 0;
	font-size: 16px;
	font-weight: 700;
	color: var(--sw-white);
}
.sw-why-item .et_pb_blurb_description p { margin: 0; font-size: 14px; line-height: 1.7; color: var(--sw-blue-200); }
.sw-why-item .sw-why-item__icon {
	font-family: ETmodules;
	font-size: 20px;
	font-weight: 400;
	font-style: normal;
	line-height: 1;
	text-transform: none;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}

/* ---- statistics: Number Counter modules ---------------------------------- */
.sw-why-panel .sw-statgrid > .et_pb_module { margin-bottom: 0 !important; }
.sw-why-panel .sw-stat.et_pb_number_counter .percent { margin: 0; }
.sw-why-panel .sw-stat .percent p {
	margin: 0;
	padding: 0;
	font-size: 30px;
	font-weight: 800;
	line-height: 1.1;
	color: var(--sw-white);
}
.sw-why-panel .sw-stat .title {
	margin: 4px 0 0;
	padding: 0;
	font-size: 13px;
	font-weight: 400;
	color: var(--sw-blue-200);
}

/* ---- testimonial: Testimonial module ------------------------------------- */
.sw-why-quote.et_pb_testimonial {
	margin-top: 28px !important;
	padding: 24px 0 0;
	border-top: 1px solid var(--sw-border-dark);
	background: none;
	box-shadow: none;
}
.sw-why-quote .et_pb_testimonial_description_inner p {
	margin: 0 0 14px;
	font-size: 16px;
	line-height: 1.7;
	color: var(--sw-white);
}
.sw-why-quote .et_pb_testimonial_author {
	display: block;
	font-size: 14px;
	font-weight: 700;
	font-style: normal;
	color: var(--sw-white);
}
.sw-why-quote .et_pb_testimonial_meta { display: block; font-size: 13px; color: var(--sw-blue-200); }

.sw-why-item__head { display: flex; align-items: center; gap: 12px; min-height: 44px; margin-bottom: 8px; }
.sw-why-item__icon {
	flex: 0 0 auto;
	display: grid;
	place-items: center;
	width: 42px;
	height: 42px;
	border-radius: 12px;
	background: rgba(155, 194, 229, 0.14);
	color: var(--sw-blue-200);
}
.sw-why-item h3 { margin: 0; padding: 0; font-size: 16px; font-weight: 700; color: var(--sw-white); }
.sw-why-item p { margin: 0; font-size: 14px; line-height: 1.7; color: var(--sw-blue-200); }

.sw-why-panel {
	background: var(--sw-navy-850);
	border-radius: 22px;
	padding: 32px 28px;
}
.sw-why-panel .sw-statgrid { gap: 24px 16px; }
.sw-why-quote { margin-top: 28px !important; padding-top: 24px;
	border-top: 1px solid var(--sw-border-dark); }
.sw-why-quote .sw-quote2__text { font-size: 16px; }

/* ---- 6. final CTA -------------------------------------------------------- */
.sw-s2-cta__panel {
	align-items: center;
	width: 90%;
	max-width: 1240px;
	padding: 52px 48px;
	border-radius: 22px;
	background-image: var(--sw-gradient);
}
/* The columns are a plain 1_2 + 1_2 now, so Divi's own widths apply and the
   declared structure matches what renders — no override. They were 3_5/2_5
   with a CSS width override, which made the builder show one split and the
   page show another. */
/* The two labels measure ~520px together; the column had to reach that before
   they would sit on one line, and trimming the horizontal padding closed the
   last 20px without shrinking the type. */
.sw-s2-cta__btns .sw-btn.et_pb_button { padding: 0 20px !important; }
.sw-s2-cta__copy h2 {
	margin: 0 0 12px;
	padding: 0;
	font-size: 30px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.6px;
	color: var(--sw-white);
	text-wrap: balance;
}
.sw-s2-cta__copy p { margin: 0; max-width: 480px; font-size: 16px; line-height: 1.7;
	color: rgba(255, 255, 255, 0.86); }
.sw-s2-cta__copy .et_pb_module:last-child { margin-bottom: 0; }
.sw-s2-cta__btns { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 12px; }
.sw-s2-cta__btns .et_pb_button { margin-bottom: 0; }
/* Same contrast fix as the homepage panel: the outline button sits on the light
   end of the brand ramp, where a white label falls under AA without a scrim. */
.sw-s2-cta__btns .sw-btn--ghost-dark,
.sw-divi .sw-s2-cta__btns .sw-btn--ghost-dark.et_pb_button {
	background-color: rgba(4, 31, 56, 0.22);
	border-color: rgba(255, 255, 255, 0.55) !important;
}

/* ---- responsive ---------------------------------------------------------- */
/* Desktop is already six across, so the old 1100px step down to six is gone.
   Chevrons come off as soon as the row count changes, since the :nth-child(6n)
   exclusion above only describes a six-column row. */
@media (max-width: 1100px) {
	.sw-s2-auto__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
	.sw-s2-auto__grid .sw-auto-tile::after { display: none; }
}

@media (max-width: 980px) {
	.et_pb_section.sw-s2-hero { padding: 84px 0; }
	.et_pb_section.sw-s2-core, .et_pb_section.sw-s2-auto, .et_pb_section.sw-s2-proc, .et_pb_section.sw-s2-why { padding: 72px 0; }
	.et_pb_section.sw-s2-cta { padding: 0 0 72px; }

	.sw-s2-hero__title h1 { font-size: 42px; }
	.sw-s2-head h2 { font-size: 32px; }
	.sw-s2-why__title h2 { font-size: 30px; }

	.sw-s2-hero__lede p { font-size: 17px; }

	.sw-s2-core .sw-svc-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	/* Divi collapses every column to full width at tablet, which would stack
	   four steps. Grid on the ROW overrides the children's widths whether Divi
	   laid them out with floats or flex, so one rule covers both builders. */
	.et_pb_row.sw-s2-proc__row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 28px 12px; }
	.et_pb_row.sw-s2-proc__row > .et_pb_column { width: auto !important; margin: 0 !important; float: none !important; }
	/* At 2-across the connector between steps 2 and 3 would run backwards. */
	.sw-s2-proc .sw-pstep__link { display: none; }

	.sw-divi .sw-s2-why-grid,
	.sw-divi .sw-why-grid,
	.sw-divi .sw-why-panel { width: 100%; margin-right: 0; }
	.sw-why-panel { margin-top: 28px; }

	.sw-s2-cta__panel { padding: 40px 32px; }
	.sw-s2-cta__panel > .et_pb_column:first-child,
	.sw-s2-cta__panel > .et_pb_column:last-child { width: 100%; margin-right: 0; }
	.sw-s2-cta__btns { justify-content: flex-start; margin-top: 24px; }
}

@media (max-width: 767px) {
	.et_pb_section.sw-s2-hero { padding: 64px 0; }
	.et_pb_section.sw-s2-core, .et_pb_section.sw-s2-auto, .et_pb_section.sw-s2-proc, .et_pb_section.sw-s2-why { padding: 56px 0; }
	.et_pb_section.sw-s2-cta { padding: 0 0 56px; }

	.sw-s2-hero__title h1 { font-size: 34px; letter-spacing: -0.8px; }
	.sw-s2-head h2 { font-size: 26px; }
	.sw-s2-head { margin-bottom: 32px !important; }
	.sw-s2-why__title h2 { font-size: 25px; }

	.sw-s2-hero__btns .et_pb_button,
	.sw-s2-cta__btns .et_pb_button { width: 100%; }

	.sw-s2-core .sw-svc-grid { grid-template-columns: 1fr; }
	.sw-s2-auto__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
	.et_pb_row.sw-s2-proc__row { grid-template-columns: 1fr; }
	.sw-why-grid { grid-template-columns: 1fr; }
	.sw-s2-cta__panel { padding: 32px 24px; }
	.sw-s2-cta__copy h2 { font-size: 25px; }
}

/* ===========================================================================
   37. Websites & Web Development v3  —  templates/page-websites-v3.php
   ---------------------------------------------------------------------------
   Only this page's own blocks. Everything shared is reused rather than
   restated: .sw-svc-card (§16), .sw-check-list / .sw-check (§16, both need the
   .sw-page ancestor each section carries), .sw-pstep* (§35), .sw-card--project
   and .sw-project-* (§6), .sw-h2-panel--grad and .sw-h2-cta-* (§35), .sw-btn*
   (§2, §27), .sw-eyebrow, .sw-grad-text, .sw-card-more.

   Section classes are new (sw-w3-*) rather than reusing v1's .sw-websites-* or
   v2's .sw-wd-*, so restyling this page cannot change either page already
   built — /services/websites/ is still on page-websites-development.php.

   Bare selectors, so the same rules serve the PHP template and an export.
   Section PADDING uses the compound `.et_pb_section.sw-w3-*` form: Divi's own
   `.et_pb_section { padding: 54px 0 }` is (0,1,0) and loads after this
   stylesheet, so a bare class loses the tie.
   =========================================================================== */

/* ---- section surfaces and rhythm ---------------------------------------- */
.et_pb_section.sw-w3-hero  { background-color: var(--sw-navy-900); padding: 112px 0; }
.et_pb_section.sw-w3-build { background-color: var(--sw-white); padding: 96px 0; }
.et_pb_section.sw-w3-perf  { background-color: var(--sw-light); padding: 96px 0; }
.et_pb_section.sw-w3-tech  { background-color: var(--sw-white); padding: 96px 0; }
.et_pb_section.sw-w3-work  { background-color: var(--sw-light); padding: 96px 0; }
.et_pb_section.sw-w3-cap   { background-color: var(--sw-white); padding: 96px 0; }
/* A half-step lighter than --sw-light, so this band does not read as the same
   slab as the two above it. */
.et_pb_section.sw-w3-proc  { background-color: var(--sw-blue-25); padding: 96px 0; }
.et_pb_section.sw-w3-auto  { background-color: var(--sw-navy-900); padding: 96px 0; }
.et_pb_section.sw-w3-cta   { background-color: var(--sw-white); padding: 96px 0; }

/* Shared section heading block. */
.sw-w3-head { max-width: 720px !important; text-align: center; margin-bottom: 48px !important; }
.sw-w3-head .et_pb_module { margin-bottom: 12px; }
.sw-w3-head h2 {
	margin: 0;
	padding: 0;
	font-size: 36px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.8px;
	color: var(--sw-slate);
	text-wrap: balance;
}
.sw-w3-head__sub p { margin: 0; font-size: 16px; line-height: 1.7; color: var(--sw-muted); }
.sw-w3-build .sw-eyebrow p,
.sw-w3-tech .sw-eyebrow p,
.sw-w3-work .sw-eyebrow p,
.sw-w3-proc .sw-eyebrow p,
.sw-w3-perf .sw-eyebrow p { font-size: 13px; letter-spacing: 1.6px; color: var(--sw-blue-500); }
.sw-w3-hero .sw-eyebrow p,
.sw-w3-auto .sw-eyebrow p { font-size: 13px; letter-spacing: 1.6px; color: var(--sw-blue-200); }

/* ---- 1. hero -------------------------------------------------------------
   Split 3_5 / 2_5, per the mockup. Two soft light sources so the band is not a
   flat navy rectangle — offset left rather than centred, because this hero has
   artwork on the right where services v2 has nothing. */
.et_pb_section.sw-w3-hero { position: relative; overflow: hidden; }
.sw-w3-hero::before,
.sw-w3-hero::after {
	content: "";
	position: absolute;
	border-radius: 50%;
	pointer-events: none;
	z-index: 0;
}
.sw-w3-hero::before {
	top: -260px;
	left: -160px;
	width: 900px;
	height: 700px;
	background: radial-gradient(circle, rgba(8, 82, 150, 0.38) 0%, rgba(8, 82, 150, 0) 66%);
}
.sw-w3-hero::after {
	right: -220px;
	bottom: -300px;
	width: 780px;
	height: 620px;
	background: radial-gradient(circle, rgba(91, 155, 213, 0.22) 0%, rgba(91, 155, 213, 0) 68%);
}
.sw-w3-hero .et_pb_row { position: relative; z-index: 1; }

/* COMPOUND, not the bare class. `.sw-divi .et_pb_row { align-items: stretch }`
   in §27 is (0,2,0), so a bare `.sw-w3-hero__row { align-items: center }` at
   (0,1,0) loses the cascade silently and every split band top-aligns instead.
   Measured, not assumed — see probe.ps1. The compound form is (0,2,0), later in
   the file, and still matches in an export where there is no .sw-divi wrapper.
   Every centred row on this page is written this way. */
.et_pb_row.sw-w3-hero__row { align-items: center; }
/* No min-height on the row. The mockup's "min 520px" is the whole band, and the
   band is already 619px from 112px padding plus the copy — a 520px row on top
   of that just added 125px of dead navy under the buttons. */
.sw-w3-hero__title h1 {
	max-width: 620px;
	margin: 0;
	padding: 0;
	font-size: 52px;
	font-weight: 700;
	line-height: 1.12;
	letter-spacing: -1.2px;
	color: var(--sw-white);
}
.sw-w3-hero__title { margin-bottom: 20px !important; }
.sw-w3-hero__lede p {
	max-width: 520px;
	margin: 0;
	font-size: 17px;
	line-height: 1.75;
	color: var(--sw-muted-dark);
}
.sw-w3-hero__lede { margin-bottom: 32px !important; }

/* The button pair, WITHOUT a wrapper div. .sw-s2-hero__btns on services v2 is a
   plain <div> that no export can carry, because a Divi column's children are
   modules. .et_pb_button_module_wrapper exists in both DOMs. */
.sw-w3-hero__copy > .et_pb_button_module_wrapper { display: inline-block; vertical-align: top; margin: 0 12px 0 0; }
/* No `:last-of-type` here. Every child of this column is a div, so it selects
   the points Text module rather than the second button and matches no button
   wrapper at all — cascade-audit reported it DEAD. The trailing 12px sits
   against the column edge and is invisible, so the rule is simply gone. */
.sw-w3-hero__copy .et_pb_button { margin-bottom: 0; }

.sw-w3-hero__points { margin-top: 28px !important; }
.sw-w3-hero__points ul { display: flex; flex-wrap: wrap; gap: 12px 24px; margin: 0; padding: 0; list-style: none; }
.sw-w3-hero__points li {
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 0;
	font-size: 13.5px;
	line-height: 1.4;
	color: var(--sw-blue-200);
}
.sw-w3-hero__points svg { flex: 0 0 auto; color: var(--sw-blue-400); }

/* ---- the hero artwork ----------------------------------------------------
   Built, not photographed. The mockup's laptop + phone composite does not
   exist as a file, and the only candidates in uploads/ are Divi's own
   layout-pack demos. This illustrates "a website" without claiming to be a
   screenshot of one, and it stays crisp at any density. */
.sw-w3-mock { position: relative; margin-bottom: 0 !important; }
.sw-w3-mock__browser {
	border-radius: 12px;
	overflow: hidden;
	background: var(--sw-white);
	border: 1px solid rgba(255, 255, 255, 0.14);
	box-shadow: 0 30px 60px -30px rgba(0, 0, 0, 0.65);
}
.sw-w3-mock__bar {
	display: flex;
	align-items: center;
	gap: 6px;
	padding: 10px 12px;
	background: var(--sw-blue-50);
	border-bottom: 1px solid var(--sw-blue-100);
}
.sw-w3-mock__bar span { width: 9px; height: 9px; border-radius: 50%; background: var(--sw-blue-150); }
.sw-w3-mock__body { padding: 18px; }
.sw-w3-mock__hero {
	height: 84px;
	margin-bottom: 14px;
	border-radius: 8px;
	background: linear-gradient(120deg, var(--sw-blue-600) 0%, var(--sw-blue-400) 100%);
}
.sw-w3-mock__line { height: 8px; margin-bottom: 8px; border-radius: 4px; background: var(--sw-blue-100); }
.sw-w3-mock__line--w80 { width: 80%; }
.sw-w3-mock__line--w70 { width: 70%; }
.sw-w3-mock__line--w55 { width: 55%; }
.sw-w3-mock__line--w45 { width: 45%; }
.sw-w3-mock__cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-top: 14px; }
.sw-w3-mock__cards span { height: 42px; border-radius: 6px; background: var(--sw-blue-50); border: 1px solid var(--sw-blue-100); }

.sw-w3-mock__phone {
	position: absolute;
	right: -22px;
	bottom: -48px;
	width: 122px;
	padding: 14px 10px;
	border-radius: 16px;
	background: var(--sw-white);
	border: 1px solid rgba(255, 255, 255, 0.18);
	box-shadow: 0 22px 44px -20px rgba(0, 0, 0, 0.7);
}
.sw-w3-mock__phone-hero {
	height: 40px;
	margin-bottom: 10px;
	border-radius: 6px;
	background: linear-gradient(120deg, var(--sw-blue-600) 0%, var(--sw-blue-400) 100%);
}
.sw-w3-mock__pill { width: 54px; height: 14px; margin-top: 10px; border-radius: 7px; background: var(--sw-blue-600); }

/* §27 carries `.sw-divi .et_pb_text_inner > *:last-child { padding-bottom: 0 }`
   at (0,3,0) to kill the trailing margin on a stray <p> inside a Text module.
   Two blocks on this page are the last child of their module and lose their
   bottom padding to it — a few pixels each, which reads as a spacing choice
   rather than a defect. Both restated at (0,3,0) and later in the file.
   Found by cascade-audit; three screenshot passes had missed them. */
.sw-w3-mock .et_pb_text_inner > .sw-w3-mock__phone { padding-bottom: 14px; }

/* ---- 2. what we build ----------------------------------------------------
   Six Blurb modules in two rows of three real 1_3 columns. The bridge below
   maps Divi's blurb DOM onto §16's card, and it has to undo three Divi
   defaults: the 550px cap, centred text, and the 96px icon. */
.sw-w3-build__row { margin-bottom: 0 !important; }
.sw-w3-build__row .et_pb_column { margin-bottom: 24px; }
.sw-w3-build__row:last-of-type .et_pb_column { margin-bottom: 0; }
.sw-w3-build .sw-svc-card.et_pb_blurb {
	height: 100%;
	max-width: none;
	text-align: left;
	margin-bottom: 0 !important;
}
.sw-w3-build .sw-svc-card .et_pb_blurb_content { max-width: none; }
.sw-w3-build .sw-svc-card .et_pb_main_blurb_image {
	display: grid;
	place-items: center;
	width: 50px;
	height: 50px;
	margin: 0 0 18px;
	border-radius: 50%;
	background: var(--sw-blue-50);
	color: var(--sw-blue-600);
}
/* (0,4,0). Divi's `.et_pb_blurb_position_top .et-pb-icon { font-size: 96px }`
   is (0,2,0), and icon_font_size on the module frequently emits no CSS at all —
   so the size is written here rather than left to a module setting. */
.sw-w3-build .sw-svc-card .et_pb_main_blurb_image .et-pb-icon {
	font-family: ETmodules;
	font-size: 22px;
	font-weight: 400;
	font-style: normal;
	line-height: 1;
	text-transform: none;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}
.sw-w3-build .sw-svc-card .et_pb_module_header {
	margin: 0 0 10px;
	padding: 0;
	font-size: 19px;
	font-weight: 800;
	line-height: 1.3;
	color: var(--sw-slate);
}
.sw-w3-build .sw-svc-card .et_pb_blurb_description p {
	margin: 0;
	padding-bottom: 0;
	font-size: 14.5px;
	line-height: 1.7;
	color: var(--sw-muted);
}

/* ---- 3. performance ----------------------------------------------------- */
.et_pb_row.sw-w3-perf__row { align-items: center; }
.sw-w3-perf__title h2 {
	margin: 0;
	padding: 0;
	font-size: 34px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.8px;
	color: var(--sw-slate);
}
.sw-w3-perf__title { margin-bottom: 16px !important; }
.sw-w3-perf__lede p { margin: 0; max-width: 520px; font-size: 16px; line-height: 1.7; color: var(--sw-muted); }
.sw-w3-perf__lede { margin-bottom: 24px !important; }
.sw-w3-perf__list { margin-bottom: 24px !important; }
/* The <a> carries .et_pb_module, so §27's module margin applies to the button
   as well and left a stray gap under this column. */
.sw-w3-perf__copy .et_pb_button { margin-bottom: 0; }
.sw-w3-perf__list .sw-check-list { margin-bottom: 0; }
.sw-w3-perf__list .sw-check-list li { font-size: 15px; }

/* The score panel. Placeholder by default — see $sw_scores_measured. */
.sw-w3-scores {
	padding: 28px 24px 24px;
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-card-radius);
	box-shadow: var(--sw-card-shadow);
	margin-bottom: 0 !important;
}
.sw-w3-scores__head {
	margin: 0 0 24px;
	padding-bottom: 0;
	font-size: 15px;
	font-weight: 700;
	color: var(--sw-slate);
}
.sw-w3-scores__rings { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; }
.sw-w3-ring { display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center; }
.sw-w3-ring__val {
	display: grid;
	place-items: center;
	width: 62px;
	height: 62px;
	border: 3px solid var(--sw-blue-100);
	border-radius: 50%;
	font-size: 19px;
	font-weight: 800;
	color: var(--sw-blue-600);
}
.sw-w3-ring__label { font-size: 11.5px; line-height: 1.3; color: var(--sw-muted); }
.sw-w3-scores__note {
	margin: 24px 0 0;
	padding: 12px 14px;
	border-radius: 8px;
	background: var(--sw-blue-25);
	border: 1px dashed var(--sw-blue-150);
	font-size: 12.5px;
	line-height: 1.6;
	color: var(--sw-muted);
}
/* Same §27 `:last-child` trap as the phone mock above — this note ends its
   Text module, so its 12px bottom padding was being zeroed. */
.sw-w3-scores .et_pb_text_inner > .sw-w3-scores__note { padding-bottom: 12px; }

/* ---- 4. technology -------------------------------------------------------
   Seven items is above Divi's 1_6 ceiling, so the grid goes on the column and
   the modules become its children. When real logo SVGs exist these <li> become
   Image modules inside the same grid, with nothing else to change. */
.sw-w3-techgrid { margin-bottom: 0 !important; }
.sw-w3-techgrid ul {
	display: grid;
	grid-template-columns: repeat(7, 1fr);
	gap: 14px;
	margin: 0;
	padding: 0;
	list-style: none;
}
.sw-w3-techgrid li {
	display: grid;
	place-items: center;
	height: 80px;
	margin: 0;
	padding: 0 10px;
	border: 1px solid var(--sw-border-light);
	border-radius: 10px;
	background: var(--sw-white);
	font-size: 14px;
	font-weight: 700;
	letter-spacing: -0.2px;
	color: var(--sw-slate);
	text-align: center;
	transition: var(--sw-card-transition);
}
.sw-w3-techgrid li:hover {
	transform: translateY(-3px);
	box-shadow: var(--sw-card-shadow);
	border-color: var(--sw-blue-200);
}

/* ---- 5. our work ---------------------------------------------------------
   The COLUMN is the card (.sw-card--project, §6). Media is a CSS placeholder
   rather than an <img>: there are no screenshots in the tree. */
.sw-w3-work__headinner { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; }
.sw-w3-work__title h2 {
	margin: 0;
	padding: 0;
	font-size: 34px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.8px;
	color: var(--sw-slate);
}
.sw-w3-work__head { margin-bottom: 40px !important; }
.sw-w3-work__all { margin: 0 !important; white-space: nowrap; }
.sw-w3-work__row .et_pb_column { margin-bottom: 0; }
.sw-w3-proj__media { display: block; }
.sw-w3-proj__ph {
	display: grid;
	place-items: center;
	aspect-ratio: 16 / 9;
	background: repeating-linear-gradient(-45deg, var(--sw-blue-50) 0 10px, var(--sw-blue-25) 10px 20px);
	border-bottom: 1px dashed var(--sw-blue-150);
	font-size: 12px;
	letter-spacing: 0.4px;
	color: var(--sw-muted);
}
.sw-w3-hold {
	margin: 24px 0 0 !important;
	padding: 12px 16px;
	border-radius: 8px;
	background: var(--sw-blue-25);
	border: 1px dashed var(--sw-blue-150);
}
.sw-w3-hold p { margin: 0; padding-bottom: 0; font-size: 12.5px; color: var(--sw-muted); }

/* ---- 6. capabilities ---------------------------------------------------- */
.sw-w3-cap__row { align-items: stretch; }
.sw-w3-cap__panel {
	padding: 32px 28px;
	background: var(--sw-blue-25);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-card-radius);
}
.sw-w3-cap__title h3 {
	margin: 0;
	padding: 0;
	font-size: 19px;
	font-weight: 800;
	line-height: 1.3;
	color: var(--sw-slate);
}
.sw-w3-cap__title { margin-bottom: 18px !important; }
.sw-w3-cap__list { margin-bottom: 0 !important; }
.sw-w3-cap__list .sw-check-list { margin-bottom: 0; }
.sw-w3-cap__list .sw-check-list li { font-size: 15px; margin-bottom: 12px; }
.sw-w3-cap__list .sw-check-list li:last-child { margin-bottom: 0; }

/* ---- 7. process ----------------------------------------------------------
   Four real 1_4 columns, so .sw-pstep is the COLUMN. §35's .sw-pstep* rules
   still apply — they were written against the class, not the element. */
.sw-w3-proc .sw-pstep { position: relative; text-align: center; }
.sw-w3-proc .sw-pstep > .et_pb_module { margin-bottom: 0; }
/* Filled circle here, where services v2 uses a white circle with a blue border:
   the mockup asks for a solid accent badge on this page.

   The `>` is load-bearing. Written as `.sw-w3-proc .sw-pstep__badge` this is
   (0,2,0) and loses its 18px bottom margin to the (0,3,0) reset one line above,
   putting the badge hard against the step number. cascade-audit found it; the
   export had already been patched with !important for the same reason, so the
   preview and the export disagreed by 18px and neither looked obviously wrong. */
.sw-w3-proc .sw-pstep > .sw-pstep__badge {
	position: relative;
	z-index: 1;
	display: grid;
	place-items: center;
	width: 64px;
	height: 64px;
	margin: 0 auto 18px;
	border: 0;
	border-radius: 50%;
	background: var(--sw-blue-600);
	color: var(--sw-white);
}
.sw-w3-proc .sw-pstep__badge .et-pb-icon {
	font-family: ETmodules;
	font-size: 24px;
	font-weight: 400;
	font-style: normal;
	line-height: 1;
	text-transform: none;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}
/* The connector Divider modules. Each sits inside the column to its right and
   is pulled back across the gutter to meet the previous circle — Divi cannot
   place a module between two columns, and 4 steps + 3 dividers would need
   seven columns against a ceiling of six. */
.sw-w3-proc .sw-pstep__link {
	position: absolute;
	top: 32px;
	left: -50%;
	z-index: 0;
	width: 100%;
	margin: 0 !important;
	padding: 0 !important;
}
.sw-w3-proc .sw-pstep__link .et_pb_divider_internal { border-top: 2px dashed var(--sw-blue-150); }
.sw-w3-proc .sw-pstep__head { margin-bottom: 0; }

/* ---- 8. website + business automation ----------------------------------- */
.et_pb_row.sw-w3-auto__row { align-items: center; }
.sw-w3-auto__copy .et_pb_button { margin-bottom: 0; }
.sw-w3-auto__title h2 {
	margin: 0;
	padding: 0;
	font-size: 34px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.8px;
	color: var(--sw-white);
}
.sw-w3-auto__title { margin-bottom: 16px !important; }
.sw-w3-auto__lede p { margin: 0; max-width: 540px; font-size: 16px; line-height: 1.75; color: var(--sw-muted-dark); }
.sw-w3-auto__lede { margin-bottom: 0 !important; }

.sw-w3-chips { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin: 28px 0 32px; }
.sw-w3-chip.et_pb_blurb {
	max-width: none;
	margin-bottom: 0 !important;
	padding: 12px 14px;
	text-align: left;
	background: rgba(255, 255, 255, 0.045);
	border: 1px solid var(--sw-border-dark);
	border-radius: 10px;
	transition: background-color 0.25s var(--sw-ease), border-color 0.25s var(--sw-ease);
}
.sw-w3-chip.et_pb_blurb:hover { background: rgba(255, 255, 255, 0.075); border-color: rgba(91, 155, 213, 0.4); }
.sw-w3-chip .et_pb_blurb_content { display: flex; align-items: center; gap: 10px; max-width: none; }
.sw-w3-chip .et_pb_main_blurb_image { width: auto; margin: 0; }
.sw-w3-chip .et_pb_main_blurb_image .et-pb-icon {
	font-family: ETmodules;
	font-size: 16px;
	font-weight: 400;
	font-style: normal;
	line-height: 1;
	text-transform: none;
	color: var(--sw-blue-400);
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}
.sw-w3-chip .et_pb_module_header {
	margin: 0;
	padding: 0;
	font-size: 13.5px;
	font-weight: 600;
	line-height: 1.4;
	color: var(--sw-blue-150);
}

/* The flow diagram, built rather than drawn. */
.sw-w3-flow { margin-bottom: 0 !important; }
.sw-w3-flow__node {
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 14px 16px;
	background: rgba(255, 255, 255, 0.05);
	border: 1px solid var(--sw-border-dark);
	border-radius: 12px;
}
.sw-w3-flow__node + .sw-w3-flow__node { position: relative; margin-top: 32px; }
.sw-w3-flow__node + .sw-w3-flow__node::before {
	content: "";
	position: absolute;
	top: -32px;
	left: 33px;
	height: 32px;
	border-left: 2px dashed var(--sw-blue-600);
}
.sw-w3-flow__icon {
	display: grid;
	place-items: center;
	flex: 0 0 auto;
	width: 36px;
	height: 36px;
	border-radius: 9px;
	background: rgba(8, 82, 150, 0.5);
	color: var(--sw-blue-200);
}
.sw-w3-flow__label { font-size: 14.5px; font-weight: 600; color: var(--sw-white); }

/* ---- 9. final CTA --------------------------------------------------------
   The panel is the ROW — .sw-h2-panel--grad (§35) carries gradient, radius and
   padding. Only the pending state of the WhatsApp button is new. */
.et_pb_row.sw-w3-cta__panel { align-items: center; }
.sw-btn--pending.et_pb_button { cursor: not-allowed; opacity: 0.55; }

/* ---- responsive ---------------------------------------------------------- */
@media (max-width: 980px) {
	.et_pb_section.sw-w3-hero { padding: 88px 0; }
	.et_pb_section.sw-w3-build,
	.et_pb_section.sw-w3-perf,
	.et_pb_section.sw-w3-tech,
	.et_pb_section.sw-w3-work,
	.et_pb_section.sw-w3-cap,
	.et_pb_section.sw-w3-proc,
	.et_pb_section.sw-w3-auto,
	.et_pb_section.sw-w3-cta { padding: 76px 0; }

	.sw-w3-hero__title h1 { font-size: 42px; letter-spacing: -1px; }
	.sw-w3-head h2 { font-size: 30px; }
	.sw-w3-perf__title h2,
	.sw-w3-work__title h2,
	.sw-w3-auto__title h2 { font-size: 29px; }

	/* Hero, performance, automation, capabilities and the CTA all stack. */
	.et_pb_row.sw-w3-hero__row,
	.et_pb_row.sw-w3-perf__row,
	.et_pb_row.sw-w3-auto__row,
	.et_pb_row.sw-w3-cta__panel { align-items: stretch; }

	/* §27 adds `gap: 24px` to every row below 980px while the gutter is ALSO a
	   right margin. Two columns at 48.75% plus a 2.5% margin already sum to
	   100%, so the extra 24px overflowed and every grid on this page collapsed
	   to ONE card per line with the other half of the band empty. Measured at
	   980px, not assumed.

	   This page does its stacking arithmetic in margins, like the desktop
	   layout above, so the gap is zeroed for its own rows. Compound form
	   because §27's rule is (0,2,0); it is inert in an export, which has no
	   .sw-divi wrapper and therefore never gets the gap. */
	.et_pb_row.sw-w3-hero__row,
	.et_pb_row.sw-w3-build__row,
	.et_pb_row.sw-w3-perf__row,
	.et_pb_row.sw-w3-work__row,
	.et_pb_row.sw-w3-cap__row,
	.et_pb_row.sw-w3-proc__row,
	.et_pb_row.sw-w3-auto__row,
	.et_pb_row.sw-w3-cta__panel { gap: 0; }
	.sw-w3-hero__row > .et_pb_column,
	.sw-w3-perf__row > .et_pb_column,
	.sw-w3-auto__row > .et_pb_column,
	.sw-w3-cap__row > .et_pb_column,
	.sw-w3-cta__panel > .et_pb_column { width: 100%; margin-right: 0; }
	.sw-w3-hero__art { margin-top: 52px; }
	/* The cap goes on .sw-w3-mock, not on the browser inside it: the mock is the
	   positioning context for the absolutely-placed phone, so capping only the
	   browser left the phone pinned to the far right of a full-width column,
	   floating on its own with 300px of navy between them. */
	.sw-w3-mock { max-width: 520px; margin: 0 auto; }
	.sw-w3-hero__title h1,
	.sw-w3-hero__lede p { max-width: none; }

	/* Copy leads in both split bands; the visual follows it. */
	.sw-w3-perf__left { order: 2; margin-top: 32px; }
	.sw-w3-perf__copy { order: 1; }
	/* Compound with .et_pb_row .et_pb_column and !important, because Divi's
	   `.et_pb_row .et_pb_column.et-last-child { margin-right: 0 !important }`
	   is (0,3,0) !important and kills the auto right margin — so the diagram
	   sat hard left instead of centred once the row stacked. Same rule that
	   pushed the homepage hero 190px off centre in an earlier session; it went
	   unnoticed here until cascade-audit named it. */
	.et_pb_row .et_pb_column.sw-w3-auto__art { order: 2; margin: 40px auto 0 !important; max-width: 420px; }
	.sw-w3-auto__copy { order: 1; }
	.sw-w3-cap__panel + .sw-w3-cap__panel { margin-top: 24px; }

	/* Projects 4-across to 2, tech tiles 7 to 4.
	   The six service cards STAY 3-across here. Two rows of three cannot make a
	   clean 2-across grid: each row container lays out 2 + 1, so the band reads
	   2, 1, 2, 1 with a hole beside every third card. Measured at 980px in both
	   the template and the export before choosing this. */
	.sw-w3-build__row > .et_pb_column { width: 31.666%; margin-right: 2.5%; margin-bottom: 24px; }
	.sw-w3-build__row > .et_pb_column:nth-child(3n) { margin-right: 0; }
	.sw-w3-build__row:last-of-type > .et_pb_column { margin-bottom: 0; }
	.sw-w3-work__row > .et_pb_column { width: 48.75%; margin-right: 2.5%; margin-bottom: 24px; }
	.sw-w3-work__row > .et_pb_column:nth-child(2n) { margin-right: 0; }
	.sw-w3-techgrid ul { grid-template-columns: repeat(4, 1fr); }

	/* Process goes 2-across; connectors are meaningless once wrapped. */
	.sw-w3-proc__row > .et_pb_column { width: 48.75%; margin-right: 2.5%; margin-bottom: 36px; }
	.sw-w3-proc__row > .et_pb_column:nth-child(2n) { margin-right: 0; }
	.sw-w3-proc .sw-pstep__link { display: none; }
}

@media (max-width: 767px) {
	.et_pb_section.sw-w3-hero { padding: 72px 0; }
	.et_pb_section.sw-w3-build,
	.et_pb_section.sw-w3-perf,
	.et_pb_section.sw-w3-tech,
	.et_pb_section.sw-w3-work,
	.et_pb_section.sw-w3-cap,
	.et_pb_section.sw-w3-proc,
	.et_pb_section.sw-w3-auto,
	.et_pb_section.sw-w3-cta { padding: 60px 0; }

	.sw-w3-hero__title h1 { font-size: 34px; letter-spacing: -0.8px; }
	.sw-w3-head h2 { font-size: 26px; }
	.sw-w3-head { margin-bottom: 32px !important; }
	.sw-w3-perf__title h2,
	.sw-w3-work__title h2,
	.sw-w3-auto__title h2 { font-size: 25px; }

	/* Full-width buttons, and the hero pair stops sitting side by side. */
	.sw-w3-hero__copy > .et_pb_button_module_wrapper { display: block; margin: 0 0 10px; }
	.sw-w3-hero__copy .et_pb_button,
	.sw-w3-cta__panel .et_pb_button { width: 100%; justify-content: center; }

	.sw-w3-hero__points ul { gap: 10px 18px; }
	.sw-w3-mock__phone { right: -2px; bottom: -26px; width: 100px; }

	.sw-w3-build__row > .et_pb_column,
	.sw-w3-work__row > .et_pb_column,
	.sw-w3-proc__row > .et_pb_column { width: 100%; margin-right: 0; }
	.sw-w3-techgrid ul { grid-template-columns: repeat(2, 1fr); }
	.sw-w3-scores__rings { grid-template-columns: repeat(2, 1fr); gap: 20px 14px; }
	.sw-w3-chips { grid-template-columns: 1fr; }
	.sw-w3-work__headinner { flex-direction: column; align-items: flex-start; gap: 14px; }
	.sw-w3-cap__panel { padding: 24px 20px; }
}

/* ===========================================================================
   38. Our Work v2  —  templates/page-our-work-v2.php
   ---------------------------------------------------------------------------
   Only this page's own blocks. Everything shared is reused rather than
   restated: .sw-card--project / .sw-project-* (§6), .sw-check-list / .sw-check
   (§16, both need the .sw-page ancestor each section carries), .sw-pstep*
   (§35), .sw-btn* (§2, §27), .sw-eyebrow, .sw-grad-text, .sw-card-more (§3).

   Section classes are new (sw-ow2-*) rather than reusing v1's .sw-ow-*, so
   restyling this page cannot change the page already built — /our-work/ is
   still on page-our-work.php with its own §21.

   Bare selectors, so the same rules serve the PHP template and an export.
   Section PADDING uses the compound `.et_pb_section.sw-ow2-*` form: Divi's own
   `.et_pb_section { padding: 54px 0 }` is (0,1,0) and loads after this
   stylesheet, so a bare class loses the tie.

   NO METRICS ON THIS PAGE, BY DESIGN. v1 carries six unevidenced figures
   (200+ projects, 98% satisfaction, $2M+ saved …) flagged in its own header as
   DO NOT SHIP. The redesign drops them entirely; §04's result beat states a
   mechanism instead. Do not reintroduce a number here without a measurement.
   =========================================================================== */

/* ---- section surfaces and rhythm ----------------------------------------
   MIGRATED TO SECTION 41. Ten rules of background + padding, and their two
   responsive restatements, used to live here. The sections now carry
   `sw-band sw-band--<surface>` and inherit all of it:

       hero  sw-band--dark sw-band--tall    (navy-900, 112px)
       feat  sw-band--light                 (--sw-light, 96px)
       web   sw-band--white
       psr   sw-band--light
       work  sw-band--white
       proc  sw-band--tint                  (--sw-blue-25 — a half-step lighter
             than --light, so a third light band in a row does not read as the
             same slab as the one above it)
       cta   sw-band--tight sw-band--darkest (navy-950, 72px)

   Eyebrow size and colour moved with them: section 41 sets 13px / 1.6px and
   picks the colour off the surface class, which is what the six rules deleted
   from here were doing by hand. */

/* ---- layout scaffolding -------------------------------------------------
   Divi's OWN stylesheet is not enqueued on a page template — only the child
   theme's — so there is no `.et_pb_row { margin: 0 auto }` and no column
   widths to inherit. §34 emulates both, but every rule is scoped `.sw-divi`,
   so each section here carries `sw-divi` beside `sw-page` and each row carries
   the plain `sw-row` that §34 sizes. Drop either and the page renders as one
   full-bleed stack with no columns at all.

   This matters only for the PHP template. In an export Divi 5 generates its
   own `et_flex_column_<n>_24` widths and never emits `et_pb_column_1_4`, so
   §34's emulation simply stops matching and nothing fights.

   3_4 is the one fraction §34 does not define (it has 4_4, 3_5, 2_5, 1_2, 1_3,
   1_4, 1_5, 1_6). 74.375% = 100 - 23.125 - 2.5, i.e. the 1_4 width and one
   gutter, so the pair sums exactly like every other Divi split. */
.sw-divi .et_pb_column_3_4 { width: 74.375%; }

/* Wider than §34's 90%/1240px, for the card rows. Same specificity as
   `.sw-divi .sw-row` (0,2,0) and later in the file, so it wins the tie. */
.et_pb_row.sw-ow2-row--wide { width: 92%; max-width: 1280px; }

/* Shared centred section heading block.
   Both selectors are compound, and both need to be:
   - `max-width` at (0,1,0) TIED with Divi's generated `.et_pb_row_1
     { max-width: 1240px !important }` and lost on source order, so the head
     spanned the full row instead of capping at 720px.
   - `margin-bottom` on the modules lost to Divi's gutter rule
     `.et_pb_gutters3 .et_pb_column_4_4.et_block_column .et_pb_module` at
     (0,4,0) = 2.75%, which is far wider than 12px.
   Neither shows up on the PHP template — Divi generates both only for an
   exported layout. The cascade audit named them; the eye did not. */
.et_pb_row.sw-ow2-head { max-width: 720px !important; text-align: center; margin-bottom: 44px !important; }
.sw-ow2-head .et_pb_module.et_pb_text { margin-bottom: 12px !important; }
.sw-ow2-head h2 {
	margin: 0;
	padding: 0;
	font-size: 36px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.8px;
	color: var(--sw-slate);
	text-wrap: balance;
}
.sw-ow2-head__sub p { margin: 0; font-size: 16px; line-height: 1.7; color: var(--sw-muted); }

/* Eyebrow sizing and colour: section 41, keyed off the surface class. */

/* ---- export bridge -------------------------------------------------------
   Rules that only bite in an exported layout. Harmless in the PHP template,
   where neither element exists — so one stylesheet serves both DOMs.

   1. Divi stamps `.et_pb_text_align_left` on EVERY text module. text-align on
      the row or column is inherited, and inheritance always loses to a direct
      rule, so every centred block on this page came back left-aligned on
      import. Won back at (0,3,0) per block that must be centred.

   2. Divi wraps each button module in a block-level
      `.et_pb_button_module_wrapper`. The PHP template has the anchor as a
      direct child, so `display: inline-flex` on the anchor is enough there; in
      an export the block wrapper forces each button onto its own line and the
      hero and CTA pairs stack. */
.sw-ow2-head .et_pb_text.et_pb_module,
.sw-ow2-psrcard .et_pb_text.sw-ow2-psrcard__body,
.sw-ow2-proc .sw-pstep .et_pb_text.et_pb_module { text-align: center; }
/* The category cells are cards now and read left-aligned like every other card
   on the page, so they are deliberately NOT in the centred list above. */
.sw-ow2-web__grid .et_pb_text.sw-ow2-cat { text-align: left; }

/* !important because Divi's gutter rule
   `.et_pb_gutters3 .et_pb_column_2_5.et_block_column .et_pb_module` is (0,4,0)
   and sets margin-bottom to 7.493% — a ~50px gap under the hero buttons. */
.sw-ow2-hero .et_pb_button_module_wrapper,
.sw-ow2-cta .et_pb_button_module_wrapper { display: inline-block; margin: 0 12px 10px 0 !important; }

/* The head grid places its children explicitly, and in an export the child is
   the wrapper, not the anchor — without this the link lands in row 1. */
.sw-ow2-work__headcol > .et_pb_button_module_wrapper {
	grid-column: 2;
	grid-row: 2;
	justify-self: end;
	margin: 0;
}

/* ---- shared asset placeholder -------------------------------------------
   Thirteen of this page's fourteen images do not exist yet. An Image module
   pointed at a missing file ships a broken-image icon to a live page; this
   ships a block that says what belongs there. Same decision as §37. */
.sw-ow2-ph {
	display: grid;
	place-items: center;
	aspect-ratio: 16 / 9;
	background: repeating-linear-gradient(-45deg, var(--sw-blue-50) 0 10px, var(--sw-blue-25) 10px 20px);
	border: 1px dashed var(--sw-blue-150);
	border-radius: 10px;
	font-size: 12px;
	letter-spacing: 0.4px;
	color: var(--sw-muted);
	text-align: center;
}
.sw-ow2-ph--sq { aspect-ratio: 4 / 3; }
/* The dark-surface placeholder variant was removed with the hero artwork. */
/* Inside a card the media is flush — no radius, no side borders. */
.sw-card--project .sw-ow2-ph { border-radius: 0; border-width: 0 0 1px; }

.sw-ow2-hold {
	margin: 24px 0 0 !important;
	padding: 12px 16px;
	border: 1px dashed var(--sw-blue-150);
	border-radius: 10px;
	background: var(--sw-blue-25);
}
.sw-ow2-hold p { margin: 0; font-size: 12.5px; line-height: 1.6; color: var(--sw-muted); }

/* ---- 1. hero -------------------------------------------------------------
   Split 2_5 / 3_5. The mockup's 44/54 has no Divi fraction; 40/60 is the
   closest available. Two soft light sources so the band is not a flat navy
   rectangle. */
.et_pb_section.sw-ow2-hero { position: relative; overflow: hidden; }
.sw-ow2-hero::before,
.sw-ow2-hero::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: 0;
	pointer-events: none;
	z-index: 0;
}

/* BOTH GLOWS LIVE IN ::before, as two background layers on one full-bleed box.
   A section has exactly two pseudo-elements and this page spent one on each
   glow, which left nothing for the decoration below. Collapsing them is free —
   they were only ever radial gradients — but the geometry has to be converted
   exactly, not re-eyeballed, or the band's lighting shifts:

     old: a 940x660 box at top:30px left:-220px holding `radial-gradient(circle)`
          -> centre (250px, 360px); farthest-corner radius √(470²+330²) = 574px
     old: a 780x620 box at right:-220px bottom:-300px
          -> centre (100%-170px, 100%-10px); radius √(390²+310²) = 498px

   THE GLOW STILL BLOOMS BELOW THE FOLD OF THE HEADER, which is the whole point
   and predates this change. The header is --sw-ink, rgb(4,31,56), the exact
   colour this hero starts from, so the two read as one surface only while the
   hero's first ~200px stay flat. This glow was once centred at top:-260px —
   brightest at the section's top edge — and the flat header met a lit hero on a
   hard line across the full width. The top mask now states that intent
   explicitly instead of relying on the offset alone, and it is section-relative
   because the box is full-bleed: `transparent 0, #000 150px` means what it says.
   Measured after: 0 delta across the width at the boundary. */
.sw-ow2-hero::before {
	background-image:
		radial-gradient(574px 574px at 250px 360px,
			rgba(8, 82, 150, 0.34) 0%, rgba(8, 82, 150, 0) 68%),
		radial-gradient(498px 498px at calc(100% - 170px) calc(100% - 10px),
			rgba(91, 155, 213, 0.22) 0%, rgba(91, 155, 213, 0) 68%);
	-webkit-mask-image: linear-gradient(180deg, transparent 0, #000 150px);
	mask-image: linear-gradient(180deg, transparent 0, #000 150px);
}

/* ---- hero decoration ------------------------------------------------------
   The vocabulary shared with §42 (Contact v2), §44 (Home v3) and §45 (Services
   v3): a diagonal ruling, a soft corner sweep and an outlined square.

   ::after carries the two full-bleed layers, which is what freeing it above was
   for — a row-level element cannot do this job, because the row is capped at
   1240px and centred and stops well short of the band's edges.

   THE RULING IS MASKED OFF THE CENTRE FROM THE START. Sparse diagonals plus
   centred copy is the defect that had to be fixed on Contact v2 after the fact:
   with ~3 sweeps across 1440px one lands on the headline, and a hairline
   through a title reads as a rendering artifact rather than as light.
   Tightening the spacing is NOT the fix — §42 records that attempt and it
   hatched. The same top fade keeps both layers off the header. */
.sw-ow2-hero::after {
	background-image:
		/* An over-sized ellipse whose EDGE is the curve, so only its top-left
		   arc crosses the band and what shows is one long sweep, not a blob. */
		radial-gradient(ellipse 1100px 520px at 106% 126%,
			rgba(155, 194, 229, 0.10) 0 60%, rgba(155, 194, 229, 0) 61%),
		/* A DOUBLE RULE, not a single hairline. Each sweep is a 1px line with a
		   fainter companion 7px behind it, then 452px of nothing — so the
		   spacing stays as sparse as §42 requires (denser was tried there and
		   it hatched) while each sweep reads as a drawn, deliberate mark rather
		   than as one stray line that happened to cross the band. The paired
		   rule is the language of a drawing, which is what this page is about. */
		repeating-linear-gradient(168deg,
			rgba(155, 194, 229, 0.14) 0 1px,
			transparent 1px 7px,
			rgba(155, 194, 229, 0.07) 7px 8px,
			transparent 8px 460px);
	-webkit-mask-image:
		linear-gradient(180deg, transparent 0, #000 150px, #000 74%, transparent 98%),
		radial-gradient(ellipse 42% 56% at 50% 48%, transparent 0 58%, #000 100%);
	mask-image:
		linear-gradient(180deg, transparent 0, #000 150px, #000 74%, transparent 98%),
		radial-gradient(ellipse 42% 56% at 50% 48%, transparent 0 58%, #000 100%);
	-webkit-mask-composite: source-in;
	mask-composite: intersect;
}

.sw-ow2-hero__row { position: relative; z-index: 1; }

/* THE MOTIF — a portfolio grid, and it is deliberately NOT the plain outlined
   square the other heroes carry.

   Each page's motif says something about that page, in the same ink and weight:

     Home v3      four nodes, dashed links, a branch and a merge  -> a FLOW
     Services v3  four equal tiles on a 2x2 grid, connected       -> a SET
     Our Work v2  tiles at four different sizes, masonry-packed   -> a BODY OF WORK

   The distinction between the last two is the whole point and is worth stating:
   Services' tiles are equal because the four pillars are peers, and this page's
   are unequal because projects are not — they differ in scale, and a grid of
   identical squares would say "four categories" on a page that is about a
   portfolio. A lone square said nothing at all.

   Inline SVG data URI: outlined rectangles at four sizes are what background
   gradients are worst at, and one background-image beats four stacked
   pseudo-elements the section does not have. `currentColor` does NOT resolve
   inside a data URI, so the stroke colour is stated rather than inherited.

   `visibility: visible` and `clear: none` are load-bearing: Divi ships
   `.et_block_row:after { content:""; clear:both; visibility:hidden; height:0;
   width:0 }` as its float clearfix — note `.et_block_row`, NOT `.et_pb_row`,
   which is why grepping for the latter finds nothing and looks like proof there
   is no collision. It is (0,1,0), so this rule's (0,2,0) already wins width and
   height; `visibility` is the one thing it does not contest unless stated, and
   the motif renders full-size and completely invisible. */
.et_pb_row.sw-ow2-hero__row::after {
	content: "";
	position: absolute;
	display: block;
	visibility: visible;
	clear: none;
	line-height: 0;
	top: -24px;
	right: -46px;
	width: 200px;
	height: 150px;
	background-repeat: no-repeat;
	background-size: contain;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='150' fill='none' stroke='rgba(155,194,229,0.34)' stroke-width='1'%3E%3Crect x='6' y='12' width='104' height='74' rx='6'/%3E%3Crect x='120' y='12' width='64' height='34' rx='5'/%3E%3Crect x='120' y='52' width='64' height='34' rx='5'/%3E%3Crect x='6' y='96' width='178' height='40' rx='6'/%3E%3C/svg%3E");
	pointer-events: none;
	z-index: 0;
}

/* The eyebrow becomes a pill. In a centred hero a bare 13px label floats with
   nothing to anchor it; a bordered chip gives it an edge to sit against and
   reads as a category rather than a stray line. Colour and tracking still come
   from section 41 — this only adds the shell. */
/* `--sw-border-dark` is rgba(…, 0.16), which is right for a divider but far too
   faint to describe a shape — the pill read as a smudge rather than an edge, so
   the border and fill are both carried up.

   `line-height: 1` is what makes the label sit centred. Inherited line-height
   leaves the line box taller than the glyphs, and the label is all-caps with no
   descenders, so the text hangs toward the top of that box.

   Written at (0,3,1) — `.sw-eyebrow.et_pb_module p` — because two other rules
   out-rank the obvious (0,2,1) form and both were breaking it:

     .sw-divi .et_pb_text_inner > :last-child { padding-bottom: 0 }   (0,3,0)
         zeroed the pill's BOTTOM padding, so the label sat hard against the
         bottom edge with 10px above it. That was the "not vertically centred"
         symptom, and no amount of adjusting the shorthand would have fixed it.
     .sw-band--dark .sw-eyebrow p { color: var(--sw-blue-200) }       (0,2,1)
         is section 41 and comes later in the file, so it took the colour back
         off white on a specificity tie. */
.sw-ow2-hero .sw-eyebrow.et_pb_module p {
	display: inline-block;
	padding: 10px 18px !important;
	border: 1px solid rgba(155, 194, 229, 0.32);
	border-radius: 999px;
	background: rgba(155, 194, 229, 0.11);
	color: var(--sw-white);
	line-height: 1;
}

/* Larger and tighter. The hero carries no artwork now, so the headline has to
   hold the band on its own — at 52px it sat in the middle of ~690px of navy
   with dead space above and below. `text-wrap: balance` plus the max-width
   breaks it after "Make", keeping the accent phrase whole on line two. */
.sw-ow2-hero__title h1 {
	margin: 0 0 20px;
	padding: 0;
	font-size: 60px;
	font-weight: 700;
	line-height: 1.08;
	letter-spacing: -1.6px;
	color: var(--sw-white);
	text-wrap: balance;
}
/* Centred, single column — the hero carries no artwork.
   `text-align` on the COLUMN is enough for the buttons, because Divi only
   stamps `.et_pb_text_align_left` on text MODULES, not on columns; the text
   modules are handled by `sw-center` from section 39. */
.et_pb_column.sw-ow2-hero__copy { text-align: center; }
.sw-ow2-hero__title h1 { max-width: 820px; margin-left: auto; margin-right: auto; }

/* A shorter measure than the 620px it had: centred text is harder to track
   line-to-line than left-aligned, so the line length has to come down. */
.sw-ow2-hero__lede p {
	margin: 0 auto 30px;
	font-size: 17px;
	line-height: 1.7;
	color: var(--sw-blue-200);
	max-width: 560px;
}

/* Divi modules are block-level; the hero pair sits side by side. */
.sw-ow2-hero .sw-btn.et_pb_button { display: inline-flex; margin: 0 6px; }

/* The capability line becomes a row of pills. As bare check-and-label pairs it
   read as a loose caption trailing off under the buttons; as chips it is a
   deliberate strip that closes the hero and gives the band a bottom edge. */
.sw-ow2-hero__caps { margin-top: 34px !important; }
.sw-ow2-hero__caps ul {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 10px;
	margin: 0;
	padding: 0;
	list-style: none;
}
.sw-ow2-hero__caps li {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 8px 16px;
	border: 1px solid var(--sw-border-dark);
	border-radius: 999px;
	background: rgba(155, 194, 229, 0.05);
	font-size: 13px;
	font-weight: 600;
	color: var(--sw-blue-200);
	transition: border-color 0.25s var(--sw-ease), background-color 0.25s var(--sw-ease);
}
.sw-ow2-hero__caps li:hover {
	border-color: rgba(155, 194, 229, 0.4);
	background: rgba(155, 194, 229, 0.1);
}
.sw-ow2-hero__caps svg { flex: 0 0 auto; color: var(--sw-blue-400); }

/* ---- 2. featured projects ------------------------------------------------
   THE COLUMN IS THE CARD — .sw-card--project inside .sw-row--projects (§6)
   already carries background, border, radius, overflow and hover, so there is
   no wrapper div to convert. */
.sw-ow2-feat__row > .et_pb_column { margin-bottom: 0; }
.sw-ow2-projcard__cat {
	margin: 18px 20px 0 !important;
	font-size: 11px;
	font-weight: 800;
	letter-spacing: 1.2px;
	text-transform: uppercase;
	color: var(--sw-blue-500);
}
.sw-ow2-projcard__body { padding: 8px 20px 0 !important; margin-bottom: 0 !important; flex: 0 0 auto; }
.sw-ow2-projcard__body h3 {
	margin: 0 0 8px;
	padding: 0;
	font-size: 19px;
	font-weight: 700;
	line-height: 1.3;
	letter-spacing: -0.3px;
	color: var(--sw-slate);
}
.sw-ow2-projcard__body p { margin: 0; font-size: 14px; line-height: 1.65; color: var(--sw-muted); }
.sw-ow2-projcard__feats { flex: 1 1 auto; padding: 14px 20px 0 !important; margin-bottom: 0 !important; }
.sw-ow2-projcard__feats li { font-size: 12.5px; margin-bottom: 7px; }

/* Card link styled as a link, not a slab.
   Written at (0,2,0): the base rule `.sw-page .sw-btn` sets
   `border: 1px solid transparent` at (0,2,0), so a (0,1,0) modifier would lose
   its borderless state silently — the §35 trap. Both forms listed because the
   PHP template and the export put .sw-page in different places. */
.sw-page .sw-btn--card,
.sw-btn--card.et_pb_button {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	margin: 0 20px 22px !important;
	padding: 0 !important;
	background: none !important;
	border: 0 !important;
	font-size: 13.5px;
	font-weight: 700;
	color: var(--sw-blue-600);
}
.sw-page .sw-btn--card:hover,
.sw-btn--card.et_pb_button:hover {
	transform: none;
	gap: 12px;
	color: var(--sw-blue-500);
	background: none !important;
}
/* The label already ends in an arrow; Divi's own ::after glyph would double it. */
.sw-btn--card.et_pb_button::after,
.sw-page .sw-btn--card::after { display: none !important; }

/* ---- 3. websites and digital experiences ---------------------------------
   Rows cannot nest, so the five category cells are a CSS grid on the right
   column and the five Text modules are its direct grid children. */
.sw-ow2-web__title h2 {
	margin: 0 0 14px;
	padding: 0;
	font-size: 30px;
	font-weight: 700;
	line-height: 1.22;
	letter-spacing: -0.6px;
	color: var(--sw-slate);
	text-wrap: balance;
}
.sw-ow2-web__lede p { margin: 0; font-size: 14.5px; line-height: 1.7; color: var(--sw-muted); }
.sw-ow2-web__intro .sw-btn--card { margin: 20px 0 0 !important; }

/* THREE across, not five. Five cells across a 3_4 column left ~138px of usable
   text width, so every description wrapped to three centred lines, and the
   band was the flattest on a page whose language is cards.

   Three-up in two rows fixes four things at once: each card gets ~290px, the
   two rows stand roughly as tall as the intro column beside them (which had
   been leaving ~250px of dead space under the band), the dividers go away with
   the cards replacing them, and the text can left-align like everything else.

   The dividers were the visible symptom of the real bug: the right column
   stretches to match the taller left one, and `border-left` on a stretched
   grid cell ran a 460px rule down 150px of content. Cards absorb that height
   legitimately; a hairline rule cannot. */
.et_pb_column.sw-ow2-web__grid {
	float: none;
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 16px;
	align-content: center;
}
.sw-ow2-web__grid > .et_pb_module { margin-bottom: 0 !important; }
/* Card shell, padding, radius, shadow and hover all come from .sw-card /
   .sw-card--tight in section 41 — this only sets what is specific here. */
.sw-ow2-cat svg { display: block; margin: 0 0 12px; color: var(--sw-blue-600); }
.sw-ow2-cat h3 {
	margin: 0 0 8px;
	padding: 0;
	font-size: 15px;
	font-weight: 700;
	line-height: 1.3;
	color: var(--sw-slate);
	text-wrap: balance;
}
.sw-ow2-cat p { margin: 0; font-size: 13px; line-height: 1.65; color: var(--sw-muted); }
/* Intro sits against the middle of the two card rows rather than the top. */
.et_pb_column.sw-ow2-web__intro { display: flex; flex-direction: column; justify-content: center; }

/* ---- 4. problem / solution / result --------------------------------------
   The result beat states a MECHANISM, not a number. Nothing on this page has
   been measured, and an unevidenced outcome claim is this project's stated
   single biggest risk. */
.sw-ow2-psr__title h2 {
	margin: 0 0 14px;
	padding: 0;
	font-size: 32px;
	font-weight: 700;
	line-height: 1.24;
	letter-spacing: -0.8px;
	color: var(--sw-slate);
}
.sw-ow2-psr__lede p { margin: 0; font-size: 14.5px; line-height: 1.7; color: var(--sw-muted); }
.sw-ow2-psr__intro .sw-btn--card { margin: 20px 0 0 !important; }
.sw-ow2-psr__row > .et_pb_column { margin-bottom: 0; }

.et_pb_column.sw-ow2-psrcard {
	position: relative;
	display: flex;
	flex-direction: column;
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-card-radius);
	padding: 22px 20px 24px;
	box-shadow: var(--sw-shadow-sm);
	transition: var(--sw-card-transition);
}
.et_pb_column.sw-ow2-psrcard:hover { transform: translateY(-4px); box-shadow: var(--sw-shadow-md); }
.sw-ow2-psrcard__media { margin-bottom: 14px !important; }
.sw-ow2-psrcard__body { margin-bottom: 0 !important; text-align: center; }
.sw-ow2-psrcard__label {
	margin: 0 0 12px;
	font-size: 11px;
	font-weight: 800;
	letter-spacing: 1.4px;
	text-transform: uppercase;
}
/* The only two hues on this page outside the blue ramp. They carry the
   three-beat's meaning, and appear at 11px on white only. */
.sw-ow2-psrcard--problem .sw-ow2-psrcard__label { color: #b3453c; }
.sw-ow2-psrcard--solution .sw-ow2-psrcard__label { color: var(--sw-blue-600); }
.sw-ow2-psrcard--result .sw-ow2-psrcard__label { color: #2f7d55; }
.sw-ow2-psrcard__body h3 {
	margin: 0 0 8px;
	padding: 0;
	font-size: 16px;
	font-weight: 700;
	line-height: 1.35;
	color: var(--sw-slate);
	text-wrap: balance;
}
.sw-ow2-psrcard__body p { margin: 0; font-size: 13px; line-height: 1.65; color: var(--sw-muted); }

/* A divider module cannot sit between two columns, so each arrow is a
   pseudo-element on the column to its right, positioned across the gutter. */
.sw-ow2-psr__row > .et_pb_column.sw-ow2-psrcard--solution::before,
.sw-ow2-psr__row > .et_pb_column.sw-ow2-psrcard--result::before {
	content: "\2192";
	position: absolute;
	top: 50%;
	left: -30px;
	transform: translateY(-50%);
	font-size: 20px;
	line-height: 1;
	color: var(--sw-blue-400);
	pointer-events: none;
}

/* ---- 5. selected website work -------------------------------------------- */
.sw-ow2-work__head { margin-bottom: 40px !important; }
/* Grid on the COLUMN, not a wrapper div — a wrapper has no equivalent in an
   export. Children placed explicitly so a wpautop empty <p> cannot shift them. */
.et_pb_column.sw-ow2-work__headcol {
	display: grid;
	float: none;
	grid-template-columns: minmax(0, 1fr) auto;
	align-items: end;
	column-gap: 24px;
}
.sw-ow2-work__headcol > .sw-eyebrow { grid-column: 1; grid-row: 1; margin-bottom: 6px; }
.sw-ow2-work__headcol > .sw-ow2-work__title { grid-column: 1; grid-row: 2; margin-bottom: 0; }
.sw-ow2-work__headcol > .sw-ow2-work__all { grid-column: 2; grid-row: 2; justify-self: end; }
.sw-ow2-work__headcol > p:empty { display: none; }
.sw-ow2-work__title h2 {
	margin: 0;
	padding: 0;
	font-size: 34px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.8px;
	color: var(--sw-slate);
}
.sw-ow2-work__all { margin: 0 !important; white-space: nowrap; }
.sw-ow2-work__row > .et_pb_column { margin-bottom: 0; }

.sw-ow2-workcard__head { padding: 16px 16px 0 !important; margin-bottom: 0 !important; }
.sw-ow2-workcard__head h3 {
	margin: 0 0 6px;
	padding: 0;
	font-size: 15.5px;
	font-weight: 700;
	line-height: 1.3;
	color: var(--sw-slate);
}
.sw-ow2-workcard__cat { margin: 0; font-size: 11.5px; font-weight: 600; letter-spacing: 0.3px; color: var(--sw-blue-500); }
.sw-ow2-workcard__desc { padding: 10px 16px 18px !important; margin-bottom: 0 !important; }
.sw-ow2-workcard__desc p { margin: 0; font-size: 12.5px; line-height: 1.6; color: var(--sw-muted); }

/* Whole card clickable. Divi cannot wrap a column in an anchor, so the media
   link is stretched over the column instead — one link per card, which is also
   the right accessibility outcome. */
.et_pb_column.sw-ow2-workcard { position: relative; }
.sw-ow2-workcard .sw-ow2-workcard__media a::after { content: ""; position: absolute; inset: 0; z-index: 2; }
.sw-ow2-workcard:focus-within { outline: 2px solid var(--sw-blue-400); outline-offset: 3px; }
.sw-ow2-workcard__media { margin-bottom: 0 !important; }

/* ---- 6. how we work ------------------------------------------------------
   Six real 1_6 columns — exactly Divi's ceiling — so .sw-pstep is the COLUMN
   rather than a div inside a Text module. §35's .sw-pstep* rules still apply.
   No icons and no .sw-pstep__badge disc on this page: the number carries the
   whole visual weight. */
.sw-ow2-proc__head { margin-bottom: 44px !important; }
.sw-ow2-proc__head h2 {
	margin: 0;
	padding: 0;
	font-size: 34px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.8px;
	color: var(--sw-slate);
}
.sw-ow2-proc__row > .et_pb_column { margin-bottom: 0; }
.sw-ow2-proc .sw-pstep { position: relative; text-align: center; padding: 0 10px; }
.sw-ow2-proc .sw-pstep > .et_pb_module { margin-bottom: 0; }

/* §35 sets .sw-pstep__num at 13px/800 for the badge layout. This page has no
   badge — the number IS the mark, so it goes large. (0,2,0) beats (0,1,0). */
.sw-ow2-proc .sw-pstep__num {
	margin: 0 0 12px;
	font-size: 30px;
	font-weight: 800;
	line-height: 1;
	letter-spacing: -0.5px;
	color: var(--sw-blue-400);
}
.sw-ow2-proc .sw-pstep__head { margin-bottom: 0 !important; }
.sw-ow2-proc .sw-pstep__head h3 {
	margin: 0 0 8px;
	padding: 0;
	font-size: 15px;
	font-weight: 700;
	line-height: 1.3;
	letter-spacing: -0.2px;
	color: var(--sw-slate);
}
.sw-ow2-proc .sw-pstep__head p { margin: 0; font-size: 12.5px; line-height: 1.65; color: var(--sw-muted); }

/* Arrow connectors and vertical rules, per the mockup.
   Written COMPOUND (`.et_pb_column.sw-pstep`), not descendant: the column IS
   the step here, and an element is not its own ancestor — the descendant form
   matches nothing and both connectors silently vanish. */
.sw-ow2-proc__row > .et_pb_column.sw-pstep:not(:first-child)::before {
	content: "\2192";
	position: absolute;
	top: 6px;
	left: -14px;
	font-size: 15px;
	line-height: 1;
	color: var(--sw-blue-300);
	pointer-events: none;
}
.sw-ow2-proc__row > .et_pb_column.sw-pstep:not(:first-child)::after {
	content: "";
	position: absolute;
	top: 0;
	bottom: 0;
	left: -2px;
	border-left: 1px solid var(--sw-border-light);
}

/* ---- 7. final CTA -------------------------------------------------------- */
.et_pb_section.sw-ow2-cta { position: relative; overflow: hidden; }
.sw-ow2-cta::after {
	content: "";
	position: absolute;
	top: 0;
	right: 0;
	width: 340px;
	height: 100%;
	background-image: radial-gradient(rgba(155, 194, 229, 0.16) 1px, transparent 1px);
	background-size: 14px 14px;
	pointer-events: none;
}
.sw-ow2-cta__row { position: relative; z-index: 1; }
.sw-ow2-cta__mark { margin-bottom: 0 !important; }
.sw-ow2-cta__mark img { width: 92px; height: auto; display: block; }
.sw-ow2-cta__title h2 {
	margin: 0 0 10px;
	padding: 0;
	font-size: 30px;
	font-weight: 700;
	line-height: 1.24;
	letter-spacing: -0.8px;
	color: var(--sw-white);
	text-wrap: balance;
}
.sw-ow2-cta__lede p { margin: 0; font-size: 14.5px; line-height: 1.75; color: var(--sw-blue-200); }
.sw-ow2-cta .sw-btn.et_pb_button { display: inline-flex; margin: 0 10px 10px 0; }
.sw-ow2-cta__points { margin-top: 34px !important; padding-top: 22px; border-top: 1px solid var(--sw-border-dark); }
.sw-ow2-cta__points ul {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 10px 34px;
	margin: 0;
	padding: 0;
	list-style: none;
}
.sw-ow2-cta__points li {
	display: flex;
	align-items: center;
	gap: 8px;
	font-size: 13px;
	font-weight: 600;
	color: var(--sw-blue-200);
}
.sw-ow2-cta__points svg { flex: 0 0 auto; color: var(--sw-blue-400); }

/* ---- tablet -------------------------------------------------------------- */
@media (max-width: 980px) {
	/* Section padding: section 41. */
	.sw-ow2-hero__title h1 { font-size: 44px; letter-spacing: -1.1px; }
	.sw-ow2-hero__lede p { font-size: 16px; }
	.sw-ow2-head h2,
	.sw-ow2-work__headinner h2,
	.sw-ow2-proc__head h2 { font-size: 30px; }
	.sw-ow2-psr__title h2 { font-size: 28px; }
	.sw-ow2-cta__title h2 { font-size: 26px; }

	/* Hero: copy first, graphic below — the diagram is not the entry point. */
	/* One column now, so no stacking gap to add. */
	.sw-ow2-hero__row > .et_pb_column { width: 100%; margin: 0; }

	/* The outlined square comes off: the row narrows to the copy's own measure
	   here, so it would sit on the text rather than beside it. The ruling and
	   curve stay — they are full-bleed and already masked away from the centre. */
	.et_pb_row.sw-ow2-hero__row::after { display: none; }

	/* 4 -> 2 */
	.sw-ow2-feat__row > .et_pb_column { width: 48.75%; margin-right: 2.5%; margin-bottom: 24px; }
	.sw-ow2-feat__row > .et_pb_column:nth-child(2n) { margin-right: 0; }

	/* Split stacks. The card grid is already 3-up at desktop, so it stays. */
	.sw-ow2-web__row > .et_pb_column { width: 100%; margin: 0 0 32px; }

	/* Intro full width; the three cards keep their row. */
	.sw-ow2-psr__row > .et_pb_column.sw-ow2-psr__intro { width: 100%; margin-right: 0; margin-bottom: 28px; }
	.sw-ow2-psr__row > .et_pb_column.sw-ow2-psrcard { width: 30.66%; margin-right: 4%; }
	.sw-ow2-psr__row > .et_pb_column.sw-ow2-psrcard--result { margin-right: 0; }

	/* 5 -> 3, so the last two wrap to a second line. */
	.sw-ow2-work__row > .et_pb_column { width: 30.66%; margin-right: 4%; margin-bottom: 24px; }
	.sw-ow2-work__row > .et_pb_column:nth-child(3n) { margin-right: 0; }

	/* 6 -> 3. Connectors and rules die at the wrap, so drop both. */
	.sw-ow2-proc__row > .et_pb_column { width: 30.66%; margin-right: 4%; margin-bottom: 30px; }
	.sw-ow2-proc__row > .et_pb_column:nth-child(3n) { margin-right: 0; }
	.sw-ow2-proc__row > .et_pb_column.sw-pstep::before,
	.sw-ow2-proc__row > .et_pb_column.sw-pstep::after { display: none; }

	.sw-ow2-cta__row > .et_pb_column { width: 100%; margin: 0 0 22px; }
	.sw-ow2-cta::after { display: none; }
}

/* ---- phone --------------------------------------------------------------- */
@media (max-width: 767px) {
	/* Section padding: section 41. */
	.sw-ow2-hero__title h1 { font-size: 33px; letter-spacing: -0.7px; line-height: 1.14; }
	.sw-ow2-hero__lede p { font-size: 15.5px; }
	/* Pills get tighter rather than wrapping to four rows on a 375px screen. */
	.sw-ow2-hero__caps ul { gap: 8px; }
	.sw-ow2-hero__caps li { padding: 7px 12px; font-size: 12px; }
	.sw-ow2-head h2,
	.sw-ow2-work__headinner h2,
	.sw-ow2-proc__head h2,
	.sw-ow2-psr__title h2 { font-size: 25px; letter-spacing: -0.5px; }
	.sw-ow2-cta__title h2 { font-size: 23px; }

	.sw-ow2-feat__row > .et_pb_column,
	.sw-ow2-psr__row > .et_pb_column,
	.sw-ow2-proc__row > .et_pb_column { width: 100%; margin-right: 0; margin-bottom: 20px; }

	.et_pb_column.sw-ow2-web__grid { grid-template-columns: minmax(0, 1fr); }

	.sw-ow2-work__row > .et_pb_column { width: 48.75%; margin-right: 2.5%; }
	.sw-ow2-work__row > .et_pb_column:nth-child(2n) { margin-right: 0; }

	/* Arrows point down once the cards stack. */
	.sw-ow2-psr__row > .et_pb_column.sw-ow2-psrcard--solution::before,
	.sw-ow2-psr__row > .et_pb_column.sw-ow2-psrcard--result::before {
		content: "\2193";
		top: auto;
		bottom: -22px;
		left: 50%;
		transform: translateX(-50%);
	}

	/* Full-width buttons need the export's wrapper to go full width too. */
	.sw-ow2-hero .et_pb_button_module_wrapper,
	.sw-ow2-cta .et_pb_button_module_wrapper { display: block; margin: 0 0 12px; }
	.sw-ow2-hero .sw-btn.et_pb_button,
	.sw-ow2-cta .sw-btn.et_pb_button { width: 100%; margin: 0 0 12px !important; justify-content: center; }
	/* Only the CTA has a link-style button; the hero's pair are both real
	   buttons, so the hero half of this guard was dead. */
	.sw-ow2-cta .sw-btn--card.et_pb_button { width: auto; }
	.et_pb_column.sw-ow2-work__headcol { grid-template-columns: minmax(0, 1fr); row-gap: 14px; }
	.sw-ow2-work__headcol > .sw-ow2-work__all { grid-column: 1; grid-row: 3; justify-self: start; }
	.sw-ow2-cta__points ul { justify-content: flex-start; gap: 10px 22px; }
}

/* ===========================================================================
   39. Divi export bridge — shared
   ---------------------------------------------------------------------------
   Rules that exist because of how DIVI builds an exported layout, not because
   of any one page's design. They were derived twice, per page, before this
   section existed; each is structural and will apply to every future export.

   All of it is inert in a PHP template, where neither element exists — so one
   stylesheet keeps serving both DOMs.

   OPT-IN, by class. Nothing here fires on its own: a page adds `sw-center` to
   a text module it wants centred, or `sw-btn-inline` to a button row that must
   not stack. Making it automatic would mean guessing from naming conventions,
   which is how a rule ends up firing on a page nobody tested.

   Section 38 (Our Work v2) predates this block and states the same two fixes
   against its own classes. It is left alone deliberately — that page is
   verified end to end, and re-pointing it at these classes would mean editing
   fifteen modules and re-running the whole render test to prove nothing
   changed. New pages should use the classes below instead.
   =========================================================================== */

/* ---- 1. centring ---------------------------------------------------------
   Divi stamps `.et_pb_text_align_left` on EVERY text module. text-align set on
   a row or column is INHERITED, and inheritance always loses to a direct rule,
   so any block centred via its parent comes back left-aligned on import.

   Won back at (0,2,0) on the module itself. Both forms are listed because the
   class may sit on the module or on an ancestor the page controls. */
.et_pb_text.sw-center,
.sw-center > .et_pb_text.et_pb_module { text-align: center; }
/* A heading module is `.et_pb_heading > .et_pb_heading_container > h<n>`, NOT
   `.et_pb_text`, so the arm above misses it entirely and a centred band heading
   imports left-aligned while the eyebrow above it centres correctly — which
   reads as a spacing bug rather than an alignment one. Added when Home v3's
   headings moved from text modules to divi/heading. */
.et_pb_heading.sw-center,
.sw-center > .et_pb_heading.et_pb_module { text-align: center; }

/* A BUTTON is not a text module, so the rule above never reached it and a
   centred section would still show a left-aligned button. Divi wraps each one
   in a block-level `.et_pb_button_module_wrapper`, which `text-align` cannot
   move — it has to become inline-block first, and then the column's own
   centring applies to it like any other inline box. */
.sw-center { text-align: center; }
.sw-center > .et_pb_button_module_wrapper { display: inline-block; }

.et_pb_text.sw-left,
.sw-left > .et_pb_text.et_pb_module { text-align: left; }

/* ---- 2. button wrappers --------------------------------------------------
   Divi wraps each button module in a block-level
   `.et_pb_button_module_wrapper`. In a PHP template the anchor is a direct
   child, so `display: inline-flex` on the anchor is enough; in an export the
   wrapper puts one button per line and every side-by-side pair breaks.

   The wrapper also defeats explicit grid placement — a rule written
   `.my-head > .my-button` no longer matches the grid child, so the button
   lands in the wrong cell. Place the WRAPPER, not the anchor. */
/* The margins are !important because Divi's own gutter rule —
   `.et_pb_gutters3 .et_pb_column_<type>.et_block_column .et_pb_module` — is
   (0,4,0) and sets margin-bottom as a PERCENTAGE of the column (7.5% in a 2_5,
   9.3% in a 1_3). Without this a button row carries a ~50px gap underneath it
   that exists in the export and nowhere else. */
.sw-btn-inline .et_pb_button_module_wrapper { display: inline-block; margin: 0 12px 10px 0 !important; }
.sw-btn-inline .et_pb_button_module_wrapper:last-child { margin-right: 0 !important; }

/* Full-width buttons need the wrapper to go full width too, or the anchor
   stretches inside a shrink-wrapped inline-block and nothing appears to change. */
.sw-btn-block .et_pb_button_module_wrapper { display: block; margin: 0 0 12px !important; }
.sw-btn-block .et_pb_button.et_pb_module { width: 100%; justify-content: center; }

/* ---- 3. doubled arrows ---------------------------------------------------
   Divi appends its own glyph via .et_pb_button::after. A label that already
   ends in an arrow renders two. Entities are a separate trap: `&rarr;` inside
   a Divi ATTRIBUTE value renders literally, so an exported button label must
   carry the real character. */
.sw-btn-noglyph.et_pb_button::after,
.sw-page .sw-btn-noglyph::after { display: none !important; }

/* ---- 4. asset placeholder ------------------------------------------------
   Emitted by sw_dom_placeholder(). Every page so far has shipped with more
   images missing than present, and an Image module pointed at a file that does
   not exist puts a broken-image icon on a live page. This says what belongs
   there instead. Section 38's .sw-ow2-ph is the same thing, page-scoped. */
.sw-ph {
	display: grid;
	place-items: center;
	aspect-ratio: 16 / 9;
	background: repeating-linear-gradient(-45deg, var(--sw-blue-50) 0 10px, var(--sw-blue-25) 10px 20px);
	border: 1px dashed var(--sw-blue-150);
	border-radius: 10px;
	font-size: 12px;
	letter-spacing: 0.4px;
	color: var(--sw-muted);
	text-align: center;
}
.sw-ph--sq { aspect-ratio: 4 / 3; }
.sw-ph--wide { aspect-ratio: 16 / 10; }
/* On a dark band the light hatch glares. */
.sw-section--dark .sw-ph,
.sw-ph--dark {
	border-color: var(--sw-border-dark);
	color: var(--sw-blue-200);
	background: repeating-linear-gradient(-45deg, rgba(155, 194, 229, 0.07) 0 10px, rgba(155, 194, 229, 0.03) 10px 20px);
}
/* Inside a card the media is flush — no radius, no side borders. */
.sw-card--project .sw-ph { border-radius: 0; border-width: 0 0 1px; }

/* ---- 5. wpautop phantom children ----------------------------------------
   Divi runs module content through wpautop, which can inject an empty <p>.
   Inside a grid or flex container laid out by implicit order that phantom is a
   real child and shifts every sibling along one slot. Any container whose
   children come from module content wants this plus explicit placement. */
.sw-grid > p:empty,
.sw-center > p:empty,
.sw-btn-inline > p:empty { display: none; }

/* ===========================================================================
   40. AI Invoice Processing v2  —  page "ai-invoice-processing-v2" (Divi layout)
   ---------------------------------------------------------------------------
   Built with pipeline v2: authored as Divi blocks and installed onto a page,
   not rendered from a PHP template. There is no page-ai-invoice-processing-v2
   .php — the spec at templates/jsonimports/ai-invoice-v2.spec.json is the
   source of truth.

   New namespace sw-inv2-*, NOT the sw-inv-* of section 29 — that page is live
   at /ai-invoice/ and /ai-invoice-processing/ and restyling it must not be a
   side effect of building this one.

   Shared components are reused rather than restated: .sw-svc-card (§16),
   .sw-check-list / .sw-check (§16, need the .sw-page ancestor each section
   carries), .sw-pstep* (§35), .sw-btn*, .sw-eyebrow, .sw-grad-text, .sw-tint--*
   discs (§19), and the export bridge classes in §39.

   THE BIG DECISION, recorded here because it shapes every band:
   the brief asked for ~13 "one designed image" graphics. None of those files
   exist, and a page of thirteen placeholder boxes cannot ship. Looking at the
   mockup, almost every one of them is structurally a CARD GRID — icons plus
   labels plus checklists — not an illustration. Those are built natively here,
   one Text module holding the whole grid, which keeps the brief's module COUNT
   while making the content real text: indexable, translatable, screen-readable,
   and shippable today. Only genuinely diagrammatic pieces would need artwork,
   and none were left that a flow of boxes cannot express honestly.

   NO METRICS ANYWHERE ON THIS PAGE. Invoice automation is exactly the subject
   where a fabricated "80% faster" is most tempting and most damaging. Every
   claim here describes a mechanism.
   =========================================================================== */

/* ---- surfaces and rhythm ------------------------------------------------- */
.et_pb_section.sw-inv2-hero  { background-color: var(--sw-navy-900); padding: 104px 0; }
.et_pb_section.sw-inv2-prob  { background-color: var(--sw-light); padding: 88px 0; }
.et_pb_section.sw-inv2-sol   { background-color: var(--sw-blue-25); padding: 88px 0; }
.et_pb_section.sw-inv2-data  { background-color: var(--sw-white); padding: 88px 0; }
.et_pb_section.sw-inv2-logic { background-color: var(--sw-light); padding: 88px 0; }
.et_pb_section.sw-inv2-conn  { background-color: var(--sw-white); padding: 88px 0; }
.et_pb_section.sw-inv2-e2e   { background-color: var(--sw-blue-25); padding: 88px 0; }
.et_pb_section.sw-inv2-bene  { background-color: var(--sw-white); padding: 88px 0; }
.et_pb_section.sw-inv2-fit   { background-color: var(--sw-light); padding: 88px 0; }
.et_pb_section.sw-inv2-cta   { background-color: var(--sw-navy-950); padding: 72px 0; }

/* Eyebrows: blue-500 on light bands, blue-200 on dark. */
.sw-inv2-prob .sw-eyebrow p, .sw-inv2-sol .sw-eyebrow p, .sw-inv2-data .sw-eyebrow p,
.sw-inv2-logic .sw-eyebrow p, .sw-inv2-conn .sw-eyebrow p, .sw-inv2-e2e .sw-eyebrow p,
.sw-inv2-bene .sw-eyebrow p, .sw-inv2-fit .sw-eyebrow p {
	font-size: 12px; letter-spacing: 1.6px; color: var(--sw-blue-500);
}
.sw-inv2-hero .sw-eyebrow p, .sw-inv2-cta .sw-eyebrow p {
	font-size: 12px; letter-spacing: 1.6px; color: var(--sw-blue-400);
}

/* Shared heading scale. h2 is 30px here, not 36px: this page has ten headings
   and several sit in half-width columns, where 36px wraps to three lines. */
.sw-inv2-h2 h2 {
	margin: 0 0 14px; padding: 0;
	font-size: 30px; font-weight: 700; line-height: 1.22;
	letter-spacing: -0.7px; color: var(--sw-slate); text-wrap: balance;
}
.sw-inv2-lede p { margin: 0 0 12px; font-size: 14.5px; line-height: 1.75; color: var(--sw-muted); }
.sw-inv2-lede p:last-child { margin-bottom: 0; }

/* MODULE-LEVEL spacing, and it has to be here rather than on the inner element.
   Section 27 sets `.sw-divi .et_pb_text_inner > :last-child { margin-bottom: 0 }`
   at (0,3,0) — every heading and lede is the last child of its own text module,
   so its bottom margin was being zeroed and the page had no vertical rhythm at
   all. Putting the gap on the module instead sidesteps that; !important is for
   Divi's gutter rule `.et_pb_gutters3 .et_pb_column_<t> .et_pb_module`, which is
   (0,4,0) and sets margin-bottom as a percentage of the column.

   Targeted at the prose modules only. A blanket
   `.sw-inv2-row .et_pb_module.et_pb_text` was tried first and was worse: at
   (0,3,0) with !important it out-ranked every component's own
   `margin-bottom: 0`, so the grids and the process badges silently gained 14px
   they had explicitly set to zero. Components that manage their own spacing
   already do so with !important at (0,1,0), which beats Divi's gutter rule
   without needing to be listed here. */
.sw-inv2-row .sw-inv2-h2.et_pb_module,
.sw-inv2-row .sw-inv2-lede.et_pb_module,
.sw-inv2-row .sw-inv2-hero__title.et_pb_module,
.sw-inv2-row .sw-inv2-hero__lede.et_pb_module,
.sw-inv2-row .sw-inv2-cta__title.et_pb_module,
.sw-inv2-row .sw-inv2-cta__lede.et_pb_module { margin-bottom: 14px !important; }
.sw-inv2-row .sw-eyebrow.et_pb_module { margin-bottom: 8px !important; }
.sw-inv2-row .sw-inv2-cta__lede.et_pb_module:last-child { margin-bottom: 0 !important; }

/* Reusable card shell for every grid on this page. */
.sw-inv2-card {
	display: flex; flex-direction: column;
	padding: 18px 16px 20px;
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: 12px;
	box-shadow: var(--sw-shadow-sm);
	transition: var(--sw-card-transition);
}
.sw-inv2-card:hover { transform: translateY(-3px); box-shadow: var(--sw-shadow-md); }
.sw-inv2-card svg { color: var(--sw-blue-600); margin-bottom: 10px; }
.sw-inv2-card h3 {
	margin: 0 0 6px; padding: 0;
	font-size: 14px; font-weight: 700; line-height: 1.3;
	color: var(--sw-slate); text-wrap: balance;
}
.sw-inv2-card p { margin: 0; font-size: 12.5px; line-height: 1.6; color: var(--sw-muted); }

/* ---- 1. hero -------------------------------------------------------------
   The right half is the brief's "Invoice Workflow Diagram". It is six labelled
   boxes with arrows — a card grid, so it is built as one, on the dark surface. */
.et_pb_section.sw-inv2-hero { position: relative; overflow: hidden; }
.sw-inv2-hero::before {
	content: ""; position: absolute; top: -280px; left: -180px;
	width: 940px; height: 720px; border-radius: 50%; pointer-events: none;
	background: radial-gradient(circle, rgba(8, 82, 150, 0.4) 0%, rgba(8, 82, 150, 0) 66%);
}
.sw-inv2-hero__row { position: relative; z-index: 1; }
.sw-inv2-hero__title h1 {
	margin: 0 0 18px; padding: 0;
	font-size: 44px; font-weight: 700; line-height: 1.14;
	letter-spacing: -1.1px; color: var(--sw-white); text-wrap: balance;
}
.sw-inv2-hero__lede p {
	margin: 0 0 14px; font-size: 15px; line-height: 1.75; color: var(--sw-blue-200); max-width: 460px;
}
.sw-inv2-hero__lede p:last-child { margin-bottom: 24px; }
.sw-inv2-hero__caps { margin-top: 24px !important; }
.sw-inv2-hero__caps ul,
.sw-inv2-cta__caps ul {
	display: flex; flex-wrap: wrap; gap: 8px 20px; margin: 0; padding: 0; list-style: none;
}
.sw-inv2-hero__caps li,
.sw-inv2-cta__caps li {
	display: flex; align-items: center; gap: 7px;
	font-size: 12.5px; font-weight: 600; color: var(--sw-blue-200);
}
.sw-inv2-hero__caps svg,
.sw-inv2-cta__caps svg { flex: 0 0 auto; color: var(--sw-blue-400); }

/* The flow: two rows of three, arrows between, a connector down the middle. */
.sw-inv2-flow { margin-bottom: 0 !important; }
.sw-inv2-flow__row {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 10px 26px;
	position: relative;
}
.sw-inv2-flow__row + .sw-inv2-flow__row { margin-top: 34px; }
.sw-inv2-flow__box {
	position: relative;
	display: flex; flex-direction: column; align-items: center; justify-content: center;
	gap: 8px; padding: 18px 12px;
	text-align: center;
	background: rgba(155, 194, 229, 0.06);
	border: 1px solid var(--sw-border-dark);
	border-radius: 12px;
}
.sw-inv2-flow__box svg { color: var(--sw-blue-200); }
.sw-inv2-flow__box b {
	display: block; font-size: 11.5px; font-weight: 800;
	letter-spacing: 0.8px; text-transform: uppercase; color: var(--sw-white);
}
.sw-inv2-flow__box span { font-size: 10.5px; line-height: 1.45; color: var(--sw-blue-200); }
/* Arrow between boxes, across the gap. */
.sw-inv2-flow__box:not(:first-child)::before {
	content: "\2192"; position: absolute; top: 50%; left: -18px;
	transform: translateY(-50%); font-size: 15px; line-height: 1;
	color: var(--sw-blue-400); pointer-events: none;
}
/* Connector from row 1 into row 2. */
.sw-inv2-flow__row + .sw-inv2-flow__row::before {
	content: "\2193"; position: absolute; top: -26px; left: 50%;
	transform: translateX(-50%); font-size: 15px; line-height: 1; color: var(--sw-blue-400);
}

/* ---- 2. the problem ------------------------------------------------------
   Eight steps as one grid, 4 x 2. One Text module, not eight — no per-item
   setting is worth exposing in the builder, and the whole point of the band is
   that the steps are monotonous. */
.sw-inv2-steps { margin-bottom: 0 !important; }
.sw-inv2-steps ol {
	display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 12px; margin: 0; padding: 0; list-style: none; counter-reset: step;
}
.sw-inv2-steps li {
	display: flex; flex-direction: column; align-items: center; gap: 8px;
	padding: 16px 10px; text-align: center;
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: 12px;
}
.sw-inv2-steps svg { color: var(--sw-blue-600); }
.sw-inv2-steps b { font-size: 12px; font-weight: 700; line-height: 1.35; color: var(--sw-slate); }

/* The flex lives on an INNER div, not the module. Module content starts with an
   inline <svg>, and wpautop wraps that in a stray <p> — which made the module a
   flex container with one child and dropped the icon onto its own line. Starting
   the content with a block-level element is the documented defence. */
.sw-inv2-alert {
	margin: 14px 0 0 !important; padding: 16px 20px;
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: 12px;
}
.sw-inv2-alert__in { display: flex; align-items: center; gap: 12px; }
.sw-inv2-alert__in > p:empty { display: none; }
.sw-inv2-alert svg { flex: 0 0 auto; color: #b3453c; }
.sw-inv2-alert p, .sw-inv2-alert span { margin: 0; font-size: 13.5px; font-weight: 600; color: var(--sw-slate); }

/* ---- 3. the solution -----------------------------------------------------
   Five stages, each a card with a checklist. Arrows between. */
.sw-inv2-stages { margin-bottom: 0 !important; }
.sw-inv2-stages__grid {
	display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 10px 22px;
}
/* Each stage is a card in the mockup, not bare text on the band. */
.sw-inv2-stage {
	position: relative;
	padding: 16px 14px 18px;
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: 12px;
	box-shadow: var(--sw-shadow-sm);
}
.sw-inv2-stage:not(:first-child)::before {
	content: "\2192"; position: absolute; top: 46px; left: -16px;
	font-size: 15px; line-height: 1; color: var(--sw-blue-400); pointer-events: none;
}
.sw-inv2-stage__head { text-align: center; margin-bottom: 12px; }
.sw-inv2-stage__head svg { color: var(--sw-blue-600); margin-bottom: 8px; }
.sw-inv2-stage__head b {
	display: block; font-size: 14px; font-weight: 700; color: var(--sw-slate);
}
.sw-inv2-stage__head span { display: block; font-size: 11px; color: var(--sw-muted); margin-top: 3px; }
.sw-inv2-stage ul { list-style: none; margin: 0; padding: 0; }
.sw-inv2-stage li {
	display: flex; align-items: flex-start; gap: 7px;
	margin-bottom: 7px; font-size: 11.5px; line-height: 1.45; color: var(--sw-slate);
}
.sw-inv2-stage li svg { flex: 0 0 auto; color: var(--sw-blue-500); margin-top: 2px; }

/* ---- 4. intelligent data extraction --------------------------------------
   A real invoice rendered as a TABLE, not a picture of one. It is tabular data;
   marking it up as a table is both more honest and readable to a screen reader. */
/* Document and extracted fields side by side, as the mockup has them.
   The grid goes on `.et_pb_text_inner`, NOT the module: Divi wraps every text
   module's content in that div, so a grid on the module itself has exactly one
   child and nothing lays out. Any grid whose items are top-level content of a
   text module needs this — the grids nested inside content (stages, ocr, int)
   are unaffected because they have their own wrapper. */
.sw-inv2-extract .et_pb_text_inner {
	display: grid;
	grid-template-columns: 1.05fr 1fr;
	gap: 14px;
	align-items: start;
}
.sw-inv2-extract .et_pb_text_inner > p:empty { display: none; }

.sw-inv2-doc {
	margin-bottom: 0 !important;
	padding: 14px;
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: 12px;
	box-shadow: var(--sw-shadow-sm);
}
.sw-inv2-doc h3 {
	margin: 0 0 12px; padding: 0;
	font-size: 17px; font-weight: 800; letter-spacing: 0.5px; color: var(--sw-slate);
}
/* WordPress content styles reach this table: `.entry-content tr td` is (0,1,2)
   with 24px side padding and `.entry-content thead th` likewise. Written as
   `.sw-inv2-doc td` at (0,1,1) these lost, and a 10px invoice table rendered
   with 24px cell padding — wide enough to break the column. `.sw-page` prefix
   takes them to (0,2,2), which wins outright rather than on source order. */
.sw-page .sw-inv2-doc table { width: 100%; border-collapse: collapse; font-size: 10.5px; }
.sw-page .sw-inv2-doc table th {
	text-align: left; padding: 5px 6px;
	border: 0; border-bottom: 1px solid var(--sw-border-light);
	font-weight: 700; color: var(--sw-slate);
}
.sw-page .sw-inv2-doc table td {
	padding: 5px 6px; border: 0; border-bottom: 1px solid var(--sw-blue-50); color: var(--sw-muted);
}
.sw-page .sw-inv2-doc table td:last-child,
.sw-page .sw-inv2-doc table th:last-child { text-align: right; }
.sw-page .sw-inv2-doc table tfoot td { font-weight: 700; color: var(--sw-slate); border-bottom: 0; }
.sw-inv2-doc__meta {
	display: flex; justify-content: space-between; gap: 12px;
	margin-bottom: 12px; font-size: 10.5px; line-height: 1.5; color: var(--sw-muted);
}

.sw-inv2-fields { margin-bottom: 0 !important; }
.sw-inv2-fields b {
	display: block; margin-bottom: 10px;
	font-size: 12px; font-weight: 800; letter-spacing: 0.6px; color: var(--sw-slate);
}
.sw-inv2-fields ul { list-style: none; margin: 0; padding: 0; }
.sw-inv2-fields li {
	display: grid; grid-template-columns: 1fr auto 18px;
	align-items: center; gap: 10px;
	padding: 7px 10px;
	border-bottom: 1px solid var(--sw-blue-50);
	font-size: 11.5px;
}
.sw-inv2-fields li span:first-child { color: var(--sw-muted); }
.sw-inv2-fields li span:nth-child(2) { font-weight: 700; color: var(--sw-slate); }
.sw-inv2-fields li svg { color: #2f7d55; }
.sw-inv2-cap p { margin: 10px 0 0; font-size: 11.5px; color: var(--sw-muted); font-style: italic; }

/* ---- 5. beyond OCR — four numbered stages -------------------------------- */
.sw-inv2-ocr { margin-bottom: 0 !important; }
.sw-inv2-ocr__grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
.sw-inv2-ocr__card {
	padding: 16px 14px 18px;
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: 12px;
}
.sw-inv2-ocr__num {
	display: block; margin-bottom: 8px;
	font-size: 24px; font-weight: 800; line-height: 1; color: var(--sw-blue-400);
}
.sw-inv2-ocr__card b { display: block; margin-bottom: 6px; font-size: 13.5px; color: var(--sw-slate); }
.sw-inv2-ocr__card p { margin: 0; font-size: 11.5px; line-height: 1.55; color: var(--sw-muted); }

/* ---- 6. business logic ---------------------------------------------------
   Validation rules two-up, then the decision tree as a vertical flow. The
   mockup draws the tree with yes/no branches; a linear flow with the two
   outcomes side by side at the foot says the same thing and does not need an
   illustration that nobody has drawn. */
.sw-inv2-rules { margin-bottom: 0 !important; }
.sw-inv2-rules ul {
	display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 14px 18px; margin: 0; padding: 0; list-style: none;
}
.sw-inv2-rules li { display: flex; gap: 10px; }
.sw-inv2-rules svg { flex: 0 0 auto; color: var(--sw-blue-600); margin-top: 2px; }
.sw-inv2-rules b { display: block; font-size: 12.5px; font-weight: 700; color: var(--sw-slate); }
.sw-inv2-rules span { font-size: 11.5px; line-height: 1.5; color: var(--sw-muted); }

.sw-inv2-tree { margin: 18px 0 0 !important; }
.sw-inv2-tree ol {
	display: flex; flex-direction: column; align-items: center; gap: 0;
	margin: 0; padding: 0; list-style: none;
}
.sw-inv2-tree li {
	position: relative;
	padding: 8px 16px;
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: 8px;
	font-size: 11.5px; font-weight: 600; color: var(--sw-slate);
}
.sw-inv2-tree li + li { margin-top: 26px; }
.sw-inv2-tree li + li::before {
	content: "\2193"; position: absolute; top: -21px; left: 50%;
	transform: translateX(-50%); font-size: 13px; color: var(--sw-blue-400);
}
.sw-inv2-tree__ends { display: flex; justify-content: center; gap: 14px; margin-top: 26px; position: relative; }
.sw-inv2-tree__ends::before {
	content: "\2193"; position: absolute; top: -21px; left: 50%;
	transform: translateX(-50%); font-size: 13px; color: var(--sw-blue-400);
}
.sw-inv2-tree__end {
	padding: 8px 16px; border-radius: 8px;
	font-size: 11.5px; font-weight: 700;
}
.sw-inv2-tree__end--auto { background: #e8f4ec; border: 1px solid #bcdcc7; color: #2f7d55; }
.sw-inv2-tree__end--review { background: #fdf1e7; border: 1px solid #f0cfae; color: #a8642a; }

/* ---- 7. human in the loop ------------------------------------------------ */
.sw-inv2-hitl { margin-bottom: 0 !important; }
.sw-inv2-hitl__split { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.sw-inv2-hitl__branch { padding: 14px; border-radius: 12px; text-align: center; }
.sw-inv2-hitl__branch--ok { background: #e8f4ec; border: 1px solid #bcdcc7; }
.sw-inv2-hitl__branch--ex { background: #fdf1e7; border: 1px solid #f0cfae; }
.sw-inv2-hitl__branch b {
	display: block; margin-bottom: 6px;
	font-size: 11px; font-weight: 800; letter-spacing: 1px; text-transform: uppercase;
}
.sw-inv2-hitl__branch--ok b { color: #2f7d55; }
.sw-inv2-hitl__branch--ex b { color: #a8642a; }
.sw-inv2-hitl__branch span { font-size: 12px; font-weight: 600; color: var(--sw-slate); }

.sw-inv2-review { margin: 16px 0 0 !important; }
.sw-inv2-review b {
	display: block; margin-bottom: 10px;
	font-size: 12px; font-weight: 800; letter-spacing: 0.6px; color: var(--sw-slate);
}
.sw-inv2-review ul { list-style: none; margin: 0; padding: 0; }
.sw-inv2-review li {
	display: flex; align-items: flex-start; gap: 9px;
	margin-bottom: 9px; font-size: 12px; line-height: 1.5; color: var(--sw-slate);
}
.sw-inv2-review svg { flex: 0 0 auto; color: var(--sw-blue-500); margin-top: 1px; }

/* ---- 8. connected automation — six integrations -------------------------- */
.sw-inv2-int { margin-bottom: 0 !important; }
.sw-inv2-int__grid { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 12px; }

/* ---- 9. end to end ------------------------------------------------------- */
.sw-inv2-e2e__head { margin-bottom: 40px !important; }
.sw-inv2-e2e__row > .et_pb_column { margin-bottom: 0; }
/* (0,3,0): Divi stamps .et_pb_text_align_left on every text module, and
   text-align set on the column is inherited — inheritance always loses to a
   direct rule, so the steps came back left-aligned under centred badges. */
.sw-inv2-e2e .sw-pstep .et_pb_text.et_pb_module { text-align: center; }
.sw-inv2-e2e .sw-pstep { position: relative; text-align: center; padding: 0 8px; }
.sw-inv2-e2e .sw-pstep > .et_pb_module { margin-bottom: 0; }
/* Compound, not descendant: the COLUMN is the step, and an element is not its
   own ancestor — the descendant form matches nothing and the badge vanishes. */
.sw-inv2-e2e__row > .et_pb_column.sw-pstep > .sw-pstep__badge {
	display: grid; place-items: center;
	width: 44px; height: 44px; margin: 0 auto 12px;
	border-radius: 50%;
	background: var(--sw-blue-600); color: var(--sw-white);
	font-size: 14px; font-weight: 800;
}
.sw-inv2-e2e__row > .et_pb_column.sw-pstep:not(:first-child)::before {
	content: "\2192"; position: absolute; top: 14px; left: -12px;
	font-size: 14px; line-height: 1; color: var(--sw-blue-300); pointer-events: none;
}
.sw-inv2-e2e .sw-pstep__head h3 {
	margin: 0 0 7px; padding: 0;
	font-size: 14px; font-weight: 700; line-height: 1.3; color: var(--sw-slate);
}
.sw-inv2-e2e .sw-pstep__head p { margin: 0; font-size: 11.5px; line-height: 1.6; color: var(--sw-muted); }

/* ---- 10. benefits -------------------------------------------------------- */
.sw-inv2-bene__head { margin-bottom: 36px !important; }
.sw-inv2-bene__row > .et_pb_column { margin-bottom: 0; }
.sw-inv2-benecard { height: 100%; margin-bottom: 0 !important; }
.sw-inv2-benecard .sw-inv2-card { height: 100%; padding: 22px 20px 24px; }
.sw-inv2-benecard h3 { font-size: 15px; }
.sw-inv2-benecard p { font-size: 13px; }

/* Benefit blurbs. The icon slot ships EMPTY — it is chosen in the builder — so
   these three resets exist for the moment one is added, not for today:

   1. Divi's top-placed blurb icon is `.et_pb_blurb_position_top .et-pb-icon
      { font-size: 96px }` at (0,2,0), and setting icon_font_size on the module
      frequently emits no CSS at all. The (0,3,0) override is not optional.
   2. `max-width: 550px` and centred text are blurb defaults; both are wrong in
      a 1_4 column.
   3. An image icon needs a size cap of its own, or it renders at natural size. */
.sw-inv2-blurb.et_pb_blurb {
	height: 100%;
	margin-bottom: 0 !important;
	padding: 22px 20px 24px;
	background: var(--sw-white);
	border: 1px solid var(--sw-border-light);
	border-radius: 12px;
	box-shadow: var(--sw-shadow-sm);
	transition: var(--sw-card-transition);
}
.sw-inv2-blurb.et_pb_blurb:hover { transform: translateY(-3px); box-shadow: var(--sw-shadow-md); }
.sw-inv2-blurb.et_pb_blurb .et_pb_blurb_content,
.sw-inv2-blurb.et_pb_blurb[class*="et_pb_text_align_"] .et_pb_blurb_content .et_pb_blurb_container {
	max-width: 100%;
	text-align: left;
}
.sw-inv2-blurb .et_pb_main_blurb_image { margin-bottom: 12px; display: block; }
.sw-inv2-blurb .et_pb_main_blurb_image .et-pb-icon { font-size: 26px; line-height: 1; color: var(--sw-blue-600); }
.sw-inv2-blurb .et_pb_main_blurb_image img { width: 26px; height: auto; }
.sw-inv2-blurb .et_pb_module_header {
	margin: 0 0 6px; padding: 0;
	font-size: 15px; font-weight: 700; line-height: 1.3; color: var(--sw-slate);
}
.sw-inv2-blurb .et_pb_blurb_description p { margin: 0; font-size: 13px; line-height: 1.6; color: var(--sw-muted); }

/* Image modules ship with an empty src — Divi renders nothing rather than a
   broken image, so these bands are simply blank until artwork is added. */
.sw-inv2-img { margin-bottom: 0 !important; }
.sw-inv2-img img { display: block; width: 100%; height: auto; border-radius: 12px; }

/* ---- 11. is this right for you ------------------------------------------- */
.sw-inv2-fit__list { margin-bottom: 0 !important; }
.sw-inv2-fit__list ul {
	display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 12px 28px; margin: 0; padding: 0; list-style: none;
}
.sw-inv2-fit__list li {
	display: flex; align-items: flex-start; gap: 10px;
	font-size: 13.5px; line-height: 1.55; color: var(--sw-slate);
}
.sw-inv2-fit__list svg { flex: 0 0 auto; color: var(--sw-blue-600); margin-top: 2px; }

/* ---- 12. final CTA ------------------------------------------------------- */
.et_pb_section.sw-inv2-cta { position: relative; overflow: hidden; }
.sw-inv2-cta::after {
	content: ""; position: absolute; top: 0; right: 0; width: 320px; height: 100%;
	background-image: radial-gradient(rgba(155, 194, 229, 0.16) 1px, transparent 1px);
	background-size: 14px 14px; pointer-events: none;
}
.sw-inv2-cta__row { position: relative; z-index: 1; }
.sw-inv2-cta__mark { margin-bottom: 0 !important; }
.sw-inv2-cta__mark img { width: 84px; height: auto; display: block; }
.sw-inv2-cta__title h2 {
	margin: 0 0 10px; padding: 0;
	font-size: 28px; font-weight: 700; line-height: 1.24;
	letter-spacing: -0.7px; color: var(--sw-white); text-wrap: balance;
}
.sw-inv2-cta__lede p { margin: 0; font-size: 14px; line-height: 1.75; color: var(--sw-blue-200); }
.sw-inv2-cta__caps { margin-top: 18px !important; }

/* ---- tablet -------------------------------------------------------------- */
@media (max-width: 980px) {
	.et_pb_section.sw-inv2-hero { padding: 72px 0; }
	.et_pb_section.sw-inv2-prob, .et_pb_section.sw-inv2-sol, .et_pb_section.sw-inv2-data,
	.et_pb_section.sw-inv2-logic, .et_pb_section.sw-inv2-conn, .et_pb_section.sw-inv2-e2e,
	.et_pb_section.sw-inv2-bene, .et_pb_section.sw-inv2-fit { padding: 68px 0; }
	.et_pb_section.sw-inv2-cta { padding: 56px 0; }

	.sw-inv2-hero__title h1 { font-size: 34px; letter-spacing: -0.8px; }
	.sw-inv2-h2 h2 { font-size: 26px; }
	.sw-inv2-cta__title h2 { font-size: 24px; }

	/* Every split stacks; copy leads. */
	.sw-inv2-row > .et_pb_column { width: 100% !important; margin: 0 0 28px !important; }

	.sw-inv2-steps ol { grid-template-columns: repeat(4, minmax(0, 1fr)); }
	.sw-inv2-stages__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); row-gap: 26px; }
	.sw-inv2-stage:nth-child(3n+1)::before { display: none; }
	.sw-inv2-ocr__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.sw-inv2-int__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }

	/* 6 -> 3; connectors die at the wrap. */
	.sw-inv2-e2e__row > .et_pb_column { width: 30.66% !important; margin-right: 4% !important; margin-bottom: 28px; }
	.sw-inv2-e2e__row > .et_pb_column:nth-child(3n) { margin-right: 0 !important; }
	.sw-inv2-e2e__row > .et_pb_column.sw-pstep::before { display: none; }

	.sw-inv2-bene__row > .et_pb_column { width: 48.75% !important; margin-right: 2.5% !important; margin-bottom: 20px; }
	.sw-inv2-bene__row > .et_pb_column:nth-child(2n) { margin-right: 0 !important; }
	.sw-inv2-cta::after { display: none; }
}

/* ---- phone --------------------------------------------------------------- */
@media (max-width: 767px) {
	.et_pb_section.sw-inv2-hero, .et_pb_section.sw-inv2-prob, .et_pb_section.sw-inv2-sol,
	.et_pb_section.sw-inv2-data, .et_pb_section.sw-inv2-logic, .et_pb_section.sw-inv2-conn,
	.et_pb_section.sw-inv2-e2e, .et_pb_section.sw-inv2-bene, .et_pb_section.sw-inv2-fit,
	.et_pb_section.sw-inv2-cta { padding: 52px 0; }

	.sw-inv2-hero__title h1 { font-size: 28px; letter-spacing: -0.5px; }
	.sw-inv2-h2 h2 { font-size: 23px; letter-spacing: -0.4px; }
	.sw-inv2-cta__title h2 { font-size: 21px; }

	/* Everything one-up. The end-to-end flow becomes vertical, as the brief asks. */
	.sw-inv2-flow__row { grid-template-columns: 1fr; gap: 26px; }
	.sw-inv2-flow__box:not(:first-child)::before {
		content: "\2193"; top: -20px; left: 50%; transform: translateX(-50%);
	}
	.sw-inv2-steps ol { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.sw-inv2-stages__grid { grid-template-columns: 1fr; row-gap: 26px; }
	.sw-inv2-stage::before { display: none !important; }
	.sw-inv2-ocr__grid, .sw-inv2-int__grid { grid-template-columns: 1fr; }
	.sw-inv2-rules ul, .sw-inv2-fit__list ul { grid-template-columns: 1fr; }
	.sw-inv2-hitl__split { grid-template-columns: 1fr; }
	.sw-inv2-tree__ends { flex-direction: column; align-items: center; }

	.sw-inv2-e2e__row > .et_pb_column,
	.sw-inv2-bene__row > .et_pb_column { width: 100% !important; margin-right: 0 !important; margin-bottom: 22px; }
	.sw-inv2-doc table { font-size: 9.5px; }
}

/* ===========================================================================
   41. Shared components  —  the layer that should have existed first
   ---------------------------------------------------------------------------
   Every page section before this one re-declared its own surfaces, section
   padding, heading scale, eyebrow, card and grid under its own namespace. That
   was defensible once — a new page must not restyle a shipped one — but it was
   applied to everything rather than only to what is genuinely page-specific,
   and the result drifted. design-lint on the stylesheet as it stood:

       12,702 lines · 6,937 declarations
       64 card-like component definitions, 32 of them repeating the same
          white background / radius / shadow trio
       34 distinct line-height values (the linter flags anything over 4)
       ~20 page namespaces

   Sixty-four card definitions for what is, visually, about three cards.

   WHAT IS IN HERE is only what already agreed. Values are the measured
   majority across the existing sheet, not new inventions:

       section padding  96px        17 uses (88px was next at 9)
       eyebrow tracking 1.6px       11 uses (1.4px next at 4)
       card             the --sw-card-* tokens that already exist in :root

   NEW CLASSES ONLY. Nothing here renames or edits an existing selector, so no
   page currently live can change. Migration is opt-in, page by page, each one
   verified by screenshot diff before and after.

   ONE KNOWN DISAGREEMENT, deliberately not resolved here: `--sw-card-radius`
   resolves to 14px, but 30 hand-written rules use 12px against 9 that use the
   token. The token wins in this layer because it is the declared system value;
   whether the system should become 12px is a design decision, not a cleanup,
   and changing it would move every card on every live page.
   =========================================================================== */

/* ---- band: a full-width section with vertical rhythm ---------------------
   Compound `.et_pb_section.sw-band`, because Divi's own
   `.et_pb_section { padding: 54px 0 }` is (0,1,0) and loads after this sheet —
   a bare class loses the tie. */
.et_pb_section.sw-band { padding: 96px 0; }
.et_pb_section.sw-band--tight { padding: 72px 0; }
.et_pb_section.sw-band--tall { padding: 112px 0; }

/* Surfaces, in the order they alternate down a page. */
.sw-band--dark { background-color: var(--sw-navy-900); }
.sw-band--darkest { background-color: var(--sw-navy-950); }
.sw-band--light { background-color: var(--sw-light); }
/* A half-step lighter than --light, so a third light band in a row does not
   read as the same slab as the one above it. */
.sw-band--tint { background-color: var(--sw-blue-25); }
.sw-band--white { background-color: var(--sw-white); }

/* ---- type ----------------------------------------------------------------
   One scale. `sw-h2` is the default; the two modifiers exist because a heading
   in a half-width column genuinely needs to be smaller than one spanning a
   centred full-width row, and both sizes were already in use. */
.sw-h2 h2 {
	margin: 0;
	padding: 0;
	font-size: 34px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.8px;
	color: var(--sw-slate);
	text-wrap: balance;
}
.sw-h2--lg h2 { font-size: 36px; }
.sw-h2--sm h2 { font-size: 30px; letter-spacing: -0.7px; line-height: 1.22; }
.sw-band--dark .sw-h2 h2,
.sw-band--darkest .sw-h2 h2 { color: var(--sw-white); }

.sw-lede p { margin: 0 0 12px; font-size: 15px; line-height: 1.75; color: var(--sw-muted); }
.sw-lede p:last-child { margin-bottom: 0; }
.sw-band--dark .sw-lede p,
.sw-band--darkest .sw-lede p { color: var(--sw-blue-200); }

/* Eyebrow sizing and colour by surface. Section 3 owns the uppercase and the
   zero margin; this only settles size and colour, which every page restated. */
.sw-band .sw-eyebrow p { font-size: 13px; letter-spacing: 1.6px; color: var(--sw-blue-500); }
.sw-band--dark .sw-eyebrow p,
.sw-band--darkest .sw-eyebrow p { color: var(--sw-blue-200); }

/* ---- module rhythm -------------------------------------------------------
   THE TRAP THIS SOLVES. Section 27 sets
   `.sw-divi .et_pb_text_inner > :last-child { margin-bottom: 0 }` at (0,3,0),
   and every heading and lede is the last child of its own text module — so
   spacing written on the inner element is silently zeroed and the page has no
   rhythm. The gap therefore goes on the MODULE. !important is for Divi's own
   gutter rule, `.et_pb_gutters3 .et_pb_column_<t> .et_pb_module`, which is
   (0,4,0) and sets margin-bottom as a percentage of the column.

   Listed per component rather than as a blanket `.et_pb_module` rule: a
   blanket version was tried and out-ranked every component's own
   `margin-bottom: 0`, so grids and badges silently gained space they had
   explicitly removed. */
.sw-stack .sw-h2.et_pb_module,
.sw-stack .sw-lede.et_pb_module { margin-bottom: 14px !important; }
.sw-stack .sw-eyebrow.et_pb_module { margin-bottom: 8px !important; }
.sw-stack > .et_pb_module:last-child { margin-bottom: 0 !important; }

/* ---- button arrows -------------------------------------------------------
   OPT-IN, because section 27 kills Divi's own button glyph outright:
   `.sw-divi .sw-btn.et_pb_button:after { display: none !important }`. That rule
   is right — Divi otherwise puts an arrow on every button whether or not one
   was asked for — but it means a button that DOES want an arrow has to say so.

   Written at (0,4,0) with !important so it beats that rule on specificity
   rather than on source order, which would break if the sections were ever
   reordered. The glyph is a pseudo-element, so it stays out of the accessible
   name: the button reads as "Explore Our Projects", not "…right arrow". */
.sw-divi .sw-btn.sw-btn--arw.et_pb_button::after,
.sw-page .sw-btn.sw-btn--arw::after {
	content: "\2192";
	display: inline-block !important;
	/* Zero, not a nudge: `.sw-btn.et_pb_button` is inline-flex with `gap: 0.5em`,
	   and the pseudo-element is a flex item — any margin here compounds it. */
	margin: 0 !important;
	font-family: inherit !important;
	font-size: 1em !important;
	opacity: 1 !important;
	transition: transform 0.25s var(--sw-ease);

	/* Optical correction, and the two arrows need DIFFERENT amounts — which is
	   why one shared value looked wrong on one of them.

	   `↓` (U+2193) is a tall glyph spanning roughly ascender to descender, so
	   it centres against the label almost by itself. `→` (U+2192) is a short
	   horizontal mark drawn on the font's math axis, well above the optical
	   centre of a line of caps-and-lowercase, so it reads high and needs
	   pushing down about twice as far.

	   Measured off a 160px slice at 1440 rather than computed: box metrics say
	   the baselines already align, so this is glyph design, not layout. `top`,
	   not `transform`, because the hover slide owns transform. */
	position: relative !important;
	line-height: 1 !important;
	top: 4px;
}
.sw-divi .sw-btn.sw-btn--arw-down.et_pb_button::after,
.sw-page .sw-btn.sw-btn--arw-down::after { top: 2px; }
/* Down, for a button that scrolls to a section on the same page rather than
   navigating away — the direction should tell you which it is. */
.sw-divi .sw-btn.sw-btn--arw-down.et_pb_button::after,
.sw-page .sw-btn.sw-btn--arw-down::after { content: "\2193"; }

.sw-btn--arw.et_pb_button:hover::after { transform: translateX(3px); }
.sw-btn--arw-down.et_pb_button:hover::after { transform: translateY(3px); }

/* ---- card ----------------------------------------------------------------
   The tokens already existed in :root and already described this. Thirty-two
   of the sheet's sixty-four card definitions were re-typing them. */
.sw-card {
	display: flex;
	flex-direction: column;
	padding: var(--sw-card-pad);
	background: var(--sw-white);
	border: var(--sw-card-border);
	border-radius: var(--sw-card-radius);
	box-shadow: var(--sw-card-shadow);
	transition: var(--sw-card-transition);
}
.sw-card:hover { transform: translateY(-4px); box-shadow: var(--sw-card-shadow-hover); }
.sw-card--flush { padding: 0; overflow: hidden; }
.sw-card--tight { padding: 18px 16px 20px; }
/* A card that IS a Divi column, rather than a div inside one. Divi lays columns
   out with flex, so the column has to be told to stack its modules. */
.et_pb_column.sw-card { float: none; }

/* ---- grid ----------------------------------------------------------------
   On the COLUMN, so the modules inside become its direct grid children. This
   is how a design gets more than six items across, and it keeps the responsive
   step-downs in one place instead of per page. */
.et_pb_column.sw-grid { float: none; display: grid; gap: 18px; }
.sw-grid > .et_pb_module { margin-bottom: 0 !important; }
.sw-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.sw-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.sw-grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.sw-grid--5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.sw-grid--6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
/* wpautop can inject an empty <p>, which becomes a real grid child and shifts
   every sibling along one slot. Section 39 carries the same guard. */
.sw-grid > p:empty { display: none; }

/* ---- responsive ----------------------------------------------------------
   Written once. Every page that adopts .sw-band and .sw-grid inherits the
   step-downs instead of restating them. */
@media (max-width: 980px) {
	/* A tall band collapses to the same 72px as a normal one at tablet: the
	   extra desktop height is breathing room for a hero, and there is none to
	   spare at 980px. 72/56 is also what every existing page already uses. */
	.et_pb_section.sw-band,
	.et_pb_section.sw-band--tall { padding: 72px 0; }
	.et_pb_section.sw-band--tight { padding: 56px 0; }

	.sw-h2 h2 { font-size: 30px; }
	.sw-h2--lg h2 { font-size: 32px; }
	.sw-h2--sm h2 { font-size: 26px; }

	.sw-grid--4, .sw-grid--5, .sw-grid--6 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 767px) {
	.et_pb_section.sw-band,
	.et_pb_section.sw-band--tight,
	.et_pb_section.sw-band--tall { padding: 56px 0; }

	.sw-h2 h2, .sw-h2--lg h2 { font-size: 25px; letter-spacing: -0.5px; }
	.sw-h2--sm h2 { font-size: 23px; }

	.sw-grid--3, .sw-grid--4, .sw-grid--5, .sw-grid--6 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.sw-grid--stack-phone { grid-template-columns: minmax(0, 1fr); }
}

/* ===========================================================================
   42. Contact v2  —  page "contact-v2" (Divi layout, pipeline v2)
   ---------------------------------------------------------------------------
   ADDITIVE ONLY. Every selector here begins sw-c2-, so nothing on the live
   /contact/ page can change. That page stays on templates/page-contact.php
   with its own section 28.

   THE FORM IS REUSED, NOT REBUILT. It is a real PHP form with a nonce, a
   honeypot, server-side validation and repopulation after a failed submit —
   none of which a static layout can express. It goes in as the shortcode
   [seriousweb_contact_form], exactly as the export skill prescribes for a form
   with a server-side dependency.

   That has one consequence worth stating plainly: every form rule in section 28
   is scoped `.sw-contact .sw-form`, so the v2 form SECTION also carries the
   `sw-contact` class. Without it the form renders completely unstyled. Adding a
   class to a new page cannot affect the old one, so this is safe reuse rather
   than duplication — the alternative was copying ~200 lines of form CSS under a
   new prefix, which is exactly the drift this stylesheet already has too much
   of.

   WHAT THIS REDESIGN FIXES, all observed on the live page:
     1. A neon purple/magenta 3D graphic in the hero. The site's entire system
        is one blue ramp at ~207 degrees; that image is the only thing on the
        site from a different palette, and it dominated the hero.
     2. ~230px of empty white band between the last section and the footer.
     3. Four "what happens next" steps separated by vertical rules that ran far
        past their content — the same stretched-cell bug fixed in section 38.
     4. Trust items that wrapped unevenly and lost their baseline.
     5. The Phone Number field rendering unstyled — see the tel fix below.
   =========================================================================== */

/* ---- 1. hero -------------------------------------------------------------
   Deliberately compact. A contact page converts on how fast the form appears;
   the old hero spent ~650px on a headline and an off-palette illustration
   before anything actionable. Centred, no artwork, and the trust points become
   pills so they hold a line instead of wrapping into three ragged blocks. */
.et_pb_section.sw-c2-hero { position: relative; overflow: hidden; }
/* Modelled on the seriousweb.ch hero: sparse long diagonals sweeping the full
   width, outlined geometric shapes floating over them, and a soft curve at the
   foot of the band.

   PALETTE IS THIS SITE'S, NOT THE REFERENCE'S, and that is deliberate. The .ch
   hero is mid-blue with a coral accent; .com is the dark navy end of the 207
   degree ramp. Bringing coral across would introduce a second palette and the
   page would read as a different site. The structure is copied; the colour is
   mapped onto the existing tokens. Reversible if the brands are meant to
   converge, but that is a decision to take deliberately.

   Diagonals are long and VERY sparse — one set only, 1px at 460px spacing, so
   roughly three lines cross the band. Two sets at 210px and 260px was the first
   attempt and it hatched: the reference has three or four sweeps, and anything
   denser stops reading as light and starts reading as texture.

   The mask keeps the first 120px clear so the top of the band stays flat navy
   against the header, and fades them before the band ends.

   IT ALSO CLEARS THE CENTRE, and that second job was added later. Sparse is the
   right call — see above — but sparse and centred copy do not mix: with roughly
   three sweeps across 1440px, one of them lands on the headline, and a single
   hairline crossing "Great Together." and the trust pills reads as a rendering
   artifact rather than as light. Tightening the spacing is NOT the fix; that was
   the first attempt and it hatched.

   So the ruling now keeps to the edges, where it does the job it was drawn for,
   and fades out behind the copy. Two mask layers combined with `intersect`:
   the vertical fade AND an elliptical punch-out over the text column. The
   `-webkit-` pair is the legacy spelling of the same thing (`source-in`), not a
   different effect — both are needed, and a mask with only one of the two
   composite properties silently applies just the first layer. */
.sw-c2-hero::before {
	content: "";
	position: absolute;
	inset: 0;
	pointer-events: none;
	background-image:
		repeating-linear-gradient(168deg, rgba(155, 194, 229, 0.16) 0 1px, transparent 1px 460px);
	-webkit-mask-image:
		linear-gradient(180deg, transparent 0, #000 120px, #000 70%, transparent 97%),
		radial-gradient(ellipse 44% 58% at 50% 50%, transparent 0 58%, #000 100%);
	mask-image:
		linear-gradient(180deg, transparent 0, #000 120px, #000 70%, transparent 97%),
		radial-gradient(ellipse 44% 58% at 50% 50%, transparent 0 58%, #000 100%);
	-webkit-mask-composite: source-in;
	mask-composite: intersect;
}

/* ---- floating outlined shapes -------------------------------------------
   The reference's squares and ring are OUTLINES, not fills — that is what
   keeps them quiet enough to sit behind a headline. Drawn on the row's and the
   column's pseudo-elements because the section's two are already spent on the
   diagonals and the curve; each shape is one box with a border. */
.sw-c2-hero__row::before,
.sw-c2-hero__row::after,
.sw-c2-hero__copy::before {
	content: "";
	position: absolute;
	pointer-events: none;
	border: 1px solid rgba(155, 194, 229, 0.34);
	z-index: 0;
}
/* Large square, upper right. */
.sw-c2-hero__row::before {
	top: 10px;
	right: -6px;
	width: 88px;
	height: 88px;
	border-radius: 6px;
}
/* Small square, lower left — offset so the two do not mirror each other.
   Alphas here are HIGHER than the reference's look would suggest, because the
   reference sits on mid-blue where a hairline carries. On this navy the same
   value disappears: at 0.16 this square was invisible on screen. */
.sw-c2-hero__row::after {
	bottom: 14px;
	left: 8px;
	width: 46px;
	height: 46px;
	border-radius: 5px;
	border-color: rgba(155, 194, 229, 0.26);
}
/* Ring, right of the copy. */
.sw-c2-hero__copy::before {
	top: 56%;
	right: 7%;
	width: 34px;
	height: 34px;
	border-radius: 50%;
	border-color: rgba(91, 155, 213, 0.5);
}
.et_pb_column.sw-c2-hero__copy { position: relative; }

/* One wide, soft wash behind the copy so the headline is not sitting directly
   on the ruling. Linear and off-centre, so it reads as light falling across the
   band rather than as a lamp behind the text.

   It carries THE SAME top fade as the grid, and that is the whole trick for the
   header seam. The header is `--sw-ink`, rgb(4,31,56) — the exact colour this
   band starts from — so the two only read as one surface while the hero's first
   ~140px stay untouched. Any treatment that is at full strength at y=0 puts a
   lighter band directly against the flat header and draws a hard line across
   the full width, which is what this wash did before the mask. */
.sw-c2-hero::after {
	content: "";
	position: absolute;
	inset: 0;
	pointer-events: none;
	/* The soft curve sweeping out of the lower right, as in the reference. An
	   over-sized ellipse whose edge is the curve: only its top-left arc crosses
	   the band, so what shows is a single long sweep rather than a blob. Paired
	   with a wide directional wash so the band is lit from the upper left and
	   the curve reads as the shadow line of that light. */
	background-image:
		radial-gradient(ellipse 1100px 520px at 108% 128%,
			rgba(155, 194, 229, 0.1) 0 60%, rgba(155, 194, 229, 0) 61%),
		linear-gradient(158deg,
			rgba(8, 82, 150, 0.34) 0%,
			rgba(8, 82, 150, 0.1) 44%,
			rgba(4, 31, 56, 0) 74%);
	-webkit-mask-image: linear-gradient(180deg, transparent 0, #000 140px);
	mask-image: linear-gradient(180deg, transparent 0, #000 140px);
}
.sw-c2-hero__row { position: relative; z-index: 1; }

/* Matches the Our Work v2 pill: --sw-border-dark is a divider alpha and too
   faint to describe a shape, so the border and fill are carried up. (0,3,1)
   because `.sw-divi .et_pb_text_inner > :last-child` zeroes padding-bottom at
   (0,3,0), which pins the label to the bottom edge and reads as "not centred". */
.sw-c2-hero .sw-eyebrow.et_pb_module p {
	display: inline-block;
	padding: 10px 18px !important;
	border: 1px solid rgba(155, 194, 229, 0.32);
	border-radius: 999px;
	background: rgba(155, 194, 229, 0.11);
	color: var(--sw-white);
	line-height: 1;
}

/* The gap below the headline is on the MODULE. On the inner h1 it was being
   zeroed by `.sw-divi .et_pb_text_inner > :last-child` at (0,3,0) — the space
   that appeared came from Divi's gutter margin by accident, not by intent. */
.sw-c2-hero__title.et_pb_module { margin-bottom: 18px !important; }
.sw-c2-hero__lede.et_pb_module { margin-bottom: 0 !important; }

.sw-c2-hero__title h1 {
	margin: 0 auto;
	padding: 0;
	max-width: 780px;
	font-size: 52px;
	font-weight: 700;
	line-height: 1.1;
	letter-spacing: -1.4px;
	color: var(--sw-white);
	text-wrap: balance;
}
.sw-c2-hero__lede p {
	margin: 0 auto;
	max-width: 580px;
	font-size: 16px;
	line-height: 1.75;
	color: var(--sw-blue-200);
}

.sw-c2-hero__trust { margin-top: 30px !important; }
.sw-c2-hero__trust ul {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 10px;
	margin: 0;
	padding: 0;
	list-style: none;
}
.sw-c2-hero__trust li {
	display: flex;
	align-items: center;
	gap: 9px;
	padding: 10px 18px;
	border: 1px solid var(--sw-border-dark);
	border-radius: 999px;
	background: rgba(155, 194, 229, 0.05);
	font-size: 13px;
	font-weight: 600;
	color: var(--sw-blue-200);
}
.sw-c2-hero__trust svg { flex: 0 0 auto; color: var(--sw-blue-400); }

/* ---- 2. form and aside ---------------------------------------------------
   3_5 / 2_5: the form is the page, the aside supports it. */
.sw-c2-form__row > .et_pb_column { margin-bottom: 0; }

.sw-c2-card {
	padding: 30px 28px 32px;
	background: var(--sw-white);
	border: var(--sw-card-border);
	border-radius: var(--sw-card-radius);
	box-shadow: var(--sw-card-shadow);
}
.sw-c2-card h2 {
	margin: 0 0 8px;
	padding: 0;
	font-size: 24px;
	font-weight: 700;
	line-height: 1.25;
	letter-spacing: -0.5px;
	color: var(--sw-slate);
}
/* Through `.et_pb_text_inner`, not a direct child of the module. Divi wraps
   every text module's content in that div, so `.sw-c2-card > p` matches nothing
   and the paragraph renders unstyled — the audit reports it as DEAD. */
.sw-c2-card .et_pb_text_inner > p { margin: 0 0 22px; font-size: 14.5px; line-height: 1.7; color: var(--sw-muted); }

/* THE TEL FIX. Section 28 styles `input[type="text"]` and `[type="email"]` but
   not `[type="tel"]`, so Phone Number falls back to the browser default: narrow,
   no left padding, and the absolutely-positioned icon ends up outside the box.
   It is a genuine defect on the live page. Scoped to sw-c2- here so v2 is
   correct without changing /contact/ — the same one-line fix belongs in
   section 28 whenever that page is next touched. */
.sw-c2-form .sw-form input[type="tel"] {
	width: 100%;
	padding: 13px 14px;
	font: inherit;
	color: var(--sw-slate);
	background-color: #fff;
	border: 1px solid var(--sw-border-light);
	border-radius: 10px;
}
.sw-c2-form .sw-form .sw-form__field--icon input[type="tel"] { padding-left: 40px; }
.sw-c2-form .sw-form input[type="tel"]:focus {
	outline: none;
	border-color: var(--sw-blue-400);
	box-shadow: 0 0 0 3px rgba(91, 155, 213, 0.18);
}

/* Controls read as one set.
   Section 28 fills text inputs and the textarea with --sw-blue-25 but leaves
   `select` white, so the two dropdowns sat visibly apart from the four fields
   above them and the form looked half-finished. The tint is clearly the theme's
   intent — two of three control types use it — so the selects are brought into
   line rather than overriding all three to white. One rule instead of three,
   and it keeps the theme's own decision.

   Also `font-size: 15px` to match the inputs; the selects were 14.5px, which is
   the kind of half-pixel difference that reads as sloppy without being nameable. */
.sw-c2-form .sw-form select {
	background-color: var(--sw-blue-25);
	font-size: 15px;
}
.sw-c2-form .sw-form select:focus {
	outline: none;
	border-color: var(--sw-blue-400);
	box-shadow: 0 0 0 3px rgba(91, 155, 213, 0.18);
}

/* Aside */
.sw-c2-aside { margin-bottom: 20px !important; }
.sw-c2-aside h2 { font-size: 19px; margin-bottom: 4px; }
.sw-c2-aside .et_pb_text_inner > p { margin-bottom: 18px; font-size: 13.5px; }
.sw-c2-aside ul { list-style: none; margin: 0; padding: 0; }
.sw-c2-aside li { display: flex; gap: 13px; padding: 13px 0; border-top: 1px solid var(--sw-border-light); }
.sw-c2-aside li:first-child { border-top: 0; padding-top: 0; }
.sw-c2-aside__icon {
	display: grid;
	place-items: center;
	flex: 0 0 auto;
	width: 38px;
	height: 38px;
	border-radius: 10px;
	background: var(--sw-blue-50);
	color: var(--sw-blue-600);
}
.sw-c2-aside b { display: block; font-size: 13.5px; font-weight: 700; color: var(--sw-slate); }
.sw-c2-aside a { color: var(--sw-blue-600); font-weight: 600; text-decoration: none; }
.sw-c2-aside a:hover { text-decoration: underline; }
/* A value that is not a link must not look like one. Same weight as an anchor
   so the rows still align, but slate rather than blue and not italic. */
.sw-c2-aside__val { font-style: normal; font-weight: 600; color: var(--sw-slate); }
/* Classed, NOT `.sw-c2-aside span`. That bare form is (0,1,1) and out-ranked
   the icon tile's own (0,1,0) rule, so the tile inherited `display: block` plus
   a 2px nudge meant for this sub-line and its glyph sat top-left instead of
   centred. A rule aimed at one element hitting its sibling is the failure this
   whole stylesheet keeps repeating. */
.sw-c2-aside__sub { display: block; font-size: 12px; line-height: 1.55; color: var(--sw-muted); margin-top: 2px; }
.sw-c2-aside__body { display: block; }

/* The audit card is the page's one primary CTA, so it gets the dark surface.
   The button stays a separate MODULE so it remains editable in the Builder
   rather than baked into the card's HTML — but the two are joined visually into
   one component: the card loses its bottom corners, the button loses its top
   corners, and the gap between them goes to zero. Previously they read as two
   unrelated blocks with a gap, which is what made that corner of the page look
   unresolved. */
.sw-c2-audit { margin-bottom: 0 !important; }
.sw-c2-form__side .et_pb_button_module_wrapper { margin: 0 !important; }
.sw-c2-form__side .sw-btn.et_pb_button {
	width: 100%;
	justify-content: center;
	border-radius: 0 0 var(--sw-card-radius) var(--sw-card-radius);
}
/* Padding written at (0,3,1) — through `.et_pb_text_inner` — for two reasons.
   It matches `.sw-c2-card` (30/28/32) so the two cards stacked in this column
   agree instead of differing by 4-6px on every edge. And the bottom value only
   survives at this specificity: `.sw-divi .et_pb_text_inner > :last-child`
   zeroes padding-bottom at (0,3,0), and this card IS that last child, so at
   (0,1,0) the bottom padding computed to 0 and the list sat flush against the
   button below. */
.sw-c2-audit .et_pb_text_inner > .sw-c2-audit__in {
	padding: 30px 28px 32px;
}
.sw-c2-audit__in {
	position: relative;
	overflow: hidden;
	/* Top corners only: the button module directly below takes the bottom two,
	   so card and button read as one component rather than two stacked blocks. */
	border-radius: var(--sw-card-radius) var(--sw-card-radius) 0 0;
	background: var(--sw-navy-850);
}
/* One soft light source so the panel is not a flat navy rectangle. Same device
   as the hero, at a fraction of the size. */
.sw-c2-audit__in::before {
	content: "";
	position: absolute;
	top: -90px;
	right: -70px;
	width: 260px;
	height: 220px;
	border-radius: 50%;
	pointer-events: none;
	background: radial-gradient(circle, rgba(91, 155, 213, 0.22) 0%, rgba(91, 155, 213, 0) 70%);
}
.sw-c2-audit__in > * { position: relative; z-index: 1; }

/* "Fixed fee" is the one commitment the offer makes, so it gets to be a label
   rather than a clause buried mid-sentence. */
.sw-c2-audit__tag {
	display: inline-block;
	margin: 0 0 12px !important;
	padding: 5px 11px;
	border: 1px solid rgba(155, 194, 229, 0.3);
	border-radius: 999px;
	background: rgba(155, 194, 229, 0.1);
	font-size: 10.5px;
	font-weight: 800;
	letter-spacing: 1.2px;
	text-transform: uppercase;
	line-height: 1;
	color: var(--sw-blue-200);
}
.sw-c2-audit h3 {
	margin: 0 0 10px;
	padding: 0;
	font-size: 19px;
	font-weight: 700;
	line-height: 1.25;
	letter-spacing: -0.4px;
	color: var(--sw-white);
	text-wrap: balance;
}
.sw-c2-audit ul { list-style: none; margin: 16px 0 0; padding: 0; }
.sw-c2-audit li {
	display: flex;
	align-items: flex-start;
	gap: 9px;
	margin-bottom: 9px;
	font-size: 12.5px;
	line-height: 1.5;
	color: var(--sw-blue-200);
}
.sw-c2-audit li:last-child { margin-bottom: 0; }
.sw-c2-audit li svg { flex: 0 0 auto; margin-top: 2px; color: var(--sw-blue-400); }
/* Second defence, per the documented wpautop trap: even with block-then-block
   content, an empty <p> can still appear, and its margin is invisible until it
   opens a gap nobody can find in the CSS. */
.sw-c2-audit p:empty,
.sw-c2-audit__in > p:empty { display: none; }
/* Zero bottom margin: the paragraph is the card's last child and the card's own
   28px padding owns that space. A trailing margin here was the same 18px as the
   gap that appeared under the card. */
.sw-c2-audit p { margin: 0; font-size: 13.5px; line-height: 1.7; color: var(--sw-blue-200); }

/* ---- 3. what happens next ------------------------------------------------
   Cards, not divided columns. The live page draws vertical rules between four
   equal cells; the cells stretch to the tallest, so the rules run well past the
   text they are meant to separate. Cards absorb that height legitimately. */
.sw-c2-next__head { max-width: 720px !important; text-align: center; margin-bottom: 40px !important; }
.sw-c2-next__head .et_pb_module { margin-bottom: 12px; }
.sw-c2-next__head h2 {
	margin: 0;
	padding: 0;
	font-size: 34px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.8px;
	color: var(--sw-slate);
	text-wrap: balance;
}
.sw-c2-next__head p { margin: 0; font-size: 15px; line-height: 1.7; color: var(--sw-muted); }
/* Divi stamps .et_pb_text_align_left on every text module; centring inherited
   from the row loses to it, so it is won back here at (0,3,0). */
.sw-c2-next__head .et_pb_text.et_pb_module { text-align: center; }

/* Equal heights come from DIVI: the row sets `makeEqual` — Divi's "Equalize
   Column Heights" — which is a real Builder toggle a client can see, and it
   emits `et_pb_equal_columns` to stretch the columns.

   The MODULE is the card, with no inner wrapper. That is what lets the card
   actually fill the stretched column: a wrapper div inside `.et_pb_text_inner`
   is two levels down from the column, and a percentage height cannot resolve
   through them. Styling the module directly means Divi's equalisation reaches
   the card with one rule instead of a flex override at every level. */
.sw-c2-next__row > .et_pb_column { margin-bottom: 0; }
.sw-c2-step {
	height: 100%;
	margin-bottom: 0 !important;
	padding: 24px 22px 26px;
	background: var(--sw-white);
	border: var(--sw-card-border);
	border-radius: var(--sw-card-radius);
	box-shadow: var(--sw-shadow-sm);
	transition: var(--sw-card-transition);
}
.sw-c2-step:hover { transform: translateY(-3px); box-shadow: var(--sw-shadow-md); }
.sw-c2-step__num {
	display: block;
	margin-bottom: 12px;
	font-size: 12px;
	font-weight: 800;
	letter-spacing: 1.4px;
	color: var(--sw-blue-400);
}
.sw-c2-step b {
	display: block;
	margin-bottom: 7px;
	font-size: 16px;
	font-weight: 700;
	line-height: 1.3;
	color: var(--sw-slate);
}
.sw-c2-step p { margin: 0; font-size: 13.5px; line-height: 1.65; color: var(--sw-muted); }

/* ---- tablet -------------------------------------------------------------- */
@media (max-width: 980px) {
	.sw-c2-hero__title h1 { font-size: 40px; letter-spacing: -1px; }
	.sw-c2-next__head h2 { font-size: 30px; }

	/* Form leads; the aside follows it rather than sitting beside it. */
	.sw-c2-form__row > .et_pb_column { width: 100% !important; margin: 0 0 24px !important; }
	.sw-c2-form__row > .et_pb_column:last-child { margin-bottom: 0 !important; }

	/* 4 -> 2 */
	.sw-c2-next__row > .et_pb_column { width: 48.75% !important; margin-right: 2.5% !important; margin-bottom: 20px; }
	.sw-c2-next__row > .et_pb_column:nth-child(2n) { margin-right: 0 !important; }
}

/* ---- phone --------------------------------------------------------------- */
@media (max-width: 767px) {
	.sw-c2-hero__title h1 { font-size: 30px; letter-spacing: -0.6px; }
	.sw-c2-next__head h2 { font-size: 24px; letter-spacing: -0.5px; }

	.sw-c2-card { padding: 22px 18px 24px; }
	.sw-c2-hero__trust ul { gap: 8px; }
	.sw-c2-hero__trust li { padding: 8px 13px; font-size: 12px; }

	.sw-c2-next__row > .et_pb_column { width: 100% !important; margin-right: 0 !important; margin-bottom: 16px; }
}

/* ===========================================================================
   43. About v2  —  page "about-us-v2" (Divi layout, pipeline v2)
   ---------------------------------------------------------------------------
   ADDITIVE ONLY: every selector begins sw-ab2-, so /about-us/ cannot change.
   That page stays on templates/page-about.php with its own section 33.

   Deliberately SHORT, because section 41 now carries the shared layer. Bands,
   surfaces, heading scale, ledes, cards and grids all come from there; what is
   left here is only what is genuinely specific to this page.

   WHAT THIS REDESIGN FIXES, all observed on the live page:

     1. FOUR PLACEHOLDER METRICS SHIPPED PUBLICLY — "##+ Years of Experience",
        "##+ Projects Delivered", "##% Client Satisfaction", "##K+ Hours
        Automated". Somebody did the right thing by not inventing numbers, but
        `##` renders to visitors as a broken page. v2 drops the strip and puts
        three VERIFIABLE facts in its place: founded 2016, Swiss infrastructure,
        registered as Stadeli LLC — every one of them already stated elsewhere
        on the same page.
     2. A large empty box in the hero captioned "SeriousWeb Studio", holding
        space for artwork that does not exist.
     3. Project tiles in purple and green. The site is one blue ramp at ~207
        degrees; those were leftover placeholder colours.
     4. A grey circle captioned "Founder" where a portrait would go.
     5. The closing CTA read "Schedule a Free Consultation" — a different offer
        from the site's stated lead offer, and not the canonical CTA label.
   =========================================================================== */

/* ---- 1. hero -------------------------------------------------------------
   Same construction as the contact hero so the two dark heroes are siblings:
   sparse diagonal, outlined shapes, soft curve, all masked clear of the header
   so the band and the header read as one surface. */
.et_pb_section.sw-ab2-hero { position: relative; overflow: hidden; }
.sw-ab2-hero::before {
	content: "";
	position: absolute;
	inset: 0;
	pointer-events: none;
	background-image:
		repeating-linear-gradient(168deg, rgba(155, 194, 229, 0.16) 0 1px, transparent 1px 460px);
	-webkit-mask-image: linear-gradient(180deg, transparent 0, #000 120px, #000 70%, transparent 97%);
	mask-image: linear-gradient(180deg, transparent 0, #000 120px, #000 70%, transparent 97%);
}
.sw-ab2-hero::after {
	content: "";
	position: absolute;
	inset: 0;
	pointer-events: none;
	background-image:
		radial-gradient(ellipse 1100px 520px at 108% 128%,
			rgba(155, 194, 229, 0.1) 0 60%, rgba(155, 194, 229, 0) 61%),
		linear-gradient(158deg,
			rgba(8, 82, 150, 0.34) 0%,
			rgba(8, 82, 150, 0.1) 44%,
			rgba(4, 31, 56, 0) 74%);
	-webkit-mask-image: linear-gradient(180deg, transparent 0, #000 140px);
	mask-image: linear-gradient(180deg, transparent 0, #000 140px);
}
.sw-ab2-hero__row { position: relative; z-index: 1; }
.sw-ab2-hero__row::before,
.sw-ab2-hero__row::after {
	content: "";
	position: absolute;
	pointer-events: none;
	border: 1px solid rgba(155, 194, 229, 0.3);
	z-index: 0;
}
.sw-ab2-hero__row::before { top: 8px; right: -6px; width: 88px; height: 88px; border-radius: 6px; }
.sw-ab2-hero__row::after {
	bottom: 12px; left: 6px; width: 44px; height: 44px; border-radius: 50%;
	border-color: rgba(91, 155, 213, 0.42);
}

.sw-ab2-hero .sw-eyebrow.et_pb_module p {
	display: inline-block;
	padding: 10px 18px !important;
	border: 1px solid rgba(155, 194, 229, 0.32);
	border-radius: 999px;
	background: rgba(155, 194, 229, 0.11);
	color: var(--sw-white);
	line-height: 1;
}
.sw-ab2-hero__title.et_pb_module { margin-bottom: 18px !important; }
.sw-ab2-hero__title h1 {
	margin: 0 auto;
	padding: 0;
	max-width: 840px;
	font-size: 52px;
	font-weight: 700;
	line-height: 1.1;
	letter-spacing: -1.4px;
	color: var(--sw-white);
	text-wrap: balance;
}
.sw-ab2-hero__lede p {
	margin: 0 auto;
	max-width: 620px;
	font-size: 16px;
	line-height: 1.75;
	color: var(--sw-blue-200);
}

/* ---- 2. the fact strip ---------------------------------------------------
   THIS REPLACES THE "##" METRICS. Three statements, each verifiable from the
   company record already published further down this same page. No counts, no
   percentages, no durations — if a real measured figure ever exists it belongs
   here, but until then this says something true rather than something shaped
   like a number. */
.sw-ab2-hero__facts { margin-top: 32px !important; }
.sw-ab2-hero__facts ul {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 10px;
	margin: 0;
	padding: 0;
	list-style: none;
}
.sw-ab2-hero__facts li {
	display: flex;
	align-items: center;
	gap: 9px;
	padding: 10px 18px;
	border: 1px solid var(--sw-border-dark);
	border-radius: 999px;
	background: rgba(155, 194, 229, 0.05);
	font-size: 13px;
	font-weight: 600;
	color: var(--sw-blue-200);
}
.sw-ab2-hero__facts svg { flex: 0 0 auto; color: var(--sw-blue-400); }

/* ---- 3. capability cards -------------------------------------------------
   Shell, padding, radius and hover all come from .sw-card in section 41. */
.sw-ab2-cap { height: 100%; margin-bottom: 0 !important; }
.sw-ab2-cap svg { display: block; margin: 0 0 12px; color: var(--sw-blue-600); }
.sw-ab2-cap h3 {
	margin: 0 0 7px;
	padding: 0;
	font-size: 15.5px;
	font-weight: 700;
	line-height: 1.3;
	color: var(--sw-slate);
}
.sw-ab2-cap p { margin: 0; font-size: 13.5px; line-height: 1.65; color: var(--sw-muted); }

/* ---- 4. project cards ----------------------------------------------------
   Text only, and that is the honest choice: there are no screenshots in the
   tree, and on an About page the projects are supporting proof rather than the
   subject — four more placeholder boxes would say less than four clean cards.
   The live page used purple and green tiles, which were leftover placeholder
   colours from an old dataset and the only non-ramp hues on the site. */
.sw-ab2-proj { height: 100%; margin-bottom: 0 !important; }
.sw-ab2-proj__cat {
	display: block;
	margin-bottom: 8px;
	font-size: 10.5px;
	font-weight: 800;
	letter-spacing: 1.2px;
	text-transform: uppercase;
	color: var(--sw-blue-500);
}
.sw-ab2-proj h3 {
	margin: 0 0 7px;
	padding: 0;
	font-size: 16px;
	font-weight: 700;
	line-height: 1.3;
	color: var(--sw-slate);
}
.sw-ab2-proj p { margin: 0; font-size: 13px; line-height: 1.65; color: var(--sw-muted); }

/* ---- 5. founder ----------------------------------------------------------
   A monogram, not a grey circle captioned "Founder". No portrait exists, and a
   set of initials in the brand's own colours reads as a deliberate mark rather
   than a missing asset. Swap for a real photograph when there is one. */
.sw-ab2-founder { margin-bottom: 0 !important; }
.sw-ab2-founder__grid { display: grid; grid-template-columns: 96px minmax(0, 1fr); gap: 22px; }
.sw-ab2-mono {
	display: grid;
	place-items: center;
	width: 96px;
	height: 96px;
	border-radius: 50%;
	background: linear-gradient(140deg, var(--sw-blue-600) 0%, var(--sw-blue-400) 100%);
	color: var(--sw-white);
	font-size: 30px;
	font-weight: 800;
	letter-spacing: 0.5px;
	line-height: 1;
}
.sw-ab2-founder h3 { margin: 0 0 2px; padding: 0; font-size: 21px; font-weight: 700; color: var(--sw-slate); }
.sw-ab2-founder__role {
	margin: 0 0 14px;
	font-size: 13px;
	font-weight: 700;
	letter-spacing: 0.4px;
	color: var(--sw-blue-500);
}
.sw-ab2-founder p { margin: 0 0 14px; font-size: 14px; line-height: 1.7; color: var(--sw-muted); }
.sw-ab2-founder ul { list-style: none; margin: 0; padding: 0; }
.sw-ab2-founder li {
	display: flex;
	align-items: flex-start;
	gap: 9px;
	margin-bottom: 8px;
	font-size: 13px;
	line-height: 1.5;
	color: var(--sw-slate);
}
.sw-ab2-founder li svg { flex: 0 0 auto; margin-top: 2px; color: var(--sw-blue-500); }

/* ---- 6. company facts ----------------------------------------------------
   A definition list, because that is what it is: term and value. The live page
   used a table, which is heavier markup for the same two columns. */
.sw-ab2-co { margin-bottom: 0 !important; }
/* Sized to match the founder card's name beside it. Without this the h2 falls
   back to the theme's default heading size and the record card shouts louder
   than the person it sits next to. */
.sw-ab2-co h2 {
	margin: 0 0 14px;
	padding: 0;
	font-size: 19px;
	font-weight: 700;
	line-height: 1.3;
	letter-spacing: -0.3px;
	color: var(--sw-slate);
}
.sw-ab2-co dl { display: grid; grid-template-columns: 128px minmax(0, 1fr); margin: 0; }
.sw-ab2-co dt,
.sw-ab2-co dd {
	margin: 0;
	padding: 11px 0;
	border-top: 1px solid var(--sw-border-light);
	font-size: 13px;
	line-height: 1.6;
}
.sw-ab2-co dt:first-of-type,
.sw-ab2-co dl > dt:first-of-type + dd { border-top: 0; }
.sw-ab2-co dt { color: var(--sw-muted); }
.sw-ab2-co dd { font-weight: 600; color: var(--sw-slate); }
.sw-ab2-co a { color: var(--sw-blue-600); text-decoration: none; }
.sw-ab2-co a:hover { text-decoration: underline; }

/* ---- 7. closing CTA ------------------------------------------------------ */
.et_pb_section.sw-ab2-cta { position: relative; overflow: hidden; }
.sw-ab2-cta::after {
	content: "";
	position: absolute;
	top: 0;
	right: 0;
	width: 320px;
	height: 100%;
	background-image: radial-gradient(rgba(155, 194, 229, 0.16) 1px, transparent 1px);
	background-size: 14px 14px;
	pointer-events: none;
}
.sw-ab2-cta__row { position: relative; z-index: 1; }
.sw-ab2-cta__title h2 {
	margin: 0 0 10px;
	padding: 0;
	font-size: 30px;
	font-weight: 700;
	line-height: 1.24;
	letter-spacing: -0.8px;
	color: var(--sw-white);
	text-wrap: balance;
}
.sw-ab2-cta__lede p { margin: 0; font-size: 14.5px; line-height: 1.75; color: var(--sw-blue-200); }

/* ---- tablet -------------------------------------------------------------- */
@media (max-width: 980px) {
	.sw-ab2-hero__title h1 { font-size: 40px; letter-spacing: -1px; }
	.sw-ab2-row > .et_pb_column { width: 100% !important; margin: 0 0 26px !important; }
	.sw-ab2-row > .et_pb_column:last-child { margin-bottom: 0 !important; }
	.sw-ab2-grid > .et_pb_column { width: 48.75% !important; margin-right: 2.5% !important; margin-bottom: 20px; }
	.sw-ab2-grid > .et_pb_column:nth-child(2n) { margin-right: 0 !important; }
}

/* ---- phone --------------------------------------------------------------- */
@media (max-width: 767px) {
	.sw-ab2-hero__title h1 { font-size: 30px; letter-spacing: -0.6px; }
	.sw-ab2-cta__title h2 { font-size: 23px; }
	.sw-ab2-hero__facts li { padding: 8px 13px; font-size: 12px; }
	.sw-ab2-grid > .et_pb_column { width: 100% !important; margin-right: 0 !important; margin-bottom: 16px; }
	.sw-ab2-founder__grid { grid-template-columns: minmax(0, 1fr); gap: 16px; }
	.sw-ab2-co dl { grid-template-columns: minmax(0, 1fr); }
	.sw-ab2-co dt { padding-bottom: 0; border-top: 0; }
	.sw-ab2-co dd { padding-top: 2px; border-top: 0; }
	.sw-ab2-co dt { border-top: 1px solid var(--sw-border-light); padding-top: 11px; }
}

/* ===========================================================================
   44. Homepage v3  —  page "home-v3" (Divi layout, pipeline v2)
   ---------------------------------------------------------------------------
   SOURCE OF TRUTH IS templates/jsonimports/home-v3.spec.json, not a PHP
   template. This is a real builder page: the layout is stored as Divi 5 blocks,
   `_et_pb_use_builder` is set, and it opens in the Divi Builder. Rebuild with

       node .claude/skills/divi-export/page-sync.mjs \
            wp-content/themes/seriousweb/templates/jsonimports/home-v3.spec.json 319

   It was first built the v1 way, as templates/page-home-v3.php, and migrated
   with spec-from-page.mjs. That template has been retired — see the note at the
   end of this section for what changed in the move, because several rules here
   were correct on the template and would have been wrong on the layout.

   THE DESIGN. Rebuilt from the live site, restyled so no two neighbouring bands
   share a surface. v2 (§35) ran white / light / white / white / tint / white /
   white: six of its eight bands sat within one step of each other, which is why
   the middle of that page reads as a single slab about 1400px tall. v3 rotates
   three tones, and every seam is a real edge:

       hero       --sw-navy-900  #041f38   .sw-band--dark
       caps       --sw-white     #ffffff   .sw-band--white
       solutions  --sw-blue-25   #f5f9fc   .sw-band--tint
       process    --sw-navy-900  #041f38   .sw-band--dark
       why        --sw-white     #ffffff   .sw-band--white
       close      --sw-blue-25   #f5f9fc   .sw-band--tint

   `close` is ONE section holding two rows — the dark results panel and the
   gradient CTA panel. On the template those were two sections sharing a tint
   trough, with the CTA carrying no top padding so the 96px gap between the
   panels was not split by a seam. A spec cannot express that: `pad` is
   [desktop, tablet, phone] applied symmetrically, so 0-top / 96-bottom has no
   representation. Merging them says the same thing honestly, and every section
   now shows padding numbers in the Builder that match what it renders.

   THE BACKGROUNDS ARE ON THE BLOCKS, and so is the padding. Divi generates a
   per-section rule from the layout's own attributes that out-ranks a shared
   class, so `.sw-band--*` and `.et_pb_section.sw-band` are the fallback they
   always were. Both agree today. Change a surface in the Builder, not here.

   THIS PAGE ADOPTS SECTION 41, which is most of why this block is a third the
   length of §35. Surfaces, heading scale, lede, eyebrow, card surface, grid and
   their breakpoints all come from there. The rotation is nearly free as a
   result: §41 already switches heading, lede and eyebrow to their on-dark
   colours under .sw-band--dark, so moving the process band onto navy needed no
   per-element colour rules — only the step component, which is this page's own,
   has on-dark variants restated below.

   WHAT THE v1 -> v2 MOVE CHANGED, all of it the same lesson — Divi's own
   generated CSS and its module wrappers do not exist on a PHP template, so the
   template can look right while the layout is wrong:

     - `.sw-h3-head` had to become `.et_pb_row.sw-h3-head`. Divi writes
       `.et_pb_row_<n> { max-width: 1240px !important }` at (0,1,0), later in
       source, so the bare class tied and lost and the centred heading block
       spanned the full row.
     - `.sw-h3-cta-copy .et_pb_module` needed !important, against the gutter
       rule `.et_pb_gutters3 .et_pb_column_<t> .et_pb_module` — (0,4,0), and a
       PERCENTAGE, so the loss is tens of pixels rather than a few.
     - The hero's `<div class="sw-h3-btns">` flex row is gone. A wrapper div
       inside a column has no equivalent in a layout; the column carries §39's
       `sw-btn-inline` instead.
     - Full-width phone buttons had to move to the wrapper, not the anchor.

   Classes are sw-h3-* rather than reusing v2's sw-h2-*, per the house rule that
   a new page never borrows another page's namespace — restyling this page must
   not be able to change any page already assigned to Home v2.
   =========================================================================== */

/* ---- band padding ---------------------------------------------------------
   NOT SET HERE. This is a pipeline-v2 builder page, so every section's padding
   is an attribute on the section block (128/92/68 on the hero, 96/72/56 on the
   rest) and Divi generates a per-section rule for it that out-ranks any shared
   class. §41's `.et_pb_section.sw-band { padding: 96px 0 }` remains as the
   fallback it always was.

   The practical consequence, and the reason this note exists rather than a
   rule: section padding on this page is edited in the Builder, not in the
   stylesheet. A padding rule written here would look authoritative and lose. */

/* ---- 1. hero -------------------------------------------------------------
   Centred, matching every band heading below it, so the hero is not the one
   band with its own alignment. .sw-hero's base glows (§4) sit hard right, where
   this design has no artwork; these re-centre them behind the headline. Same
   (0,1,0) as the base rules and later in the file, so no !important is needed
   and the v1 homepage, which still has its artwork, is untouched. */
/* THE TOP FADE IS WHAT MAKES THE HEADER SEAM DISAPPEAR, and it is the half
   that is easy to leave out. The header is --sw-ink, rgb(4,31,56), the exact
   colour this band's gradient starts from — so the two read as one surface only
   while the hero's first ~120px are untouched. This glow is centred and at
   nearly full strength at y=0, which measured #053057 against the header's
   #041F38: a light band pressed straight against flat navy, drawing a hard line
   across the full width. §42 hit the same thing on Contact v2 and records the
   same fix.

   BOTH GLOWS NOW LIVE IN ::before, as two background layers on one full-bleed
   box. §4 gives .sw-hero two pseudo-elements and the v1 template spent one on
   each glow — which left nothing for the decoration below, since a section has
   only those two. Collapsing them costs nothing: they were only ever radial
   gradients, and a gradient positioned `at <x> <y>` places as precisely as a
   sized, offset box did.

   It also makes the mask honest. Full-bleed, it is section-relative, so
   `transparent 0, #000 150px` means what it says. On the old 720px box offset
   top:-260px the same intent had to be written 36% and 58%, and silently broke
   if either number moved. */
.sw-h3-hero::before {
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	width: auto;
	height: auto;
	transform: none;
	border-radius: 0;
	background-image:
		radial-gradient(900px 720px at 50% -260px,
			rgba(8, 82, 150, 0.38) 0%, rgba(8, 82, 150, 0) 66%),
		radial-gradient(760px 620px at 50% calc(100% + 320px),
			rgba(91, 155, 213, 0.22) 0%, rgba(91, 155, 213, 0) 68%);
	-webkit-mask-image: linear-gradient(180deg, transparent 0, #000 150px);
	mask-image: linear-gradient(180deg, transparent 0, #000 150px);
}

/* ---- hero decoration ------------------------------------------------------
   Same vocabulary as Contact v2's hero (§42) — diagonal ruling, soft corner
   sweep, an outlined square and a ring — so the two pages read as one site.
   What differs is the motif on the row, deliberately; see .sw-h3-hero-row.

   ::after carries the two FULL-BLEED layers, which is what freeing it above was
   for. A row-level element cannot do this: the row is capped at 1240px and
   centred, so anything drawn on it stops well short of the band's edges.

   THE RULING IS MASKED OFF THE CENTRE FROM THE START. Sparse diagonals plus
   centred copy is precisely the defect just fixed on Contact v2 — with ~3
   sweeps across 1440px one lands on the headline, and a single hairline through
   a title reads as a rendering artifact rather than as light. Tightening the
   spacing is NOT the fix; §42 records that attempt and it hatched. So the
   sweeps keep to the edges, and the same top fade keeps them off the header. */
.sw-h3-hero::after {
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	width: auto;
	height: auto;
	transform: none;
	border-radius: 0;
	background-image:
		/* An over-sized ellipse whose EDGE is the curve, so only its top-left arc
		   crosses the band and what shows is one long sweep, not a blob. */
		radial-gradient(ellipse 1100px 520px at 106% 126%,
			rgba(155, 194, 229, 0.10) 0 60%, rgba(155, 194, 229, 0) 61%),
		repeating-linear-gradient(168deg,
			rgba(155, 194, 229, 0.13) 0 1px, transparent 1px 460px);
	-webkit-mask-image:
		linear-gradient(180deg, transparent 0, #000 150px, #000 74%, transparent 98%),
		radial-gradient(ellipse 42% 56% at 50% 48%, transparent 0 58%, #000 100%);
	mask-image:
		linear-gradient(180deg, transparent 0, #000 150px, #000 74%, transparent 98%),
		radial-gradient(ellipse 42% 56% at 50% 48%, transparent 0 58%, #000 100%);
	-webkit-mask-composite: source-in;
	mask-composite: intersect;
}

/* ---- the motif, and why it is not Contact v2's squares ---------------------
   Contact v2's shapes are abstract on purpose: that page is a form, and its
   hero should not compete for meaning. This page's hero says "we help
   businesses work smarter with AI", and the page itself already speaks a
   visual language for that — the process band draws five nodes joined by 2px
   dashed connectors. So the home hero gets the same graph, quietly, at the
   right-hand edge: four nodes, dashed links, one branch and one merge. It reads
   as an automation flow to anyone who looks and as texture to anyone who does
   not, and it is the page's own vocabulary rather than an import.

   Drawn as an inline SVG data URI, not with gradients. Rings and short diagonal
   dashed segments are the two things background gradients are worst at, and one
   background-image beats five stacked pseudo-elements the page does not have.
   The stroke colour is baked in: currentColor does NOT resolve inside a data
   URI, so this cannot inherit and has to be stated. */
/* `visibility: visible` AND `clear: none` are both load-bearing, and the reason
   is Divi's float clearfix on the ROW:

     .et_block_row:after {
       content: ""; display: block; clear: both;
       visibility: hidden; line-height: 0; height: 0; width: 0;
     }

   Note `.et_block_row`, not `.et_pb_row` — grepping for the latter finds
   nothing and reads as proof there is no collision. It is (0,1,0), so this
   rule's (0,2,0) already wins width, height and border; what it does NOT
   contest unless stated is `visibility`. The square therefore rendered at its
   full 84x84 with its border, entirely invisible.

   It applies to `:after` only, which is why ::before drew perfectly and
   ::after did not — a split that reads as a typo in one rule rather than as a
   collision, and cost a wrong diagnosis before a loud-colour test settled it.
   Anything decorative on a Divi row's ::after needs this line. */
.et_pb_row.sw-h3-hero-row { position: relative; }
.et_pb_row.sw-h3-hero-row::before,
.et_pb_row.sw-h3-hero-row::after {
	content: "";
	position: absolute;
	display: block;
	visibility: visible;
	clear: none;
	line-height: 0;
	pointer-events: none;
	z-index: 0;
}
.et_pb_row.sw-h3-hero-row::before {
	top: 12%;
	right: -58px;
	width: 218px;
	height: 160px;
	background-repeat: no-repeat;
	background-size: contain;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='218' height='160' fill='none' stroke='rgba(155,194,229,0.38)' stroke-width='1'%3E%3Cpath d='M26 80 L96 42 M26 80 L96 118 M96 42 L166 80 M96 118 L166 80' stroke-dasharray='4 5'/%3E%3Ccircle cx='26' cy='80' r='7'/%3E%3Ccircle cx='96' cy='42' r='7'/%3E%3Ccircle cx='96' cy='118' r='7'/%3E%3Ccircle cx='166' cy='80' r='7'/%3E%3C/svg%3E");
}

/* Outlined square, upper right — an OUTLINE, not a fill, which is what keeps it
   quiet enough to sit near a headline. The alpha is higher than the Contact
   reference's because it sits on navy, where a hairline at 0.16 disappears. */
.et_pb_row.sw-h3-hero-row::after {
	top: -14px;
	right: -10px;
	width: 84px;
	height: 84px;
	border: 1px solid rgba(155, 194, 229, 0.30);
	border-radius: 6px;
}

/* Ring, left of the copy — offset rather than mirrored, so the two sides do not
   read as a frame. */
.sw-h3-hero-copy::after {
	content: "";
	position: absolute;
	left: -6px;
	bottom: 12%;
	width: 34px;
	height: 34px;
	border: 1px solid rgba(91, 155, 213, 0.46);
	border-radius: 50%;
	pointer-events: none;
	z-index: 0;
}
.et_pb_column.sw-h3-hero-copy { position: relative; }

/* Everything above is decoration, and at tablet the hero has no room to spare:
   the row narrows to the copy's own measure, so the motif and the square would
   sit on the text rather than beside it. */
@media (max-width: 980px) {
	.et_pb_row.sw-h3-hero-row::before,
	.et_pb_row.sw-h3-hero-row::after,
	.sw-h3-hero-copy::after { display: none; }
}

/* The column stays full width and the measure is capped on the children.
   Centring the column itself does not work: auto margins would have to beat
   `.sw-divi .et_pb_column.et-last-child { margin-right: 0 }` at (0,3,0), so
   only margin-left resolves to auto and the hero lands ~190px right of centre. */
.sw-h3-hero-copy { display: block; }

.sw-h3-hero-title h1 {
	max-width: 860px;
	margin: 0 auto;
	padding: 0;
	font-size: 58px;
	font-weight: 700;
	line-height: 1.1;
	letter-spacing: -1.6px;
	color: var(--sw-white);
}
.sw-h3-hero-intro p {
	max-width: 620px;
	margin: 0 auto;
	padding-bottom: 0;
	font-size: 18px;
	line-height: 1.7;
	color: var(--sw-muted-dark);
}
/* The gaps go on the MODULE, not on the h1 or the p: §27 zeroes margin and
   padding on the last child of a text module at (0,3,0), and each of these is
   the only child of its own. !important is for Divi's gutter rule,
   `.et_pb_gutters3 .et_pb_column_<t> .et_pb_module`, which is (0,4,0). */
.sw-stack .sw-h3-hero-title.et_pb_module { margin-bottom: 24px !important; }
.sw-stack .sw-h3-hero-intro.et_pb_module { margin-bottom: 32px !important; }

/* The hero buttons carry NO rule of their own. Each is a real divi/button
   module, and Divi wraps each in a block-level .et_pb_button_module_wrapper —
   so the v1 template's flex `<div class="sw-h3-btns">` has no equivalent here
   (a wrapper div inside a column cannot exist; modules are direct children of
   the column). The column carries `sw-center sw-btn-inline` instead, which is
   §39's bridge for precisely this and is already written to win. Adding an
   sw-h3- rule beside it would be a second answer to a solved problem.

   Only the gap under the row is local: the bridge leaves 10px, and the trust
   line needs to sit clear of the buttons rather than tucked under them. It is
   written as margin-TOP on the trust module, not margin-bottom on the last
   button wrapper. `> .et_pb_button_module_wrapper:last-of-type` is the obvious
   way to say it and is DEAD: `:last-of-type` matches on tag name, every child
   of the column is a `div`, so it selects the trust module itself. That exact
   selector is in this skill's list of rules that silently do nothing. */
.sw-h3-trust.et_pb_module { margin: 22px 0 0 !important; }
.sw-h3-trust__line { margin: 0; padding-bottom: 0; font-size: 14px; color: var(--sw-blue-200); }
.sw-h3-trust__line strong { color: var(--sw-white); font-weight: 700; }

/* ---- band heads -----------------------------------------------------------
   `.et_pb_row.sw-h3-head`, not the bare class. Divi generates `.et_pb_row_<n>
   { max-width: 1240px !important }` per row from the layout's own width
   attribute — (0,1,0) with !important, and it loads after this sheet, so a bare
   `.sw-h3-head { max-width: 760px !important }` ties and loses on source order.
   The heading block then spans the full row and stops reading as centred. This
   is the first entry in the skill's table of rules Divi's generated CSS beats. */
.et_pb_row.sw-h3-head { max-width: 760px !important; margin-bottom: 46px !important; }

/* ---- grids ---------------------------------------------------------------
   .sw-grid (§41) supplies the tracks, the 18px gap and the breakpoint
   step-downs. Two things it deliberately does not do, because they would land
   on every page that has adopted it, are added here instead. */

/* Equal card heights. Each module is a grid item and each module IS a card —
   .sw-card sits on the blurb module itself, not on a div inside it — so the
   module has to fill its track or the cards in a row stop matching.

   There is no longer a companion rule restoring the cards' bottom padding.
   That was needed while the cards were divs inside a Text module, where §27's
   `.sw-divi .et_pb_text_inner > :last-child { padding-bottom: 0 }` flattened
   --sw-card-pad's 28px. A blurb has no .et_pb_text_inner, so the rule cannot
   reach it and the padding survives on its own. */
.sw-h3-grid > .et_pb_module { height: 100%; }

/* The process row is five tracks of short text, not four cards; the shared 18px
   gap leaves the dashed connectors too long to read as one line. */
.et_pb_column.sw-h3-pgrid { gap: 12px; }

/* ===========================================================================
   THE 16 CARDS ARE divi/blurb MODULES.

   So everything below styles DIVI'S blurb DOM, which is:

       .et_pb_blurb                    <- carries .sw-card .sw-h3-card
         .et_pb_blurb_content
           .et_pb_main_blurb_image
             .et_pb_image_wrap
               .et-pb-icon             <- the glyph, from Divi's icon font
           .et_pb_blurb_container
             h3.et_pb_module_header
             .et_pb_blurb_description  <- the <p>s

   Why they are blurbs: the icon, title and description are now fields, so a
   client edits three boxes instead of a div of markup, and can change the glyph
   from the Builder's icon picker. The cost, taken deliberately, is that these
   16 icons are Divi font glyphs rather than the theme's inline SVG set — all
   chosen from Divi's `line` style, the closest match to the theme's stroke
   weight, and each verified against iconList.json with the renderer's own
   three-field comparison. A glyph failing any of the three renders as an empty
   .et-pb-icon, which reads as a design choice rather than a defect.

   NOTE THE REMAINING MIX. The five process badges and four stat icons are
   still inline SVGs, because neither component can be a blurb: a step puts its
   number above the title, and Divi always renders a blurb's title first. Those
   nine sit on the navy and panel surfaces, well away from the card bands, but
   it is a real inconsistency and worth a decision rather than a discovery.
   =========================================================================== */

/* ---- icon tile -----------------------------------------------------------
   The tile is .et_pb_image_wrap, the innermost wrapper around the glyph, so the
   grid cell around it can still be positioned independently. 42px and radius 12
   are the values already used across §35 and §41's card token block.

   Divi's own defaults being undone here: .et_pb_main_blurb_image has a 30px
   bottom margin and the glyph renders at 96px. */
.sw-h3-card .et_pb_main_blurb_image { margin: 0; line-height: 0; }
.sw-h3-scard .et_pb_main_blurb_image { margin: 0 0 14px; line-height: 0; }

/* The tile only. NO `color` here — the glyph's colour is a block attribute
   (`imageIcon.advanced.color`), because Divi generates
   `.et_pb_blurb_<n> > .et_pb_blurb_content > .et_pb_main_blurb_image .et-pb-icon`
   at (0,4,0) inline and any sane stylesheet rule loses to it. Setting it here
   as well would be a rule that reads as authoritative and does nothing. */
.sw-h3-card .et_pb_image_wrap,
.sw-h3-scard .et_pb_image_wrap {
	display: grid;
	place-items: center;
	width: 42px;
	height: 42px;
	border-radius: 12px;
	background: rgba(8, 82, 150, 0.09);
	transition: background-color 0.25s var(--sw-ease);
}
.sw-h3-card .et-pb-icon,
.sw-h3-scard .et-pb-icon { font-size: 22px; line-height: 1; }

/* Hover, and the featured card's own colour, are the two things Divi has no
   setting for — so they ARE CSS, and they need !important to reach past that
   same (0,4,0) generated rule. This is the case where out-ranking is correct
   rather than lazy: there is no attribute to set instead. The tile fills on
   hover so the card has one clear focal response, not just a drift upward. */
.sw-card:hover .et_pb_image_wrap { background: var(--sw-blue-600); }
.sw-card:hover .et_pb_image_wrap .et-pb-icon { color: var(--sw-white) !important; }

/* ---- feature card (bands 2 and 5) ----------------------------------------
   Surface, radius, border, shadow and the hover lift are §41's .sw-card. Only
   the head layout and two type sizes are local. Shared by "How we support your
   business" and "Why businesses choose SeriousWeb" — they are the same
   component and changing one should change both. */
.sw-card.sw-h3-card:hover { border-color: var(--sw-blue-200); }

/* The design puts the icon BESIDE the title, with the description full width
   below — Divi's blurb offers icon-above (position top) or icon-left-of-
   everything, and neither is that. A two-column grid on .et_pb_blurb_content
   with `display: contents` on .et_pb_blurb_container lifts the h3 and the
   description out of their wrapper and into the grid, which reproduces the
   layout exactly without changing the module or adding markup.

   The first row's minmax(52px, auto) is the old .sw-h3-card__head min-height:
   it reserves two lines of title, so a card whose title wraps — "Web Design &
   Development" — does not start its description ~40px below its neighbours'
   and cost the row its shared baseline. */
.sw-h3-card .et_pb_blurb_content {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	grid-template-rows: minmax(52px, auto) auto;
	column-gap: 12px;
	row-gap: 12px;
	max-width: none;
}
.sw-h3-card .et_pb_blurb_container { display: contents; }
.sw-h3-card .et_pb_main_blurb_image { grid-area: 1 / 1; align-self: center; }
.sw-h3-card .et_pb_blurb_description { grid-area: 2 / 1 / 3 / -1; }

/* The `h3` is load-bearing, here and on the step titles below. The shared page
   shell sets `.sw-page h3 { margin-bottom: 0; letter-spacing: -0.4px; color:
   var(--sw-slate) }` at (0,1,1), and every section carries .sw-page — so a bare
   class at (0,1,0) loses all three declarations. On a light band that costs 8px
   and 0.2px of tracking; on the navy process band it replaced white with
   --sw-slate, i.e. navy text on navy. Found by audit.ps1. */
.sw-h3-card h3.et_pb_module_header {
	grid-area: 1 / 2;
	align-self: center;
	margin: 0;
	padding: 0;
	font-size: 17px;
	font-weight: 700;
	line-height: 1.3;
	letter-spacing: -0.2px;
	color: var(--sw-slate);
	text-wrap: balance;
}
.sw-h3-card .et_pb_blurb_description p {
	margin: 0;
	padding-bottom: 0;
	font-size: 15px;
	line-height: 1.7;
	color: var(--sw-muted);
}

/* ---- solution card (band 3) ----------------------------------------------
   Icon above the title here, which IS Divi's default blurb position, so this
   one needs no grid — only a flex chain deep enough to push .sw-card-more to
   the bottom of a card whose description may be shorter than its neighbour's.
   Three levels because the description's <p>s are three wrappers down. */
.sw-h3-scard { position: relative; }
.sw-card.sw-h3-scard:hover { border-color: var(--sw-blue-200); }
.sw-h3-scard .et_pb_blurb_content,
.sw-h3-scard .et_pb_blurb_container,
.sw-h3-scard .et_pb_blurb_description {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	max-width: none;
}
.sw-h3-scard .et_pb_main_blurb_image { flex: 0 0 auto; }

/* The four solution marks step down the blue ramp — one hue, four steps,
   distinguishable without a second palette, the same approach .sw-step--1..4
   uses in §8. That used to be two nth-child rules here; it is now the
   `iconColor` attribute on each of the four blurbs, so the colours are visible
   and editable in the Builder and do not depend on card order. */

.sw-h3-scard h3.et_pb_module_header {
	flex: 0 0 auto;
	margin: 0 0 8px;
	padding: 0;
	font-size: 18px;
	font-weight: 700;
	line-height: 1.3;
	letter-spacing: -0.2px;
	color: var(--sw-slate);
	text-wrap: balance;
}
/* margin-bottom:auto on the description paragraph is what anchors .sw-card-more
   to the bottom. padding-bottom:0 is separate and also doing real work: a global
   `p { padding-bottom: 1em }` applies, and the `p:last-of-type` rule that
   normally cancels it does not match — the last <p> in this card is
   .sw-card-more, not the description. Left alone it puts 15px of dead space in
   every card, which is most of why they stand taller than they need to. */
.sw-h3-scard .et_pb_blurb_description > p:first-child {
	margin: 0 0 auto;
	padding-bottom: 0;
	font-size: 15px;
	line-height: 1.7;
	color: var(--sw-muted);
}

/* Descriptions vary in length, so `margin-bottom: auto` above leaves a gap of
   whatever is left over. A hairline turns that leftover into a deliberate
   footer rule and gives every card the same anchor line regardless of copy. */
.sw-h3-scard .sw-card-more {
	margin: 18px 0 0 !important;
	padding-top: 14px;
	border-top: 1px solid var(--sw-border-light);
}
.sw-h3-scard .sw-card-more a { display: inline-flex; gap: 6px; border-bottom: 0; transition: gap 0.25s var(--sw-ease); }
.sw-h3-scard:hover .sw-card-more a { gap: 12px; }
/* The whole card becomes the click target by stretching the existing link over
   it — no extra markup, and the anchor stays the one focusable element rather
   than the card growing a second tab stop. */
.sw-h3-scard .sw-card-more a::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: var(--sw-card-radius);
}

/* The featured card. A flat fill read as "this one is a different colour"; the
   wash lifts the top-left corner behind the mark and title so the card has its
   own light source and looks intentional next to three white ones. */
.sw-h3-scard--featured {
	background:
		radial-gradient(120% 90% at 0% 0%, rgba(91, 155, 213, 0.22) 0%, rgba(91, 155, 213, 0) 58%),
		var(--sw-navy-850);
	border-color: transparent;
	box-shadow: 0 1px 2px rgba(4, 31, 56, 0.08), 0 16px 34px -20px rgba(4, 31, 56, 0.55);
}
.sw-card.sw-h3-scard--featured:hover {
	border-color: transparent;
	box-shadow: 0 2px 4px rgba(4, 31, 56, 0.1), 0 26px 52px -22px rgba(4, 31, 56, 0.65);
}
.sw-h3-scard--featured .et_pb_image_wrap { background: rgba(155, 194, 229, 0.16); }
.sw-card.sw-h3-scard--featured:hover .et_pb_image_wrap { background: var(--sw-blue-200); }
.sw-card.sw-h3-scard--featured:hover .et_pb_image_wrap .et-pb-icon { color: var(--sw-navy-850) !important; }
.sw-h3-scard--featured h3.et_pb_module_header { color: var(--sw-white); }
.sw-h3-scard--featured .et_pb_blurb_description > p:first-child { color: var(--sw-blue-200); }
.sw-h3-scard--featured .sw-card-more { border-top-color: var(--sw-border-dark); }
.sw-h3-scard--featured .sw-card-more a { color: var(--sw-blue-200); }

/* ---- process step (band 4, on navy) --------------------------------------
   The one component the rotation actually cost. §41 switches headings, ledes
   and eyebrows on .sw-band--dark, but this component is local to the page, so
   its on-dark colours are set here rather than inherited. Text modules, not
   blurbs: the number sits above the title and Divi renders a blurb's title
   before its description, always. */
.sw-h3-step { position: relative; padding: 0 8px; text-align: center; }
.sw-h3-step__badge {
	position: relative;
	z-index: 1;
	display: grid;
	place-items: center;
	width: 62px;
	height: 62px;
	margin: 0 auto 16px;
	border: 1px solid var(--sw-border-dark);
	border-radius: 50%;
	background: var(--sw-navy-800);
	color: var(--sw-blue-200);
}
/* Dashed connector, drawn behind the badges and only between items. */
.sw-h3-pgrid > .et_pb_module:not(:first-child) .sw-h3-step::before {
	content: "";
	position: absolute;
	top: 31px;
	right: 50%;
	left: -50%;
	z-index: 0;
	border-top: 2px dashed var(--sw-border-dark);
}
/* padding-bottom:0 because this <p> is not the last of its type in the step —
   .sw-h3-step__text is — so the global paragraph padding is not cancelled for
   it and would open a 15px hole between the number and the title. */
.sw-h3-step__num {
	margin: 0 0 2px;
	padding-bottom: 0;
	font-size: 13px;
	font-weight: 800;
	letter-spacing: 1px;
	color: var(--sw-blue-400);
}
h3.sw-h3-step__title {
	margin: 0 0 8px;
	padding: 0;
	font-size: 17px;
	font-weight: 700;
	line-height: 1.3;
	letter-spacing: -0.2px;
	color: var(--sw-white);
	text-wrap: balance;
}
.sw-h3-step__text { margin: 0; padding-bottom: 0; font-size: 15px; line-height: 1.7; color: var(--sw-blue-200); }

/* ---- panels (bands 6 and 7) ----------------------------------------------
   The panel is the ROW: background, radius and padding are all things a Divi
   row carries natively, so there is no wrapper div to convert on export. Width
   and max-width are restated because §27 sizes .sw-row and the panel padding
   would otherwise push it past the 1240px measure. */
/* `.et_pb_row.sw-h3-panel`, not the bare class. Divi ships
   `.et_block_row { padding: 27px 0 }` at (0,1,0) inside an inline
   `@media (min-width: 1350px)`, which ties with a bare class and wins on source
   order — so the panels rendered with 27px of vertical padding and none at all
   horizontally, i.e. the copy touching the panel edge. Nothing about that is
   visible in the markup, and it does not happen on a PHP template because that
   rule is part of Divi's generated row CSS. Found by audit.ps1. */
.et_pb_row.sw-h3-panel {
	width: 90%;
	max-width: 1240px;
	padding: 52px 48px;
	border-radius: 22px;
}
/* align-items is split into its own rule, and ONLY it carries the compound
   form. It has to beat `.sw-divi .et_pb_row { align-items: stretch }` (§27,
   (0,2,0)) on the template while standing alone in an export — but a (0,2,0)
   selector wins over a bare class from inside a media query too, so folding the
   padding in with it silently pinned the panel to its desktop 52/48 at tablet
   and phone. Keeping padding at (0,1,0) leaves the breakpoints in charge. */
.sw-h3-panel,
.sw-divi .sw-h3-panel { align-items: center; }
.sw-h3-panel--dark { background-color: var(--sw-navy-850); }
.sw-h3-panel--grad {
	background-image: linear-gradient(
		90deg,
		var(--sw-cta-grad-start) 0%,
		var(--sw-cta-grad-start) 42%,
		var(--sw-cta-grad-end) 100%
	);
}

/* NO column-width overrides. The v1 template needed them — §27's emulated
   fractions are computed against the row's full width, and this row's 48px
   padding ate into them. On a builder page Divi generates its own gutter maths
   against the PADDED content box and gets it right: 47.25 / 5.5 / 47.25 for the
   halves, 57.8 / 5.5 / 36.7 for the 3_5 + 2_5 pair. The template's hand figures
   (47.5 / 5 / 47.5) were a fifth of a percent away and lost anyway.

   Deleted rather than out-ranked, per the house preference for Divi's own
   settings over CSS that restates them. The only widths this page still sets
   are the stacking ones in the tablet block below, which Divi does not do until
   479px — far later than this design wants. */

/* ---- 6. results ---------------------------------------------------------- */
/* Same size as the CTA panel heading below: the two panels are the same width,
   the same radius and adjacent, so a 26 here against a 32 there reads as a
   mistake rather than as a hierarchy. */
.sw-h3-results-title h2,
.sw-h3-cta-copy h2 {
	margin: 0;
	padding: 0;
	font-size: 30px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.6px;
	color: var(--sw-white);
	text-wrap: balance;
}
.sw-h3-results-title.et_pb_module { margin-bottom: 32px !important; }

.sw-h3-statgrid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 24px 16px; }
.sw-h3-stat { display: flex; flex-direction: column; gap: 8px; }
.sw-h3-stat__icon {
	display: grid;
	place-items: center;
	width: 42px;
	height: 42px;
	border-radius: 12px;
	background: rgba(155, 194, 229, 0.14);
	color: var(--sw-blue-200);
}
.sw-h3-stat__num { font-size: 30px; font-weight: 800; line-height: 1.1; color: var(--sw-white); }
.sw-h3-stat__label { font-size: 13px; color: var(--sw-blue-200); }

.sw-h3-quote-col { border-left: 1px solid var(--sw-border-dark); padding-left: 40px; }

/* ---- the quote is a divi/testimonial ------------------------------------
   So this styles DIVI'S DOM, not markup this page wrote. It was a <blockquote>
   with two classed <p> children while the page was a PHP template; as a real
   module the attribution is its own field, which is the whole point — a client
   replacing the placeholder fills in two boxes instead of editing HTML.

   The module arrives with Divi's own card chrome (background, padding, border,
   a quote glyph on ::before) and stamped `et_pb_bg_layout_light`, which sets
   dark text. All of that is wrong on a dark panel, so it is turned off rather
   than worked around. Compound selectors because Divi's own rules are (0,2,0)
   and this sheet has to out-rank them, not tie. */
.sw-h3-quote.et_pb_testimonial {
	margin: 0;
	padding: 0;
	border: 0;
	background-color: transparent;
}
.sw-h3-quote.et_pb_testimonial::before { display: none; }
/* The empty .et_pb_testimonial_meta wrapper only; NOT the portrait. Divi emits
   no portrait element at all without one (it stamps `et_pb_testimonial_no_image`
   instead), so a rule hiding it audits DEAD — and if someone later adds a
   portrait in the Builder, hiding it would be overriding a deliberate choice. */
.sw-h3-quote .et_pb_testimonial_meta { display: none; }
.sw-h3-quote .et_pb_testimonial_description { margin: 0; }
.sw-h3-quote .et_pb_testimonial_content p {
	margin: 0 0 16px;
	padding-bottom: 0;
	font-size: 19px;
	line-height: 1.7;
	color: var(--sw-white);
}
.sw-h3-quote .et_pb_testimonial_content p:last-child { margin-bottom: 16px; }
.sw-h3-quote .et_pb_testimonial_author {
	margin: 0;
	font-size: 14px;
	font-style: normal;
	font-weight: 400;
	color: var(--sw-blue-200);
}

/* ---- 7. final CTA -------------------------------------------------------- */
.sw-h3-cta-copy p {
	margin: 0;
	padding-bottom: 0;
	max-width: 480px;
	font-size: 16px;
	line-height: 1.7;
	color: rgba(255, 255, 255, 0.86);
}
/* !important on both: Divi's gutter rule
   `.et_pb_gutters3 .et_pb_column_<t> .et_pb_module` is (0,4,0) and sets
   margin-bottom as a PERCENTAGE of the column — measured at 7.493% on the page
   that produced these notes, which is roughly 50px of phantom gap. Nothing
   short of !important reaches it, and it does not exist on a PHP template,
   which is why the v1 version of this rule looked correct. */
.sw-h3-cta-copy .et_pb_module { margin-bottom: 14px !important; }
.sw-h3-cta-copy .et_pb_module:last-child { margin-bottom: 0 !important; }

/* ---- the closing band's two panels ----------------------------------------
   Results and the final CTA are two rows in one section now, not two sections
   sharing a trough. Divi gives every row a bottom margin of its own; this makes
   the gap between the panels the same 96px the bands use, and removes it under
   the last one so the section's own 96px bottom padding is the whole space. */
.sw-h3-close > .et_pb_row.sw-h3-panel { margin-bottom: 96px !important; }
.sw-h3-close > .et_pb_row.sw-h3-panel:last-child { margin-bottom: 0 !important; }

/* align-items:center is load-bearing, not cosmetic. The column is a flex item
   of the row and stretches to full panel height; without this the buttons —
   flex items themselves — stretch with it and render as two 140px-tall slabs. */
.sw-h3-cta-btns {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: flex-end;
	gap: 12px;
}
.sw-h3-cta-btns .et_pb_button { margin-bottom: 0; }
/* !important is against the gutter rule again —
   `.et_pb_gutters3 .et_pb_column_2_5.et_block_column .et_pb_module` at (0,4,0)
   sets margin-bottom: 7.493%, about 50px of phantom gap under each button.
   These wrappers are the flex items of .sw-h3-cta-btns, so that margin also
   breaks the two-button row's alignment, not just its spacing. */
.sw-h3-cta-btns > .et_pb_button_module_wrapper { margin: 0 !important; }

/* The outline button sits at 85-97% across the gradient, which on the brand
   ramp is #4588C5 to #5696D1 — white label contrast there measures 3.8:1 and
   3.1:1, under AA for a 14px bold label. A navy scrim under the button lifts it
   to 5.1:1 without touching the brand gradient. Matches
   `.sw-divi .sw-btn--ghost-dark` at (0,2,0) and sits later in the file. */
.sw-h3-cta-btns .sw-btn--ghost-dark,
.sw-divi .sw-h3-cta-btns .sw-btn--ghost-dark.et_pb_button {
	background-color: rgba(4, 31, 56, 0.22);
	border-color: rgba(255, 255, 255, 0.55) !important;
}

/* ---- tablet --------------------------------------------------------------
   §41 already steps .sw-band down to 72px and the grids down a track; only the
   two overridden paddings and this page's own type need restating. */
@media (max-width: 980px) {
	/* Section padding steps down via the layout's own tablet/phone spacing
	   attributes, not here — see the note at the top of this section. */
	.sw-h3-close > .et_pb_row.sw-h3-panel { margin-bottom: 72px !important; }

	.sw-h3-hero-title h1 { font-size: 44px; letter-spacing: -1.2px; }
	.sw-h3-hero-intro p { font-size: 17px; }
	.sw-h3-results-title h2, .sw-h3-cta-copy h2 { font-size: 26px; }
	.et_pb_row.sw-h3-head { margin-bottom: 40px !important; }

	/* §41 takes .sw-grid--4 to three tracks; eight cards then leave a row of
	   two, so these go to two tracks and stay in even rows. */
	.sw-h3-grid.sw-grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	/* Same selector as the desktop gap rule above, not `.sw-h3-pgrid.sw-grid--5`:
	   a breakpoint restating its OWN selector is responsive CSS, which audit.ps1
	   passes over, while a different selector winning from inside a media query
	   is the shape of a real bug and gets reported. Keeping them identical means
	   the next audit run has nothing to triage here. */
	.et_pb_column.sw-h3-pgrid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 28px 12px; }
	/* At three across the connector between items 3 and 4 would run backwards
	   across the wrap, so they come off entirely. */
	.sw-h3-pgrid > .et_pb_module:not(:first-child) .sw-h3-step::before { display: none; }

	.et_pb_row.sw-h3-panel { padding: 40px 32px; }
	/* Divi does not stack columns until 479px; this design wants it at the
	   tablet boundary. !important is for Divi's own (0,3,0) gutter widths. */
	.sw-h3-panel > .et_pb_column_1_2,
	.sw-h3-panel > .et_pb_column_3_5,
	.sw-h3-panel > .et_pb_column_2_5 { width: 100% !important; margin-right: 0 !important; }
	.sw-h3-quote-col {
		margin-top: 32px;
		border-left: 0;
		border-top: 1px solid var(--sw-border-dark);
		padding-left: 0;
		padding-top: 32px;
	}
	.sw-h3-cta-btns { justify-content: flex-start; margin-top: 26px; }
}

/* ---- phone --------------------------------------------------------------- */
@media (max-width: 767px) {
	.sw-h3-close > .et_pb_row.sw-h3-panel { margin-bottom: 56px !important; }

	.sw-h3-hero-title h1 { font-size: 34px; letter-spacing: -0.8px; }
	.sw-h3-hero-intro p { font-size: 16px; }
	.et_pb_row.sw-h3-head { margin-bottom: 32px !important; }

	/* Full-width buttons need the WRAPPER to go full width too, or the anchor
	   stretches inside a shrink-wrapped inline-block and nothing changes. */
	.sw-h3-hero-copy > .et_pb_button_module_wrapper,
	.sw-h3-cta-btns > .et_pb_button_module_wrapper { display: block; width: 100%; margin-right: 0 !important; }
	.sw-h3-hero-copy .et_pb_button,
	.sw-h3-cta-btns .et_pb_button { width: 100%; justify-content: center; }

	.sw-h3-grid.sw-grid--4 { grid-template-columns: minmax(0, 1fr); }
	.et_pb_column.sw-h3-pgrid { grid-template-columns: minmax(0, 1fr); }
	.sw-h3-statgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

	.et_pb_row.sw-h3-panel { padding: 32px 24px; }
	.sw-h3-results-title h2, .sw-h3-cta-copy h2 { font-size: 24px; }
	.sw-h3-quote .et_pb_testimonial_content p { font-size: 17px; }
}

/* ===========================================================================
   45. Services v3  —  page "services-v3" (#330, Divi layout, pipeline v2)
   ---------------------------------------------------------------------------
   SOURCE OF TRUTH IS templates/jsonimports/services-v3.spec.json. Rebuild with

       node .claude/skills/divi-export/page-sync.mjs \
            wp-content/themes/seriousweb/templates/jsonimports/services-v3.spec.json 330

   Named v3, not v2: templates/page-services-v2.php exists and is assigned to
   #258. Same rule as Home v3 — a new page never borrows a shipped page's
   namespace, so nothing here can restyle it.

   Structure and copy are the live /services/ page's. Surface rotation, module
   choices and the CTA follow §44 (Home v3), so the two read as one system:

       hero     --sw-navy-900  gradient   .sw-band--dark
       core     --sw-white                .sw-band--white
       auto     --sw-blue-25              .sw-band--tint
       process  --sw-navy-900             .sw-band--dark
       close    --sw-blue-25              .sw-band--tint  (gradient panel)

   MOST OF THIS PAGE IS §41. Band padding, surfaces, heading scale, lede,
   eyebrow, card surface, grid and their breakpoints all come from there, and
   §41 already switches heading/lede/eyebrow to their on-dark colours under
   .sw-band--dark — so the navy process band needed no colour rules beyond its
   own step component.

   THE FOUR THINGS THIS INSTALL ALWAYS GETS WRONG, all applied here from the
   start rather than discovered again (see house-facts.md):
     - a ROW-level rule needs `.et_pb_row.<cls>`; Divi's own `.et_block_row`
       and `.et_pb_row_<n>` rules beat a bare class
     - a module margin needs `!important`, against a (0,4,0) gutter PERCENTAGE
     - `.sw-page h3` is (0,1,1) and beats any bare card/step title class
     - a decorative row `::after` needs `visibility: visible`, because
       `.et_block_row:after` is a clearfix that hides it
   =========================================================================== */

/* ---- 1. hero --------------------------------------------------------------
   Background and padding are block attributes, not CSS. The gradient starts at
   the header's own #041f38 at 180deg so the whole top edge matches it — at any
   other angle the top edge spans a RANGE of the ramp and no single stop can. */
.sw-s3-hero-copy { display: block; }

.sw-s3-hero-title h1 {
	max-width: 900px;
	margin: 0 auto;
	padding: 0;
	font-size: 52px;
	font-weight: 700;
	line-height: 1.12;
	letter-spacing: -1.4px;
	color: var(--sw-white);
}
.sw-s3-hero-intro p {
	max-width: 680px;
	margin: 0 auto;
	padding-bottom: 0;
	font-size: 18px;
	line-height: 1.7;
	color: var(--sw-muted-dark);
}
.sw-stack .sw-s3-hero-title.et_pb_module { margin-bottom: 22px !important; }
.sw-stack .sw-s3-hero-intro.et_pb_module { margin-bottom: 34px !important; }
/* The buttons are their own modules, each wrapped by Divi in a block-level
   .et_pb_button_module_wrapper. The column carries §39's `sw-btn-inline`, which
   is written to win; this only removes the trailing gutter margin under the
   pair. !important is for the (0,4,0) gutter percentage. */
.sw-s3-hero-copy > .et_pb_button_module_wrapper { margin-bottom: 0 !important; }

/* ---- hero decoration ------------------------------------------------------
   Same vocabulary as §42 (Contact v2) and §44 (Home v3) so the pages read as
   one site: a diagonal ruling, a soft corner sweep, an outlined square and a
   ring — and one motif that belongs to THIS page.

   Both glows live in ::before as two background layers, which is what frees
   ::after for the full-bleed ruling. A row-level element cannot do that job:
   the row is capped at 1240px and centred, so it stops short of the edges.

   The top fade is what makes the header seam disappear. The header is
   --sw-ink, rgb(4,31,56), the same colour the gradient starts from, so the two
   read as one surface only while the hero's first ~120px stay untouched. */
.sw-s3-hero::before {
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	width: auto;
	height: auto;
	transform: none;
	border-radius: 0;
	background-image:
		radial-gradient(900px 700px at 50% -240px,
			rgba(8, 82, 150, 0.36) 0%, rgba(8, 82, 150, 0) 66%),
		radial-gradient(760px 600px at 50% calc(100% + 300px),
			rgba(91, 155, 213, 0.20) 0%, rgba(91, 155, 213, 0) 68%);
	-webkit-mask-image: linear-gradient(180deg, transparent 0, #000 150px);
	mask-image: linear-gradient(180deg, transparent 0, #000 150px);
}

/* The ruling is masked off the centre FROM THE START. Sparse diagonals plus
   centred copy is the defect fixed on Contact v2: with ~3 sweeps across 1440px
   one lands on the headline, and a hairline through a title reads as a
   rendering artifact. Tightening the spacing is not the fix — §42 records that
   attempt and it hatched. */
.sw-s3-hero::after {
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	width: auto;
	height: auto;
	transform: none;
	border-radius: 0;
	background-image:
		radial-gradient(ellipse 1100px 520px at 106% 126%,
			rgba(155, 194, 229, 0.10) 0 60%, rgba(155, 194, 229, 0) 61%),
		repeating-linear-gradient(168deg,
			rgba(155, 194, 229, 0.13) 0 1px, transparent 1px 460px);
	-webkit-mask-image:
		linear-gradient(180deg, transparent 0, #000 150px, #000 74%, transparent 98%),
		radial-gradient(ellipse 42% 56% at 50% 48%, transparent 0 58%, #000 100%);
	mask-image:
		linear-gradient(180deg, transparent 0, #000 150px, #000 74%, transparent 98%),
		radial-gradient(ellipse 42% 56% at 50% 48%, transparent 0 58%, #000 100%);
	-webkit-mask-composite: source-in;
	mask-composite: intersect;
}

/* `visibility: visible` and `clear: none` are load-bearing on the ::after arm.
   Divi ships `.et_block_row:after { content:""; clear:both; visibility:hidden;
   height:0; width:0 }` as its float clearfix — note `.et_block_row`, NOT
   `.et_pb_row`, which is why grepping for the latter finds nothing and looks
   like proof there is no collision. It is (0,1,0), so this rule's (0,2,0)
   already wins width, height and border; `visibility` is the one thing it does
   not contest unless stated, and the shape renders full-size and invisible.

   NO OUTLINED SQUARE ON THIS PAGE, although §42 and §44 both have one. Built
   with it and looked: the square sat directly above the 2x2 motif, both are
   rectangles, and the two merged into a single ambiguous shape — a fifth stray
   tile beside the four that specifically MEAN the four service pillars. On Home
   v3 the same pair reads fine because the motif there is a diamond and the
   square cannot be mistaken for part of it. The vocabulary is shared; which of
   it a page uses is a per-page decision. */
.et_pb_row.sw-s3-hero-row { position: relative; }
.et_pb_row.sw-s3-hero-row::before {
	content: "";
	position: absolute;
	display: block;
	visibility: visible;
	clear: none;
	line-height: 0;
	pointer-events: none;
	z-index: 0;
}

/* THE MOTIF, and why it is not Home v3's node graph. Home's hero is about
   automation, so it draws a flow — four nodes, dashed links, a branch and a
   merge. THIS page is about four service pillars, so it draws four tiles on a
   2x2 grid with the connecting rules between them: a set, not a sequence. Same
   ink, same weight, different sentence.

   Inline SVG data URI, because outlined tiles and dashed rules are what
   background gradients are worst at, and one background-image beats four
   stacked pseudo-elements the page does not have. `currentColor` does NOT
   resolve inside a data URI, so the stroke colour is stated. */
.et_pb_row.sw-s3-hero-row::before {
	top: 14%;
	right: -54px;
	width: 196px;
	height: 150px;
	background-repeat: no-repeat;
	background-size: contain;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='196' height='150' fill='none' stroke='rgba(155,194,229,0.36)' stroke-width='1'%3E%3Crect x='18' y='16' width='68' height='50' rx='6'/%3E%3Crect x='110' y='16' width='68' height='50' rx='6'/%3E%3Crect x='18' y='86' width='68' height='50' rx='6'/%3E%3Crect x='110' y='86' width='68' height='50' rx='6'/%3E%3Cpath d='M86 41 L110 41 M86 111 L110 111 M52 66 L52 86 M144 66 L144 86' stroke-dasharray='4 5'/%3E%3C/svg%3E");
}

/* Ring, left of the copy — offset rather than mirrored, so the two sides do
   not read as a frame. */
.sw-s3-hero-copy::after {
	content: "";
	position: absolute;
	left: -4px;
	bottom: 14%;
	width: 32px;
	height: 32px;
	border: 1px solid rgba(91, 155, 213, 0.44);
	border-radius: 50%;
	pointer-events: none;
	z-index: 0;
}
.et_pb_column.sw-s3-hero-copy { position: relative; }

/* ---- band heads -----------------------------------------------------------
   `.et_pb_row.` and not the bare class: Divi writes `.et_pb_row_<n> {
   max-width: 1240px !important }` at (0,1,0) from the layout's own width, later
   in source, so a bare rule ties and loses and the centred head spans the row. */
.et_pb_row.sw-s3-head { max-width: 820px !important; margin-bottom: 46px !important; }

/* ---- 2. core services -----------------------------------------------------
   THE COLUMN IS THE CARD. §41's .sw-card carries the surface, radius, border,
   shadow and hover lift; a wrapper div inside a column has no equivalent in a
   layout, and Divi lays columns out with flex, so `float: none` (also §41) is
   what lets the modules stack. `makeEqual` on the row is Divi's OWN
   equal-height setting and is set in the spec, not emulated here.

   The accent is a top rule stepping down the blue ramp — the reference's
   purple / green / orange / blue would be a second palette on a one-hue site,
   which is the same call .sw-step--1..4 makes in §8. */
.et_pb_column.sw-s3-card {
	padding: 30px 28px 30px;
	border-top: 3px solid var(--sw-blue-600);
}
.et_pb_column.sw-s3-card--2 { border-top-color: var(--sw-blue-500); }
.et_pb_column.sw-s3-card--3 { border-top-color: var(--sw-blue-400); }
.et_pb_column.sw-s3-card--4 { border-top-color: var(--sw-blue-200); }
.et_pb_row.sw-s3-cards { margin-bottom: 26px !important; }
.et_pb_row.sw-s3-cards:last-child { margin-bottom: 0 !important; }

/* `.sw-s3-card h3` beats `.sw-page h3` (0,1,1), which otherwise sets
   margin-bottom: 0, letter-spacing: -0.4px and --sw-slate on every one. */
.sw-s3-card h3.et_pb_module_header {
	margin: 0;
	padding: 0;
	font-size: 21px;
	font-weight: 700;
	line-height: 1.25;
	letter-spacing: -0.4px;
	color: var(--sw-slate);
	text-wrap: balance;
}
/* Module rhythm. !important against the (0,4,0) gutter percentage, which is
   the rule that silently opens tens of pixels between modules in a column. */
.sw-s3-card > .et_pb_module { margin-bottom: 12px !important; }
.sw-s3-card > .et_pb_module:last-child { margin-bottom: 0 !important; }
.sw-s3-card__body p {
	margin: 0;
	padding-bottom: 0;
	font-size: 15px;
	line-height: 1.7;
	color: var(--sw-muted);
}

/* The feature list. `margin-bottom: auto` on the module is what pins the
   "Learn more" link to the bottom of a card whose neighbour has longer copy —
   makeEqual levels the COLUMNS, not what is inside them. */
.sw-s3-feats.et_pb_module { margin-bottom: auto !important; }
.sw-s3-feats ul {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 6px 18px;
	margin: 4px 0 0;
	padding: 0;
	list-style: none;
}
/* The list's own bottom gap, restated at (0,3,1) so it out-ranks §27's
   `.sw-divi .et_pb_text_inner > :last-child { margin-bottom: 0 }` at (0,3,0).
   The <ul> IS the last child of its text module, so the plain declaration
   above is eaten and the "Learn more" link sits hard against the last feature.
   This is the same rule that has now silently swallowed spacing on four
   separate components — see house-facts. */
.sw-divi .sw-s3-feats.et_pb_module ul { margin-bottom: 18px; }
.sw-s3-feats li {
	position: relative;
	padding-left: 20px;
	font-size: 14px;
	line-height: 1.55;
	color: var(--sw-muted);
}
/* A drawn tick rather than a list marker or an icon font: two borders and a
   rotation, so it inherits colour and needs no glyph to be enqueued. */
.sw-s3-feats li::before {
	content: "";
	position: absolute;
	top: 6px;
	left: 2px;
	width: 5px;
	height: 9px;
	border: solid var(--sw-blue-400);
	border-width: 0 1.5px 1.5px 0;
	transform: rotate(45deg);
}

/* "Learn more" is a real divi/button so the label and URL are fields, but it
   should read as a text link. Divi stamps `et_pb_bg_layout_light` on every
   button and `.et_pb_bg_layout_light.et_pb_module.et_pb_button { color:#2ea3f2 }`
   is (0,3,0) — so this is written at (0,3,0) too and sits later in the file.
   Divi's own trailing glyph is replaced rather than suppressed: it comes from
   an icon font that IS enqueued on a builder page, and left alone it renders
   its own arrow beside this one. */
.sw-s3-card .et_pb_button.sw-s3-more {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 0;
	border: 0;
	border-radius: 0;
	background: none;
	background-color: transparent;
	font-size: 14px;
	font-weight: 700;
	/* !important on these two only: Divi's generated `.et_pb_button` carries
	   `line-height: 1.7em !important` and `transition: all !important` at
	   (0,1,0). Specificity cannot reach past !important, so matching it is the
	   only option — and without the line-height the link sits ~10px taller than
	   its text and breaks the card's bottom alignment. */
	line-height: 1.4 !important;
	letter-spacing: 0;
	color: var(--sw-blue-600);
	transition: gap 0.25s var(--sw-ease), color 0.25s var(--sw-ease) !important;
}
.sw-s3-card .et_pb_button.sw-s3-more::after,
.sw-s3-card .et_pb_button.sw-s3-more::before {
	content: "";
	display: none;
}
.sw-s3-card .et_pb_button.sw-s3-more::after {
	content: "\2192";
	display: inline-block;
	margin: 0;
	font-family: inherit;
	font-size: 1em;
	line-height: 1;
	opacity: 1;
	position: relative;
	top: 1px;
	transition: transform 0.25s var(--sw-ease);
}
.sw-s3-card:hover .et_pb_button.sw-s3-more { gap: 11px; }

/* ---- 3. automation examples -----------------------------------------------
   ONE text module holding a twelve-item list, not twelve modules. It is a
   single list of examples; twelve fields would be twelve things to edit for
   one thought, and the page already has real modules everywhere it matters. */
.sw-s3-tiles ul {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 12px;
	margin: 0;
	padding: 0;
	list-style: none;
}
.sw-s3-tiles li {
	padding: 11px 20px;
	border: 1px solid var(--sw-border-light);
	border-radius: 999px;
	background: var(--sw-white);
	box-shadow: var(--sw-shadow-sm);
	font-size: 14.5px;
	font-weight: 600;
	line-height: 1.3;
	color: var(--sw-slate);
	transition: var(--sw-card-transition);
}
.sw-s3-tiles li:hover {
	transform: translateY(-2px);
	border-color: var(--sw-blue-200);
	box-shadow: var(--sw-card-shadow);
}

/* ---- 4. process (navy) ----------------------------------------------------
   Text modules, not blurbs: the number sits ABOVE the title and Divi renders a
   blurb's title before its description, always. §41 handles the band's heading
   and eyebrow colours; only this component needs on-dark rules. */
.sw-s3-step { position: relative; padding: 0 6px; text-align: center; }
.sw-s3-step__num {
	margin: 0 0 10px;
	padding-bottom: 0;
	font-size: 30px;
	font-weight: 800;
	line-height: 1;
	letter-spacing: -1px;
	color: var(--sw-blue-400);
}
h3.sw-s3-step__title {
	margin: 0 0 8px;
	padding: 0;
	font-size: 17px;
	font-weight: 700;
	line-height: 1.3;
	letter-spacing: -0.2px;
	color: var(--sw-white);
	text-wrap: balance;
}
.sw-s3-step__text { margin: 0; padding-bottom: 0; font-size: 15px; line-height: 1.7; color: var(--sw-blue-200); }
/* Dashed connector between steps, drawn behind the numbers. */
.sw-s3-pgrid > .et_pb_module:not(:first-child) .sw-s3-step::before {
	content: "";
	position: absolute;
	top: 16px;
	right: 50%;
	left: -50%;
	z-index: 0;
	border-top: 2px dashed var(--sw-border-dark);
}
.sw-s3-step__num { position: relative; z-index: 1; }

/* ---- 5. closing CTA panel -------------------------------------------------
   The panel is the ROW: background, radius and padding are all things a Divi
   row carries natively, so there is no wrapper div. `.et_pb_row.` because
   `.et_block_row { padding: 27px 0 }` inside an inline @media (min-width:1350px)
   is (0,1,0) and beats a bare class — the panel then renders with 27px top and
   bottom and ZERO left and right, i.e. copy against the edge. */
.et_pb_row.sw-s3-panel {
	width: 90%;
	max-width: 1240px;
	padding: 52px 48px;
	border-radius: 22px;
}
.sw-s3-panel,
.sw-divi .sw-s3-panel { align-items: center; }
.sw-s3-panel--grad {
	background-image: linear-gradient(
		90deg,
		var(--sw-cta-grad-start) 0%,
		var(--sw-cta-grad-start) 42%,
		var(--sw-cta-grad-end) 100%
	);
}
/* No column-width overrides: Divi's gutter maths computes against the padded
   content box and is already correct. Hand figures lose to it at (0,3,0) and
   have to be re-derived whenever the row's gutter setting changes. */

.sw-s3-cta-copy h2 {
	margin: 0;
	padding: 0;
	font-size: 30px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.6px;
	color: var(--sw-white);
	text-wrap: balance;
}
.sw-s3-cta-copy p {
	margin: 0;
	padding-bottom: 0;
	max-width: 520px;
	font-size: 16px;
	line-height: 1.7;
	color: rgba(255, 255, 255, 0.86);
}
.sw-s3-cta-copy > .et_pb_module { margin-bottom: 14px !important; }
.sw-s3-cta-copy > .et_pb_module:last-child { margin-bottom: 0 !important; }

/* align-items:center is load-bearing. The column is a flex item of the row and
   stretches to full panel height; without it the buttons, being flex items
   themselves, stretch too and render as two very tall slabs. */
.sw-s3-cta-btns {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: flex-end;
	gap: 12px;
}
.sw-s3-cta-btns > .et_pb_button_module_wrapper { margin: 0 !important; }
.sw-s3-cta-btns .et_pb_button { margin-bottom: 0; }
/* The outline button sits at 85-97% across the gradient, where white measures
   3.8:1 and 3.1:1 — under AA for a 14px bold label. A navy scrim lifts it to
   5.1:1 without touching the brand gradient. */
.sw-s3-cta-btns .sw-btn--ghost-dark,
.sw-divi .sw-s3-cta-btns .sw-btn--ghost-dark.et_pb_button {
	background-color: rgba(4, 31, 56, 0.22);
	border-color: rgba(255, 255, 255, 0.55) !important;
}

/* ---- tablet ---------------------------------------------------------------
   §41 already steps .sw-band to 72px and .sw-grid--4 down a track; only this
   page's own type, panel and decoration need restating. */
@media (max-width: 980px) {
	.sw-s3-hero-title h1 { font-size: 40px; letter-spacing: -1px; }
	.sw-s3-hero-intro p { font-size: 17px; }
	.sw-s3-cta-copy h2 { font-size: 26px; }
	.et_pb_row.sw-s3-head { margin-bottom: 40px !important; }

	/* Decoration comes off: the row narrows to the copy's own measure, so the
	   motif and the square would sit on the text rather than beside it. */
	.et_pb_row.sw-s3-hero-row::before,
	.sw-s3-hero-copy::after { display: none; }

	/* Divi stacks columns only at 479px; this design wants it at the tablet
	   boundary. !important is for Divi's own (0,3,0) gutter widths. */
	.sw-s3-cards > .et_pb_column,
	.sw-s3-panel > .et_pb_column { width: 100% !important; margin-right: 0 !important; }
	.et_pb_column.sw-s3-card { margin-bottom: 20px !important; }
	.sw-s3-cards > .et_pb_column:last-child { margin-bottom: 0 !important; }
	/* Once the columns stack, the four cards should be evenly spaced — but they
	   are two ROWS of two, and Divi adds `.et_block_row { padding: 30px 0 }` at
	   this breakpoint, so the gap between card 2 and card 3 came out at ~80px
	   against 20px everywhere else. (0,2,0) beats that (0,1,0) rule; the row
	   margin then carries the whole gap and matches the card margin. */
	.et_pb_row.sw-s3-cards { padding-top: 0; padding-bottom: 0; margin-bottom: 20px !important; }
	.et_pb_row.sw-s3-cards:last-child { margin-bottom: 0 !important; }

	.et_pb_row.sw-s3-panel { padding: 40px 32px; }
	.sw-s3-cta-btns { justify-content: flex-start; margin-top: 26px; }

	.sw-s3-pgrid > .et_pb_module:not(:first-child) .sw-s3-step::before { display: none; }
}

/* ---- phone ---------------------------------------------------------------- */
@media (max-width: 767px) {
	.sw-s3-hero-title h1 { font-size: 31px; letter-spacing: -0.6px; }
	.sw-s3-hero-intro p { font-size: 16px; }
	.sw-s3-cta-copy h2 { font-size: 24px; }
	.et_pb_row.sw-s3-head { margin-bottom: 32px !important; }

	.sw-s3-feats ul { grid-template-columns: minmax(0, 1fr); }
	.sw-s3-tiles ul { gap: 9px; }
	.sw-s3-tiles li { padding: 9px 15px; font-size: 13.5px; }

	/* Full-width buttons need the WRAPPER to go full width too, or the anchor
	   stretches inside a shrink-wrapped inline-block and nothing changes. */
	.sw-s3-hero-copy > .et_pb_button_module_wrapper,
	.sw-s3-cta-btns > .et_pb_button_module_wrapper { display: block; width: 100%; margin-right: 0 !important; }
	.sw-s3-hero-copy .sw-btn.et_pb_button,
	.sw-s3-cta-btns .et_pb_button { width: 100%; justify-content: center; }

	.et_pb_row.sw-s3-panel { padding: 32px 24px; }
	.et_pb_column.sw-s3-card { padding: 24px 20px; }
}

/* ===========================================================================
   46. Web Design  —  page "web-design" (#333, Divi layout, pipeline v2)
   ---------------------------------------------------------------------------
   SOURCE OF TRUTH IS templates/jsonimports/web-design.spec.json. Rebuild with

       node .claude/skills/divi-export/page-sync.mjs \
            wp-content/themes/seriousweb/templates/jsonimports/web-design.spec.json 333

   NAMESPACE IS sw-dsn-. `sw-wd-` (§32), `sw-w3-` (§37) and `sw-web-` are all
   taken by the three existing Websites templates, and a new page never borrows
   a shipped page's namespace — so restyling this one cannot touch them.

   Copy and structure come from websites-v3 (§37), the current house design for
   this subject. Surfaces rotate as §44/§45 do, so no two neighbouring bands
   share one:

       hero      --sw-navy-900  gradient  .sw-band--dark
       build     --sw-white               .sw-band--white
       perf      --sw-blue-25             .sw-band--tint
       tech      --sw-navy-900            .sw-band--dark
       process   --sw-white               .sw-band--white
       connect   --sw-blue-25             .sw-band--tint
       close     --sw-white               .sw-band--white  (gradient panel)

   MOST OF THIS PAGE IS §41 AND §46-adjacent SHARED WORK. Band padding,
   surfaces, heading scale, lede, eyebrow, card surface, grid and breakpoints
   come from §41; the section backgrounds and padding are block attributes, not
   CSS. §41 also switches heading, lede and eyebrow to their on-dark colours
   under .sw-band--dark, which is why the two navy bands cost no colour rules
   beyond the components this page invents.

   WRITTEN AGAINST THE PRE-FLIGHT LIST in SKILL.md rather than discovering it:
   row rules are `.et_pb_row.<cls>`, module margins carry !important against the
   (0,4,0) gutter percentage, card and step titles are qualified by tag against
   `.sw-page h3` (0,1,1), and the decorative row ::after states
   `visibility: visible` against Divi's `.et_block_row:after` clearfix.
   =========================================================================== */

/* ---- shared: the head row emitted by spec-helpers' head() -----------------
   Compound, because Divi writes `.et_pb_row_<n> { max-width: 1240px !important }`
   per row at (0,1,0) and later in source — a bare `.sw-head` ties and loses, and
   the centred heading block then spans the full row. First definition of this
   class; it belongs to the helper, not to this page, so keep it generic and put
   page-specific differences on the page's own hook. */
.et_pb_row.sw-head { max-width: 820px !important; margin-bottom: 46px !important; }

/* ---- 1. hero --------------------------------------------------------------
   Background and padding are block attributes. The gradient runs 180deg from
   the header's own #041f38, so the whole top edge matches it at every width —
   at any other angle the top edge spans a range of the ramp and no single stop
   can. Measured: 0-2 levels across the boundary. */
.sw-dsn-hero-copy { display: block; }

.sw-dsn-hero-title h1 {
	max-width: 880px;
	margin: 0 auto;
	padding: 0;
	font-size: 54px;
	font-weight: 700;
	line-height: 1.1;
	letter-spacing: -1.5px;
	color: var(--sw-white);
}
.sw-dsn-hero-intro p {
	max-width: 660px;
	margin: 0 auto;
	padding-bottom: 0;
	font-size: 18px;
	line-height: 1.7;
	color: var(--sw-muted-dark);
}
.sw-stack .sw-dsn-hero-title.et_pb_module { margin-bottom: 22px !important; }
.sw-stack .sw-dsn-hero-intro.et_pb_module { margin-bottom: 32px !important; }
.sw-dsn-hero-copy > .et_pb_button_module_wrapper { margin-bottom: 0 !important; }

/* Hero chips. margin-top, not margin-bottom on the buttons: §39's sw-btn-inline
   leaves 10px under the wrappers, and the gap belongs to the thing that needs
   clearance rather than to the row above it. */
.sw-dsn-chips.et_pb_module { margin: 26px 0 0 !important; }
.sw-dsn-chips ul {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 10px;
	margin: 0;
	padding: 0;
	list-style: none;
}
.sw-dsn-chips li {
	padding: 8px 16px;
	border: 1px solid var(--sw-border-dark);
	border-radius: 999px;
	font-size: 13.5px;
	font-weight: 600;
	color: var(--sw-blue-200);
}

/* ---- hero decoration ------------------------------------------------------
   The vocabulary shared with §42, §44, §45 and §38. Both glows live in ::before
   as two background layers, which frees ::after for the full-bleed ruling and
   curve — a row-level element is capped at 1240px and stops short of the edges.

   The top fade is what keeps the header seam shut: the header is --sw-ink,
   rgb(4,31,56), the colour this gradient starts from, so the two read as one
   surface only while the hero's first ~150px stay untouched. The centre
   punch-out keeps the ruling off the centred copy — with ~3 sweeps across
   1440px one lands on the headline. Tightening the spacing is NOT the fix;
   §42 tried it and it hatched. Both mask-composite spellings are required. */
.sw-dsn-hero::before {
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	width: auto;
	height: auto;
	transform: none;
	border-radius: 0;
	background-image:
		radial-gradient(880px 700px at 50% -250px,
			rgba(8, 82, 150, 0.36) 0%, rgba(8, 82, 150, 0) 66%),
		radial-gradient(740px 600px at 50% calc(100% + 300px),
			rgba(91, 155, 213, 0.20) 0%, rgba(91, 155, 213, 0) 68%);
	-webkit-mask-image: linear-gradient(180deg, transparent 0, #000 150px);
	mask-image: linear-gradient(180deg, transparent 0, #000 150px);
}
.sw-dsn-hero::after {
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	width: auto;
	height: auto;
	transform: none;
	border-radius: 0;
	background-image:
		radial-gradient(ellipse 1100px 520px at 106% 126%,
			rgba(155, 194, 229, 0.10) 0 60%, rgba(155, 194, 229, 0) 61%),
		repeating-linear-gradient(168deg,
			rgba(155, 194, 229, 0.13) 0 1px, transparent 1px 460px);
	-webkit-mask-image:
		linear-gradient(180deg, transparent 0, #000 150px, #000 74%, transparent 98%),
		radial-gradient(ellipse 42% 56% at 50% 48%, transparent 0 58%, #000 100%);
	mask-image:
		linear-gradient(180deg, transparent 0, #000 150px, #000 74%, transparent 98%),
		radial-gradient(ellipse 42% 56% at 50% 48%, transparent 0 58%, #000 100%);
	-webkit-mask-composite: source-in;
	mask-composite: intersect;
}

/* `visibility: visible` and `clear: none` are load-bearing. Divi ships
   `.et_block_row:after { content:""; clear:both; visibility:hidden; height:0;
   width:0 }` as its float clearfix — `.et_block_row`, NOT `.et_pb_row`, which is
   why grepping for the latter finds nothing and looks like proof there is no
   collision. It is (0,1,0), so these compound rules already win width, height
   and border; `visibility` is the one thing they do not contest unless stated,
   and the shape renders full-size and completely invisible. */
.et_pb_row.sw-dsn-hero-row { position: relative; }
.et_pb_row.sw-dsn-hero-row::before,
.et_pb_row.sw-dsn-hero-row::after {
	content: "";
	position: absolute;
	display: block;
	visibility: visible;
	clear: none;
	line-height: 0;
	pointer-events: none;
	z-index: 0;
}

/* THE MOTIF — a browser frame with a layout inside it. Each page's motif says
   something about that page, in the same ink and weight:

     Home v3      four nodes, dashed links, a branch and a merge  -> a FLOW
     Services v3  four equal tiles, 2x2, connected                -> a SET
     Our Work v2  tiles at four sizes, masonry-packed             -> A BODY OF WORK
     Web Design   a browser chrome holding a hero and two columns -> A PAGE

   This one is the most literal of the four, and deliberately: the page is about
   designing pages, so the thing it draws is a page. Inline SVG data URI —
   outlined rectangles and a dashed rule are what background gradients are worst
   at, and `currentColor` does NOT resolve inside a data URI, so the stroke is
   stated rather than inherited. */
.et_pb_row.sw-dsn-hero-row::before {
	top: 11%;
	right: -56px;
	width: 210px;
	height: 158px;
	background-repeat: no-repeat;
	background-size: contain;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='210' height='158' fill='none' stroke='rgba(155,194,229,0.36)' stroke-width='1'%3E%3Crect x='8' y='10' width='194' height='138' rx='8'/%3E%3Cpath d='M8 34 L202 34' stroke-dasharray='4 5'/%3E%3Ccircle cx='22' cy='22' r='3'/%3E%3Ccircle cx='34' cy='22' r='3'/%3E%3Ccircle cx='46' cy='22' r='3'/%3E%3Crect x='22' y='48' width='166' height='40' rx='5'/%3E%3Crect x='22' y='100' width='78' height='34' rx='5'/%3E%3Crect x='110' y='100' width='78' height='34' rx='5'/%3E%3C/svg%3E");
}

/* Outlined square, upper right. An OUTLINE, not a fill — that is what keeps it
   quiet enough to sit near a headline. Higher alpha than a mid-blue reference
   would suggest, because on navy a hairline at 0.16 disappears. */
.et_pb_row.sw-dsn-hero-row::after {
	top: -16px;
	right: -8px;
	width: 76px;
	height: 76px;
	border: 1px solid rgba(155, 194, 229, 0.26);
	border-radius: 6px;
}

/* Ring, left of the copy — offset rather than mirrored, so the two sides do not
   read as a frame. */
.sw-dsn-hero-copy::after {
	content: "";
	position: absolute;
	left: -4px;
	bottom: 16%;
	width: 32px;
	height: 32px;
	border: 1px solid rgba(91, 155, 213, 0.44);
	border-radius: 50%;
	pointer-events: none;
	z-index: 0;
}
.et_pb_column.sw-dsn-hero-copy { position: relative; }

/* ---- 2 & 6. cards ---------------------------------------------------------
   divi/blurb modules, so icon, title and description are fields. `.sw-card`
   (§41) supplies surface, radius, border, shadow and the hover lift.

   Icon colour is NOT set here: it is `imageIcon.advanced.color` on each block,
   because Divi generates
   `.et_pb_blurb_<n> > .et_pb_blurb_content > .et_pb_main_blurb_image .et-pb-icon`
   at (0,4,0) inline and any stylesheet rule loses to it. Hover IS here, because
   Divi has no setting for it — and it needs !important to reach past that same
   generated rule. */
.sw-dsn-grid > .et_pb_module { height: 100%; }

/* TWO !importants, both against Divi's own inline blurb CSS, both found by
   audit.ps1 rather than by looking:

     .et_block_module > .et_pb_blurb_content .et_pb_main_blurb_image
         { margin-bottom: 30px }                                    (0,3,0)
     .et_pb_blurb .et_pb_image_wrap:not(.et_flex_module):…
         { display: block }                                         (0,4,0)

   The second is the one that matters. `display: block` kills `place-items`,
   so the glyph stops being centred in its tile and sits top-left — which is
   exactly the symptom the LIVE site shows on its own cards, for the related
   reason that it has no rule contesting Divi's defaults at all. Specificity
   cannot reliably beat a (0,4,0) selector carrying `:not()`, and Divi has no
   setting for "make the icon tile a grid", so !important is the honest fix
   rather than a specificity arms race. */
.sw-dsn-card .et_pb_main_blurb_image,
.sw-dsn-ccard .et_pb_main_blurb_image { margin: 0 0 14px !important; line-height: 0; }
.sw-dsn-card .et_pb_image_wrap,
.sw-dsn-ccard .et_pb_image_wrap {
	display: grid !important;
	place-items: center;
	width: 44px;
	height: 44px;
	border-radius: 12px;
	background: rgba(8, 82, 150, 0.09);
	transition: background-color 0.25s var(--sw-ease);
}
.sw-dsn-card .et-pb-icon,
.sw-dsn-ccard .et-pb-icon { font-size: 22px; line-height: 1; }
.sw-card:hover .et_pb_image_wrap { background: var(--sw-blue-600); }
.sw-card:hover .et_pb_image_wrap .et-pb-icon { color: var(--sw-white) !important; }

.sw-card.sw-dsn-card:hover,
.sw-card.sw-dsn-ccard:hover { border-color: var(--sw-blue-200); }

/* `.sw-dsn-card h3` beats `.sw-page h3` (0,1,1), which otherwise sets
   margin-bottom: 0, letter-spacing -0.4px and --sw-slate on every card title. */
.sw-dsn-card h3.et_pb_module_header,
.sw-dsn-ccard h3.et_pb_module_header {
	/* No margin-bottom in the shared rule: the two variants want different
	   values, and declaring 8px here and 0 below made the audit report a real
	   loss for what is just one rule overriding another. Set it per variant. */
	margin: 0;
	padding: 0;
	font-size: 18px;
	font-weight: 700;
	line-height: 1.3;
	letter-spacing: -0.2px;
	color: var(--sw-slate);
	text-wrap: balance;
}
.sw-dsn-card .et_pb_blurb_description p {
	margin: 0;
	padding-bottom: 0;
	font-size: 15px;
	line-height: 1.7;
	color: var(--sw-muted);
}
/* The connect cards carry a title only, so the heading is the last thing in the
   card and needs no trailing gap. */
.sw-dsn-ccard h3.et_pb_module_header { margin-bottom: 0; }
.et_pb_column.sw-dsn-cgrid { gap: 14px; }

/* ---- 3. performance ------------------------------------------------------- */
.sw-dsn-checks.et_pb_module { margin-bottom: 26px !important; }
.sw-dsn-checks ul {
	display: inline-grid;
	grid-template-columns: repeat(2, minmax(0, auto));
	gap: 10px 30px;
	margin: 0;
	padding: 0;
	list-style: none;
	text-align: left;
}
.sw-dsn-checks li {
	position: relative;
	padding-left: 24px;
	font-size: 15px;
	line-height: 1.6;
	color: var(--sw-muted);
}
/* A drawn tick: two borders and a rotation, so it inherits colour and needs no
   glyph to be enqueued. */
.sw-dsn-checks li::before {
	content: "";
	position: absolute;
	top: 6px;
	left: 3px;
	width: 5px;
	height: 10px;
	border: solid var(--sw-blue-400);
	border-width: 0 1.5px 1.5px 0;
	transform: rotate(45deg);
}

/* ---- 4. technology (navy) ------------------------------------------------- */
.sw-dsn-tech-chips ul {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 12px;
	margin: 0;
	padding: 0;
	list-style: none;
}
.sw-dsn-tech-chips li {
	padding: 11px 22px;
	border: 1px solid var(--sw-border-dark);
	border-radius: 999px;
	background: var(--sw-navy-800);
	font-size: 14.5px;
	font-weight: 600;
	color: var(--sw-blue-200);
	transition: var(--sw-card-transition);
}
.sw-dsn-tech-chips li:hover {
	transform: translateY(-2px);
	border-color: var(--sw-blue-400);
	color: var(--sw-white);
}

/* ---- 5. process ----------------------------------------------------------- */
.sw-dsn-step { position: relative; padding: 0 6px; text-align: center; }
.sw-dsn-step__num {
	position: relative;
	z-index: 1;
	margin: 0 0 10px;
	padding-bottom: 0;
	font-size: 30px;
	font-weight: 800;
	line-height: 1;
	letter-spacing: -1px;
	color: var(--sw-blue-400);
}
h3.sw-dsn-step__title {
	margin: 0 0 8px;
	padding: 0;
	font-size: 17px;
	font-weight: 700;
	line-height: 1.3;
	letter-spacing: -0.2px;
	color: var(--sw-slate);
	text-wrap: balance;
}
.sw-dsn-step__text { margin: 0; padding-bottom: 0; font-size: 15px; line-height: 1.7; color: var(--sw-muted); }
.sw-dsn-pgrid > .et_pb_module:not(:first-child) .sw-dsn-step::before {
	content: "";
	position: absolute;
	top: 16px;
	right: 50%;
	left: -50%;
	z-index: 0;
	border-top: 2px dashed var(--sw-border-light);
}

/* ---- 6. connect CTA row --------------------------------------------------- */
.et_pb_row.sw-dsn-connect-cta { margin-top: 34px !important; }

/* ---- 7. closing panel -----------------------------------------------------
   The panel is the ROW. `.et_pb_row.` because `.et_block_row { padding: 27px 0 }`
   inside an inline @media (min-width:1350px) is (0,1,0) and beats a bare class —
   the panel then renders with 27px top and bottom and ZERO left and right. */
.et_pb_row.sw-dsn-panel {
	width: 90%;
	max-width: 1240px;
	padding: 52px 48px;
	border-radius: 22px;
}
.sw-dsn-panel,
.sw-divi .sw-dsn-panel { align-items: center; }
.sw-dsn-panel--grad {
	background-image: linear-gradient(
		90deg,
		var(--sw-cta-grad-start) 0%,
		var(--sw-cta-grad-start) 42%,
		var(--sw-cta-grad-end) 100%
	);
}
.sw-dsn-cta-copy h2 {
	margin: 0;
	padding: 0;
	font-size: 30px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.6px;
	color: var(--sw-white);
	text-wrap: balance;
}
.sw-dsn-cta-copy p {
	margin: 0;
	padding-bottom: 0;
	max-width: 520px;
	font-size: 16px;
	line-height: 1.7;
	color: rgba(255, 255, 255, 0.86);
}
.sw-dsn-cta-copy > .et_pb_module { margin-bottom: 14px !important; }
.sw-dsn-cta-copy > .et_pb_module:last-child { margin-bottom: 0 !important; }
.sw-dsn-cta-btns {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: flex-end;
	gap: 12px;
}
.sw-dsn-cta-btns > .et_pb_button_module_wrapper { margin: 0 !important; }
.sw-dsn-cta-btns .et_pb_button { margin-bottom: 0; }
/* White on the gradient measures 3.1-3.8:1 at the light end, under AA for a
   14px bold label. A navy scrim lifts it to ~5:1 without touching the brand
   gradient. */
.sw-dsn-cta-btns .sw-btn--ghost-dark,
.sw-divi .sw-dsn-cta-btns .sw-btn--ghost-dark.et_pb_button {
	background-color: rgba(4, 31, 56, 0.22);
	border-color: rgba(255, 255, 255, 0.55) !important;
}

/* ---- tablet --------------------------------------------------------------- */
@media (max-width: 980px) {
	.sw-dsn-hero-title h1 { font-size: 40px; letter-spacing: -1px; }
	.sw-dsn-hero-intro p { font-size: 17px; }
	.sw-dsn-cta-copy h2 { font-size: 26px; }
	.et_pb_row.sw-head { margin-bottom: 40px !important; }

	/* Decoration comes off: the row narrows to the copy's own measure, so the
	   motif and the square would sit on the text rather than beside it. */
	.et_pb_row.sw-dsn-hero-row::before,
	.et_pb_row.sw-dsn-hero-row::after,
	.sw-dsn-hero-copy::after { display: none; }

	.sw-dsn-panel > .et_pb_column { width: 100% !important; margin-right: 0 !important; }
	.et_pb_row.sw-dsn-panel { padding: 40px 32px; }
	.sw-dsn-cta-btns { justify-content: flex-start; margin-top: 26px; }

	.sw-dsn-pgrid > .et_pb_module:not(:first-child) .sw-dsn-step::before { display: none; }
}

/* ---- phone ---------------------------------------------------------------- */
@media (max-width: 767px) {
	.sw-dsn-hero-title h1 { font-size: 31px; letter-spacing: -0.6px; }
	.sw-dsn-hero-intro p { font-size: 16px; }
	.sw-dsn-cta-copy h2 { font-size: 24px; }
	.et_pb_row.sw-head { margin-bottom: 32px !important; }

	.sw-dsn-checks ul { grid-template-columns: minmax(0, 1fr); }
	.sw-dsn-tech-chips li { padding: 9px 16px; font-size: 13.5px; }
	.sw-dsn-chips li { padding: 7px 13px; font-size: 12.5px; }

	/* Full-width buttons need the WRAPPER to go full width too, or the anchor
	   stretches inside a shrink-wrapped inline-block and nothing changes. */
	.sw-dsn-hero-copy > .et_pb_button_module_wrapper,
	.sw-dsn-cta-btns > .et_pb_button_module_wrapper { display: block; width: 100%; margin-right: 0 !important; }
	.sw-dsn-hero-copy .sw-btn.et_pb_button,
	.sw-dsn-cta-btns .et_pb_button { width: 100%; justify-content: center; }

	.et_pb_row.sw-dsn-panel { padding: 32px 24px; }
}

/* ---- 7. why a new web design (objections) ---------------------------------
   divi/toggle modules, so each question and answer is a real field and the
   client can add or reorder items without touching markup. Divi's own JS drives
   the open/close and stamps `.et_pb_toggle_open` / `.et_pb_toggle_close`.

   NOT divi/accordion: its items are child modules build-page.mjs cannot emit,
   and an accordion closes its siblings — right for alternatives, wrong for a
   list of objections where a reader may want two open at once.

   Rendered DOM is
       .et_pb_toggle > h3.et_pb_toggle_title + .et_pb_toggle_content
   so everything below styles Divi's markup, not markup this page wrote. */
/* THE COLUMN IS NOT CENTRED — the measure is capped on its children instead,
   and that is the documented way round a trap this project has already paid
   for. Centring a Divi column needs `margin: 0 auto`, but
   `.et_pb_row .et_pb_column.et-last-child { margin-right: 0 !important }` is
   (0,3,0) with !important, so only margin-LEFT resolves to auto and the whole
   block lands well right of centre. It is the same fault that once put the
   homepage hero 190px off. `float: none` still needs the compound form against
   `.et_block_row .et_pb_column { float: left }` at (0,2,0). */
.et_pb_column.sw-dsn-why-col { float: none; }

/* !important against the (0,4,0) gutter percentage, which is what otherwise
   opens tens of pixels between consecutive toggles. `margin-inline: auto` with
   an explicit max-width is what centres the band — on the modules, where no
   Divi rule is competing for it. */
.sw-dsn-toggle.et_pb_module {
	max-width: 900px;
	margin: 0 auto 12px !important;
}

.sw-dsn-toggle.et_pb_toggle {
	padding: 0;
	border: 1px solid var(--sw-border-light);
	border-radius: var(--sw-card-radius);
	background: var(--sw-white);
	box-shadow: var(--sw-shadow-sm);
	transition: border-color 0.25s var(--sw-ease), box-shadow 0.25s var(--sw-ease);
}
.sw-dsn-toggle.et_pb_toggle_open {
	border-color: var(--sw-blue-200);
	box-shadow: var(--sw-card-shadow);
}

/* `.sw-dsn-toggle h3` is (0,2,1) and beats `.sw-page h3` at (0,1,1), which
   otherwise sets margin-bottom: 0, letter-spacing -0.4px and --sw-slate on
   every question. padding-right reserves the indicator's column. */
.sw-dsn-toggle h3.et_pb_toggle_title {
	position: relative;
	margin: 0;
	padding: 20px 58px 20px 24px;
	font-size: 17px;
	font-weight: 700;
	line-height: 1.45;
	letter-spacing: -0.2px;
	color: var(--sw-slate);
	cursor: pointer;
	text-wrap: balance;
}
.sw-dsn-toggle.et_pb_toggle_open h3.et_pb_toggle_title { color: var(--sw-blue-600); }

/* A DRAWN indicator, replacing Divi's icon-font glyph. Two rules do it: a
   horizontal bar always, and a vertical one that disappears when the item
   opens — so closed reads "+" and open reads "−" with no font dependency and
   no second element. Divi's own ::before is suppressed rather than restyled;
   left alone it renders its glyph beside this one. */
.sw-dsn-toggle h3.et_pb_toggle_title::before {
	content: "" !important;
	display: block !important;
	position: absolute;
	top: 50%;
	right: 24px;
	width: 14px;
	height: 2px;
	margin: -1px 0 0;
	border-radius: 2px;
	background: var(--sw-blue-400);
	font-size: 0 !important;
	transform: none;
	transition: background-color 0.25s var(--sw-ease);
}
.sw-dsn-toggle h3.et_pb_toggle_title::after {
	content: "";
	position: absolute;
	top: 50%;
	right: 30px;
	width: 2px;
	height: 14px;
	margin: -7px 0 0;
	border-radius: 2px;
	background: var(--sw-blue-400);
	transition: opacity 0.25s var(--sw-ease), transform 0.25s var(--sw-ease);
}
.sw-dsn-toggle.et_pb_toggle_open h3.et_pb_toggle_title::after {
	opacity: 0;
	transform: rotate(90deg);
}

.sw-dsn-toggle .et_pb_toggle_content {
	padding: 0 58px 22px 24px;
	font-size: 15.5px;
	line-height: 1.75;
	color: var(--sw-muted);
}
.sw-dsn-toggle .et_pb_toggle_content p { margin: 0; padding-bottom: 0; }

/* COLLAPSING IS GATED BEHIND html.js, and that is the whole safety of it.
   Divi ships neither the CSS nor the JS for this module on a front-end page:
   the `.et_pb_toggle_close` hide rule lives in module-library.css, which is not
   enqueued here, and no loaded script touches the module — probe.ps1 on a
   closed item reports "no rule sets it directly · computed block". So the
   behaviour comes from js/toggle.js instead.

   header.php swaps `no-js` for `js` on <html> inline in <head>, so with no
   JavaScript every question and answer stays visible and readable — a longer
   band, but a working one — and nothing collapses until the script has run.
   Hiding content behind a control that may not work is the failure this theme
   has already shipped twice; this is the same progressive-enhancement doctrine
   header.php documents for the nav.

   The +/- indicator is gated the same way: with no JS there is no state to
   indicate, and a plus sign that does nothing is worse than no plus sign. */
html.js .sw-dsn-toggle.et_pb_toggle_close .et_pb_toggle_content { display: none; }
.sw-dsn-toggle h3.et_pb_toggle_title::before,
.sw-dsn-toggle h3.et_pb_toggle_title::after { display: none; }
html.js .sw-dsn-toggle h3.et_pb_toggle_title::before { display: block; }
html.js .sw-dsn-toggle h3.et_pb_toggle_title::after { display: block; }
/* THIS RULE AUDITS DEAD, AND THAT IS CORRECT — do not delete it. audit.ps1
   drives a browser with JavaScript enabled, where header.php has already
   swapped `no-js` for `js`, so `html:not(.js)` can never match there. It is the
   no-JS fallback: without the script the title is not a control, so it should
   not offer a pointer cursor or reserve room for an indicator that is also
   hidden. Audit both DOMs before removing anything reported DEAD. */
html:not(.js) .sw-dsn-toggle h3.et_pb_toggle_title { cursor: default; padding-right: 24px; }

/* The closing line. Centred and a step up in size, so the band resolves into a
   statement rather than trailing off after the last answer. */
.sw-dsn-why-close.et_pb_module { max-width: 900px; margin: 30px auto 0 !important; }
.sw-dsn-why-close p {
	margin: 0 auto;
	padding-bottom: 0;
	max-width: 720px;
	font-size: 16.5px;
	line-height: 1.75;
	color: var(--sw-slate);
	text-align: center;
	text-wrap: balance;
}

@media (max-width: 767px) {
	.sw-dsn-toggle h3.et_pb_toggle_title { padding: 16px 48px 16px 18px; font-size: 16px; }
	.sw-dsn-toggle .et_pb_toggle_content { padding: 0 48px 18px 18px; font-size: 15px; }
	.sw-dsn-toggle h3.et_pb_toggle_title::before { right: 18px; }
	.sw-dsn-toggle h3.et_pb_toggle_title::after { right: 24px; }
}
