/*! Sohnas Media global CSS v0.8.1 — built from src/css. Do not edit directly. */

/* ---- foundations/tokens.css ---- */
/* ==========================================================================
   Sohnas Media — Design tokens
   Palette: Option C (approved 2026-09-29)
     CD-01 Deep Navy, Ink, Soft Violet, Cloud White + logo-aligned blue #1A68E6
   Source of truth for all colours, type, spacing and motion.
   Elementor Global Colours / Fonts mirror these values — see
   docs/elementor-globals.md and keep both in sync.
   Contrast figures are WCAG 2.x ratios, calculated from the hex values;
   browser-measured results are in the implementation report.
   Semantic role names follow Global System Pre-Implementation Review
   Revision 3.1, Section 3.1 (renamed in v0.2.0; brand values unchanged).
   ========================================================================== */

:root {
	/* ---- Brand colours ------------------------------------------------ */
	--sm-navy: #17223B;            /* CD-01 Deep Navy · white text 15.8:1 */
	--sm-blue: #1A68E6;            /* Interactive blue (from logo #2372EF) · on white 5.04, on Cloud 4.70 */
	--sm-blue-hover: #1052C2;      /* on white 6.98 */
	--sm-blue-active: #0D46A6;     /* on white 8.59 */
	--sm-blue-on-dark: #6FA3F6;    /* links / accents on navy · 6.21 */
	--sm-blue-on-dark-hover: #9CC0F9; /* on navy 8.52 */
	--sm-violet: #8176D9;          /* CD-01 Soft Violet · DECORATIVE and large text only (3.80 on white) */
	--sm-violet-text: #6A5DCF;     /* small violet text on light · on white 5.15, on Cloud 4.80 */
	--sm-violet-on-dark: #A69EEA;  /* violet text on navy · 6.55 */

	/* Logo colours are NOT interface tokens. The logo is used as supplied
	   artwork (#003463 / #2372EF) and never recoloured. */

	/* ---- Neutrals ------------------------------------------------------ */
	--sm-white: #FFFFFF;
	--sm-cloud: #F5F7FC;           /* CD-01 Cloud White */
	--sm-ink: #222B3C;             /* CD-01 Ink · on white 14.2 */
	--sm-muted: #586277;           /* secondary text · on white 6.13, on Cloud 5.71 */
	--sm-text-on-dark: #C9D1E3;    /* body text on navy · 10.3 */
	--sm-muted-on-dark: #A9B3C9;   /* secondary text on navy · 7.51 */
	--sm-divider: #DCE1EC;         /* decorative rules only (not a UI boundary) */
	--sm-divider-on-dark: rgba(255, 255, 255, 0.18);
	--sm-border-input: #7E879B;    /* form control boundary · on white 3.60, on Cloud 3.36 */
	--sm-disabled-surface: #E9EDF4;
	--sm-disabled-text: #7E879B;   /* disabled content is exempt from contrast rules; 3.07 */

	/* ---- Status -------------------------------------------------------- */
	--sm-error: #B42318;           /* on white 6.57 */
	--sm-error-on-dark: #FDA29B;   /* on navy 8.14 */
	--sm-success: #067647;         /* on white 5.69 */
	--sm-success-on-dark: #75E0A7; /* on navy 9.77 */
	--sm-warning: #A15C07;         /* on white 5.19, on Cloud 4.84 (least margin: no tinted backgrounds) */
	--sm-warning-on-dark: #FEC84B; /* on navy 10.22 */

	/* ---- Gradient (selective use only — CD-01 3.1) --------------------- */
	--sm-gradient-accent: linear-gradient(135deg, var(--sm-blue) 0%, var(--sm-violet) 100%);

	/* ---- Semantic roles (components use these, not raw colours) --------
	   Rev 3.1 §3.1. Every role is redeclared in .sm-surface-dark below:
	   a custom property resolves where it is declared, so a role that
	   points at another role would NOT follow the dark remap. */
	--sm-color-primary: var(--sm-navy);
	--sm-color-secondary: var(--sm-violet);          /* decorative / large text only */
	--sm-color-accent: var(--sm-blue);
	--sm-color-accent-hover: var(--sm-blue-hover);
	--sm-color-accent-active: var(--sm-blue-active);
	--sm-color-text-on-accent: var(--sm-white);      /* text on an accent fill (primary button) */
	--sm-color-link: var(--sm-blue);
	--sm-color-link-hover: var(--sm-blue-hover);
	--sm-color-text-heading: var(--sm-navy);
	--sm-color-text-primary: var(--sm-ink);
	--sm-color-text-secondary: var(--sm-muted);      /* also serves "muted" text */
	--sm-color-text-accent: var(--sm-violet-text);   /* eyebrows, small violet text */
	--sm-color-background: var(--sm-white);
	--sm-color-background-alt: var(--sm-cloud);
	--sm-color-surface-elevated: var(--sm-white);    /* with --sm-shadow-md; light sections only */
	--sm-color-surface-contrast: var(--sm-navy);
	--sm-color-border: var(--sm-border-input);       /* form controls (3:1 boundary) */
	--sm-color-divider: var(--sm-divider);           /* decorative rules only */
	--sm-color-focus: var(--sm-blue);
	--sm-color-error: var(--sm-error);
	--sm-color-success: var(--sm-success);
	--sm-color-warning: var(--sm-warning);
	--sm-color-disabled-surface: var(--sm-disabled-surface);
	--sm-color-disabled-text: var(--sm-disabled-text);

	/* ---- Typography ---------------------------------------------------- */
	--sm-font-heading: "Manrope", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
	--sm-font-body: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
	/* Typography decision (approved 2026-09-29): Manrope for headings only;
	   Inter for body, navigation, buttons, forms and all interface elements.
	   Resolves the Design System (Manrope nav/buttons) vs CD-01 conflict in
	   favour of CD-01. */
	--sm-font-ui: var(--sm-font-body);

	--sm-fw-regular: 400;
	--sm-fw-medium: 500;
	--sm-fw-semibold: 600;
	--sm-fw-bold: 700;

	/* Fluid sizes: min at 375px viewport, max at 1280px. rem-based so text
	   scales with browser zoom / 200% text enlargement. */
	--sm-fs-h1: clamp(2.5rem, 1.775rem + 3.094vw, 4.25rem);     /* 40 → 68px */
	--sm-fs-h2: clamp(2rem, 1.637rem + 1.547vw, 2.875rem);      /* 32 → 46px */
	--sm-fs-h3: clamp(1.5rem, 1.396rem + 0.442vw, 1.75rem);     /* 24 → 28px */
	--sm-fs-h4: clamp(1.25rem, 1.172rem + 0.332vw, 1.4375rem);  /* 20 → 23px */
	--sm-fs-h5: 1.125rem;          /* 18px · Manrope 600 (Rev 3.1 decision 3) */
	--sm-fs-h6: 1rem;              /* 16px · Manrope 600 (Rev 3.1 decision 3) */
	--sm-fs-lead: clamp(1.0625rem, 1.037rem + 0.11vw, 1.125rem);/* 17 → 18px */
	--sm-fs-body: 1rem;            /* 16px */
	--sm-fs-small: 0.875rem;       /* 14px */
	--sm-fs-label: 0.875rem;       /* 14px · Inter 500 (Rev 3.1 decision 3) */
	--sm-fs-caption: 0.8125rem;    /* 13px · Inter 400 (Rev 3.1 decision 3) */
	--sm-fs-eyebrow: 0.8125rem;    /* 13px */
	--sm-fs-nav: 0.9375rem;        /* 15px desktop; mobile nav uses body size */
	--sm-fs-button: 1rem;          /* 16px */

	--sm-lh-display: 1.06;         /* H1 */
	--sm-lh-heading: 1.14;         /* H2 */
	--sm-lh-subheading: 1.25;      /* H3–H6 */
	--sm-lh-body: 1.65;
	--sm-lh-small: 1.55;           /* small text, captions, help text */
	--sm-lh-ui: 1.3;               /* buttons, nav, labels */

	--sm-ls-display: -0.02em;
	--sm-ls-heading: -0.015em;
	--sm-ls-eyebrow: 0.1em;

	--sm-measure: 68ch;            /* long-form line length */
	--sm-measure-narrow: 58ch;

	/* ---- Spacing (Design System 5) ------------------------------------- */
	--sm-space-xs: 4px;
	--sm-space-sm: 8px;
	--sm-space-md: 16px;
	--sm-space-lg: 24px;
	--sm-space-xl: 32px;
	--sm-space-2xl: 48px;
	--sm-space-3xl: 64px;
	--sm-space-4xl: 96px;
	--sm-space-5xl: 128px;

	/* ---- Layout (mobile values; overridden at breakpoints below) ------- */
	--sm-container: 1280px;        /* content width, excluding gutters */
	--sm-container-narrow: 760px;  /* editorial text */
	--sm-gutter: 20px;
	--sm-section-pad: 56px;
	--sm-section-pad-major: 72px;
	--sm-header-height: 80px;      /* mobile: fits a 120px-wide logo (tested) */
	--sm-logo-width: 120px;        /* minimum legible width on mobile */
	--sm-header-height-compact: 80px;  /* desktop after scrolling (Rev 3.1 §5) */
	--sm-logo-width-compact: 120px;
	--sm-logo-scale-compact: calc(120 / 140);  /* compact logo, applied as a transform */
	--sm-logo-width-footer: 140px; /* white logo in the footer */
	--sm-admin-offset: 0px;        /* WordPress admin bar, set in header.css */

	/* ---- Shape --------------------------------------------------------- */
	--sm-radius-sm: 6px;
	--sm-radius-md: 10px;          /* buttons, inputs */
	--sm-radius-lg: 16px;          /* panels, mega menu */
	--sm-radius-xl: 24px;          /* large media */
	--sm-radius-pill: 999px;
	--sm-border-width: 1px;

	/* ---- Elevation (navy-tinted, used sparingly) ----------------------- */
	--sm-shadow-sm: 0 1px 2px rgba(23, 34, 59, 0.06);
	--sm-shadow-md: 0 8px 24px -12px rgba(23, 34, 59, 0.18);
	--sm-shadow-lg: 0 24px 48px -24px rgba(23, 34, 59, 0.22);

	/* ---- Focus --------------------------------------------------------- */
	--sm-focus-width: 3px;
	--sm-focus-offset: 3px;

	/* ---- Motion (Design System 11) ------------------------------------- */
	--sm-dur-fast: 160ms;          /* button hover */
	--sm-dur-nav: 220ms;           /* navigation */
	--sm-dur-accordion: 260ms;
	--sm-dur-reveal: 420ms;
	--sm-ease-out: cubic-bezier(0.2, 0.7, 0.2, 1);
	--sm-ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);

	/* ---- Interaction --------------------------------------------------- */
	--sm-touch-min: 44px;          /* WCAG 2.5.5 target; applies to every control */
	--sm-control-height: 48px;     /* buttons and form fields share one height */

	/* ---- Layering ------------------------------------------------------ */
	--sm-z-header: 100;
	--sm-z-mega: 110;
	--sm-z-overlay: 200;
	--sm-z-skip: 1000;
}

/* Tablet: 768–1024px (matches Elementor's default tablet breakpoint) */
@media (min-width: 768px) {
	:root {
		--sm-gutter: 32px;
		--sm-section-pad: 72px;
		--sm-section-pad-major: 96px;
	}
}

/* Desktop: 1025px and above */
@media (min-width: 1025px) {
	:root {
		--sm-gutter: 48px;
		--sm-section-pad: 96px;
		--sm-section-pad-major: 128px;
	}
}

/* Desktop header (96px bar, 140px logo). Same em breakpoint as the
   navigation in header.css (= 1025px at the default text size), so the
   header size always matches the navigation layout, even when a visitor
   enlarges the browser's text size. */
@media (min-width: 64.0625em) {
	:root {
		--sm-header-height: 96px;
		--sm-logo-width: 140px;
	}
}

/* Reduced motion: collapse durations; components must not depend on motion. */
@media (prefers-reduced-motion: reduce) {
	:root {
		--sm-dur-fast: 0.01ms;
		--sm-dur-nav: 0.01ms;
		--sm-dur-accordion: 0.01ms;
		--sm-dur-reveal: 0.01ms;
	}
}

/* Dark surface scope — remaps every semantic role so components work on
   navy without dark-specific variants. Apply .sm-surface-dark to a section
   wrapper; layout.css paints the background and base text colour.
   Not remapped: --sm-color-primary (navy is the surface itself) and
   --sm-color-surface-elevated / -surface-contrast (not used on dark). */
.sm-surface-dark {
	--sm-color-secondary: var(--sm-violet-on-dark);
	--sm-color-accent: var(--sm-blue-on-dark);
	--sm-color-accent-hover: var(--sm-blue-on-dark-hover);
	--sm-color-accent-active: var(--sm-blue-on-dark-hover);
	--sm-color-text-on-accent: var(--sm-navy);       /* white on #6FA3F6 is 2.55:1 — fails */
	--sm-color-link: var(--sm-blue-on-dark);
	--sm-color-link-hover: var(--sm-blue-on-dark-hover);
	--sm-color-text-heading: var(--sm-white);
	--sm-color-text-primary: var(--sm-text-on-dark);
	--sm-color-text-secondary: var(--sm-muted-on-dark);
	--sm-color-text-accent: var(--sm-violet-on-dark);
	--sm-color-background: var(--sm-navy);
	--sm-color-background-alt: var(--sm-navy);
	--sm-color-border: var(--sm-border-input);       /* 4.39:1 on navy — see report */
	--sm-color-divider: var(--sm-divider-on-dark);
	--sm-color-focus: var(--sm-blue-on-dark);
	--sm-color-error: var(--sm-error-on-dark);
	--sm-color-success: var(--sm-success-on-dark);
	--sm-color-warning: var(--sm-warning-on-dark);
	--sm-color-disabled-surface: var(--sm-divider-on-dark);
	--sm-color-disabled-text: var(--sm-muted-on-dark);
}

/* ---- foundations/base.css ---- */
/* ==========================================================================
   Sohnas Media — Base
   Box model, document defaults, media, focus, skip link, reduced motion.

   Cascade layering used throughout the global CSS
   ------------------------------------------------
   1. Element baseline  :where(.sm-site) h1 { … }        specificity 0,0,1
      Same weight as Hello Elementor's reset and loaded after it, so it
      replaces the reset — but any Elementor rule (Theme Style / kit CSS,
      widget defaults, per-widget settings) has a class and wins. Elementor
      Site Settings mirror these values (docs/elementor-globals.md).
   2. Components        .sm-eyebrow, .sm-container …        0,1,0 – 0,2,0
      Buttons and form controls are prefixed .sm-site (0,2,0 – 0,4,0)
      because Hello's reset styles button / input[type=…] at up to 0,2,1.
   3. Elementor bridge  .sm-site .sm-button--primary .elementor-button
                                                            0,3,0
      Beats Elementor's global defaults (0,2,0), loses to per-widget
      settings (0,4,0+), so a widget can still be edited in Elementor.
   4. Utilities         loaded last; single class.

   Rules: no Elementor-generated IDs; !important only in the two documented
   places (reduced motion, end of this file; .sm-visually-hidden in
   utilities.css); no overflow-x on html/body (it breaks position: sticky
   for the header).
   ========================================================================== */

/* ---- Box model --------------------------------------------------------- */

:where(.sm-site) *,
:where(.sm-site) *::before,
:where(.sm-site) *::after {
	box-sizing: border-box;
}

/* ---- Document ---------------------------------------------------------- */

html {
	-webkit-text-size-adjust: 100%;  /* iOS landscape: keep the set sizes */
	text-size-adjust: 100%;
	/* Anchors and focused elements land below the sticky header
	   (Rev 3.1 §5, WCAG 2.2 2.4.11 Focus Not Obscured). */
	scroll-padding-top: var(--sm-header-height);
}

body:where(.sm-site) {
	margin: 0;
	background-color: var(--sm-color-background);
	color: var(--sm-color-text-primary);
	font-family: var(--sm-font-body);
	font-size: var(--sm-fs-body);
	font-weight: var(--sm-fw-regular);
	line-height: var(--sm-lh-body);
	overflow-wrap: break-word;        /* long URLs / emails never force overflow */
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	text-rendering: optimizeLegibility;
}

/* ---- Media ------------------------------------------------------------- */

:where(.sm-site) :where(img, video) {
	max-width: 100%;
	height: auto;
}

:where(.sm-site) :where(img, svg, video, canvas, picture) {
	vertical-align: middle;
}

/* ---- Selection --------------------------------------------------------- */

:where(.sm-site) ::selection {
	background-color: var(--sm-blue);
	color: var(--sm-white);           /* 5.04:1 */
}

/* ---- Focus -------------------------------------------------------------
   One visible focus ring everywhere: 3px, 3px offset, blue on light,
   blue-on-dark inside .sm-surface-dark. Keyboard only (:focus-visible);
   text fields show it on every focus, as browsers do. */

:where(.sm-site) :focus-visible {
	outline: var(--sm-focus-width) solid var(--sm-color-focus);
	outline-offset: var(--sm-focus-offset);
}

/* Programmatic focus targets (the skip-link target, a heading focused
   after a form error) aren't interactive, so they don't get a ring.
   Interactive elements using tabindex="-1" (e.g. roving focus in menus)
   are not in this list and keep theirs. */
:where(.sm-site) :is(main, [role="main"], section, article, h1, h2, h3, h4, h5, h6)[tabindex="-1"]:focus {
	outline: none;
}

/* ---- Skip link ---------------------------------------------------------
   Styles Hello Elementor's existing skip link (.skip-link, "Skip to
   content") and the theme's own .sm-skip-link. Hidden until focused, then
   shown above the sticky header. Hello's .screen-reader-text rules handle
   the hiding. Hello forces position: absolute (!important), so its link
   sits at the top of the page rather than fixed — equivalent in practice,
   because the skip link is the first focus stop, with the page at the top. */

.sm-skip-link {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

.sm-site :is(.sm-skip-link, .skip-link):focus {
	position: fixed;
	top: var(--sm-space-sm);
	left: var(--sm-space-sm);
	z-index: var(--sm-z-skip);
	width: auto;
	height: auto;
	margin: 0;
	clip: auto;
	clip-path: none;
	display: inline-flex;
	align-items: center;
	min-height: var(--sm-touch-min);
	padding: var(--sm-space-sm) var(--sm-space-md);
	border-radius: var(--sm-radius-md);
	background-color: var(--sm-navy);
	color: var(--sm-white);           /* 15.8:1 */
	font-family: var(--sm-font-ui);
	font-size: var(--sm-fs-small);
	font-weight: var(--sm-fw-semibold);
	line-height: var(--sm-lh-ui);
	text-decoration: none;
	box-shadow: var(--sm-shadow-md);
	outline: var(--sm-focus-width) solid var(--sm-blue-on-dark);
	outline-offset: var(--sm-focus-offset);
}

/* ---- Forced colours (Windows High Contrast) ---------------------------
   Transparent borders on controls become visible; focus uses the system
   highlight so it is never lost. */

@media (forced-colors: active) {
	:where(.sm-site) :focus-visible {
		outline-color: Highlight;
	}
}

/* ---- Reduced motion ----------------------------------------------------
   Tokens already collapse durations (tokens.css). This catches motion the
   tokens don't control — Elementor entrance animations, third-party
   widgets — so the site stays still for users who ask for it.
   - Animations finish instantly (0.01ms) and keep their end state, and
     animationend still fires.
   - Transitions are switched off (0s), not shortened: a tiny duration on
     every element would turn every style change into a transition, so a
     script measuring an element right after changing it would read stale
     values. Site scripts must not wait for transitionend.
   DOCUMENTED EXCEPTION: !important is required because Elementor and
   plugins set these properties with higher specificity. */

@media (prefers-reduced-motion: reduce) {
	html,
	:where(.sm-site),
	:where(.sm-site) *,
	:where(.sm-site) *::before,
	:where(.sm-site) *::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		animation-delay: 0s !important;
		transition-duration: 0s !important;
		transition-delay: 0s !important;
		scroll-behavior: auto !important;
	}
}

/* ---- foundations/typography.css ---- */
/* ==========================================================================
   Sohnas Media — Typography
   Manrope: H1–H6 and display text. Inter: body, labels, captions, UI.
   Sizes, weights and line heights come from tokens.css (Stage 2
   Foundation §4; H5/H6/label/caption from Rev 3.1 decision 3).

   Semantic level and visual style are independent: use the right element
   (h1–h6) for the outline, then .sm-h1 … .sm-h6 to change its appearance.
   A large visual heading must not become an <h1> just to look large.
   ========================================================================== */

/* ---- Headings: element baseline + matching classes ---------------------
   Headings take the heading colour rather than inheriting (Hello's reset
   inherits). A third-party overlay with a dark background and unstyled
   <h2> (e.g. a cookie banner) needs .sm-surface-dark or its own colour —
   check when such plugins are chosen. */

:where(.sm-site) :is(h1, h2, h3, h4, h5, h6) {
	margin-block: 0 var(--sm-space-md);
	color: var(--sm-color-text-heading);
	font-family: var(--sm-font-heading);
}

.sm-h1,
.sm-h2,
.sm-h3,
.sm-h4,
.sm-h5,
.sm-h6 {
	color: var(--sm-color-text-heading);
	font-family: var(--sm-font-heading);
}

:where(.sm-site) h1,
.sm-h1 {
	font-size: var(--sm-fs-h1);
	font-weight: var(--sm-fw-bold);
	line-height: var(--sm-lh-display);
	letter-spacing: var(--sm-ls-display);
	text-wrap: balance;
}

:where(.sm-site) h2,
.sm-h2 {
	font-size: var(--sm-fs-h2);
	font-weight: var(--sm-fw-bold);
	line-height: var(--sm-lh-heading);
	letter-spacing: var(--sm-ls-heading);
	text-wrap: balance;
}

:where(.sm-site) h3,
.sm-h3 {
	font-size: var(--sm-fs-h3);
	font-weight: var(--sm-fw-bold);
	line-height: var(--sm-lh-subheading);
	letter-spacing: 0;
	text-wrap: balance;
}

:where(.sm-site) h4,
.sm-h4 {
	font-size: var(--sm-fs-h4);
	font-weight: var(--sm-fw-semibold);
	line-height: var(--sm-lh-subheading);
	letter-spacing: 0;
}

:where(.sm-site) h5,
.sm-h5 {
	font-size: var(--sm-fs-h5);
	font-weight: var(--sm-fw-semibold);
	line-height: var(--sm-lh-subheading);
	letter-spacing: 0;
}

:where(.sm-site) h6,
.sm-h6 {
	font-size: var(--sm-fs-h6);
	font-weight: var(--sm-fw-semibold);
	line-height: var(--sm-lh-subheading);
	letter-spacing: 0;
}

/* ---- Body text --------------------------------------------------------- */

:where(.sm-site) p {
	margin-block: 0 var(--sm-space-md);
	text-wrap: pretty;                /* fewer orphans where supported */
}

:where(.sm-site) :is(strong, b) {
	font-weight: var(--sm-fw-semibold);
}

:where(.sm-site) small {
	font-size: var(--sm-fs-small);
}

.sm-text-lead {
	font-family: var(--sm-font-body);
	font-size: var(--sm-fs-lead);
	font-weight: var(--sm-fw-regular);
	line-height: var(--sm-lh-body);
}

.sm-text-body {
	font-family: var(--sm-font-body);
	font-size: var(--sm-fs-body);
	font-weight: var(--sm-fw-regular);
	line-height: var(--sm-lh-body);
}

.sm-text-small {
	font-family: var(--sm-font-body);
	font-size: var(--sm-fs-small);
	line-height: var(--sm-lh-small);
}

/* ---- Labels, captions, eyebrows ---------------------------------------- */

.sm-label {
	font-family: var(--sm-font-ui);
	font-size: var(--sm-fs-label);
	font-weight: var(--sm-fw-medium);
	line-height: var(--sm-lh-ui);
	letter-spacing: 0;
}

.sm-caption,
:where(.sm-site) figcaption {
	color: var(--sm-color-text-secondary);
	font-family: var(--sm-font-body);
	font-size: var(--sm-fs-caption);
	font-weight: var(--sm-fw-regular);
	line-height: var(--sm-lh-small);
}

/* Uppercase label above a heading. Use sparingly (CD-01 4.2).
   Violet text token: 5.15:1 on white, 4.80 on Cloud, 6.55 on navy. */
.sm-eyebrow {
	display: block;
	margin-block: 0 var(--sm-space-md);
	color: var(--sm-color-text-accent);
	font-family: var(--sm-font-ui);
	font-size: var(--sm-fs-eyebrow);
	font-weight: var(--sm-fw-semibold);
	line-height: var(--sm-lh-ui);
	letter-spacing: var(--sm-ls-eyebrow);
	text-transform: uppercase;
}

/* ---- Links ----------------------------------------------------------------
   All links take the link colour. Links inside running text are also
   underlined: blue on Ink is only 2.82:1, so colour alone can't identify
   them (WCAG 1.4.1). Links with a class (buttons, navigation, Elementor
   widgets) are left to their component. The baseline doesn't depend on
   Hello's reset being active. */

:where(.sm-site) a {
	color: var(--sm-color-link);
	text-decoration: none;          /* as Hello's reset; running text adds it back below */
	transition:
		color var(--sm-dur-fast) var(--sm-ease-out),
		text-decoration-color var(--sm-dur-fast) var(--sm-ease-out);
}

/* 0,1,1: replaces Hello's a:hover/a:active colour (#336), which would
   otherwise apply to every link without its own hover rule. */
:where(.sm-site) a:is(:hover, :active) {
	color: var(--sm-color-link-hover);
}

:where(.sm-site) :is(p, .sm-prose, .elementor-widget-text-editor) a:not([class]),
.sm-link {
	color: var(--sm-color-link);
	text-decoration-line: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.2em;
}

:where(.sm-site) :is(p, .sm-prose, .elementor-widget-text-editor) a:not([class]):hover,
.sm-link:hover {
	color: var(--sm-color-link-hover);
	text-decoration-thickness: 2px;
}

.sm-link:active {
	color: var(--sm-color-accent-active);
}

/* ---- Long-form content (Insights articles, legal pages) ------------------ */

.sm-prose {
	max-width: var(--sm-measure);
}

.sm-prose > * {
	margin-block: 0;
}

.sm-prose > * + * {
	margin-block-start: var(--sm-space-md);
}

.sm-prose > * + :is(h2, h3) {
	margin-block-start: var(--sm-space-2xl);
}

.sm-prose > * + :is(h4, h5, h6) {
	margin-block-start: var(--sm-space-xl);
}

.sm-prose > :is(h2, h3, h4, h5, h6) + * {
	margin-block-start: var(--sm-space-sm);
}

.sm-prose :is(ul, ol) {
	padding-inline-start: 1.25em;
}

.sm-prose li + li {
	margin-block-start: var(--sm-space-sm);
}

.sm-prose li::marker {
	color: var(--sm-color-text-secondary);
}

.sm-prose blockquote {
	margin-inline: 0;
	padding-inline-start: var(--sm-space-lg);
	border-inline-start: 2px solid var(--sm-color-secondary);
	color: var(--sm-color-text-heading);
	font-size: var(--sm-fs-lead);
}

.sm-prose hr {
	height: 0;
	margin-block: var(--sm-space-2xl);
	border: 0;
	border-block-start: var(--sm-border-width) solid var(--sm-color-divider);
}

/* ---- Elementor bridge (needs staging verification) -----------------------
   Elementor puts a widget's "CSS Classes" on the widget wrapper, not on the
   <h2> inside it. These rules pass the class through to the heading and
   make dark sections override Elementor's navy default heading colour. */

.sm-site :is(.sm-h1, .sm-h2, .sm-h3, .sm-h4, .sm-h5, .sm-h6) .elementor-heading-title {
	color: inherit;
	font: inherit;
	letter-spacing: inherit;
}

/* Eyebrow on a Heading widget (e.g. a <p> tag Heading above a section
   title): same pass-through, plus the uppercase transform. (v0.6.0) */
.sm-site .sm-eyebrow .elementor-heading-title {
	color: inherit;
	font: inherit;
	letter-spacing: inherit;
	text-transform: inherit;
}

.sm-site .sm-surface-dark .elementor-heading-title {
	color: var(--sm-color-text-heading);
}

.sm-site .sm-surface-dark .elementor-widget-text-editor {
	color: var(--sm-color-text-primary);
}

/* ---- foundations/layout.css ---- */
/* ==========================================================================
   Sohnas Media — Layout
   Container, section spacing, responsive gutters and surfaces.

   Breakpoints (Design System 9; match Elementor's defaults — CSS custom
   properties can't be used inside media queries, so they are written out):
     Mobile        ≤ 767px        gutter 20 · section 56 / major 72
     Tablet        768 – 1024px   gutter 32 · section 72 / major 96
     Desktop       ≥ 1025px       gutter 48 · section 96 / major 128
     Large desktop ≥ 1440px       same values; the 1280px container centres
   The gutter and section values switch in tokens.css.

   Horizontal responsibility is the container's; vertical is the section's.
   A full-width background goes on the section, content alignment on the
   container inside it.

   Plain HTML (HTML widget, templates): the classes set padding and width
   directly. Elementor containers (.e-con) are excluded from those rules
   and use the bridge at the end of this file instead, so the two systems
   never set the same property.
   ========================================================================== */

/* ---- Container --------------------------------------------------------- */

.sm-container:not(.e-con) {
	width: 100%;
	max-width: calc(var(--sm-container) + 2 * var(--sm-gutter));
	margin-inline: auto;
	padding-inline: var(--sm-gutter);
}

/* Editorial text column (760px) */
.sm-container--narrow:not(.e-con) {
	max-width: calc(var(--sm-container-narrow) + 2 * var(--sm-gutter));
}

/* Edge to edge, gutters kept (full-width imagery, wide compositions) */
.sm-container--full:not(.e-con) {
	max-width: none;
}

/* ---- Section ----------------------------------------------------------- */

.sm-section:not(.e-con) {
	position: relative;             /* containing block for decorative layers */
	padding-block: var(--sm-section-pad);
}

/* Major sections: hero, framework, final conversion */
.sm-section--major:not(.e-con) {
	padding-block: var(--sm-section-pad-major);
}

/* Adjacent sections on the same background: drop the doubled spacing
   (CD-01 6.3 — spacing follows content, not a fixed rhythm). */
.sm-section--flush-top:not(.e-con) {
	padding-block-start: 0;
}

.sm-section--flush-bottom:not(.e-con) {
	padding-block-end: 0;
}

/* ---- Surfaces ----------------------------------------------------------
   Backgrounds are painted from the semantic roles, so the same markup
   works on every surface. Don't nest a light surface inside a dark one. */

.sm-surface-alt {
	background-color: var(--sm-color-background-alt);
}

.sm-surface-dark {
	background-color: var(--sm-color-background);   /* navy (remapped in tokens.css) */
	color: var(--sm-color-text-primary);
	color-scheme: dark;                             /* native controls, scrollbars */
}

/* Elementor widgets take their default colours from the kit's four system
   colours. Redeclaring them here flips widget defaults (headings, text,
   icons, links) inside dark sections. Custom global colours are not
   remapped — on dark sections, pick colours from the on-dark globals.
   (Elementor bridge — needs staging verification.) */
.sm-surface-dark {
	--e-global-color-primary: var(--sm-white);
	--e-global-color-secondary: var(--sm-violet-on-dark);
	--e-global-color-text: var(--sm-text-on-dark);
	--e-global-color-accent: var(--sm-blue-on-dark);
}

/* White panel with the approved elevation (Rev 3.1 decision 4).
   Light sections only. */
.sm-surface-elevated {
	background-color: var(--sm-color-surface-elevated);
	border-radius: var(--sm-radius-lg);
	box-shadow: var(--sm-shadow-md);
}

/* Decorative dividers (not UI boundaries) */
.sm-divider {
	height: 0;
	margin: 0;
	border: 0;
	border-block-start: var(--sm-border-width) solid var(--sm-color-divider);
}

/* ---- Elementor bridge ------------------------------------------------------
   Flexbox containers read their padding and boxed width from custom
   properties. Setting the properties (not padding itself) at 0,2,0 beats
   Elementor's defaults (0,1,0) but still loses to a container's own
   Advanced → Padding setting, so it stays editable in Elementor.

   Verified against Elementor 4.3.3 source (assets/dev/scss/frontend/
   _container.scss, v0.6.0):
   - .e-con defines --padding-top/-right/-bottom/-left (default 10px from
     the kit) and derives --padding-block-start/-end from them.
   - Boxed containers (.e-con-boxed) apply the BLOCK padding to their inner
     .e-con-inner, not to themselves; the inline padding stays on the
     container. Full-width containers apply both to themselves. So a boxed
     sm-section reads padding-top 0px on its outer element by design — the
     section spacing is on .e-con-inner. (This explains the R1 reading.)
   - --content-width sets .e-con-inner's max-width.
   v0.6.0: sm-section now also zeroes the inline padding, so Elementor's
   10px default no longer adds to the container gutter. */

.e-con.sm-section {
	--padding-top: var(--sm-section-pad);
	--padding-bottom: var(--sm-section-pad);
	--padding-left: 0px;                     /* horizontal spacing is the container's (v0.6.0) */
	--padding-right: 0px;
}

.e-con.sm-section--major {
	--padding-top: var(--sm-section-pad-major);
	--padding-bottom: var(--sm-section-pad-major);
}

.e-con.sm-section--flush-top {
	--padding-top: 0px;
}

.e-con.sm-section--flush-bottom {
	--padding-bottom: 0px;
}

.e-con.sm-container {
	--content-width: min(100%, var(--sm-container));
	--padding-left: var(--sm-gutter);
	--padding-right: var(--sm-gutter);
}

.e-con.sm-container--narrow {
	--content-width: min(100%, var(--sm-container-narrow));
}

/* ---- components/buttons.css ---- */
/* ==========================================================================
   Sohnas Media — Buttons
   Three variants (Design System 6.2): primary, secondary, text link.
   States: default, hover, focus (global ring), active, disabled.

   Markup
     Link (navigation):  <a class="sm-button sm-button--primary" href="/contact-us/#consultation">Request a Consultation</a>
     Action:             <button type="submit" class="sm-button sm-button--primary">Send inquiry</button>
     With icon:          <a class="sm-button sm-button--text" href="/portfolio/">View Our Work
                           <svg class="sm-button__icon" aria-hidden="true" focusable="false">…</svg></a>
     Disabled action:    <button class="sm-button sm-button--primary" disabled>…</button>
     Disabled link:      remove href and add aria-disabled="true" (a link with
                         an href can still be followed from the keyboard).

   Elementor Button widget: Advanced → CSS Classes = "sm-button--primary"
   (or --secondary / --text). Add ONLY the modifier: the widget's wrapper
   receives the class, and the bridge selectors style the link inside it.
   Elementor Form widget: the submit button takes the primary style when
   the form has the class "sm-form".

   Contrast (calculated; browser-measured values in the report)
     Primary     white on #1A68E6 5.04 · hover 6.98 · active 8.59
                 on navy: navy on #6FA3F6 6.21 · hover 8.52
     Secondary   #1A68E6 text/border on white 5.04, on Cloud 4.70
                 on navy: #6FA3F6 6.21
     Text link   link colour, underline added on hover (not colour alone)
   ========================================================================== */

/* ---- Base --------------------------------------------------------------
   .sm-site prefix: Hello's reset styles button, [type=submit] and their
   :hover/:focus states (up to 0,2,0); the prefix keeps these rules ahead
   whatever the stylesheet order. */

.sm-site .sm-button,
.sm-site :is(.sm-button--primary, .sm-button--secondary, .sm-button--text) .elementor-button,
.sm-site .sm-form .elementor-button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--sm-space-sm);
	min-width: var(--sm-touch-min);
	min-height: var(--sm-control-height);
	margin: 0;
	padding: var(--sm-space-sm) var(--sm-space-lg);
	border: var(--sm-border-width) solid transparent;   /* visible in forced-colours mode */
	border-radius: var(--sm-radius-md);
	background-color: transparent;
	color: inherit;
	font-family: var(--sm-font-ui);
	font-size: var(--sm-fs-button);
	font-weight: var(--sm-fw-semibold);
	line-height: var(--sm-lh-ui);
	letter-spacing: 0;
	text-align: center;
	text-decoration: none;
	text-transform: none;
	white-space: normal;            /* long labels wrap instead of overflowing */
	cursor: pointer;
	user-select: none;
	-webkit-tap-highlight-color: transparent;
	transition:
		background-color var(--sm-dur-fast) var(--sm-ease-out),
		border-color var(--sm-dur-fast) var(--sm-ease-out),
		color var(--sm-dur-fast) var(--sm-ease-out),
		box-shadow var(--sm-dur-fast) var(--sm-ease-out),
		text-decoration-color var(--sm-dur-fast) var(--sm-ease-out);
}

.sm-button__icon {
	flex: none;
	width: 1.125em;
	height: 1.125em;
	fill: currentColor;
}

/* Elementor sometimes sets outline: none on its buttons; restore the ring. */
.sm-site :is(.sm-button--primary, .sm-button--secondary, .sm-button--text) .elementor-button:focus-visible,
.sm-site .sm-form .elementor-button:focus-visible {
	outline: var(--sm-focus-width) solid var(--sm-color-focus);
	outline-offset: var(--sm-focus-offset);
}

/* ---- Primary: main conversion action ---------------------------------- */

.sm-site .sm-button.sm-button--primary,
.sm-site .sm-button--primary .elementor-button,
.sm-site .sm-form .elementor-button {
	border-color: var(--sm-color-accent);
	background-color: var(--sm-color-accent);
	color: var(--sm-color-text-on-accent);
}

.sm-site .sm-button.sm-button--primary:hover,
.sm-site .sm-button--primary .elementor-button:hover,
.sm-site .sm-form .elementor-button:hover {
	border-color: var(--sm-color-accent-hover);
	background-color: var(--sm-color-accent-hover);
	color: var(--sm-color-text-on-accent);
}

.sm-site .sm-button.sm-button--primary:active,
.sm-site .sm-button--primary .elementor-button:active,
.sm-site .sm-form .elementor-button:active {
	border-color: var(--sm-color-accent-active);
	background-color: var(--sm-color-accent-active);
}

/* ---- Secondary: supporting action (outlined) --------------------------- */

.sm-site .sm-button.sm-button--secondary,
.sm-site .sm-button--secondary .elementor-button {
	border-color: var(--sm-color-accent);
	background-color: transparent;
	color: var(--sm-color-accent);
}

/* Hover: darker colour AND a 2px border, so the change isn't colour alone. */
.sm-site .sm-button.sm-button--secondary:hover,
.sm-site .sm-button--secondary .elementor-button:hover {
	border-color: var(--sm-color-accent-hover);
	background-color: transparent;  /* Hello's reset fills buttons on hover */
	color: var(--sm-color-accent-hover);
	box-shadow: inset 0 0 0 var(--sm-border-width) var(--sm-color-accent-hover);
}

.sm-site .sm-button.sm-button--secondary:active,
.sm-site .sm-button--secondary .elementor-button:active {
	border-color: var(--sm-color-accent-active);
	color: var(--sm-color-accent-active);
	box-shadow: inset 0 0 0 var(--sm-border-width) var(--sm-color-accent-active);
}

/* ---- Text link: contextual navigation ---------------------------------- */

.sm-site .sm-button.sm-button--text,
.sm-site .sm-button--text .elementor-button {
	min-width: 0;
	padding-inline: 0;
	border-color: transparent;
	background-color: transparent;
	color: var(--sm-color-link);
	text-decoration-line: underline;
	text-decoration-color: transparent;
	text-decoration-thickness: 2px;
	text-underline-offset: 0.3em;
}

.sm-site .sm-button.sm-button--text:hover,
.sm-site .sm-button--text .elementor-button:hover {
	background-color: transparent;
	color: var(--sm-color-link-hover);
	text-decoration-color: currentColor;
}

.sm-site .sm-button.sm-button--text:active,
.sm-site .sm-button--text .elementor-button:active {
	color: var(--sm-color-accent-active);
}

@media (prefers-reduced-motion: no-preference) {
	.sm-button--text .sm-button__icon,
	.sm-site .sm-button--text .elementor-button-icon {
		transition: translate var(--sm-dur-fast) var(--sm-ease-out);
	}

	.sm-button--text:hover .sm-button__icon,
	.sm-site .sm-button--text .elementor-button:hover .elementor-button-icon {
		translate: var(--sm-space-xs) 0;
	}
}

/* ---- Disabled ----------------------------------------------------------
   Same or higher specificity than the hover rules and declared after them,
   so a disabled button never reacts to hover. Disabled controls are exempt
   from contrast requirements (WCAG 1.4.3); they are still legible (3.07). */

.sm-site .sm-button:is(.sm-button--primary, .sm-button--secondary):is(:disabled, [aria-disabled="true"]) {
	border-color: var(--sm-color-disabled-surface);
	background-color: var(--sm-color-disabled-surface);
	color: var(--sm-color-disabled-text);
	box-shadow: none;
	cursor: not-allowed;
	opacity: 1;                     /* Hello's reset also fades disabled buttons */
}

.sm-site .sm-button.sm-button--text:is(:disabled, [aria-disabled="true"]) {
	color: var(--sm-color-disabled-text);
	text-decoration-color: transparent;
	cursor: not-allowed;
	opacity: 1;
}

.sm-site .sm-button[aria-disabled="true"] {
	pointer-events: none;           /* mouse; keyboard is handled by removing href */
}

@media (prefers-reduced-motion: no-preference) {
	.sm-button--text:is(:disabled, [aria-disabled="true"]) .sm-button__icon {
		translate: none;
	}
}

/* ---- Forced colours ---------------------------------------------------- */

@media (forced-colors: active) {
	.sm-site .sm-button:is(:disabled, [aria-disabled="true"]) {
		border-color: GrayText;
		color: GrayText;
	}
}

/* ---- components/forms.css ---- */
/* ==========================================================================
   Sohnas Media — Forms
   Global styling for labels, text inputs (text, email, tel, url, number),
   textareas, selects, checkboxes/radios, help text, required indicators
   and validation messages. Styling only: no form is connected to email,
   HighLevel or any workflow in this phase.

   Markup (plain HTML)
     <div class="sm-field">
       <label class="sm-field__label" for="email">Email
         <span class="sm-required" aria-hidden="true">*</span></label>
       <input class="sm-input" id="email" type="email" required
              aria-describedby="email-help" autocomplete="email">
       <p class="sm-field__help" id="email-help">We reply within the hours on our Contact page.</p>
     </div>

     Fields stay light (white, Ink text) on every surface, including navy.

     Error: add .sm-field--error to .sm-field, aria-invalid="true" to the
     control, and a message whose id is in the control's aria-describedby:
       <p class="sm-message sm-message--error" id="email-error">
         <span class="sm-message__prefix">Error:</span> Enter an email address like name@example.com.</p>
     Warning / success: same pattern with --warning / --success and the
     prefix "Warning:" / "Success:". Messages always have an icon (CSS) and
     a text prefix (markup) — never colour alone (Rev 3.1 §4).

     A form that uses "*" needs a visible note: <p class="sm-form__note">
     <span aria-hidden="true">*</span> Required field</p>. Screen readers get
     "required" from the control's required attribute.

   Elementor Pro Form widget: Advanced → CSS Classes = "sm-form". The
   bridge section at the end maps the design onto Elementor's markup.
   Leave the Form widget's own colour/typography controls at their defaults.
   ========================================================================== */

/* ---- Form layout (plain HTML forms) ------------------------------------ */

/* minmax(0, 1fr): a field's intrinsic width (about 20 characters) must
   never widen the column — at 200% text on a phone it would overflow. */
.sm-form:not(.elementor-widget) {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--sm-space-lg);
}

.sm-field {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--sm-space-sm);
	min-width: 0;
}

.sm-fieldset {
	min-width: 0;
	margin: 0;
	padding: 0;
	border: 0;
}

.sm-fieldset > legend {
	margin-block-end: var(--sm-space-sm);
	padding: 0;
}

/* ---- Labels, required, help -------------------------------------------- */

.sm-field__label,
.sm-fieldset > legend,
.sm-site .sm-form .elementor-field-label {
	color: var(--sm-color-text-primary);
	font-family: var(--sm-font-ui);
	font-size: var(--sm-fs-label);
	font-weight: var(--sm-fw-medium);
	line-height: var(--sm-lh-ui);
}

.sm-required {
	margin-inline-start: 0.15em;
	color: var(--sm-color-error);
	font-weight: var(--sm-fw-semibold);
}

.sm-field__optional {
	color: var(--sm-color-text-secondary);
	font-weight: var(--sm-fw-regular);
}

.sm-field__help,
.sm-form__note {
	margin: 0;
	color: var(--sm-color-text-secondary);
	font-family: var(--sm-font-body);
	font-size: var(--sm-fs-small);
	line-height: var(--sm-lh-small);
}

/* ---- Text controls ------------------------------------------------------
   Fields are always light — white field, Ink text — including inside dark
   sections: a white field reads clearly on navy, and it matches Elementor's
   Form widget, whose default field background is white. So field colours
   use fixed brand values, not the dark-remapped roles. The focus ring sits
   outside the field and still follows the surface (blue-on-dark on navy).
   16px text: iOS Safari zooms the page when a field's text is smaller.
   .sm-site prefix: Hello's reset styles input[type=email] etc. at 0,1,1.
   --sm-field-state carries the 2px state ring so it can be combined with
   the autofill fix below. */

.sm-site :is(.sm-input, .sm-select, .sm-textarea),
.sm-site .sm-form .elementor-field-textual {
	--sm-field-state: 0 0 0 0 transparent;
	display: block;
	width: 100%;
	min-width: 0;
	max-width: 100%;
	min-height: var(--sm-control-height);
	margin: 0;
	padding: calc(var(--sm-space-sm) + var(--sm-space-xs)) var(--sm-space-md);
	border: var(--sm-border-width) solid var(--sm-border-input);
	border-radius: var(--sm-radius-md);
	background-color: var(--sm-white);
	color: var(--sm-ink);
	font-family: var(--sm-font-ui);
	font-size: 1rem;
	font-weight: var(--sm-fw-regular);
	line-height: var(--sm-lh-ui);
	box-shadow: var(--sm-field-state);
	appearance: none;
	color-scheme: light;
	transition:
		border-color var(--sm-dur-fast) var(--sm-ease-out),
		box-shadow var(--sm-dur-fast) var(--sm-ease-out);
}

.sm-site .sm-textarea,
.sm-site .sm-form textarea.elementor-field-textual {
	min-height: 8rem;
	line-height: var(--sm-lh-body);
	resize: vertical;
}

/* Select arrow drawn with currentColor (Ink) */
.sm-site .sm-select {
	padding-inline-end: calc(var(--sm-space-md) * 2 + 0.5rem);
	background-image:
		linear-gradient(45deg, transparent 50%, currentColor 50%),
		linear-gradient(135deg, currentColor 50%, transparent 50%);
	background-position:
		right calc(var(--sm-space-md) + 5px) center,
		right var(--sm-space-md) center;
	background-size: 5px 5px, 5px 5px;
	background-repeat: no-repeat;
	cursor: pointer;
}

.sm-site :is(.sm-input, .sm-textarea)::placeholder,
.sm-site .sm-form .elementor-field-textual::placeholder {
	color: var(--sm-muted);         /* 6.13:1; never a substitute for a label */
	opacity: 1;
}

.sm-site :is(.sm-input, .sm-select, .sm-textarea):hover,
.sm-site .sm-form .elementor-field-textual:hover {
	border-color: var(--sm-muted);
}

/* Focus: blue border on any focus + the global 3px ring (keyboard) */
.sm-site :is(.sm-input, .sm-select, .sm-textarea):focus,
.sm-site .sm-form .elementor-field-textual:focus {
	border-color: var(--sm-blue);
	outline: none;
}

.sm-site :is(.sm-input, .sm-select, .sm-textarea):focus-visible,
.sm-site .sm-form .elementor-field-textual:focus-visible {
	outline: var(--sm-focus-width) solid var(--sm-color-focus);
	outline-offset: var(--sm-focus-offset);
}

/* Chrome paints its own autofill background; cover it, keep the state ring. */
.sm-site :is(.sm-input, .sm-select, .sm-textarea):-webkit-autofill,
.sm-site .sm-form .elementor-field-textual:-webkit-autofill {
	-webkit-text-fill-color: var(--sm-ink);
	box-shadow: var(--sm-field-state), inset 0 0 0 100vmax var(--sm-white);
	caret-color: var(--sm-ink);
}

/* ---- Validation states --------------------------------------------------
   Colour AND a 2px border; the message below adds an icon and a prefix.
   Declared after hover/focus at equal specificity, so the state colour
   stays while hovered or focused (the ring shows focus). */

.sm-site :is(.sm-input, .sm-select, .sm-textarea)[aria-invalid="true"],
.sm-site .sm-field--error :is(.sm-input, .sm-select, .sm-textarea),
.sm-site .sm-form .elementor-field-textual[aria-invalid="true"],
.sm-site .sm-form .elementor-error .elementor-field-textual {
	--sm-field-state: inset 0 0 0 var(--sm-border-width) var(--sm-error);
	border-color: var(--sm-error);                  /* 6.57:1 on the white field */
}

.sm-site .sm-field--warning :is(.sm-input, .sm-select, .sm-textarea) {
	--sm-field-state: inset 0 0 0 var(--sm-border-width) var(--sm-warning);
	border-color: var(--sm-warning);                /* 5.19:1 on the white field */
}

.sm-site .sm-field--success :is(.sm-input, .sm-select, .sm-textarea) {
	border-color: var(--sm-success);                /* 5.69:1 on the white field */
}

/* ---- Disabled and read-only ------------------------------------------- */

.sm-site :is(.sm-input, .sm-select, .sm-textarea):disabled,
.sm-site .sm-form .elementor-field-textual:disabled {
	--sm-field-state: 0 0 0 0 transparent;
	border-color: var(--sm-divider);
	background-color: var(--sm-disabled-surface);
	color: var(--sm-disabled-text);
	cursor: not-allowed;
	-webkit-text-fill-color: var(--sm-disabled-text);   /* Safari dims disabled text further */
	opacity: 1;
}

.sm-site :is(.sm-input, .sm-textarea):read-only:not(:disabled) {
	background-color: var(--sm-cloud);
}

/* ---- Checkboxes and radios ---------------------------------------------
   Native controls, coloured with accent-color. The whole label row is the
   touch target (min 44px). */

.sm-check {
	display: flex;
	align-items: flex-start;
	gap: var(--sm-space-sm);
	min-height: var(--sm-touch-min);
	padding-block: calc((var(--sm-touch-min) - 1.5rem) / 2);
	color: var(--sm-color-text-primary);
	font-family: var(--sm-font-body);
	font-size: var(--sm-fs-body);
	line-height: 1.5;
	cursor: pointer;
}

.sm-check__input,
.sm-site .sm-form .elementor-field-option input {
	flex: none;
	width: 1.25rem;
	height: 1.25rem;
	margin: 0.125rem 0 0;
	accent-color: var(--sm-color-accent);
	cursor: pointer;
}

.sm-check__input:disabled {
	cursor: not-allowed;
}

/* Separate rule: browsers without :has() drop only this one. */
.sm-check:has(.sm-check__input:disabled) {
	color: var(--sm-color-disabled-text);
	cursor: not-allowed;
}

/* ---- Messages -----------------------------------------------------------
   Inline under a field, or as a form-level banner (.sm-message--banner).
   No tinted backgrounds: #A15C07 has only 4.84:1 on Cloud, so warning
   text always sits directly on the section background. */

.sm-message {
	display: block;                 /* prefix and text flow and wrap as one sentence */
	margin: 0;
	color: var(--sm-color-text-primary);
	font-family: var(--sm-font-body);
	font-size: var(--sm-fs-small);
	font-weight: var(--sm-fw-medium);
	line-height: var(--sm-lh-small);
}

.sm-message:is(.sm-message--error, .sm-message--warning, .sm-message--success) {
	position: relative;
	padding-inline-start: calc(1.125rem + var(--sm-space-sm));
}

.sm-message:is(.sm-message--error, .sm-message--warning, .sm-message--success)::before {
	content: "";
	position: absolute;
	inset-inline-start: 0;
	top: 0.125rem;                  /* centres the 18px icon on the first line */
	width: 1.125rem;
	height: 1.125rem;
	background-color: currentColor;
	-webkit-mask: var(--sm-message-icon) center / contain no-repeat;
	mask: var(--sm-message-icon) center / contain no-repeat;
}

.sm-message__prefix {
	font-weight: var(--sm-fw-semibold);
}

.sm-message--error {
	--sm-message-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M10 1.5a8.5 8.5 0 1 0 0 17 8.5 8.5 0 0 0 0-17Zm-.9 4.25h1.8v5.5H9.1v-5.5Zm.9 9a1.1 1.1 0 1 1 0-2.2 1.1 1.1 0 0 1 0 2.2Z'/%3E%3C/svg%3E");
	color: var(--sm-color-error);
}

.sm-message--warning {
	--sm-message-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M10 1.75 .9 17.5h18.2L10 1.75Zm-.9 5.5h1.8v5H9.1v-5Zm.9 8.1a1.05 1.05 0 1 1 0-2.1 1.05 1.05 0 0 1 0 2.1Z'/%3E%3C/svg%3E");
	color: var(--sm-color-warning);
}

.sm-message--success {
	--sm-message-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M10 1.5a8.5 8.5 0 1 0 0 17 8.5 8.5 0 0 0 0-17Zm-1.2 12.1L4.9 9.7l1.3-1.3 2.6 2.6 5-5 1.3 1.3-6.3 6.3Z'/%3E%3C/svg%3E");
	color: var(--sm-color-success);
}

.sm-message.sm-message--banner {
	padding: var(--sm-space-md);
	padding-inline-start: calc(var(--sm-space-lg) + 1.125rem + var(--sm-space-sm));
	border-inline-start: 3px solid currentColor;
	font-size: var(--sm-fs-body);
}

.sm-message.sm-message--banner::before {
	inset-inline-start: var(--sm-space-lg);
	top: calc(var(--sm-space-md) + 0.21rem);
}

/* Forced colours: keep the icon, drawn in the system text colour. */
@media (forced-colors: active) {
	.sm-message::before {
		forced-color-adjust: none;
		background-color: CanvasText;
	}
}

/* ---- Elementor bridge (needs staging verification) -----------------------
   Class names from Elementor Pro's Form widget markup; confirm against the
   installed version. Elementor keeps its own layout, column widths and
   caret icon; only appearance is mapped. */

.sm-site .sm-form .elementor-select-wrapper select {
	padding-inline-end: calc(var(--sm-space-md) * 2 + 0.5rem);
	background-image: none;         /* Elementor draws its own caret */
}

.sm-site .sm-form .elementor-select-wrapper :is(.select-caret-down-wrapper, .select-caret-down-wrapper i, .select-caret-down-wrapper svg) {
	color: var(--sm-color-text-primary);
	fill: currentColor;
}

.sm-site .sm-form .elementor-mark-required .elementor-field-label::after {
	color: var(--sm-color-error);
}

.sm-site .sm-form .elementor-field-option label {
	color: var(--sm-color-text-primary);
	font-family: var(--sm-font-body);
	font-size: var(--sm-fs-body);
	line-height: 1.5;
}

.sm-site .sm-form .elementor-message {
	font-family: var(--sm-font-body);
	font-size: var(--sm-fs-small);
	font-weight: var(--sm-fw-medium);
	line-height: var(--sm-lh-small);
}

.sm-site .sm-form .elementor-message-danger {
	color: var(--sm-color-error);
}

.sm-site .sm-form .elementor-message-success {
	color: var(--sm-color-success);
}

/* ---- components/section-intro.css ---- */
/* ==========================================================================
   Sohnas Media — Section introduction
   A typography and layout pattern, not a card: optional eyebrow, heading,
   supporting copy and optional actions, with a controlled width,
   alignment and rhythm. No background, border or shadow of its own; it
   takes its colours from the surface it sits on (light or .sm-surface-dark).

   Markup
     <div class="sm-intro">
       <p class="sm-eyebrow sm-intro__eyebrow">Our approach</p>
       <h2 class="sm-intro__title">One connected system for growth</h2>
       <p class="sm-intro__text">Supporting copy …</p>
       <div class="sm-intro__actions">
         <a class="sm-button sm-button--primary" href="…">…</a>
         <a class="sm-button sm-button--text" href="…">…</a>
       </div>
     </div>

   The heading level is chosen for the page outline (usually h2); its size
   follows the element, or .sm-h1 … .sm-h4 on the title to change it.

   Variants
     (default)            left-aligned, 760px wide
     .sm-intro--center    centred; actions centred
     .sm-intro--wide      title and text can use the full container
     .sm-intro--split     desktop: title left, text + actions right
                          (editorial asymmetry); stacks below 1025px
     .sm-intro--flush     no space after the intro (when the following
                          content sets its own)

   Rhythm: eyebrow → title 16px · title → text 24px · text → actions 32px
   · intro → following content 48px (mobile) / 64px (desktop).
   ========================================================================== */

.sm-intro {
	--sm-intro-width: var(--sm-container-narrow);   /* 760px */
	max-width: var(--sm-intro-width);
	margin-block: 0 var(--sm-space-2xl);
	color: var(--sm-color-text-primary);
}

.sm-intro > * {
	margin-block: 0;
}

.sm-intro__eyebrow {
	margin-block-end: var(--sm-space-md);
}

.sm-intro__title {
	color: var(--sm-color-text-heading);
	text-wrap: balance;
}

/* Supporting copy: lead size, secondary colour for a clear step down from
   the heading (6.13:1 on white, 5.71 on Cloud, 7.51 on navy). */
.sm-intro__text {
	max-width: var(--sm-measure-narrow);
	margin-block-start: var(--sm-space-lg);
	color: var(--sm-color-text-secondary);
	font-size: var(--sm-fs-lead);
	line-height: var(--sm-lh-body);
	text-wrap: pretty;
}

.sm-intro__text + .sm-intro__text {
	margin-block-start: var(--sm-space-md);
}

.sm-intro__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--sm-space-md) var(--sm-space-lg);
	margin-block-start: var(--sm-space-xl);
}

/* ---- Variants ---------------------------------------------------------- */

.sm-intro--center {
	margin-inline: auto;
	text-align: center;
}

.sm-intro--center .sm-intro__text {
	margin-inline: auto;
}

.sm-intro--center .sm-intro__actions {
	justify-content: center;
}

.sm-intro--wide {
	--sm-intro-width: var(--sm-container);
}

.sm-intro--flush {
	margin-block-end: 0;
}

/* ---- Desktop ----------------------------------------------------------- */

@media (min-width: 1025px) {
	.sm-intro {
		margin-block-end: var(--sm-space-3xl);
	}

	.sm-intro--flush {
		margin-block-end: 0;
	}

	/* Split: 7 / 5 columns, title on the left, copy aligned to the title's
	   first line on the right. Eyebrow spans above the title column. */
	.sm-intro--split {
		--sm-intro-width: var(--sm-container);
		display: grid;
		grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
		column-gap: var(--sm-space-3xl);
		align-items: start;
	}

	.sm-intro--split > .sm-intro__eyebrow {
		grid-column: 1 / -1;
	}

	.sm-intro--split > .sm-intro__title {
		grid-column: 1;
		grid-row: span 3;
	}

	.sm-intro--split > :not(.sm-intro__eyebrow, .sm-intro__title) {
		grid-column: 2;
	}

	.sm-intro--split > .sm-intro__title + .sm-intro__text {
		margin-block-start: 0.4em;   /* aligns with the title's cap height */
	}
}

/* ---- Elementor bridge (needs WordPress verification) ---------------------
   Put "sm-intro" (and any variant) on a FULL-WIDTH container (Content
   Width: Full Width — a boxed container adds an .e-con-inner wrapper the
   rules below don't reach) that holds the Heading / Text Editor / Button
   widgets, and the element classes on the widgets. The container's own gap and the widgets' default spacing are
   neutralised so the rhythm above applies. The Button widgets keep their
   sm-button--* classes. */

.sm-site .e-con.sm-intro {
	--gap: 0px;
	--row-gap: 0px;
	--column-gap: 0px;
	--widgets-spacing: 0px;
	--widgets-spacing-row: 0px;
}

.sm-site .sm-intro > .elementor-widget {
	margin-block: 0;
}

.sm-site .sm-intro > .elementor-widget.sm-intro__eyebrow {
	margin-block-end: var(--sm-space-md);
}

.sm-site .sm-intro > .elementor-widget.sm-intro__text {
	margin-block-start: var(--sm-space-lg);
}

.sm-site .sm-intro > .elementor-widget.sm-intro__actions {
	margin-block-start: var(--sm-space-xl);
}

.sm-site .sm-intro .sm-intro__text :is(p:last-child) {
	margin-block-end: 0;
}

/* Actions row as a nested Elementor container: horizontal, wrapping. */
.sm-site .e-con.sm-intro__actions {
	--flex-direction: row;
	--flex-wrap: wrap;
	--align-items: center;
	--row-gap: var(--sm-space-md);
	--column-gap: var(--sm-space-lg);
}

.sm-site .sm-intro--center > .e-con.sm-intro__actions {
	--justify-content: center;
}

@media (min-width: 1025px) {
	.sm-site .e-con.sm-intro--split {
		display: grid;
	}
}

/* Elementor styles the heading and text inside the widget wrapper; carry
   the intro's colours and size through (a widget's own Style settings
   still win). */
.sm-site .sm-intro__title .elementor-heading-title {
	color: var(--sm-color-text-heading);
}

.sm-site .sm-intro__text.elementor-widget-text-editor {
	color: var(--sm-color-text-secondary);
	font-size: var(--sm-fs-lead);
	line-height: var(--sm-lh-body);
}

/* ---- components/header.css ---- */
/* ==========================================================================
   Sohnas Media — Global header
   Markup: template-parts/site-header.php ([sm_site_header] shortcode in the
   Elementor Theme Builder header). Behaviour: src/js/sm-site.js.

   Sizes (Rev 3.1 §5, approved)
     Desktop ≥ 1025px   96px bar, 140px logo → compact 80px bar, 120px logo
     Mobile / tablet    80px bar, 120px logo, no compact state

   No layout shift: .sm-header is a spacer that reserves the full header
   height in the page flow and never changes. The visible bar inside it is
   position: fixed, so compacting it moves nothing on the page. (Sticky
   positioning can't be used: Elementor's header wrapper is only as tall as
   the header, so a sticky element inside it would scroll away.)

   Navigation layout switches at 64.0625em (= 1025px at the default text
   size). An em breakpoint means a visitor who enlarges text in browser
   settings gets the mobile navigation instead of an overflowing desktop
   bar (WCAG 1.4.4). Header heights follow tokens.css.

   Buttons here are prefixed .sm-site: Hello's reset styles <button> and
   its :hover/:focus states at up to 0,2,0.
   ========================================================================== */

/* ---- WordPress admin bar (logged-in users only) ----------------------- */

body.admin-bar {
	--sm-admin-offset: 32px;
}

@media (max-width: 782px) {
	body.admin-bar {
		--sm-admin-offset: 46px;
	}
}

/* Anchor offset for logged-in users. The offset is written out here
   because --sm-admin-offset is set on <body>, which <html> can't read.
   (Below 600px WordPress lets the admin bar scroll away, leaving a gap
   above the header for logged-in users only.) */
html:has(> body.admin-bar) {
	scroll-padding-top: calc(var(--sm-header-height) + 32px);
}

@media (max-width: 782px) {
	html:has(> body.admin-bar) {
		scroll-padding-top: calc(var(--sm-header-height) + 46px);
	}
}

/* ---- Spacer and scroll sentinels -------------------------------------- */

.sm-header {
	position: relative;
	height: var(--sm-header-height);
}

/* Two 1px markers the script watches with an IntersectionObserver:
   compact when the 64px marker has scrolled out of view, expand again only
   when the 16px marker returns. The gap between them prevents flicker. */
.sm-header__sentinel {
	position: absolute;
	left: 0;
	width: 1px;
	height: 1px;
	pointer-events: none;
}

.sm-header__sentinel--expand {
	top: 16px;
}

.sm-header__sentinel--compact {
	top: 64px;
}

/* ---- Bar --------------------------------------------------------------- */

.sm-header__bar {
	position: fixed;
	top: var(--sm-admin-offset);
	right: 0;
	left: 0;
	z-index: var(--sm-z-header);
	height: var(--sm-header-height);
	border-block-end: var(--sm-border-width) solid var(--sm-color-divider);
	background-color: var(--sm-color-background);
	color: var(--sm-color-text-primary);
	transition:
		transform var(--sm-dur-nav) var(--sm-ease-out),
		box-shadow var(--sm-dur-nav) var(--sm-ease-out);
}

.sm-header__inner {
	display: flex;
	align-items: center;
	gap: var(--sm-space-md);
	height: 100%;
}

/* ---- Logo -------------------------------------------------------------- */

.sm-header__logo {
	display: inline-flex;
	flex: none;
	align-items: center;
	border-radius: var(--sm-radius-sm);
	transition: translate var(--sm-dur-nav) var(--sm-ease-out);
}

.sm-header__logo-img {
	display: block;
	width: var(--sm-logo-width);
	height: auto;                   /* proportions always preserved */
	transform-origin: left center;
	transition: transform var(--sm-dur-nav) var(--sm-ease-out);
}

/* ---- Icons ------------------------------------------------------------- */

.sm-icon {
	flex: none;
	width: 1.25rem;
	height: 1.25rem;
	fill: currentColor;
}

/* ---- CTA and menu toggle (mobile / tablet first) ---------------------- */

/* .sm-site prefix: must outrank .sm-site .sm-button (display, margin). */
.sm-site .sm-header__cta {
	display: none;
	margin-inline-start: auto;
	transition:
		background-color var(--sm-dur-fast) var(--sm-ease-out),
		border-color var(--sm-dur-fast) var(--sm-ease-out),
		color var(--sm-dur-fast) var(--sm-ease-out),
		translate var(--sm-dur-nav) var(--sm-ease-out);
}

.sm-header__nav {
	display: none;
}

.sm-site .sm-header__toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--sm-space-sm);
	min-width: var(--sm-touch-min);
	min-height: var(--sm-touch-min);
	margin-inline-start: auto;
	padding: 0 var(--sm-space-sm) 0 calc(var(--sm-space-sm) + var(--sm-space-xs));
	border: var(--sm-border-width) solid transparent;
	border-radius: var(--sm-radius-md);
	background-color: transparent;
	color: var(--sm-color-text-heading);
	font-family: var(--sm-font-ui);
	font-size: var(--sm-fs-body);
	font-weight: var(--sm-fw-semibold);
	line-height: var(--sm-lh-ui);
	text-decoration: none;
	white-space: nowrap;
	cursor: pointer;
	-webkit-tap-highlight-color: transparent;
	transition: background-color var(--sm-dur-fast) var(--sm-ease-out);
}

.sm-site .sm-header__toggle:hover,
.sm-site .sm-header__toggle[aria-expanded="true"] {
	background-color: var(--sm-color-background-alt);
	color: var(--sm-color-text-heading);
}

.sm-header__toggle .sm-icon--close,
.sm-header__toggle[aria-expanded="true"] .sm-icon--menu {
	display: none;
}

.sm-header__toggle[aria-expanded="true"] .sm-icon--close {
	display: block;
}

/* No-JavaScript toggle (an anchor to the panel) — hidden when JS runs. */
.sm-site .sm-header__toggle--nojs {
	display: none;
}

/* CTA joins the bar once it fits on one line beside logo and toggle
   (552px needed with fallback fonts; Inter is narrower — re-check once
   the real fonts are installed). */
@media (min-width: 35em) {
	.sm-site .sm-header__cta {
		display: inline-flex;
	}

	.sm-site .sm-header__toggle {
		margin-inline-start: 0;
	}
}

/* Narrow phones: the CTA lives in the menu panel instead (see mega-menu.css) */

/* ---- Desktop ----------------------------------------------------------- */

@media (min-width: 64.0625em) {
	.sm-header__inner {
		gap: var(--sm-space-lg);
	}

	.sm-header__nav {
		display: block;
		margin-inline-start: auto;
	}

	.sm-site .sm-header__cta {
		margin-inline-start: 0;
	}

	.sm-site .sm-header__toggle,
	.sm-site .sm-header__toggle--nojs {
		display: none;
	}

	/* Compact state after scrolling (desktop only).
	   Done with transforms, not height/width: the bar slides up 16px so
	   80px remain visible, its contents move down 8px to stay centred, and
	   the logo scales 140 → 120px. Transforms don't reflow anything, so
	   the change registers no layout shift (CLS) at all. */
	.sm-header--compact .sm-header__bar {
		transform: translateY(calc(var(--sm-header-height-compact) - var(--sm-header-height)));
		box-shadow: var(--sm-shadow-sm);
	}

	/* Re-centre the bar's items. Applied to the items themselves, never to
	   an ancestor of the mega menu panel: a transformed ancestor would
	   become the panel's positioning box and move it. */
	.sm-header--compact :is(.sm-header__logo, .sm-nav__link, .sm-header__cta) {
		translate: 0 calc((var(--sm-header-height) - var(--sm-header-height-compact)) / 2);
	}

	.sm-header--compact .sm-header__logo-img {
		transform: scale(var(--sm-logo-scale-compact));
	}
}

/* ---- Primary navigation (desktop) ------------------------------------ */

.sm-nav {
	display: flex;
	align-items: center;
	gap: var(--sm-space-xs);
	margin: 0;
	padding: 0;
	list-style: none;
}

.sm-nav__item {
	margin: 0;
}

.sm-site .sm-nav__link {
	position: relative;
	display: inline-flex;
	align-items: center;
	gap: var(--sm-space-xs);
	min-height: var(--sm-touch-min);
	margin: 0;
	padding: 0 calc(var(--sm-space-sm) + var(--sm-space-xs));
	border: 0;
	border-radius: var(--sm-radius-sm);
	background-color: transparent;
	color: var(--sm-color-text-primary);
	font-family: var(--sm-font-ui);
	font-size: var(--sm-fs-nav);
	font-weight: var(--sm-fw-medium);
	line-height: var(--sm-lh-ui);
	text-decoration: none;
	white-space: nowrap;
	cursor: pointer;
	transition:
		color var(--sm-dur-fast) var(--sm-ease-out),
		translate var(--sm-dur-nav) var(--sm-ease-out);
}

/* Indicator line: hover, current page, open menu. Not colour alone. */
.sm-nav__link::after {
	content: "";
	position: absolute;
	right: calc(var(--sm-space-sm) + var(--sm-space-xs));
	bottom: 6px;
	left: calc(var(--sm-space-sm) + var(--sm-space-xs));
	height: 2px;
	border-radius: 2px;
	background-color: var(--sm-color-accent);
	transform: scaleX(0);
	transform-origin: left center;
	transition: transform var(--sm-dur-nav) var(--sm-ease-out);
}

.sm-site .sm-nav__link:hover,
.sm-site .sm-nav__link:focus,
.sm-site .sm-nav__link[aria-expanded="true"] {
	background-color: transparent;
	color: var(--sm-color-text-heading);
}

.sm-nav__link:hover::after,
.sm-nav__link[aria-current="page"]::after,
.sm-nav__link[data-current]::after,
.sm-nav__link[aria-expanded="true"]::after {
	transform: scaleX(1);
}

.sm-site .sm-nav__link:is([aria-current="page"], [data-current]) {
	color: var(--sm-color-text-heading);
	font-weight: var(--sm-fw-semibold);
}

.sm-nav__trigger .sm-icon {
	width: 1rem;
	height: 1rem;
	transition: transform var(--sm-dur-nav) var(--sm-ease-out);
}

.sm-nav__trigger[aria-expanded="true"] .sm-icon {
	transform: rotate(180deg);
}

/* ---- Forced colours, print, Elementor editor -------------------------- */

@media (forced-colors: active) {
	.sm-nav__link::after {
		forced-color-adjust: none;
		background-color: Highlight;
	}
}

@media print {
	.sm-header {
		height: auto;
	}

	.sm-header__bar {
		position: static;
		box-shadow: none;
	}

	.sm-site :is(.sm-header__nav, .sm-header__toggle, .sm-header__cta, .sm-mnav, .sm-header__sentinel) {
		display: none;
	}
}

/* In the Elementor editor the bar stays in place so it can be edited
   (needs WordPress verification). */
.elementor-editor-active .sm-header__bar {
	position: absolute;
	top: 0;
}

/* ---- components/mega-menu.css ---- */
/* ==========================================================================
   Sohnas Media — Services mega menu (desktop) and mobile navigation
   Copy and URLs: inc/header.php (Rev 3.1 §6). Behaviour: src/js/sm-site.js.
   ========================================================================== */

/* ==========================================================================
   Desktop: two-column Services mega menu
   Left: the four core services. Right: framework line, statement,
   "View all services" and the consultation CTA. No pillar tags: the four
   services do not map one-to-one to the four framework stages.
   Opens on click / Enter / Space (and on hover for mouse users); Escape,
   an outside click or tabbing away closes it.
   ========================================================================== */

/* Full-width panel hanging from the bar; content aligned to the container.
   The bar (position: fixed) is its containing block, so it follows the
   compact height automatically. */
.sm-mega__panel {
	position: absolute;
	top: 100%;
	right: 0;
	left: 0;
	max-height: calc(100vh - var(--sm-admin-offset) - var(--sm-header-height));
	overflow-y: auto;
	overscroll-behavior: contain;
	border-block-start: var(--sm-border-width) solid var(--sm-color-divider);
	background-color: var(--sm-color-background);
	box-shadow: var(--sm-shadow-lg);
	opacity: 0;
	visibility: hidden;             /* also removes it from the tab order and screen readers */
	transform: translateY(calc(var(--sm-space-sm) * -1));
	transition:
		opacity var(--sm-dur-nav) var(--sm-ease-out),
		transform var(--sm-dur-nav) var(--sm-ease-out),
		visibility 0s linear var(--sm-dur-nav);
}

.sm-mega__panel[data-open] {
	opacity: 1;
	visibility: visible;
	transform: none;
	transition-delay: 0s;
}

.sm-mega__inner {
	display: grid;
	grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
	gap: var(--sm-space-2xl);
	padding-block: var(--sm-space-2xl);
}

/* Left column: services */
.sm-mega__list {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	align-content: start;
	gap: var(--sm-space-sm) var(--sm-space-lg);
	margin: 0;
	padding: 0;
	list-style: none;
}

.sm-mega__list > li {
	margin: 0;
}

.sm-site .sm-mega__link {
	display: block;
	height: 100%;
	padding: var(--sm-space-md);
	border-radius: var(--sm-radius-md);
	color: var(--sm-color-text-primary);
	text-decoration: none;
	transition: background-color var(--sm-dur-fast) var(--sm-ease-out);
}

.sm-mega__title {
	display: flex;
	align-items: center;
	gap: var(--sm-space-sm);
	color: var(--sm-color-text-heading);
	font-family: var(--sm-font-ui);
	font-size: var(--sm-fs-body);
	font-weight: var(--sm-fw-semibold);
	line-height: var(--sm-lh-ui);
	transition: color var(--sm-dur-fast) var(--sm-ease-out);
}

.sm-mega__desc {
	display: block;
	margin-block-start: var(--sm-space-xs);
	color: var(--sm-color-text-secondary);
	font-size: var(--sm-fs-small);
	line-height: var(--sm-lh-small);
}

/* Hover and current page: Cloud background (not colour alone) + blue title.
   Blue on Cloud is 4.70:1. */
.sm-site .sm-mega__link:is(:hover, [aria-current="page"]) {
	background-color: var(--sm-color-background-alt);
	color: var(--sm-color-text-primary);
}

.sm-mega__link:is(:hover, [aria-current="page"]) .sm-mega__title {
	color: var(--sm-color-link);
}

/* Current page marker: a short accent line before the title */
.sm-mega__link[aria-current="page"] .sm-mega__title::before {
	content: "";
	flex: none;
	width: 3px;
	height: 1em;
	border-radius: 2px;
	background-color: var(--sm-color-accent);
}

/* Right column: framework statement and actions */
.sm-mega__aside {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	padding: var(--sm-space-xl);
	border-radius: var(--sm-radius-lg);
	background-color: var(--sm-color-background-alt);
}

/* .sm-site prefix: Elementor's Theme Style "Paragraph spacing" outputs
   .elementor-kit-N p (0,1,1), which would otherwise replace these margins. */
.sm-site .sm-mega__framework {
	margin-block: 0 var(--sm-space-md);
}

.sm-site .sm-mega__statement {
	max-width: 40ch;
	margin: 0;
	color: var(--sm-color-text-primary);
	font-size: var(--sm-fs-body);
	line-height: var(--sm-lh-body);
}

.sm-mega__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--sm-space-sm) var(--sm-space-lg);
	margin-block-start: var(--sm-space-lg);
}

/* Mega menu only exists on desktop */
@media not all and (min-width: 64.0625em) {
	.sm-mega__panel {
		display: none;
	}
}

/* ==========================================================================
   Mobile and tablet navigation (below 1025px)
   A dedicated panel under the 80px bar — not the desktop menu shrunk.
   Opened by the Menu button. While open: the page behind is inert and
   does not scroll; Escape closes and returns focus to the button.
   ========================================================================== */

.sm-mnav {
	position: fixed;
	top: calc(var(--sm-admin-offset) + var(--sm-header-height));
	right: 0;
	bottom: 0;
	left: 0;
	overflow-y: auto;
	overscroll-behavior: contain;
	border-block-start: var(--sm-border-width) solid var(--sm-color-divider);
	background-color: var(--sm-color-background);
	opacity: 0;
	transform: translateY(calc(var(--sm-space-sm) * -1));
	transition:
		opacity var(--sm-dur-nav) var(--sm-ease-out),
		transform var(--sm-dur-nav) var(--sm-ease-out);
}

.sm-mnav[data-open] {
	opacity: 1;
	transform: none;
}

.sm-mnav__inner {
	padding-block: var(--sm-space-md) var(--sm-space-2xl);
}

.sm-mnav__list,
.sm-mnav__sublist {
	margin: 0;
	padding: 0;
	list-style: none;
}

.sm-mnav__item {
	margin: 0;
	border-block-end: var(--sm-border-width) solid var(--sm-color-divider);
}

.sm-mnav__sublist > li {
	margin: 0;
}

/* Top-level rows: full-width, 56px tall */
.sm-site .sm-mnav__link {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--sm-space-md);
	width: 100%;
	min-height: 56px;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
	background-color: transparent;
	color: var(--sm-color-text-heading);
	font-family: var(--sm-font-ui);
	font-size: var(--sm-fs-body);
	font-weight: var(--sm-fw-medium);
	line-height: var(--sm-lh-ui);
	text-align: start;
	text-decoration: none;
	white-space: normal;
	cursor: pointer;
	transition: color var(--sm-dur-fast) var(--sm-ease-out);  /* replaces Hello's "all .3s" (ring must appear at once) */
}

.sm-site .sm-mnav__link:is(:hover, :focus, [aria-expanded="true"]) {
	background-color: transparent;
	color: var(--sm-color-text-heading);
}

.sm-site .sm-mnav__link:hover {
	color: var(--sm-color-link);
}

/* Current page: weight + underline, not colour alone */
.sm-site .sm-mnav__link:is([aria-current="page"], [data-current]) {
	font-weight: var(--sm-fw-semibold);
	text-decoration-line: underline;
	text-decoration-color: var(--sm-color-accent);
	text-decoration-thickness: 2px;
	text-underline-offset: 0.45em;
}

.sm-mnav__trigger .sm-icon {
	transition: transform var(--sm-dur-nav) var(--sm-ease-out);
}

.sm-mnav__trigger[aria-expanded="true"] .sm-icon {
	transform: rotate(180deg);
}

/* Services sub-list */
.sm-mnav__sub {
	padding-block-end: var(--sm-space-md);
}

.sm-site .sm-mnav__sublink {
	display: block;
	min-height: var(--sm-touch-min);
	padding: calc(var(--sm-space-sm) + var(--sm-space-xs)) var(--sm-space-md);
	border-radius: var(--sm-radius-md);
	color: var(--sm-color-text-primary);
	text-decoration: none;
	transition: background-color var(--sm-dur-fast) var(--sm-ease-out);
}

.sm-site .sm-mnav__sublink:is(:hover, [aria-current="page"]) {
	background-color: var(--sm-color-background-alt);
	color: var(--sm-color-text-primary);
}

.sm-mnav__title {
	display: block;
	color: var(--sm-color-text-heading);
	font-family: var(--sm-font-ui);
	font-size: var(--sm-fs-body);
	font-weight: var(--sm-fw-semibold);
	line-height: var(--sm-lh-ui);
}

.sm-mnav__sublink[aria-current="page"] .sm-mnav__title {
	color: var(--sm-color-link);
	text-decoration: underline 2px;
	text-underline-offset: 0.3em;
}

.sm-mnav__desc {
	display: block;
	margin-block-start: var(--sm-space-xs);
	color: var(--sm-color-text-secondary);
	font-size: var(--sm-fs-small);
	line-height: var(--sm-lh-small);
}

.sm-site .sm-mnav__sublink--overview {
	display: flex;
	align-items: center;
	gap: var(--sm-space-sm);
}

.sm-mnav__sublink--overview .sm-mnav__title {
	color: var(--sm-color-link);
}

.sm-mnav__cta {
	margin-block-start: var(--sm-space-xl);
}

.sm-mnav__cta .sm-button {
	width: 100%;
}

.sm-mnav__nojs-close {
	display: none;
}

/* The panel never shows on desktop, even if left open while resizing. */
@media (min-width: 64.0625em) {
	.sm-mnav {
		display: none;
	}
}

/* Page scroll is locked while the panel is open (class set by the script).
   Where scrollbars take space (desktop browsers in a narrow window), the
   script measures the scrollbar and sets --sm-scrollbar-comp, so neither
   the page nor the header shifts when the scrollbar disappears. On phones
   and other overlay-scrollbar devices the value is 0. */
html.sm-scroll-lock {
	overflow: hidden;
	padding-inline-end: var(--sm-scrollbar-comp, 0px);
}

html.sm-scroll-lock body {
	overflow: hidden;
}

html.sm-scroll-lock :is(.sm-header__bar, .sm-mnav) {
	right: var(--sm-scrollbar-comp, 0px);
}

/* ==========================================================================
   Without JavaScript (rare): the mega menu opens on hover / keyboard focus,
   and the mobile Menu link opens the panel as an in-page target with a
   "Close menu" link. Services are listed open.
   ========================================================================== */

html:not(.sm-js) .sm-mega:is(:hover, :focus-within) .sm-mega__panel {
	opacity: 1;
	visibility: visible;
	transform: none;
	transition-delay: 0s;
}

@media not all and (min-width: 64.0625em) {
	html:not(.sm-js) .sm-site .sm-header__toggle:not(.sm-header__toggle--nojs) {
		display: none;
	}

	html:not(.sm-js) .sm-site .sm-header__toggle--nojs {
		display: inline-flex;
	}

	html:not(.sm-js) .sm-mnav:target {
		display: block;
		opacity: 1;
		transform: none;
	}

	html:not(.sm-js) .sm-mnav__sub[hidden] {
		display: block;
	}

	html:not(.sm-js) .sm-mnav__trigger .sm-icon {
		display: none;
	}

	html:not(.sm-js) .sm-mnav__nojs-close {
		display: inline-flex;
		align-items: center;
		min-height: var(--sm-touch-min);
		margin-block-start: var(--sm-space-lg);
		color: var(--sm-color-link);
		text-decoration: underline;
	}
}

/* ---- components/footer.css ---- */
/* ==========================================================================
   Sohnas Media — Global footer
   Markup: template-parts/site-footer.php ([sm_site_footer] shortcode in the
   Elementor Theme Builder footer). Navy surface (.sm-surface-dark), white
   logo, so every colour comes from the dark-surface roles.

   Cascade: Elementor's Theme Style outputs element rules on the kit class
   (.elementor-kit-N h2 / p / a, specificity 0,1,1). Every footer rule that
   styles a heading or paragraph is therefore prefixed .sm-site (0,2,0), as
   the buttons, links and header already are. Without it, the column headings
   took Elementor's H2 Section style (46px, white) — found in the WordPress
   validation of 2 October 2026.

   Layout
     Mobile        one column; Services + Company side by side from 560px
     Tablet        brand row on top, link groups (and contact) below
     Desktop       brand | Services · Company; with a contact column the
                   three-column layout starts at 1200px
   ========================================================================== */

.sm-footer {
	padding-block-start: var(--sm-section-pad);
}

.sm-footer__main {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--sm-space-2xl);
	padding-block-end: var(--sm-space-2xl);
}

/* ---- Brand column ------------------------------------------------------ */

.sm-footer__brand {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
}

.sm-footer__logo {
	display: inline-flex;
	border-radius: var(--sm-radius-sm);
}

.sm-footer__logo-img {
	display: block;
	width: var(--sm-logo-width-footer);
	height: auto;
}

.sm-site .sm-footer__statement {
	max-width: 46ch;
	margin: var(--sm-space-lg) 0 0;
	color: var(--sm-color-text-primary);
	font-size: var(--sm-fs-body);
	line-height: var(--sm-lh-body);
}

.sm-site .sm-footer__framework {
	margin: var(--sm-space-md) 0 0;
}

.sm-site .sm-footer__cta {
	margin-block-start: var(--sm-space-xl);
}

/* ---- Link groups ------------------------------------------------------- */

.sm-footer__nav {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--sm-space-xl);
}

/* Column headings: H6 treatment (founder decision, 2 October 2026).
   Element stays h2 for the outline; appearance from the H6 tokens. */
.sm-site .sm-footer__heading {
	margin: 0 0 var(--sm-space-sm);
	color: var(--sm-color-text-heading);     /* white on Deep Navy · 15.8:1 */
	font-family: var(--sm-font-heading);     /* Manrope */
	font-size: var(--sm-fs-h6);              /* 16px */
	font-weight: var(--sm-fw-semibold);      /* 600 */
	line-height: var(--sm-lh-subheading);    /* 1.25 */
	letter-spacing: 0;
	text-transform: none;
}

.sm-footer__list,
.sm-footer__legal-list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.sm-footer__list > li,
.sm-footer__legal-list > li {
	margin: 0;
}

/* 44px rows: comfortable touch targets without extra visual weight. */
.sm-site .sm-footer__link,
.sm-footer__text {
	display: inline-flex;
	align-items: center;
	min-height: var(--sm-touch-min);
	padding-block: calc(var(--sm-space-xs) + 2px);  /* keeps wrapped labels apart */
	color: var(--sm-color-text-primary);     /* 10.3:1 on navy */
	font-family: var(--sm-font-body);
	font-size: var(--sm-fs-body);
	line-height: var(--sm-lh-ui);
	text-decoration: none;
	overflow-wrap: anywhere;                 /* long email addresses wrap */
}

.sm-site .sm-footer__link {
	text-decoration-line: underline;
	text-decoration-color: transparent;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.25em;
	transition:
		color var(--sm-dur-fast) var(--sm-ease-out),
		text-decoration-color var(--sm-dur-fast) var(--sm-ease-out);
}

/* Hover / current: white + underline (not colour alone) */
.sm-site .sm-footer__link:is(:hover, [aria-current="page"]) {
	color: var(--sm-color-text-heading);
	text-decoration-color: currentColor;
}

/* ---- Bottom bar -------------------------------------------------------- */

.sm-footer__bottom {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0 var(--sm-space-lg);
	padding-block: var(--sm-space-md);
	border-block-start: var(--sm-border-width) solid var(--sm-color-divider);
}

.sm-site .sm-footer__copyright {
	margin: 0;
	padding-block: var(--sm-space-sm);
	color: var(--sm-color-text-secondary);
	font-size: var(--sm-fs-small);
	line-height: var(--sm-lh-small);
}

.sm-footer__legal-list {
	display: flex;
	flex-wrap: wrap;
	gap: 0 var(--sm-space-sm);
}

.sm-footer__legal-list > li {
	display: inline-flex;
	align-items: center;
	gap: var(--sm-space-sm);
}

/* "Privacy Policy | Terms of Services": decorative divider, not announced */
.sm-footer__legal-list > li + li::before {
	content: "|";
	content: "|" / "";
	color: var(--sm-color-text-secondary);
	font-size: var(--sm-fs-small);
}

.sm-site .sm-footer__legal .sm-footer__link {
	color: var(--sm-color-text-secondary);
	font-size: var(--sm-fs-small);
}

.sm-site .sm-footer__legal .sm-footer__link:is(:hover, [aria-current="page"]) {
	color: var(--sm-color-text-heading);
}

/* ---- Responsive -------------------------------------------------------- */

/* Services labels are longer than Company labels: give them more room. */
@media (min-width: 35em) {
	.sm-footer__nav {
		grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
	}
}

@media (min-width: 768px) {
	.sm-footer__main--contact {
		grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
	}

	.sm-footer__main--contact > .sm-footer__brand {
		grid-column: 1 / -1;
	}
}

@media (min-width: 1025px) {
	.sm-footer__main {
		grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
		column-gap: var(--sm-space-3xl);
		padding-block-end: var(--sm-space-3xl);
	}

	/* With a contact column, keep the brand on its own row until 1200px */
	.sm-footer__main--contact {
		grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
	}
}

@media (min-width: 75em) {
	.sm-footer__main--contact {
		grid-template-columns: minmax(0, 4fr) minmax(0, 5fr) minmax(0, 3fr);
		column-gap: var(--sm-space-2xl);
	}

	.sm-footer__main--contact > .sm-footer__brand {
		grid-column: auto;
	}
}

/* ---- utilities.css ---- */
/* ==========================================================================
   Sohnas Media — Utilities
   Small, single-purpose classes. Loaded last so they win over components
   at equal specificity. Add one only when a real layout needs it.
   ========================================================================== */

/* ---- Accessibility ----------------------------------------------------- */

/* Hidden visually, still announced by screen readers */
.sm-visually-hidden,
.sm-visually-hidden-focusable:not(:focus, :focus-within) {
	position: absolute !important;  /* documented exception (standard pattern): a component
	                                   must never make hidden text visible by accident */
	width: 1px !important;
	height: 1px !important;
	margin: -1px !important;
	padding: 0 !important;
	overflow: hidden !important;
	clip-path: inset(50%) !important;
	white-space: nowrap !important;
	border: 0 !important;
}

/* Enlarges the hit area of a small control (icon link, close button)
   to 44 × 44px without changing its visual size. */
.sm-touch-target {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: var(--sm-touch-min);
	min-height: var(--sm-touch-min);
}

/* ---- Layout ------------------------------------------------------------ */

/* Vertical rhythm between direct children.
   Set --sm-stack-space on the element to change the gap. */
.sm-stack {
	display: flex;
	flex-direction: column;
	gap: var(--sm-stack-space, var(--sm-space-md));
}

.sm-stack > * {
	margin-block: 0;
}

/* Inline group that wraps (buttons, tags, meta). --sm-cluster-space. */
.sm-cluster {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--sm-cluster-space, var(--sm-space-md));
}

/* Responsive columns without breakpoints: as many columns of at least
   --sm-grid-min as fit, never wider than the container. */
.sm-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(var(--sm-grid-min, 16rem), 100%), 1fr));
	gap: var(--sm-grid-gap, var(--sm-space-xl));
}

/* Stops decorative layers (offsets, overlaps, oversized shapes) from
   causing horizontal scroll, without breaking sticky positioning the way
   overflow: hidden would. Use on the section that holds the layers. */
.sm-clip-x {
	overflow-x: hidden;             /* fallback: Safari < 16 */
	overflow-x: clip;
}

/* ---- Text ---------------------------------------------------------------- */

.sm-measure {
	max-width: var(--sm-measure);
}

.sm-measure-narrow {
	max-width: var(--sm-measure-narrow);
}

.sm-text-center {
	text-align: center;
}

.sm-text-secondary {
	color: var(--sm-color-text-secondary);
}

.sm-text-balance {
	text-wrap: balance;
}

.sm-nowrap {
	white-space: nowrap;
}

/* Centre a measured block (with .sm-measure / .sm-text-center) */
.sm-mx-auto {
	margin-inline: auto;
}
