@charset "UTF-8";
/* ==========================================================================
   FBH — Design System 2.0
   fouadabuhattab.com
   --------------------------------------------------------------------------
   Version : 2.0.0
   Author  : Fouad Abuhattab
   Mode    : LIGHT is the default. Dark is applied via [data-theme="dark"].
   Fonts   : IBM Plex Sans (Latin) + IBM Plex Sans Arabic (Arabic) — only.
   --------------------------------------------------------------------------
   HOW THIS FILE WORKS
   -------------------
   1. This file is the SINGLE SOURCE OF TRUTH for all design values.
   2. Elementor Global Colors must point at these variables, never at hex.
        Elementor Global "Primary"  ->  var(--color-primary)
        Elementor Global "Text"     ->  var(--color-text-primary)
        Elementor Global "Accent"   ->  var(--color-success)
   3. Never hardcode a hex value in a widget, a page, or the Customizer.
      If a value is missing here, ADD IT HERE first.

   CONTRAST
   --------
   Every colour pair used for text is annotated with its measured WCAG 2.2
   contrast ratio. Values marked (AA) pass 4.5:1 for normal text.
   Values marked (LARGE ONLY) pass 3:1 and must not be used for body copy.
   ========================================================================== */


/* ==========================================================================
   00 — FONT LOADING
   --------------------------------------------------------------------------
   Load ONE stylesheet containing both families. Self-hosting is preferred
   for performance and privacy; the Google Fonts URL below is the fallback.

   <link rel="preconnect" href="https://fonts.googleapis.com">
   <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
   <link rel="stylesheet" href="https://fonts.googleapis.com/css2?
     family=IBM+Plex+Sans:wght@400;500;600;700&
     family=IBM+Plex+Sans+Arabic:wght@400;500;600;700&display=swap">

   Only four weights: 400 / 500 / 600 / 700. Do not load 300, 800 or 900.
   ========================================================================== */


/* ==========================================================================
   01 — PRIMITIVE TOKENS (raw values — mode independent)
   ========================================================================== */

:root {

  /* --- Brand: Purple ---------------------------------------------------- */
  --purple-50 : #F3F1FF;
  --purple-100: #E9E6FF;
  --purple-200: #D8D3FF;
  --purple-300: #BEB8FF;
  --purple-400: #8D85FF;   /* dark-mode text/links — 6.24:1 on #0D0D10 (AA) */
  --purple-500: #635BFF;   /* brand core       — 4.70:1 on #FFFFFF   (AA)   */
  --purple-600: #5148E8;
  --purple-700: #443CC7;

  /* --- Accent: Results Green -------------------------------------------- */
  /* NOTE: Green 500/600 FAIL AA as text on white (3.04:1 / 4.09:1).
     Green 700 was added to Design System 2.0 for that reason.               */
  --green-500: #14A878;    /* fills, icons, borders. Dark-mode text: 6.38:1  */
  --green-600: #0E8F65;
  --green-700: #0A7A55;    /* light-mode text  — 4.86:1 on #FFFFFF   (AA)   */
  --green-800: #09724F;    /* solid fill hover — white text 5.95:1  (AA)  */
  --green-soft: #E9F8F2;

  /* --- Neutrals: Light -------------------------------------------------- */
  --neutral-0  : #FFFFFF;
  --neutral-25 : #FAFAFB;
  --neutral-50 : #F8F8FA;
  --neutral-75 : #F4F3FF;
  --neutral-100: #EEEEF1;
  --neutral-200: #E5E5EA;
  --neutral-300: #D8D8DF;
  --neutral-400: #A8A8B0;
  --neutral-500: #85858E;
  --neutral-550: #6E6E77;
  --neutral-600: #62626B;
  --neutral-900: #111114;

  /* --- Neutrals: Dark --------------------------------------------------- */
  --ink-950: #0D0D10;
  --ink-900: #121216;
  --ink-850: #15151A;
  --ink-800: #17161F;
  --ink-750: #1B1B21;
  --ink-700: #211F2D;
  --ink-600: #222228;
  --ink-500: #2A2A31;
  --ink-400: #37373F;
  --ink-300: #66666E;
  --ink-200: #888891;
  --ink-100: #B1B1BA;
  --ink-50 : #F5F5F7;

  /* --- Semantic status -------------------------------------------------- */
  --status-warning: #D99000;
  --status-error  : #D94A4A;
  --status-info   : #4F78D9;
}


/* ==========================================================================
   02 — SEMANTIC TOKENS — LIGHT MODE (DEFAULT)
   ========================================================================== */

:root {
  color-scheme: light;

  /* --- Backgrounds ------------------------------------------------------ */
  --color-bg-primary  : var(--neutral-0);
  --color-bg-secondary: var(--neutral-50);
  --color-bg-soft     : var(--neutral-75);

  /* --- Surfaces --------------------------------------------------------- */
  --color-surface          : var(--neutral-0);
  --color-surface-subtle   : var(--neutral-25);
  --color-surface-elevated : var(--neutral-0);
  --color-surface-highlight: var(--purple-50);

  /* --- Text ------------------------------------------------------------- */
  --color-text-primary  : var(--neutral-900);  /* 18.9:1 (AA)              */
  --color-text-secondary: var(--neutral-600);  /*  6.05:1 (AA)             */
  --color-text-muted    : var(--neutral-550);  /*  5.05:1 (AA) — body-safe */
  --color-text-faint    : var(--neutral-500);  /*  3.65:1 (LARGE ONLY)     */
  --color-text-disabled : var(--neutral-400);
  --color-text-on-brand : var(--neutral-0);

  /* --- Borders ---------------------------------------------------------- */
  --color-border        : var(--neutral-200);
  --color-border-strong : var(--neutral-300);
  --color-border-subtle : var(--neutral-100);

  /* --- Brand ------------------------------------------------------------ */
  --color-primary        : var(--purple-500);
  --color-primary-hover  : var(--purple-600);
  --color-primary-active : var(--purple-700);
  --color-primary-text   : var(--purple-600);  /* purple used AS text      */
  --color-primary-soft   : var(--purple-50);
  --color-primary-border : var(--purple-200);

  /* --- Success / Results ------------------------------------------------ */
  --color-success       : var(--green-500);    /* fills / icons only       */
  --color-success-strong: var(--green-700);    /* fill that carries text   */
  --color-success-strong-hover: var(--green-800);
  --color-text-on-success: var(--neutral-0);   /* white — 5.35:1 on green-700 */
  --color-success-text  : var(--green-700);    /* 4.86:1 (AA)              */
  --color-success-soft  : var(--green-soft);

  /* --- Status ----------------------------------------------------------- */
  --color-warning: var(--status-warning);
  --color-error  : var(--status-error);
  --color-info   : var(--status-info);

  /* --- Shadows (light) --------------------------------------------------- */
  --shadow-sm: 0 2px 8px rgba(17, 17, 20, 0.06);
  --shadow-md: 0 8px 24px rgba(17, 17, 20, 0.08);
  --shadow-lg: 0 16px 48px rgba(17, 17, 20, 0.10);

  /* --- Focus ring -------------------------------------------------------- */
  /* Brand surface: a faint purple glow over a technical dot grid. */
  --brand-glow: rgba(99, 91, 255, 0.07);
  --brand-dot : rgba(17, 17, 20, 0.055);

  --focus-ring-color : var(--purple-500);
  --focus-ring-width : 2px;
  --focus-ring-offset: 2px;
}


/* ==========================================================================
   03 — SEMANTIC TOKENS — DARK MODE (OVERRIDE)
   --------------------------------------------------------------------------
   Applied by adding data-theme="dark" to <html>.
   Dark is NOT an inversion — surfaces, borders and accents are re-chosen.
   ========================================================================== */

[data-theme="dark"] {
  color-scheme: dark;

  --color-bg-primary  : var(--ink-950);
  --color-bg-secondary: var(--ink-900);
  --color-bg-soft     : var(--ink-800);

  --color-surface          : var(--ink-850);
  --color-surface-subtle   : var(--ink-900);
  --color-surface-elevated : var(--ink-750);
  --color-surface-highlight: var(--ink-700);

  --color-text-primary  : var(--ink-50);   /* 17.8:1 (AA) */
  --color-text-secondary: var(--ink-100);  /*  9.12:1 (AA) */
  --color-text-muted    : var(--ink-200);  /*  5.53:1 (AA) */
  --color-text-faint    : var(--ink-200);
  --color-text-disabled : var(--ink-300);
  --color-text-on-brand : var(--neutral-0);

  --color-border        : var(--ink-500);
  --color-border-strong : var(--ink-400);
  --color-border-subtle : var(--ink-600);

  /* Purple 500 is only 4.11:1 on #0D0D10 — fails AA as text.
     Buttons keep 500 (white text sits on it); text/links move to 400.      */
  --color-primary        : var(--purple-500);
  --color-primary-hover  : var(--purple-400);
  --color-primary-active : var(--purple-300);
  --color-primary-text   : var(--purple-400);  /* 6.24:1 (AA) */
  --color-primary-soft   : rgba(99, 91, 255, 0.14);
  --color-primary-border : rgba(99, 91, 255, 0.32);

  --color-success       : var(--green-500);
  --color-success-text  : var(--green-500);    /* 6.38:1 on #0D0D10 (AA) */
  --color-success-strong: var(--green-700);
  --color-success-strong-hover: var(--green-800);
  --color-text-on-success: var(--neutral-0);
  --color-success-soft  : rgba(20, 168, 120, 0.14);

  /* Dark mode leans on surface contrast + borders, not shadows. */
  --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.40);
  --shadow-md: 0 8px 24px rgba(0, 0, 0, 0.48);
  --shadow-lg: 0 16px 48px rgba(0, 0, 0, 0.56);

  --brand-glow: rgba(99, 91, 255, 0.16);
  --brand-dot : rgba(245, 245, 247, 0.05);

  --focus-ring-color: var(--purple-400);
}

/* --- Optional: honour the OS preference for first-time visitors ----------
   Light stays the default. Uncomment ONLY if you want the OS to decide
   before the user has made an explicit choice. The theme-toggle script
   must then write data-theme="light" explicitly on opt-out.

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { ... copy the dark block here ... }
}
------------------------------------------------------------------------- */


/* ==========================================================================
   04 — TYPOGRAPHY TOKENS
   ========================================================================== */

:root {

  /* --- Families ---------------------------------------------------------
     Latin glyphs resolve from IBM Plex Sans; Arabic glyphs fall through to
     IBM Plex Sans Arabic automatically. One declaration serves both.       */
  --font-sans  : "IBM Plex Sans", "IBM Plex Sans Arabic",
                 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-arabic: "IBM Plex Sans Arabic", "IBM Plex Sans",
                 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  /* --- Weights (only four) ---------------------------------------------- */
  --fw-regular : 400;
  --fw-medium  : 500;
  --fw-semibold: 600;
  --fw-bold    : 700;

  /* --- Fluid scale ------------------------------------------------------- */
  --fs-display: clamp(2.625rem, 5vw,   4rem);      /* 42 -> 64 */
  --fs-h1     : clamp(2.25rem,  4vw,   3.25rem);   /* 36 -> 52 */
  --fs-h2     : clamp(1.875rem, 3.2vw, 2.5rem);    /* 30 -> 40 */
  --fs-h3     : clamp(1.5rem,   2.4vw, 1.75rem);   /* 24 -> 28 */
  --fs-h4     : clamp(1.25rem,  2vw,   1.375rem);  /* 20 -> 22 */
  --fs-body-lg: clamp(1rem,     1.3vw, 1.125rem);  /* 16 -> 18 */
  --fs-body   : 1rem;      /* 16 */
  --fs-small  : 0.875rem;  /* 14 */
  --fs-caption : 0.75rem;  /* 12 */
  --fs-label   : 0.75rem;  /* 12 */

  /* --- Line heights (Latin) --------------------------------------------- */
  --lh-display: 1.05;
  --lh-h1     : 1.10;
  --lh-h2     : 1.15;
  --lh-h3     : 1.20;
  --lh-h4     : 1.30;
  --lh-body   : 1.60;
  --lh-small  : 1.50;
  --lh-caption: 1.40;
  --lh-label  : 1.30;

  /* --- Tracking ---------------------------------------------------------- */
  --ls-tight  : -0.02em;
  --ls-normal : 0;
  --ls-eyebrow: 0.08em;

  /* --- Reading widths ---------------------------------------------------- */
  --measure-heading: 900px;
  --measure-body   : 68ch;   /* ≈ 640–720px at 16px */
  --measure-article: 74ch;   /* ≈ 680–760px         */
}


/* ==========================================================================
   05 — SPACING · LAYOUT · RADIUS · MOTION · LAYERS
   ========================================================================== */

:root {

  /* --- 8-point spacing scale -------------------------------------------- */
  --space-1 : 4px;
  --space-2 : 8px;
  --space-3 : 12px;
  --space-4 : 16px;
  --space-5 : 24px;
  --space-6 : 32px;
  --space-7 : 40px;
  --space-8 : 48px;
  --space-9 : 64px;
  --space-10: 80px;
  --space-11: 96px;
  --space-12: 120px;
  --space-13: 144px;

  /* --- Section rhythm (fluid, collapses properly on mobile) -------------- */
  --section-y        : clamp(3.5rem, 8vw, 7.5rem);  /* 56 -> 120 */
  --section-y-feature: clamp(4.5rem, 10vw, 9rem);   /* 72 -> 144 */

  /* --- Container --------------------------------------------------------- */
  --container-width : 1200px;
  --container-pad   : 20px;   /* mobile  */
  --container-gutter: 24px;   /* grid gutter */

  /* --- Radius ------------------------------------------------------------ */
  --radius-xs  : 6px;
  --radius-sm  : 8px;
  --radius-md  : 12px;
  --radius-lg  : 16px;
  --radius-xl  : 20px;
  --radius-full: 999px;

  /* --- Motion ------------------------------------------------------------ */
  --duration-fast  : 150ms;
  --duration-normal: 250ms;
  --duration-slow  : 400ms;
  --ease-out       : cubic-bezier(0.16, 1, 0.3, 1);

  /* --- Z-index scale ----------------------------------------------------- */
  --z-base    : 1;
  --z-dropdown: 100;
  --z-sticky  : 200;
  --z-header  : 300;
  --z-overlay : 400;
  --z-modal   : 500;
  --z-toast   : 600;
}

@media (min-width: 768px)  { :root { --container-pad: 24px; } }
@media (min-width: 1025px) { :root { --container-pad: 32px; --container-gutter: 32px; } }


/* ==========================================================================
   06 — LEGACY COMPATIBILITY LAYER  ⚠ DEPRECATED
   --------------------------------------------------------------------------
   The existing Elementor Globals and page widgets reference --fbh-* names.
   These aliases keep the live site working while pages are migrated.
   Do NOT use --fbh-* in new work. Delete this block once every page has
   been migrated to the semantic names above.
   ========================================================================== */

:root {
  --fbh-bg            : var(--color-bg-primary);
  --fbh-surface       : var(--color-surface);
  --fbh-surface-alt   : var(--color-bg-secondary);
  --fbh-surface-deep  : var(--color-surface-highlight);
  --fbh-text          : var(--color-text-primary);
  --fbh-text-secondary: var(--color-text-secondary);
  --fbh-muted         : var(--color-text-muted);
  --fbh-muted-dim     : var(--color-text-faint);
  --fbh-border        : var(--color-border);
  --fbh-border-strong : var(--color-border-strong);
  --fbh-primary       : var(--color-primary);
  --fbh-primary-hover : var(--color-primary-hover);
  --fbh-green         : var(--color-success);
  --fbh-success       : var(--color-success);
  --fbh-red           : var(--color-error);
  --fbh-gold          : var(--color-warning);
}


/* ==========================================================================
   07 — BASE ELEMENTS
   ========================================================================== */

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

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

body {
  margin: 0;
  background-color: var(--color-bg-primary);
  color: var(--color-text-primary);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-weight: var(--fw-regular);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, h5, h6 {
  margin: 0 0 var(--space-4);
  font-family: var(--font-sans);
  color: var(--color-text-primary);
  letter-spacing: var(--ls-tight);
  text-wrap: balance;
  /* Reading width is opt-in via .fbh-measure — applying it to bare elements
     would re-flow every existing Elementor page. */
}

h1 { font-size: var(--fs-h1); line-height: var(--lh-h1); font-weight: var(--fw-bold); }
h2 { font-size: var(--fs-h2); line-height: var(--lh-h2); font-weight: var(--fw-bold); }
h3 { font-size: var(--fs-h3); line-height: var(--lh-h3); font-weight: var(--fw-semibold); }
h4 { font-size: var(--fs-h4); line-height: var(--lh-h4); font-weight: var(--fw-semibold); }
h5 { font-size: var(--fs-body-lg); line-height: var(--lh-h4); font-weight: var(--fw-semibold); }
h6 { font-size: var(--fs-body); line-height: var(--lh-h4); font-weight: var(--fw-semibold); }

p {
  text-wrap: pretty;
}

a {
  color: var(--color-primary-text);
  text-decoration-color: color-mix(in srgb, currentColor 35%, transparent);
  text-underline-offset: 0.18em;
  transition: color var(--duration-fast) var(--ease-out);
}
a:hover { color: var(--color-primary-hover); text-decoration-color: currentColor; }

img, svg, video { max-width: 100%; height: auto; display: block; }

hr {
  border: 0;
  border-top: 1px solid var(--color-border);
  margin: var(--space-8) 0;
}

code, kbd, samp {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.9em;
  background: var(--color-bg-secondary);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-xs);
  padding: 0.1em 0.35em;
}

blockquote {
  margin: var(--space-6) 0;
  padding-inline-start: var(--space-5);
  border-inline-start: 3px solid var(--color-primary);
  color: var(--color-text-primary);
  font-size: var(--fs-body-lg);
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-small);
}
th, td {
  text-align: start;
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--color-border);
}
th { font-weight: var(--fw-semibold); color: var(--color-text-primary); }
td { color: var(--color-text-secondary); }

::selection {
  background: var(--color-primary);
  color: var(--color-text-on-brand);
}


/* ==========================================================================
   08 — ARABIC / RTL
   --------------------------------------------------------------------------
   Arabic is a first-class experience, not a mirrored translation.
   Applies to: <html lang="ar">, dir="rtl", or an explicit .fbh-ar class.
   ========================================================================== */

/* --- 8.1 Family ---------------------------------------------------------- */
:lang(ar),
[dir="rtl"],
.fbh-ar {
  font-family: var(--font-arabic);
  font-feature-settings: "kern" 1, "liga" 1, "calt" 1;
}

/* --- 8.2 Optical size ----------------------------------------------------
   IBM Plex Sans Arabic renders visually smaller than IBM Plex Sans at the
   same px. A ~4% bump restores perceived parity between the two languages. */
:lang(ar) body,
[dir="rtl"] body,
.fbh-ar {
  font-size: calc(var(--fs-body) * 1.04);
}

/* --- 8.3 Line heights ----------------------------------------------------
   Arabic needs more leading for body and less tightening for headings.     */
:lang(ar) p,
[dir="rtl"] p,
.fbh-ar p,
:lang(ar) li,
[dir="rtl"] li {
  line-height: 1.80;         /* spec: 1.75–1.85 */
}

:lang(ar) h1, [dir="rtl"] h1 { line-height: 1.25; }
:lang(ar) h2, [dir="rtl"] h2 { line-height: 1.28; }
:lang(ar) h3, [dir="rtl"] h3 { line-height: 1.32; }
:lang(ar) h4, [dir="rtl"] h4 { line-height: 1.35; }

/* --- 8.4 Letter spacing --------------------------------------------------
   Latin tracking rules break Arabic letterforms. Always reset to normal.   */
:lang(ar) *,
[dir="rtl"] *,
.fbh-ar * {
  letter-spacing: normal !important;
}

/* --- 8.5 Alignment -------------------------------------------------------
   Do not justify Arabic body text — it produces uneven kashida spacing.    */
:lang(ar) p,
[dir="rtl"] p {
  text-align: start;
}
:lang(ar) .fbh-measure,
[dir="rtl"] .fbh-measure {
  max-inline-size: 62ch;     /* Arabic sets denser; a slightly tighter measure */
}

/* --- 8.6 Eyebrows --------------------------------------------------------
   Arabic has no uppercase. Never force it — use weight and colour instead. */
:lang(ar) .fbh-eyebrow,
[dir="rtl"] .fbh-eyebrow {
  text-transform: none;
  letter-spacing: normal;
  font-weight: var(--fw-semibold);
  font-size: var(--fs-small);
}

/* --- 8.7 Numerals --------------------------------------------------------
   Decision: Latin (Western) digits everywhere — clearer for metrics,
   prices, dates and technical values. Remove this rule to use ٠١٢٣.       */
:lang(ar),
[dir="rtl"] {
  font-variant-numeric: lining-nums tabular-nums;
}
:lang(ar) .fbh-num,
[dir="rtl"] .fbh-num {
  direction: ltr;
  unicode-bidi: isolate;
  font-family: var(--font-sans);
}

/* --- 8.8 Latin terms inside Arabic --------------------------------------
   WordPress, WooCommerce, Elementor etc. stay Latin, in the Latin family. */
:lang(ar) .fbh-latin,
[dir="rtl"] .fbh-latin {
  font-family: var(--font-sans);
  direction: ltr;
  unicode-bidi: isolate;
}

/* --- 8.9 Directional icons ----------------------------------------------
   Arrows and chevrons mirror. Brand marks and non-directional icons do not. */
[dir="rtl"] .fbh-icon-directional,
[dir="rtl"] .fbh-btn .fbh-icon-arrow {
  transform: scaleX(-1);
}
[dir="rtl"] .fbh-no-mirror,
[dir="rtl"] .fbh-logo {
  transform: none;
}

/* --- 8.10 Blockquote / list mirroring ------------------------------------ */
[dir="rtl"] blockquote {
  border-inline-start: 3px solid var(--color-primary);
  border-inline-end: 0;
}


/* ==========================================================================
   09 — LAYOUT
   ========================================================================== */

.fbh-container {
  width: 100%;
  max-width: var(--container-width);
  margin-inline: auto;
  padding-inline: var(--container-pad);
}

.fbh-section     { padding-block: var(--section-y); }
.fbh-section--lg { padding-block: var(--section-y-feature); }
.fbh-section--alt{ background: var(--color-bg-secondary); }
.fbh-section--soft{ background: var(--color-bg-soft); }

.fbh-grid {
  display: grid;
  gap: var(--container-gutter);
  grid-template-columns: repeat(12, minmax(0, 1fr));
}
@media (max-width: 1024px) { .fbh-grid { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
@media (max-width: 767px)  { .fbh-grid { grid-template-columns: 1fr; } }

.fbh-stack > * + * { margin-block-start: var(--space-4); }
.fbh-measure       { max-inline-size: var(--measure-body); }
.fbh-measure-article { max-inline-size: var(--measure-article); }


/* ==========================================================================
   10 — SECTION HEADER PATTERN
   Eyebrow -> Heading -> Supporting text
   ========================================================================== */

.fbh-eyebrow {
  display: block;
  margin-block-end: var(--space-3);
  font-size: var(--fs-label);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-label);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--color-primary-text);
}

.fbh-section-title { margin-block-end: var(--space-4); }

.fbh-section-sub {
  font-size: var(--fs-body-lg);
  color: var(--color-text-secondary);
  max-inline-size: var(--measure-body);
}


/* ==========================================================================
   11 — BUTTONS
   ========================================================================== */

.fbh-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 13px 20px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition:
    background-color var(--duration-fast) var(--ease-out),
    border-color     var(--duration-fast) var(--ease-out),
    color            var(--duration-fast) var(--ease-out),
    transform        var(--duration-fast) var(--ease-out);
}

/* --- Primary ------------------------------------------------------------- */
.fbh-btn--primary {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-text-on-brand);
}
.fbh-btn--primary:hover  { background: var(--color-primary-hover);  border-color: var(--color-primary-hover);  transform: translateY(-1px); color: var(--color-text-on-brand); }
.fbh-btn--primary:active { background: var(--color-primary-active); border-color: var(--color-primary-active); transform: translateY(0); }

/* --- Secondary ----------------------------------------------------------- */
.fbh-btn--secondary {
  background: var(--color-surface);
  border-color: var(--color-border-strong);
  color: var(--color-text-primary);
}
.fbh-btn--secondary:hover  { background: var(--color-bg-secondary); border-color: var(--color-primary); color: var(--color-text-primary); transform: translateY(-1px); }
.fbh-btn--secondary:active { transform: translateY(0); }

/* --- Text ---------------------------------------------------------------- */
.fbh-btn--text {
  padding: 0;
  background: none;
  border: 0;
  color: var(--color-primary-text);
}
.fbh-btn--text:hover { color: var(--color-primary-hover); gap: var(--space-3); }

/* --- Sizes --------------------------------------------------------------- */
.fbh-btn--sm { padding: 9px 14px;  font-size: var(--fs-small); }
.fbh-btn--lg { padding: 16px 28px; font-size: var(--fs-body-lg); }

/* --- Disabled ------------------------------------------------------------ */
.fbh-btn:disabled,
.fbh-btn[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
  pointer-events: none;
}


/* ==========================================================================
   12 — CARDS
   ========================================================================== */

.fbh-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  transition:
    border-color var(--duration-normal) var(--ease-out),
    box-shadow   var(--duration-normal) var(--ease-out),
    transform    var(--duration-normal) var(--ease-out);
}
.fbh-card:hover {
  border-color: var(--color-border-strong);
  box-shadow: var(--shadow-sm);
  transform: translateY(-2px);
}

.fbh-card--featured {
  padding: var(--space-6);
  border-radius: var(--radius-lg);
  background: var(--color-surface-highlight);
  border-color: var(--color-primary-border);
}

.fbh-card--flat:hover { transform: none; box-shadow: none; }

.fbh-card__title {
  margin: 0;
  font-size: var(--fs-h4);
  line-height: var(--lh-h4);
  font-weight: var(--fw-semibold);
}
.fbh-card__text {
  margin: 0;
  font-size: var(--fs-body);
  color: var(--color-text-secondary);
}
.fbh-card__media {
  margin: calc(var(--space-5) * -1) calc(var(--space-5) * -1) 0;
  border-start-start-radius: var(--radius-md);
  border-start-end-radius: var(--radius-md);
  overflow: hidden;
}


/* ==========================================================================
   13 — BADGES / TAGS
   ========================================================================== */

.fbh-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 4px 10px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  background: var(--color-bg-secondary);
  color: var(--color-text-secondary);
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
  line-height: var(--lh-caption);
  letter-spacing: normal;
}
.fbh-badge--brand   { background: var(--color-primary-soft); border-color: var(--color-primary-border); color: var(--color-primary-text); }
.fbh-badge--success { background: var(--color-success-soft); border-color: transparent;                 color: var(--color-success-text); }


/* ==========================================================================
   14 — METRICS / RESULTS
   ========================================================================== */

.fbh-metric__value {
  font-size: var(--fs-h2);
  line-height: var(--lh-h2);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-tight);
  color: var(--color-text-primary);
  font-variant-numeric: lining-nums tabular-nums;
}
.fbh-metric__value--success { color: var(--color-success-text); }
.fbh-metric__value--brand   { color: var(--color-primary-text); }

.fbh-metric__label {
  font-size: var(--fs-small);
  color: var(--color-text-muted);
}


/* ==========================================================================
   15 — FORMS
   ========================================================================== */

.fbh-label {
  display: block;
  margin-block-end: var(--space-2);
  font-size: var(--fs-small);
  font-weight: var(--fw-semibold);
  color: var(--color-text-primary);
}

.fbh-input,
.fbh-select,
.fbh-textarea {
  width: 100%;
  padding: 12px 16px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-text-primary);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-weight: var(--fw-regular);
  line-height: 1.5;
  transition:
    border-color var(--duration-fast) var(--ease-out),
    box-shadow   var(--duration-fast) var(--ease-out);
}

.fbh-input::placeholder,
.fbh-textarea::placeholder { color: var(--color-text-faint); opacity: 1; }

.fbh-input:hover,
.fbh-select:hover,
.fbh-textarea:hover { border-color: var(--color-border-strong); }

.fbh-input:focus,
.fbh-select:focus,
.fbh-textarea:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--color-primary-soft);
}

.fbh-input[aria-invalid="true"],
.fbh-textarea[aria-invalid="true"] { border-color: var(--color-error); }

.fbh-input:disabled,
.fbh-textarea:disabled {
  background: var(--color-bg-secondary);
  color: var(--color-text-disabled);
  cursor: not-allowed;
}

.fbh-textarea { min-height: 130px; resize: vertical; line-height: var(--lh-body); }

.fbh-select {
  appearance: none;
  padding-inline-end: 38px;
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 14px 14px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='14' height='14' fill='none' stroke='%23635BFF' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  cursor: pointer;
}
[dir="rtl"] .fbh-select { background-position: left 14px center; }

.fbh-help  { margin-block-start: var(--space-2); font-size: var(--fs-caption); color: var(--color-text-muted); }
.fbh-error { margin-block-start: var(--space-2); font-size: var(--fs-caption); color: var(--color-error); }
.fbh-required { color: var(--color-primary-text); }


/* ==========================================================================
   16 — ACCESSIBILITY
   ========================================================================== */

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
  border-radius: var(--radius-xs);
}

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

.fbh-skip-link {
  position: absolute;
  inset-inline-start: var(--space-4);
  inset-block-start: -100px;
  z-index: var(--z-toast);
  padding: var(--space-3) var(--space-4);
  background: var(--color-primary);
  color: var(--color-text-on-brand);
  border-radius: var(--radius-sm);
  font-weight: var(--fw-semibold);
  transition: inset-block-start var(--duration-fast) var(--ease-out);
}
.fbh-skip-link:focus { inset-block-start: var(--space-4); }


/* ==========================================================================
   17 — MOTION
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .fbh-btn:hover,
  .fbh-card:hover { transform: none !important; }
}


/* ==========================================================================
   17b — BRAND SURFACE
   --------------------------------------------------------------------------
   A restrained brand backdrop for hero / empty / 404 sections: a soft purple
   glow over a fine dot grid. Both layers are token-driven, so the surface
   re-tunes itself between light and dark instead of washing out.
   The 404 template is also matched structurally, because Elementor's
   "CSS Classes" field does not render on this install — body.error404 is a
   WordPress core class, so this survives any widget rebuild.
   ========================================================================== */

.fbh-bg-brand,
body.error404 .xpro-theme-builder-singular-wrapper .e-con.e-parent:first-child {
  position: relative;
  overflow: hidden;
  background-color: var(--color-bg-primary);
}

.fbh-bg-brand::before,
body.error404 .xpro-theme-builder-singular-wrapper .e-con.e-parent:first-child::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    radial-gradient(ellipse 70% 55% at 50% 32%, var(--brand-glow) 0%, transparent 70%),
    radial-gradient(circle at 1px 1px, var(--brand-dot) 1px, transparent 0);
  background-size: 100% 100%, 32px 32px;
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 62%, transparent 100%);
          mask-image: linear-gradient(to bottom, #000 0%, #000 62%, transparent 100%);
}

/* Keep section content above the backdrop. */
.fbh-bg-brand > *,
body.error404 .xpro-theme-builder-singular-wrapper .e-con.e-parent:first-child > * { position: relative; z-index: 1; }

@media (prefers-reduced-motion: reduce) { .fbh-bg-brand::before { animation: none; } }


/* ==========================================================================
   17c — HEADER THEME TOGGLE
   --------------------------------------------------------------------------
   Lives in its own header container so the adjacent CTA button is untouched.
   Elementor renders icons as inline SVG, so moon/sun is a show/hide swap
   rather than a glyph change.
   ========================================================================== */

#fbh-theme-toggle-header,
#fbh-theme-toggle-mobile {
  position: relative;
  cursor: pointer;
  width: auto;
  min-width: 38px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  align-self: center;
  border-radius: var(--radius-full);
  flex: 0 0 auto;
  transition: background-color var(--duration-fast) var(--ease-out);
}

/* breathing room + hairline divider separating nav from the controls */
#fbh-theme-toggle-header {
  margin-inline-start: 20px;
  margin-inline-end: 6px;
}
#fbh-theme-toggle-mobile { margin-inline-end: 4px; }

#fbh-theme-toggle-header::before {
  content: "";
  position: absolute;
  inset-inline-start: -10px;
  top: 50%;
  transform: translateY(-50%);
  width: 1px;
  height: 22px;
  background-color: var(--color-border);
  pointer-events: none;
}

/* Elementor wraps the SVG in an inline box, which pushes the glyph up by ~4px.
   Flatten the wrappers so the icon is optically centred with the menu links. */
#fbh-theme-toggle-header > .elementor-element,
#fbh-theme-toggle-mobile > .elementor-element,
#fbh-theme-toggle-header .elementor-widget-container,
#fbh-theme-toggle-mobile .elementor-widget-container,
#fbh-theme-toggle-header .elementor-icon-wrapper,
#fbh-theme-toggle-mobile .elementor-icon-wrapper,
#fbh-theme-toggle-header .elementor-icon,
#fbh-theme-toggle-mobile .elementor-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 0;
  margin: 0;
  padding: 0;
}
#fbh-theme-toggle-header .elementor-icon svg,
#fbh-theme-toggle-mobile .elementor-icon svg { display: block; }

/* Moon in light, sun in dark. Uses #parent > #child so it outranks the
   display:flex normalisation above (which is id+class, i.e. lower). */
#fbh-theme-toggle-header > #fbh-tg-h-sun,
#fbh-theme-toggle-mobile > #fbh-tg-m-sun { display: none; }

[data-theme="dark"] #fbh-theme-toggle-header > #fbh-tg-h-moon,
[data-theme="dark"] #fbh-theme-toggle-mobile > #fbh-tg-m-moon { display: none; }

[data-theme="dark"] #fbh-theme-toggle-header > #fbh-tg-h-sun,
[data-theme="dark"] #fbh-theme-toggle-mobile > #fbh-tg-m-sun {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Both toggles now render the same inline Lucide-style stroke pair via an
   HTML widget, so the icon is identical in the header and the floating button. */
#fbh-theme-toggle-header .elementor-widget-html,
#fbh-theme-toggle-mobile .elementor-widget-html,
#fbh-theme-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 0;
  margin: 0;
  padding: 0;
}

#fbh-theme-toggle-header svg,
#fbh-theme-toggle-mobile svg {
  display: block;
  width: 20px;
  height: 20px;
  color: var(--color-text-primary);
  transition: color var(--duration-fast) var(--ease-out);
}

/* Floating button keeps its own colour context -- currentColor handles it. */
#fbh-theme-icon svg { display: block; width: 20px; height: 20px; }

#fbh-theme-toggle-header:hover svg,
#fbh-theme-toggle-mobile:hover svg { color: var(--color-primary); }

/* Dark mode: a thin light stroke on a near-black surface optically reads
   fainter than the same stroke on white, so lift to pure white and add
   weight. stroke-width as a CSS property overrides the SVG attribute. */
[data-theme="dark"] #fbh-theme-toggle-header svg,
[data-theme="dark"] #fbh-theme-toggle-mobile svg {
  color: var(--neutral-0);
  stroke-width: 2;
}

[data-theme="dark"] #fbh-theme-icon svg { stroke-width: 2; }

/* --color-border resolves to --ink-500 in dark, which is only 1.36:1 against
   the header surface -- effectively invisible. --ink-300 gives 3.41:1, which
   clears the WCAG 2.2 non-text minimum for a UI hairline. */
[data-theme="dark"] #fbh-theme-toggle-header::before {
  background-color: var(--ink-300);
}

#fbh-theme-toggle-header .elementor-icon,
#fbh-theme-toggle-mobile .elementor-icon {
  color: var(--color-text-primary);
  transition: color var(--duration-fast) var(--ease-out);
}

#fbh-theme-toggle-header:hover,
#fbh-theme-toggle-mobile:hover { background-color: var(--color-bg-secondary); }
#fbh-theme-toggle-header:hover .elementor-icon,
#fbh-theme-toggle-mobile:hover .elementor-icon { color: var(--color-primary); }

#fbh-theme-toggle-header:focus-visible,
#fbh-theme-toggle-mobile:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: 2px;
}

/* moon in light, sun in dark */
#fbh-tg-h-sun, #fbh-tg-m-sun { display: none; }
[data-theme="dark"] #fbh-tg-h-moon,
[data-theme="dark"] #fbh-tg-m-moon { display: none; }
[data-theme="dark"] #fbh-tg-h-sun,
[data-theme="dark"] #fbh-tg-m-sun { display: block; }


/* ==========================================================================
   18 — ELEMENTOR BRIDGE
   --------------------------------------------------------------------------
   Elementor emits --e-global-* variables from the Kit's Global settings.
   Repointing them here means every widget that uses a Global colour follows
   this file automatically — including across light/dark — with no per-widget
   editing. Confirm the generated IDs in the Kit CSS before enabling.
   ========================================================================== */

:root {
  --e-global-color-primary  : var(--color-primary);
  --e-global-color-secondary: var(--color-text-primary);
  --e-global-color-text     : var(--color-text-primary);
  --e-global-color-accent   : var(--color-success);

  --e-global-typography-primary-font-family  : "IBM Plex Sans";
  --e-global-typography-secondary-font-family: "IBM Plex Sans";
  --e-global-typography-text-font-family     : "IBM Plex Sans";
  --e-global-typography-accent-font-family   : "IBM Plex Sans";
}

/* Elementor container width — keeps builder output on the system container. */
.e-con,
.elementor-section.elementor-section-boxed > .elementor-container {
  --container-max-width: var(--container-width);
}

/* Elementor's own button widget inherits the system button. */
.elementor-button {
  font-family: var(--font-sans);
  font-weight: var(--fw-semibold);
  border-radius: var(--radius-sm);
  transition:
    background-color var(--duration-fast) var(--ease-out),
    transform        var(--duration-fast) var(--ease-out);
}

/* ==========================================================================
   END — FBH Design System 2.0
   ========================================================================== */


/* ==========================================================================
   17d - HOMEPAGE HERO
   ========================================================================== */

#fbh-hero {
  position: relative;
  overflow: hidden;
  padding-block-start: clamp(2.5rem, 5vw, 4.5rem);
  padding-block-end: var(--section-y);
  padding-inline: var(--space-5);
  align-items: center;
  --fbh-surface: var(--color-bg-soft);
  background-color: var(--fbh-surface);
}

/* Brand surface: soft lavender wash off the top-left corner plus a fine dot
   grid, both faded out before the section ends so the join to the next
   section stays seamless. Same language as the 404 page. */
#fbh-hero::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    radial-gradient(circle 380px at 2% 16%, var(--brand-glow) 0%, transparent 68%),
    radial-gradient(circle at 1px 1px, var(--brand-dot) 1px, transparent 0);
  background-size: 100% 100%, 30px 30px;
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 66%, transparent 100%);
          mask-image: linear-gradient(to bottom, #000 0%, #000 66%, transparent 100%);
}

/* Elementor puts a boxed container's own padding on .e-con-inner, so the
   rule above would stack on top of it. Zero the inner and let the token win.
   z-index keeps the content above the ::before wash. */
#fbh-hero > .e-con-inner {
  padding: 0;
  position: relative;
  z-index: 1;
}

@media (prefers-reduced-motion: reduce) { #fbh-hero::before { animation: none; } }

/* Illustration column */
#fbh-hero-illustration img {
  width: 100%;
  height: auto;
  max-width: 620px;
  display: block;
  margin-inline: auto;
}

/* Tech row under the hero buttons. Muted on purpose -- it is supporting
   evidence, not a headline, so it must not compete with the CTAs. */
#fbh-hero-tech { margin-block-start: var(--space-4); }

#fbh-hero-tech .elementor-icon-list-items {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3) var(--space-5);
  row-gap: var(--space-3);
  margin: 0;
  padding: 0;
}

#fbh-hero-tech .elementor-icon-list-item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
}

#fbh-hero-tech .elementor-icon-list-text {
  color: var(--color-text-muted);
  font-family: var(--font-sans, inherit);
  font-size: 0.9375rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  padding: 0;
}

#fbh-hero-tech .elementor-icon-list-icon svg,
#fbh-hero-tech .elementor-icon-list-icon i {
  width: 20px;
  height: 20px;
  font-size: 20px;
  color: var(--color-text-muted);
  fill: currentColor;
}

/* Hero eyebrow: colour only. --color-primary (#635BFF) is 4.13:1 on the dark
   hero, under the 4.5:1 AA floor at this size; the text-safe primary clears it.
   Typography intentionally untouched -- it is whatever the widget already had. */
#fbh-hero .elementor-element-3cd3325 .elementor-heading-title {
  color: var(--color-primary-text);
  line-height: 1.85;
  text-transform: capitalize;
}

/* WooCommerce mark: the bubble is currentColor and the 'Woo' letterforms are
   stroked in the page background, which reads as a knockout in both themes
   without needing a mask (Elementor's SVG sanitiser strips those). */
#fbh-hero-tech .fbh-woo-cut { stroke: var(--fbh-surface, var(--color-bg-primary)); }
#fbh-hero-tech .elementor-icon-list-icon svg .fbh-woo-bubble { fill: currentColor; }

/* The two hero CTAs differ by 2px because the outlined one carries a border.
   A shared min-height plus flex centring makes them sit on one baseline. */
#fbh-hero .elementor-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  box-sizing: border-box;
}

@media (max-width: 1024px) {
  /* padding-block deliberately NOT reset here -- the clamps above already
     scale down, and overriding would push the header/hero gap back up. */
  #fbh-hero-illustration img { max-width: 520px; }
}

/* Elementor's container sets --flex-wrap: wrap on this row, so on narrow
   phones the second button was dropping to its own line instead of the
   text wrapping -- read as 'buttons stacked, too big'. At the default
   14px text / 24px side padding the row needs ~320px (measured against
   the real IBM Plex Sans SemiBold metrics: 'Browse Our Services' is
   134px at 14px), which a 320-390px viewport does not have left after
   the 24px section padding on each side. Force nowrap and trim text
   size / side padding just enough to fit one row down to a 320px
   viewport, with an 8px+ margin. Vertical padding / min-height are
   untouched so tap size stays >=48px. */
@media (max-width: 400px) {
  #fbh-hero .elementor-element-78c8184 {
    --flex-wrap: nowrap;
    --flex-wrap-mobile: nowrap;
    --gap: 10px 10px;
    --row-gap: 10px;
    --column-gap: 10px;
  }

  #fbh-hero .elementor-element-78c8184 .e-con-inner {
    flex-wrap: nowrap !important;
    gap: 10px !important;
  }

  #fbh-hero .elementor-element-78c8184 .elementor-widget-button {
    flex: 0 1 auto;
    min-width: 0;
  }

  #fbh-hero .elementor-element-78c8184 .elementor-button {
    font-size: 13px;
    padding-inline: 14px;
    white-space: nowrap;
  }
}


/* ==========================================================================
   17f - MOBILE LOGO (size + centring)
   --------------------------------------------------------------------------
   The row has 4 children (logo, hamburger widget, theme toggle, CTA) and
   no explicit flex-shrink on the logo's own flex item, so on a tight real
   phone width it was shrinking below its set width (default flex-shrink:1).
   The hamburger widget (dd61ad0) already carries Xpro's own high
   shrink/grow values -- it is the element meant to absorb the space, not
   the logo. Pin the logo so it always renders at its full set width.
   Also: <img> is inline by default and keeps ~4-5px of baseline descender
   space beneath it, so even with the row's align-items:center it optically
   sits slightly above centre -- display:block removes that phantom space.
   ========================================================================== */

.elementor-element-98067e2 {
  flex-shrink: 0.4;
  flex-basis: 245px;
}

.elementor-element-98067e2 .xpro-site-logo,
.elementor-element-98067e2 .xpro-site-logo img {
  display: block;
}


/* ==========================================================================
   17g - MOBILE HEADER: hide the Get a Quote button
   --------------------------------------------------------------------------
   2c7888d only exists in the mobile bar (7ea26a4) -- the desktop CTA is a
   separate widget (c025b81), untouched. CSS-only so it's a one-line revert.
   ========================================================================== */

.elementor-element-2c7888d {
  display: none;
}


/* ==========================================================================
   17h - HOMEPAGE: CLIENT LOGOS (CAROUSEL)
   --------------------------------------------------------------------------
   Native Elementor Image Carousel widget. The section shares the hero's
   background token so the two read as one continuous surface above the
   Results section's boxed background below.
   Source files are uniform 1080x1080 squares, but the widget's own
   thumbnail crop plus swiper's square slide box rendered them far too
   large by default -- clamp the visible mark to a compact, consistent
   logo height and let width follow the source aspect ratio.
   ========================================================================== */

.elementor-element-0950dc7 .swiper-slide {
  display: flex;
  align-items: center;
  justify-content: center;
}

.elementor-element-0950dc7 .swiper-slide-image {
  width: auto;
  height: 84px;
  max-width: 190px;
  object-fit: contain;
}

@media (max-width: 767px) {
  .elementor-element-0950dc7 .swiper-slide-image {
    height: 56px;
    max-width: 140px;
  }
}


/* 18 - HOMEPAGE: SELECTED WORK (PROJECT CARDS)
   The .fbh-project-thumb rules that used to be here were dead: no image widget
   on the homepage ever carried that class, so the 220px crop never applied and
   the cards have always shown their images at natural aspect ratio. Removed
   rather than wired up, since the cards read fine as they are. */
.elementor-element-136a4b2 { flex-shrink: 0; }
.elementor-element-136a4b2 .elementor-button-text { white-space: nowrap; }


/* 19 - HOMEPAGE: SELECTED WORK - CASE STUDY LINK */
.fbh-case-link.fbh-case-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--fbh-primary);
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 14px;
  text-decoration: none;
  transition: color 0.2s ease, gap 0.2s ease;
}
.fbh-case-arrow {
  display: inline-block;
  transition: transform 0.2s ease;
}
.fbh-case-link.fbh-case-link:hover {
  color: var(--color-primary-hover);
  gap: 10px;
}
.fbh-case-link.fbh-case-link:hover .fbh-case-arrow {
  transform: translateX(3px);
}


/* 20 - HOMEPAGE: NEW SERVICES SECTION */
.elementor-element-21ae569 { flex-shrink: 0; }
.elementor-element-21ae569 .elementor-button-text { white-space: nowrap; }


/* 21 - HOMEPAGE: SERVICES SECTION - FULL-WIDTH CARDS, HEADER ROW ABOVE (matches Selected Work pattern) */
.elementor-element-f7037db {
  flex: 0 0 65% !important;
  max-width: 65%;
}
.elementor-element-8a62820 {
  flex: 0 0 100% !important;
  max-width: 100%;
}
@media (max-width: 1024px) {
  .elementor-element-f7037db {
    flex: 0 0 100% !important;
    max-width: 100%;
  }
  /* The header row itself must also switch to column, otherwise the 100%-wide
     text block + the 'Explore All Services' button stay side by side in a row
     and the button is pushed outside the viewport (Elementor only auto-stacks
     at its Mobile breakpoint <=767px, never in the 768-1024 tablet range). */
  .elementor-element-204fab2,
  .elementor-element-204fab2 > .e-con-inner {
    flex-direction: column !important;
    flex-wrap: nowrap !important;
    align-items: flex-start !important;
  }
}


/* 31 - HOMEPAGE SERVICES: pin the 'Explore ->' link to the bottom of each card.
   Card descriptions differ in length (2 vs 3 lines), and the link is just the
   last widget in a stretched column, so without this it floats up under short
   copy and the six links don't sit on one line. Only the card inners have a
   text-editor as last child -- the row inner's last child is a container, so
   the row is not affected. */
.elementor-element-8a62820 .e-con-inner > .elementor-widget-text-editor:last-child {
  margin-top: auto !important;
}


/* 22 - HOMEPAGE: WHY WORK WITH ME - LEFT/RIGHT 50/50 WIDTH */
.elementor-element-1e3a90d {
  flex: 0 0 50% !important;
  max-width: 50%;
}
.elementor-element-2cc5c53 {
  flex: 0 0 50% !important;
  max-width: 50%;
}
@media (max-width: 1024px) {
  .elementor-element-1e3a90d,
  .elementor-element-2cc5c53 {
    flex: 0 0 100% !important;
    max-width: 100%;
  }
  /* Both columns are 100% wide here, so the parent MUST become a column or the
     two of them sit side by side and blow the page out to ~2x viewport width
     (this was the source of the horizontal scrollbar across 768-1024px). */
  .elementor-element-8e1c5e4,
  .elementor-element-8e1c5e4 > .e-con-inner {
    flex-direction: column !important;
    flex-wrap: nowrap !important;
  }
}


/* 33 - HOMEPAGE "WHY WORK WITH ME": checkmark icon placement.
   Two separate defects fixed here.

   (a) Desktop/tablet: the icon widget is a plain flex item with the default
       flex-shrink:1, so in the nowrap row it got squeezed from 20px down to
       ~18px -- and the exact amount varied with the viewport (18.0 at 1280,
       18.3 at 768, 18.7 at 1024), so the ticks were subtly different sizes
       at different screen widths. Pinning the basis keeps them exactly 20px.

   (b) Mobile (<=767px): Elementor switches the row to flex-wrap:wrap and
       makes child containers full width, so the text column claimed 100% of
       the row and wrapped onto the line BELOW the tick -- leaving each tick
       stranded on its own line above its heading. Forcing nowrap plus an
       auto-width text column puts the tick back beside the heading. */
.elementor-element-cd98950,
.elementor-element-e74002b,
.elementor-element-cf1bb57,
.elementor-element-6e630b8 {
  flex: 0 0 20px !important;
  width: 20px !important;
  max-width: 20px !important;
}
.elementor-element-cd98950 svg,
.elementor-element-e74002b svg,
.elementor-element-cf1bb57 svg,
.elementor-element-6e630b8 svg {
  width: 20px !important;
  height: 20px !important;
  flex: none !important;
  display: block;
}
@media (max-width: 767px) {
  .elementor-element-f76a205 > .e-con-inner,
  .elementor-element-d16ccb0 > .e-con-inner,
  .elementor-element-9e8b17a > .e-con-inner,
  .elementor-element-d3ef9be > .e-con-inner {
    flex-wrap: nowrap !important;
    align-items: flex-start !important;
  }
  .elementor-element-2a9f1f2,
  .elementor-element-fea32c1,
  .elementor-element-6b5d731,
  .elementor-element-fc2a2e6 {
    flex: 1 1 auto !important;
    width: auto !important;
  }
}

/* 34 - HOMEPAGE "RESULTS": go 2-up across the tablet range.
   The four stat cards stay 4-across from 768px to 1023px, which squeezes each
   one to 156-203px. The icon badge in each card is position:absolute pinned to
   the card's top-right, so it does NOT reserve space -- the big number simply
   runs underneath it (measured: 44px of overlap at 768px, so "100x" lost its
   x, "2.5M+" its M+, "96/100" its 00). The cards also ended up with ragged
   bottoms (53px height spread) at those widths.
   Two-up gives each card ~328px at 768px, which clears the badge comfortably
   and evens the rows out. Below 768px Elementor already stacks them 1-up.
   Upper bound is 1099px, not 1023px: at 1024px (iPad landscape) 4-up leaves
   only 6px between the number and the badge, which still reads as cramped.
   4-up resumes at 1100px, where the clearance is a comfortable 24px+. */
/* The row is align-items:flex-start, so each stat card sizes to its own copy
   and the bottom edges come out ragged whenever one description wraps to a
   different number of lines (e.g. 20px short at 1100px). Stretch makes every
   card in a line share the tallest height. */
.elementor-element-75895a1 > .e-con-inner {
  align-items: stretch !important;
}

@media (min-width: 768px) and (max-width: 1099px) {
  .elementor-element-75895a1 > .e-con-inner {
    flex-wrap: wrap !important;
  }
  .elementor-element-deca4ce,
  .elementor-element-ed06dff,
  .elementor-element-a670362,
  .elementor-element-80fd622 {
    flex: 0 0 calc(50% - 8px) !important;
    width: calc(50% - 8px) !important;
    max-width: calc(50% - 8px) !important;
  }
}

/* 35 - GLOBAL: repair the leaked Heading-widget default colour.

   Elementor writes the Heading widget's default style into the FOOTER
   template's generated stylesheet (wp-content/uploads/elementor/css/post-40.css,
   template #40 "FBH Footer") WITHOUT the usual `.elementor-40` scope prefix:

       .elementor-widget-heading .elementor-heading-title {
           color: var( --e-global-color-primary );   <- brand purple
       }

   Because it is unscoped it applies to every Heading widget on every page of
   the site, and at (0,2,0) it outranks the Kit's own `.elementor-kit-7 h1`
   (0,1,1) -- which correctly asks for var(--fbh-text). Net effect: any heading
   that does not carry an explicit per-element colour silently renders brand
   purple instead of the text colour. That is what turned the whole hero H1
   purple and swallowed its deliberate purple accent word.

   Rather than patch each heading one at a time, restore the intended default
   here. The `body` prefix lifts this to (0,2,1) so it wins over the leaked
   rule regardless of stylesheet order, while any real per-element colour --
   Elementor emits those as `.elementor-{page} .elementor-element-{id}
   .elementor-heading-title` (0,4,0) -- still wins over this. So the purple
   eyebrow labels, the green/purple stat numbers and every other deliberate
   colour are untouched; only the accidental purple falls back to the token.

   Using the token (not a literal) also means headings now follow dark mode,
   which the leaked brand-colour rule never did. */
body .elementor-widget-heading .elementor-heading-title {
  color: var(--fbh-text);
}

/* 37 - ABOUT PAGE "EXPERIENCE": stick the intro column while the roles scroll.

   The section is a two-up row: a short intro column (f99535a) beside a much
   taller timeline column (0cc7f3e, four roles). The intro finished ~600px
   before the timeline did, leaving a large dead area on the left at desktop
   widths. Sticking the intro keeps it beside whichever role you are reading.

   align-self:flex-start is required -- as a stretched flex item the column is
   as tall as the row, so it would have nothing to travel within and sticky
   would never engage. Only applied from 1025px up: at tablet and below the
   two columns stack, and a sticky element in a stack just overlaps content. */
@media (min-width: 1025px) {
  .elementor-element-f99535a {
    position: sticky;
    top: 96px;
    align-self: flex-start;
  }
}

/* 38 - ABOUT PAGE "TECHNICAL SKILLS": readable measure + honest level bars.

   (a) The intro line ran the full 1184px. Elementor's `width` control only
       applies to containers, so setting it on a text widget did nothing --
       capping max-width here matches the ~65% measure used by the homepage
       section headers, and releases to full width once the layout stacks.

   (b) The level bars: each fill sits in a column flex track whose stretch
       alignment overrode the per-element width, so all eight rendered at
       100% and the bar carried no information. Pinning flex-basis makes the
       length actually track the label -- Expert 95%, Advanced 78%. (The
       track itself was rgba(255,255,255,0.08), a dark-mode-only colour that
       was invisible on white; it is now a themed border token, so the
       remaining portion of the bar is visible in both modes.) */
/* Elementor's own `.e-con > .elementor-widget { max-width:100% }` outranks a
   single-class selector, so this needs the page+element specificity. */
.elementor-16 .elementor-element.elementor-element-86af260 {
  max-width: 65% !important;
}
@media (max-width: 1024px) {
  .elementor-16 .elementor-element.elementor-element-86af260 { max-width: 100% !important; }
}

.elementor-element-c81963b,
.elementor-element-f232e90,
.elementor-element-4c55fbe,
.elementor-element-a92e9ef,
.elementor-element-d1ea000 {
  flex: 0 0 95% !important;
  width: 95% !important;
  max-width: 95% !important;
}
.elementor-element-7248e15,
.elementor-element-780396f,
.elementor-element-fbf065f {
  flex: 0 0 78% !important;
  width: 78% !important;
  max-width: 78% !important;
}

/* 23 - PROJECT & SERVICE TITLE LINKS (homepage + Services page)\n   Elementor free has no hover control on the Heading widget, so the linked\n   card titles get their hover tint here. Same rule, same token, both pages. - KEEP COLOR, CHANGE ON HOVER */
.elementor-element-8358faf .elementor-heading-title a,
.elementor-element-818d7de .elementor-heading-title a,
.elementor-element-f1c8040 .elementor-heading-title a,
.elementor-element-b617fd5 .elementor-heading-title a,
.elementor-element-c5f47c6 .elementor-heading-title a,
.elementor-element-ef9b786 .elementor-heading-title a,
.elementor-element-15c6712 .elementor-heading-title a,
.elementor-element-8984cde .elementor-heading-title a,
.elementor-element-91bfeeb .elementor-heading-title a,
.elementor-element-80dd3f4 .elementor-heading-title a,
.elementor-element-4fa00ac .elementor-heading-title a,
.elementor-element-6554559 .elementor-heading-title a,
.elementor-element-870fea9 .elementor-heading-title a,
.elementor-element-62bc048 .elementor-heading-title a,
.elementor-element-dd3d4ef .elementor-heading-title a,
.elementor-element-449379f .elementor-heading-title a {
  color: var(--fbh-text);
  text-decoration: none;
  transition: color 0.2s ease;
}
.elementor-element-8358faf .elementor-heading-title a:hover,
.elementor-element-818d7de .elementor-heading-title a:hover,
.elementor-element-f1c8040 .elementor-heading-title a:hover,
.elementor-element-b617fd5 .elementor-heading-title a:hover,
.elementor-element-c5f47c6 .elementor-heading-title a:hover,
.elementor-element-ef9b786 .elementor-heading-title a:hover,
.elementor-element-15c6712 .elementor-heading-title a:hover,
.elementor-element-8984cde .elementor-heading-title a:hover,
.elementor-element-91bfeeb .elementor-heading-title a:hover,
.elementor-element-80dd3f4 .elementor-heading-title a:hover,
.elementor-element-4fa00ac .elementor-heading-title a:hover,
.elementor-element-6554559 .elementor-heading-title a:hover,
.elementor-element-870fea9 .elementor-heading-title a:hover,
.elementor-element-62bc048 .elementor-heading-title a:hover,
.elementor-element-dd3d4ef .elementor-heading-title a:hover,
.elementor-element-449379f .elementor-heading-title a:hover {
  color: var(--color-primary-hover);
}

/* 29 - HOMEPAGE CTA: button row (d3e5870) inherits Elementor's base .e-con
   width:100% default, so it spans the full actions column instead of
   shrinking to fit the 2 buttons -- forcing them flush-left instead of
   letting flex-end center/right-align the row as a unit. */
.elementor-element-d3e5870 {
  width: auto !important;
  flex: 0 0 auto !important;
}

/* 30 - GLOBAL: Astra's .ast-page-builder-template / .ast-plain-container
   classes (added by Astra to <body> automatically) set background-color via
   --ast-global-color-4, a hardcoded Astra Customizer color (#FFFFFF) that
   knows nothing about our [data-theme] system. That class selector has
   higher specificity than our themed `body{background:var(--color-bg-
   primary)}` rule, so it silently wins and keeps body white even in dark
   mode -- showing as a white gap around/behind any section that isn't
   itself explicitly backgrounded (e.g. margins around the CTA card). */
body.ast-page-builder-template,
body.ast-plain-container,
.ast-plain-container,
.ast-page-builder-template {
  background-color: var(--color-bg-primary) !important;
}

/* 27 - HOMEPAGE: FINAL CTA CARD horizontal centering (content_width:full doesn't emit a width override, so width is stuck at 100%% with nothing for margin:auto to center against - must set width explicitly) */
.elementor-element-6873674 {
  width: 1200px !important;
  max-width: 100% !important;
  margin-left: auto !important;
  margin-right: auto !important;
}
/* Below the point where the 1200px card + a 48px gutter each side stops
   fitting, keep real side gutters so the rounded card never bleeds to the
   screen edges. Gutter tracks the section gutter at each breakpoint. */
@media (max-width: 1296px) {
  .elementor-element-6873674 {
    width: auto !important;
    margin-left: 48px !important;
    margin-right: 48px !important;
  }
}
@media (max-width: 1024px) {
  .elementor-element-6873674 {
    margin-left: 40px !important;
    margin-right: 40px !important;
  }
}
@media (max-width: 767px) {
  .elementor-element-6873674 {
    margin-left: 20px !important;
    margin-right: 20px !important;
  }
}

/* 32 - HOMEPAGE CTA: keep the two buttons intact on narrow screens.
   Adding the 20px side gutters made the card 40px narrower, which left the
   two buttons ~6px short of fitting on one line -- so they shrank and broke
   their labels ('Get a / Quote'). Stop them shrinking and let the row wrap
   instead, so each button drops to its own line with its label in one piece. */
@media (max-width: 767px) {
  /* Block 29 shrink-wraps this row (width:auto / flex:0 0 auto) so it can be
     centred on desktop. On phones that same shrink-wrap makes the row wider
     than the card and the buttons spill out, so give the row the full card
     width back and let it wrap: each button then drops onto its own line
     with its label in one piece. */
  .elementor-element-d3e5870 {
    width: 100% !important;
    flex: 0 1 auto !important;
  }
  /* the real flex context is the .e-con-inner wrapper, and it computes
     flex-wrap:nowrap here -- without this the buttons cannot break onto a
     second line and simply overflow the card on narrow phones. */
  .elementor-element-d3e5870 > .e-con-inner {
    flex-wrap: wrap !important;
  }
  .elementor-element-d3e5870 .elementor-widget-button {
    flex: 0 0 auto !important;
  }
  .elementor-element-d3e5870 .elementor-button {
    white-space: nowrap;
  }
}


/* 26 - HOMEPAGE: FINAL CTA CARD (Ready to Start) */
.elementor-element-d486feb {
  flex: 0 0 220px !important;
  width: 220px !important;
}
.elementor-element-d7e4262 {
  flex: 1 1 0% !important;
  min-width: 0;
}
.elementor-element-106f68a {
  flex: 0 0 420px !important;
  width: 420px !important;
  max-width: 420px;
}
@media (max-width: 1024px) {
  .elementor-element-6873674 {
    flex-direction: column !important;
    flex-wrap: nowrap !important;
    align-items: flex-start !important;
  }
  .elementor-element-d486feb {
    display: none;
  }
  .elementor-element-d7e4262 {
    flex: 0 0 auto !important;
    width: 100% !important;
  }
  .elementor-element-106f68a {
    flex: 0 0 auto !important;
    width: 100% !important;
    max-width: 100%;
    align-items: flex-start !important;
  }
  .elementor-element-106f68a .elementor-element-d3e5870 {
    width: 100%;
  }
  .elementor-element-d3e5870 .elementor-element-40de7a9,
  .elementor-element-d3e5870 .elementor-element-68d9510 {
    flex: 0 0 auto;
  }
}

/* ==========================================================================
   39. SERVICES - comparison table: horizontal scroll on small screens
   --------------------------------------------------------------------------
   The "Me vs. the alternatives" table (#a43bed7) is a 4-column flex grid
   (28/24/24/24%). It used to be hidden below 768px, which silently removed a
   whole section for mobile visitors. It is now visible; instead of squeezing
   four columns into ~350px (which clipped the 4th column entirely), the table
   body scrolls horizontally at a readable minimum width. Rows are forced to
   stay horizontal so every row lines up with the header row.
   ========================================================================== */
@media (max-width: 767px) {
  .elementor-element-5a2f492 {
    overflow-x: auto !important;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
  }
  .elementor-element-5a2f492 > .e-con-inner {
    min-width: 620px;
  }
  .elementor-element-9680c89,
  .elementor-element-de7a6ef,
  .elementor-element-2b55319,
  .elementor-element-ad05e4c,
  .elementor-element-e45063c,
  .elementor-element-75383a5,
  .elementor-element-91fd764,
  .elementor-element-deb6e26,
  .elementor-element-6f97bdf,
  .elementor-element-81ad249 {
    --flex-direction: row !important;
    --flex-wrap: nowrap !important;
  }
  .elementor-element-9680c89 > .e-con-inner,
  .elementor-element-de7a6ef > .e-con-inner,
  .elementor-element-2b55319 > .e-con-inner,
  .elementor-element-ad05e4c > .e-con-inner,
  .elementor-element-e45063c > .e-con-inner,
  .elementor-element-75383a5 > .e-con-inner,
  .elementor-element-91fd764 > .e-con-inner,
  .elementor-element-deb6e26 > .e-con-inner,
  .elementor-element-6f97bdf > .e-con-inner,
  .elementor-element-81ad249 > .e-con-inner {
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    align-items: stretch !important;
  }
  /* keep the highlighted column an unbroken band even when the label cell
     wraps to two lines */
  .elementor-element-5a2f492 .e-con-inner > .e-con {
    align-self: stretch;
  }
  /* visible scroll affordance - without it the cut-off 3rd/4th columns read as
     a rendering bug rather than as scrollable content */
  .elementor-element-5a2f492 {
    scrollbar-width: thin;
    scrollbar-color: var(--color-border-strong) transparent;
  }
  .elementor-element-5a2f492::-webkit-scrollbar { height: 6px; }
  .elementor-element-5a2f492::-webkit-scrollbar-track { background: transparent; }
  .elementor-element-5a2f492::-webkit-scrollbar-thumb {
    background: var(--color-border-strong);
    border-radius: 3px;
  }
}


/* ==========================================================================
   40. Icon-list safety net (footer link columns)
   --------------------------------------------------------------------------
   Elementor loads widget-icon-list.min.css conditionally, per document. The
   footer template's icon-lists are not always counted when a page has no
   icon-list of its own (observed on /contact/), and the lists then fall back
   to browser defaults - visible bullet markers and list-item spacing. These
   are the essential rules from Elementor's own widget stylesheet, so they are
   a no-op when that file IS enqueued.
   ========================================================================== */
.elementor-widget-icon-list .elementor-icon-list-items {
  list-style-type: none;
  margin: 0;
  padding: 0;
}
.elementor-widget-icon-list .elementor-icon-list-item {
  display: flex;
  font-size: inherit;
  align-items: var(--icon-vertical-align, center);
  list-style-type: none;
}
.elementor-widget-icon-list .elementor-icon-list-item > a {
  display: flex;
  align-items: var(--icon-vertical-align, center);
}

/* ==========================================================================
   41. SERVICES + CONTACT - tablet range (768-1099px)
   --------------------------------------------------------------------------
   Elementor only auto-stacks at its Mobile breakpoint (<=767px), so between
   768 and 1024 every one of these card grids kept its desktop column count:
   the 32%/31.3% cards collapsed to 210-220px and the copy wrapped into 5-6
   line ribbons. Same remedy as the homepage Results row (block 34): drop to
   two columns and let the odd card out span the full width, so there is never
   a hole in the grid.
   ========================================================================== */
@media (min-width: 768px) and (max-width: 1099px) {

  /* --- rows must be allowed to wrap (several had flex_wrap_tablet:nowrap) - */
  .elementor-element-5b7f8e1,
  .elementor-element-bc9dc00,
  .elementor-element-67f146a,
  .elementor-element-399bed5,
  .elementor-element-df8d69f,
  .elementor-element-2681efc {
    --flex-wrap: wrap !important;
    flex-wrap: wrap !important;
  }
  .elementor-element-bc9dc00 > .e-con-inner,
  .elementor-element-67f146a > .e-con-inner,
  .elementor-element-2681efc > .e-con-inner {
    flex-wrap: wrap !important;
  }

  /* --- services bento: 26px gap on row 1, 20px on rows 2-3 --------------- */
  .elementor-element-87452d3,
  .elementor-element-8c159b8 {
    --width: calc(50% - 13px) !important;
  }
  .elementor-element-02875d6,
  .elementor-element-36a1683,
  .elementor-element-e844434,
  .elementor-element-8cde464 {
    --width: calc(50% - 10px) !important;
  }
  .elementor-element-1878c42 {          /* Migration - odd card out */
    --width: 100% !important;
  }

  /* --- pricing tiers: Starter + Professional side by side, Enterprise wide */
  .elementor-element-91250c5,
  .elementor-element-3dabc8d {
    --width: calc(50% - 10px) !important;
  }
  .elementor-element-af05c10 {
    --width: 100% !important;
  }

  /* --- contact quick answers: 2 up, third full width --------------------- */
  .elementor-element-fb2511a,
  .elementor-element-436c0a0 {
    --width: calc(50% - 10px) !important;
  }
  .elementor-element-40f5008 {
    --width: 100% !important;
  }
}

/* --- services FAQ + final CTA: stack the two columns below desktop -------- */
@media (max-width: 1024px) {
  .elementor-element-45a9cb6,
  .elementor-element-2681efc {
    --flex-direction: column !important;
    --flex-wrap: nowrap !important;
  }
  .elementor-element-45a9cb6 > .e-con-inner,
  .elementor-element-2681efc > .e-con-inner {
    flex-direction: column !important;
    flex-wrap: nowrap !important;
    align-items: flex-start !important;
  }
  .elementor-element-882672f,
  .elementor-element-aeb07c5,
  .elementor-element-7b9cb99,
  .elementor-element-d009921 {
    --width: 100% !important;
  }
  /* the FAQ intro column carried a 20px right padding meant for a side-by-side
     layout - pointless once it is full width */
  .elementor-element-882672f {
    --padding-right: 0px !important;
  }
  .elementor-element-d009921 {
    --justify-content: flex-start !important;
  }
}

/* Block 42 (Services button rows) was fully superseded by block 43 below and
   has been removed - it only re-declared flex-wrap:wrap on rows that 43 then
   forces to nowrap. */

/* ==========================================================================
   43. BUTTON PAIRS ON MOBILE - side by side, one line each  (site-wide)
   --------------------------------------------------------------------------
   Supersedes the wrap-to-two-lines behaviour of blocks 32 and 42.

   Every two-button row now stays HORIZONTAL on phones with each label on a
   single line. The constraint is arithmetic: the widest pair is the homepage
   CTA ("Get a Quote" + "Book a Consultation" = 207px of text at 14px/600),
   the cards give VW-80px of usable width (20px section gutter + 20px card
   padding each side) and the row gap is 12px. 207 + 12 + 4x16px of button
   padding = 283px, which needs a 363px+ viewport - so below that the type and
   the button padding step down together rather than letting the labels fold
   or the buttons spill out of the card.

     Tier A   401px+       14px / 16px padding  -> needs 283px
     Tier B   345-400px    13px / 10px padding  -> needs 245px
     Tier C   up to 344px  12px /  8px padding  -> needs 222px  (fits 320px)

   Rows: homepage hero + CTA, About hero + CTA, Services hero + CTA, and the
   hero + CTA row of each of the seven service detail pages (21-27). Their
   widest pair is "Get a Quote" + "WhatsApp Me", narrower than the homepage
   pair the tiers above were measured against, so they fit inside them.
   ========================================================================== */
@media (max-width: 767px) {

  /* --- the row: horizontal, never wrapping, full width of its card ------- */
  .elementor-element-d3e5870,   /* home     - CTA card */
  .elementor-element-78c8184,   /* home     - hero     */
  .elementor-element-7610a7c,   /* about    - CTA card */
  .elementor-element-de7358b,   /* about    - hero     */
  .elementor-element-d009921,   /* services - CTA card */
  .elementor-element-51d3636,   /* svc: wp-dev  hero */
  .elementor-element-95790c3,   /* svc: wp-dev  CTA */
  .elementor-element-123080b,   /* svc: speed   hero */
  .elementor-element-753962f,   /* svc: speed   CTA */
  .elementor-element-71e88f9,   /* svc: woo     hero */
  .elementor-element-488248b,   /* svc: woo     CTA */
  .elementor-element-6bd96c0,   /* svc: maint   hero */
  .elementor-element-8612b1a,   /* svc: maint   CTA */
  .elementor-element-a08a21f,   /* svc: seo     hero */
  .elementor-element-bd38025,   /* svc: seo     CTA */
  .elementor-element-3a008bb,   /* svc: migrate hero */
  .elementor-element-d571b5b,   /* svc: rtl     hero */
  .elementor-element-b643ace,   /* svc: rtl     CTA */
  .elementor-element-0166706,   /* portfolio - CTA */
  .elementor-element-723a48e {  /* services - hero     */
    --flex-direction: row !important;
    --flex-wrap: nowrap !important;
    --width: 100% !important;
    --gap: 12px !important;
    --column-gap: 12px !important;
    --row-gap: 12px !important;
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    width: 100% !important;
    flex: 0 1 auto !important;
  }
  .elementor-element-d3e5870 > .e-con-inner,
  .elementor-element-78c8184 > .e-con-inner,
  .elementor-element-7610a7c > .e-con-inner,
  .elementor-element-de7358b > .e-con-inner,
  .elementor-element-d009921 > .e-con-inner,
  .elementor-element-51d3636 > .e-con-inner,   /* svc: wp-dev  hero */
  .elementor-element-95790c3 > .e-con-inner,   /* svc: wp-dev  CTA */
  .elementor-element-123080b > .e-con-inner,   /* svc: speed   hero */
  .elementor-element-753962f > .e-con-inner,   /* svc: speed   CTA */
  .elementor-element-71e88f9 > .e-con-inner,   /* svc: woo     hero */
  .elementor-element-488248b > .e-con-inner,   /* svc: woo     CTA */
  .elementor-element-6bd96c0 > .e-con-inner,   /* svc: maint   hero */
  .elementor-element-8612b1a > .e-con-inner,   /* svc: maint   CTA */
  .elementor-element-a08a21f > .e-con-inner,   /* svc: seo     hero */
  .elementor-element-bd38025 > .e-con-inner,   /* svc: seo     CTA */
  .elementor-element-3a008bb > .e-con-inner,   /* svc: migrate hero */
  .elementor-element-d571b5b > .e-con-inner,   /* svc: rtl     hero */
  .elementor-element-b643ace > .e-con-inner,   /* svc: rtl     CTA */
  .elementor-element-0166706 > .e-con-inner,   /* portfolio - CTA */
  .elementor-element-723a48e > .e-con-inner {
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    align-items: center !important;
    gap: 12px !important;
  }

  /* --- each button keeps its natural width and never shrinks below it ---- */
  .elementor-element-d3e5870 .elementor-widget-button,
  .elementor-element-78c8184 .elementor-widget-button,
  .elementor-element-7610a7c .elementor-widget-button,
  .elementor-element-de7358b .elementor-widget-button,
  .elementor-element-d009921 .elementor-widget-button,
  .elementor-element-51d3636 .elementor-widget-button,   /* svc: wp-dev  hero */
  .elementor-element-95790c3 .elementor-widget-button,   /* svc: wp-dev  CTA */
  .elementor-element-123080b .elementor-widget-button,   /* svc: speed   hero */
  .elementor-element-753962f .elementor-widget-button,   /* svc: speed   CTA */
  .elementor-element-71e88f9 .elementor-widget-button,   /* svc: woo     hero */
  .elementor-element-488248b .elementor-widget-button,   /* svc: woo     CTA */
  .elementor-element-6bd96c0 .elementor-widget-button,   /* svc: maint   hero */
  .elementor-element-8612b1a .elementor-widget-button,   /* svc: maint   CTA */
  .elementor-element-a08a21f .elementor-widget-button,   /* svc: seo     hero */
  .elementor-element-bd38025 .elementor-widget-button,   /* svc: seo     CTA */
  .elementor-element-3a008bb .elementor-widget-button,   /* svc: migrate hero */
  .elementor-element-d571b5b .elementor-widget-button,   /* svc: rtl     hero */
  .elementor-element-b643ace .elementor-widget-button,   /* svc: rtl     CTA */
  .elementor-element-0166706 .elementor-widget-button,   /* portfolio - CTA */
  .elementor-element-723a48e .elementor-widget-button {
    flex: 0 0 auto !important;
    width: auto !important;
    max-width: none !important;
  }
  .elementor-element-d3e5870 .elementor-button,
  .elementor-element-78c8184 .elementor-button,
  .elementor-element-7610a7c .elementor-button,
  .elementor-element-de7358b .elementor-button,
  .elementor-element-d009921 .elementor-button,
  .elementor-element-51d3636 .elementor-button,   /* svc: wp-dev  hero */
  .elementor-element-95790c3 .elementor-button,   /* svc: wp-dev  CTA */
  .elementor-element-123080b .elementor-button,   /* svc: speed   hero */
  .elementor-element-753962f .elementor-button,   /* svc: speed   CTA */
  .elementor-element-71e88f9 .elementor-button,   /* svc: woo     hero */
  .elementor-element-488248b .elementor-button,   /* svc: woo     CTA */
  .elementor-element-6bd96c0 .elementor-button,   /* svc: maint   hero */
  .elementor-element-8612b1a .elementor-button,   /* svc: maint   CTA */
  .elementor-element-a08a21f .elementor-button,   /* svc: seo     hero */
  .elementor-element-bd38025 .elementor-button,   /* svc: seo     CTA */
  .elementor-element-3a008bb .elementor-button,   /* svc: migrate hero */
  .elementor-element-d571b5b .elementor-button,   /* svc: rtl     hero */
  .elementor-element-b643ace .elementor-button,   /* svc: rtl     CTA */
  .elementor-element-0166706 .elementor-button,   /* portfolio - CTA */
  .elementor-element-723a48e .elementor-button {
    white-space: nowrap !important;
    padding-left: 16px !important;
    padding-right: 16px !important;
  }
}

/* --- Tier B ------------------------------------------------------------- */
@media (max-width: 400px) {
  .elementor-element-d3e5870 .elementor-button,
  .elementor-element-78c8184 .elementor-button,
  .elementor-element-7610a7c .elementor-button,
  .elementor-element-de7358b .elementor-button,
  .elementor-element-d009921 .elementor-button,
  .elementor-element-51d3636 .elementor-button,   /* svc: wp-dev  hero */
  .elementor-element-95790c3 .elementor-button,   /* svc: wp-dev  CTA */
  .elementor-element-123080b .elementor-button,   /* svc: speed   hero */
  .elementor-element-753962f .elementor-button,   /* svc: speed   CTA */
  .elementor-element-71e88f9 .elementor-button,   /* svc: woo     hero */
  .elementor-element-488248b .elementor-button,   /* svc: woo     CTA */
  .elementor-element-6bd96c0 .elementor-button,   /* svc: maint   hero */
  .elementor-element-8612b1a .elementor-button,   /* svc: maint   CTA */
  .elementor-element-a08a21f .elementor-button,   /* svc: seo     hero */
  .elementor-element-bd38025 .elementor-button,   /* svc: seo     CTA */
  .elementor-element-3a008bb .elementor-button,   /* svc: migrate hero */
  .elementor-element-d571b5b .elementor-button,   /* svc: rtl     hero */
  .elementor-element-b643ace .elementor-button,   /* svc: rtl     CTA */
  .elementor-element-0166706 .elementor-button,   /* portfolio - CTA */
  .elementor-element-723a48e .elementor-button {
    font-size: 13px !important;
    padding-left: 10px !important;
    padding-right: 10px !important;
  }
}

/* --- Tier C ------------------------------------------------------------- */
@media (max-width: 344px) {
  .elementor-element-d3e5870 .elementor-button,
  .elementor-element-78c8184 .elementor-button,
  .elementor-element-7610a7c .elementor-button,
  .elementor-element-de7358b .elementor-button,
  .elementor-element-d009921 .elementor-button,
  .elementor-element-51d3636 .elementor-button,   /* svc: wp-dev  hero */
  .elementor-element-95790c3 .elementor-button,   /* svc: wp-dev  CTA */
  .elementor-element-123080b .elementor-button,   /* svc: speed   hero */
  .elementor-element-753962f .elementor-button,   /* svc: speed   CTA */
  .elementor-element-71e88f9 .elementor-button,   /* svc: woo     hero */
  .elementor-element-488248b .elementor-button,   /* svc: woo     CTA */
  .elementor-element-6bd96c0 .elementor-button,   /* svc: maint   hero */
  .elementor-element-8612b1a .elementor-button,   /* svc: maint   CTA */
  .elementor-element-a08a21f .elementor-button,   /* svc: seo     hero */
  .elementor-element-bd38025 .elementor-button,   /* svc: seo     CTA */
  .elementor-element-3a008bb .elementor-button,   /* svc: migrate hero */
  .elementor-element-d571b5b .elementor-button,   /* svc: rtl     hero */
  .elementor-element-b643ace .elementor-button,   /* svc: rtl     CTA */
  .elementor-element-0166706 .elementor-button,   /* portfolio - CTA */
  .elementor-element-723a48e .elementor-button {
    font-size: 12px !important;
    padding-left: 8px !important;
    padding-right: 8px !important;
  }
}


/* ==========================================================================
   44. SERVICES - card "Explore" links + FAQ accordion
   --------------------------------------------------------------------------
   The 7 card links are Elementor Button widgets styled to match the homepage
   .fbh-case-link (block 19) exactly: purple, 14px/600, arrow icon, no border
   or background. Everything there is an Elementor setting. The only piece
   Elementor has no control for is the hover micro-motion - the gap opening
   from 6px to 10px and the arrow nudging 3px right - so it is reproduced here
   with the same values as block 19, otherwise the two pages would animate
   differently for what is meant to be the same element.

   The accordion gets its 12px radius from Elementor (Advanced > Border), but
   the radius only bites once the stacked item borders are clipped, and
   Elementor exposes no overflow control on widgets - hence the one rule here.
   ========================================================================== */
.elementor-17 .elementor-element-086a061 .elementor-widget-button .elementor-button {
  transition: color 0.2s ease;
}
.elementor-17 .elementor-element-086a061 .elementor-widget-button .elementor-button .elementor-button-content-wrapper {
  transition: gap 0.2s ease;
}
.elementor-17 .elementor-element-086a061 .elementor-widget-button .elementor-button:hover .elementor-button-content-wrapper {
  gap: 10px !important;
}
.elementor-17 .elementor-element-086a061 .elementor-widget-button .elementor-button .elementor-button-icon {
  transition: transform 0.2s ease;
}
.elementor-17 .elementor-element-086a061 .elementor-widget-button .elementor-button:hover .elementor-button-icon {
  transform: translateX(3px);
}

.elementor-element-d799d2c {
  overflow: hidden;
}


/* ==========================================================================
   45. FOOTER - link hover states
   --------------------------------------------------------------------------
   Elementor's icon-list widget exposes a "Text Color > Hover" control, but in
   this version it never emits any CSS. Verified directly: setting it to a
   plain hex and force-regenerating post-40.css produces the icon hover rule
   and no text hover rule at all, so it is not a token/var() problem - the
   control is simply dead. The three footer link columns get their hover here.
   The resting rule already carries transition:color 0.2s, emitted by the
   (working) text_color_hover_transition control.
   ========================================================================== */
.elementor-element-4d350f7 .elementor-icon-list-item:hover .elementor-icon-list-text,
.elementor-element-52776e1 .elementor-icon-list-item:hover .elementor-icon-list-text,
.elementor-element-ec54de6 .elementor-icon-list-item:hover .elementor-icon-list-text {
  color: var(--color-primary);
}

/* the two footer logos are links too - give them the same feedback */
.elementor-element-7f78248 a,
.elementor-element-b42e0c2 a {
  transition: opacity var(--duration-fast) var(--ease-out);
}
.elementor-element-7f78248 a:hover,
.elementor-element-b42e0c2 a:hover {
  opacity: 0.72;
}


/* ==========================================================================
   46. INLINE-STYLE REMOVAL - shared utility classes
   --------------------------------------------------------------------------
   Text-editor widgets across the site carried the same handful of inline
   style="" blobs, copy-pasted dozens of times. Two problems with that:

   1. An inline `color` on an <a> beats every external rule, including
      a:hover, so those links had no hover state at all and could not be
      given one without !important. The back-links on the seven service
      pages and the "Read article" links on /blog/ were both dead this way.
   2. The blobs hardcoded rgba(99,91,255,0.12) and friends, so they never
      responded to the theme switch - the same purple wash in light and
      dark, instead of the tokenised --color-primary-soft which is tuned
      per theme.

   Everything below replaces one repeated inline blob with one class. The
   markup in Elementor now carries only the class name.
   ========================================================================== */

/* --- breadcrumb: back-link / separator / service name above the H1 ---------\n   All three parts share one type spec: IBM Plex Sans 13px/500, no letter\n   spacing, no uppercasing. The service name keeps its pill but is capitalised\n   rather than shouted. */
/* Doubled class: Elementor's kit ships `.elementor-kit-7 a { color }` (0,1,1),
   which outranks a single class. Repeating the class makes this (0,2,0) so the
   link keeps its muted resting colour and gets a real hover. */
.fbh-back-link.fbh-back-link {
  display: inline-block;
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: normal;
  text-transform: none;
  color: var(--color-text-muted);
  text-decoration: none;
  transition: color var(--duration-fast) var(--ease-out);
}
.fbh-back-link.fbh-back-link:hover,
.fbh-back-link.fbh-back-link:focus-visible {
  color: var(--color-primary);
}

/* --- breadcrumb separator ------------------------------------------------ */
.fbh-crumb-sep {
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: normal;
  text-transform: none;
  color: var(--color-text-muted);
}

/* --- pill: the uppercase category badge in service / blog heroes --------- */
.fbh-pill {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--color-primary-soft);
  border: 1px solid var(--color-primary-border);
  color: var(--color-primary);
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: normal;
  text-transform: capitalize;
}

/* --- tag: the soft chips under the homepage project cards ---------------- */
.fbh-tag {
  display: inline-block;
  background: var(--color-primary-soft);
  color: var(--color-primary);
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.02em;
  padding: 5px 10px;
  border-radius: 20px;
}

/* --- icon chip: the 44px rounded square behind each service icon --------- */
.fbh-icon-chip {
  width: 44px;
  height: 44px;
  border-radius: 10px;
  background: var(--color-primary-soft);
  display: flex;
  align-items: center;
  justify-content: center;
}
.fbh-icon-chip--mb {
  margin-bottom: 16px;
}

/* --- level label on the About page skill cards --------------------------- */
.fbh-level {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.06em;
  color: var(--color-success);
}

/* --- generic: a <p> that should not add its own margin ------------------- */
.fbh-p-flush {
  margin: 0;
}


/* ==========================================================================
   47. SERVICE DETAIL PAGES (21-27)
   --------------------------------------------------------------------------
   Three things Elementor cannot express as settings on these seven pages.

   1. The FAQ accordion gets its 12px radius from Advanced > Border, but the
      radius only bites once the stacked item borders are clipped and there is
      no overflow control on widgets - same one-liner as block 44 for the
      Services page accordion.
   2. The maintenance plan lists mark excluded features with fa-times. The
      icon-list widget has a single icon colour for the whole list, so the
      crosses inherited the same green as the ticks and read as included.
      Recolour the cross - and dim its label - so exclusions look excluded.
   3. Card rows should stretch so neighbouring cards share a height rather
      than each ending at its own last line.
   ========================================================================== */

.elementor-element-7e27c84,
.elementor-element-04008dc,
.elementor-element-7d6cd33,
.elementor-element-e8311fd,
.elementor-element-4f390bb,
.elementor-element-f0f8476,
.elementor-element-08c6a2b {
  overflow: hidden;
}

/* --- excluded rows in the maintenance plan lists ------------------------- */
.elementor-24 .elementor-icon-list-icon .fa-times {
  color: var(--color-text-muted);
}
.elementor-24 .elementor-icon-list-item:has(.fa-times) .elementor-icon-list-text {
  color: var(--color-text-muted);
  text-decoration: line-through;
  text-decoration-color: var(--color-border-strong);
}

/* Neighbouring cards share a height via the container's own Align Items
   control in Elementor (stretch), not from here. */


/* ==========================================================================
   48. SERVICE DETAIL PAGES - two-column rows stack below desktop
   --------------------------------------------------------------------------
   Each of the seven pages uses the same three two-column rows the Services
   page does: 32/65 for the FAQ, 58/42 for the closing CTA card, and 52/44
   where prose sits beside a stat stack. Below 1024px those ratios stop
   working - the 42% CTA column is too narrow for a pair of buttons and they
   fold onto two lines. Same remedy and same breakpoint as block 41 uses for
   the Services page, extended to these rows. Elementor's own responsive
   controls cannot express it because the widths live on the children, not
   the row. The selectors are doubled with > .e-con-inner because some of
   these rows are boxed and some are full-width.
   ========================================================================== */
@media (max-width: 1024px) {
  .elementor-element-757ce0d,
  .elementor-element-fa368c7,
  .elementor-element-5877876,
  .elementor-element-c3fba21,
  .elementor-element-e39f9d5,
  .elementor-element-4ed9683,
  .elementor-element-a75a924,
  .elementor-element-e0a634c,
  .elementor-element-636aff4,
  .elementor-element-e011a9a,
  .elementor-element-be2eaf7,
  .elementor-element-428f081,
  .elementor-element-a975749,
  .elementor-element-8cfa640,
  .elementor-element-f30703a,
  .elementor-element-6c3b2a8,
  .elementor-element-e6196af {
    --flex-direction: column !important;
    --flex-wrap: nowrap !important;
    --align-items: flex-start !important;
    flex-direction: column !important;
    flex-wrap: nowrap !important;
    align-items: flex-start !important;
  }
  .elementor-element-757ce0d > .e-con-inner,
  .elementor-element-fa368c7 > .e-con-inner,
  .elementor-element-5877876 > .e-con-inner,
  .elementor-element-c3fba21 > .e-con-inner,
  .elementor-element-e39f9d5 > .e-con-inner,
  .elementor-element-4ed9683 > .e-con-inner,
  .elementor-element-a75a924 > .e-con-inner,
  .elementor-element-e0a634c > .e-con-inner,
  .elementor-element-636aff4 > .e-con-inner,
  .elementor-element-e011a9a > .e-con-inner,
  .elementor-element-be2eaf7 > .e-con-inner,
  .elementor-element-428f081 > .e-con-inner,
  .elementor-element-a975749 > .e-con-inner,
  .elementor-element-8cfa640 > .e-con-inner,
  .elementor-element-f30703a > .e-con-inner,
  .elementor-element-6c3b2a8 > .e-con-inner {
    flex-direction: column !important;
    flex-wrap: nowrap !important;
    align-items: flex-start !important;
  }
  .elementor-element-013dca3,
  .elementor-element-629489f,
  .elementor-element-9cd18a5,
  .elementor-element-204d49f,
  .elementor-element-72985b9,
  .elementor-element-e413d9f,
  .elementor-element-5f727c3,
  .elementor-element-46eb5d8,
  .elementor-element-99a8a71,
  .elementor-element-125bc6d,
  .elementor-element-7e0dcd7,
  .elementor-element-ecb97dc,
  .elementor-element-acd70c4,
  .elementor-element-9402ea0,
  .elementor-element-e17dcbf,
  .elementor-element-95790c3,
  .elementor-element-e3820fd,
  .elementor-element-753962f,
  .elementor-element-f92825f,
  .elementor-element-488248b,
  .elementor-element-9ae6b50,
  .elementor-element-8612b1a,
  .elementor-element-67b426f,
  .elementor-element-bd38025,
  .elementor-element-de17d24,
  .elementor-element-b643ace,
  .elementor-element-0d6708d,
  .elementor-element-8e24bb4,
  .elementor-element-79afd5a,
  .elementor-element-ec51900,
  .elementor-element-7082daf,
  .elementor-element-766fe3a,
  .elementor-element-1b1d371,
  .elementor-element-0166706 {
    --width: 100% !important;
    width: 100% !important;
    --padding-right: 0px !important;
  }

  /* the button row keeps the justify-content it needed while it sat in a 42%
     column on the right of the card. Once the card is stacked the row is full
     width, so that value pushes the pair to the right edge under left-aligned
     copy - pull them back to the text's left edge. */
  .elementor-element-95790c3,
  .elementor-element-753962f,
  .elementor-element-488248b,
  .elementor-element-8612b1a,
  .elementor-element-bd38025,
  .elementor-element-b643ace,
  .elementor-element-3a008bb,
  .elementor-element-51d3636,
  .elementor-element-123080b,
  .elementor-element-71e88f9,
  .elementor-element-6bd96c0,
  .elementor-element-a08a21f,
  .elementor-element-d571b5b,
  .elementor-element-0166706 {   /* portfolio - CTA */
    --justify-content: flex-start !important;
    justify-content: flex-start !important;
  }
}


/* ==========================================================================
   49. SERVICE DETAIL PAGES - the hero breadcrumb stays on one line
   --------------------------------------------------------------------------
   The three parts are three separate text-editor widgets, and their markup
   had drifted apart: the back-link sat in a flush <p>, the separator in a
   bare <p> carrying the theme's paragraph margin, and the service name was
   sometimes a bare <span> and sometimes wrapped in its own <p>. Three
   different box heights meant align-items:center had three different things
   to centre, so the parts sat at up to three different baselines and the row
   grew to 82px on some pages. The markup is now identical on all seven; this
   block removes what is left - inherited paragraph margins and line-height -
   and pins the row to a single line.

   Below 480px the longest name ("WordPress SEO Optimization") plus the
   back-link no longer fits at 13px inside a 320px viewport, so the whole
   crumb steps down one notch rather than folding.
   ========================================================================== */
.elementor-element-cca353b,
.elementor-element-c6a26bb,
.elementor-element-2f903f5,
.elementor-element-106e8aa,
.elementor-element-e4e16d5,
.elementor-element-dcc703c,
.elementor-element-efd302d,
.fbh-crumb {
  --flex-wrap: nowrap;
  --align-items: center;
  flex-wrap: nowrap;
  align-items: center;
}
.elementor-element-cca353b > .elementor-widget,
.elementor-element-c6a26bb > .elementor-widget,
.elementor-element-2f903f5 > .elementor-widget,
.elementor-element-106e8aa > .elementor-widget,
.elementor-element-e4e16d5 > .elementor-widget,
.elementor-element-dcc703c > .elementor-widget,
.elementor-element-efd302d > .elementor-widget,
.fbh-crumb > .elementor-widget {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  margin-bottom: 0;
}
.elementor-element-cca353b .elementor-widget-container,
.elementor-element-c6a26bb .elementor-widget-container,
.elementor-element-2f903f5 .elementor-widget-container,
.elementor-element-106e8aa .elementor-widget-container,
.elementor-element-e4e16d5 .elementor-widget-container,
.elementor-element-dcc703c .elementor-widget-container,
.elementor-element-efd302d .elementor-widget-container,
.elementor-element-cca353b p,
.elementor-element-c6a26bb p,
.elementor-element-2f903f5 p,
.elementor-element-106e8aa p,
.elementor-element-e4e16d5 p,
.elementor-element-dcc703c p,
.elementor-element-efd302d p,
.fbh-crumb .elementor-widget-container,
.fbh-crumb p {
  margin: 0;
  line-height: 1;
}
.fbh-crumb .fbh-back-link,
.fbh-crumb .fbh-crumb-sep,
.fbh-crumb .fbh-pill {
  white-space: nowrap;
  line-height: 1.5;
}

@media (max-width: 480px) {
  .fbh-crumb .fbh-back-link.fbh-back-link,
  .fbh-crumb .fbh-crumb-sep,
  .fbh-crumb .fbh-pill {
    font-size: 12px;
  }
  .fbh-crumb .fbh-pill {
    padding: 3px 8px;
  }
  .fbh-crumb {
    --gap: 8px 8px;
    --column-gap: 8px;
  }
}


/* ==========================================================================
   50. PORTFOLIO - project grid  (/projects/)
   ---------------------------------------------------------------------------
   The grid is printed by the [fbh_portfolio_grid] shortcode in
   mu-plugins/fbh-projects-cpt.php. It used to carry its own <style> block
   with hardcoded values - a 16px radius, a 20px title, a 10px pill built out
   of color-mix() - so it drifted away from the homepage project cards even
   though it shows the same six projects. All of that lives here now and
   reuses the pieces the homepage already uses: .fbh-tag for the tech chips
   and .fbh-case-link for the "View Case Study" line.

   The card is a <div>, not an <a>: the homepage pattern has a linked title
   plus a separate case-study link, and nesting those inside an <a> would be
   invalid markup. The title's ::after stretches over the card instead, so
   the whole tile is still a single click target.
   ========================================================================== */
.fbh-pgrid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px;
}
.fbh-pgrid-empty {
  color: var(--color-text-muted);
}

.fbh-pgrid-card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  overflow: hidden;
  transition: border-color var(--duration-fast) var(--ease-out),
              transform var(--duration-fast) var(--ease-out);
}
.fbh-pgrid-card:hover {
  border-color: var(--color-border-strong);
  transform: translateY(-2px);
}

.fbh-pgrid-thumb {
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--color-bg-soft);
}
.fbh-pgrid-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.fbh-pgrid-body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  padding: 24px;
}

/* Title Case, not uppercase - the service names are long enough that
   shouting them competes with the project title underneath. */
.fbh-pgrid-eyebrow {
  font-family: var(--font-sans);
  font-size: 12px;
  line-height: 20px;
  font-weight: 600;
  letter-spacing: normal;
  text-transform: capitalize;
  color: var(--color-primary);
}

a.fbh-pgrid-eyebrow {
  position: relative;
  z-index: 1;
  text-decoration: none;
  transition: color var(--duration-fast) var(--ease-out);
}
a.fbh-pgrid-eyebrow:hover {
  color: var(--color-primary-hover);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.fbh-pgrid-title {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 18px;
  line-height: 1.3;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--color-text-primary);
}
.fbh-pgrid-title a {
  color: inherit;
  text-decoration: none;
  transition: color var(--duration-fast) var(--ease-out);
}
/* stretch the title link over the whole card so the tile is one click target */
.fbh-pgrid-title a::after {
  content: "";
  position: absolute;
  inset: 0;
}
.fbh-pgrid-card:hover .fbh-pgrid-title a {
  color: var(--color-primary);
}

.fbh-pgrid-location {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: -4px;
  font-family: var(--font-sans);
  font-size: 13px;
  line-height: 1.5;
  font-weight: 400;
  color: var(--color-text-muted);
}
.fbh-pgrid-location::before {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--color-primary);
  flex: 0 0 auto;
}

.fbh-pgrid-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* the "View Case Study" line is a <span>, not a link - the stretched title
   link already covers it - so give it the motion .fbh-case-link gets on
   :hover from its own hover state, driven by the card instead. */
.fbh-pgrid-more {
  margin-top: 2px;
}
.fbh-pgrid-card:hover .fbh-pgrid-more {
  color: var(--color-primary-hover);
  gap: 10px;
}
.fbh-pgrid-card:hover .fbh-pgrid-more .fbh-case-arrow {
  transform: translateX(3px);
}

/* --- two-up on tablet, one-up on phones --------------------------------- */
@media (max-width: 1024px) {
  .fbh-pgrid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 767px) {
  .fbh-pgrid {
    grid-template-columns: minmax(0, 1fr);
    gap: 20px;
  }
  .fbh-pgrid-body {
    padding: 20px;
  }
}


/* ==========================================================================
   52. FOOTER - compact search field
   --------------------------------------------------------------------------
   The search results page had no entry point anywhere on the site, so it was
   only reachable by typing ?s= by hand. This sits in the footer's bottom bar,
   It sits at the bottom of the footer's Contact column, after the email /
   WhatsApp / message links, so nothing above it shifts.
   To remove it: delete the fbhftsrch widget from the footer template, or
   restore post 40's _fbh_revert_footer_before_search meta value.
   ========================================================================== */
.fbh-footer-search {
  display: flex;
  align-items: center;
  gap: 6px;
  background: var(--color-bg-soft);
  border: 1px solid var(--color-border);
  border-radius: 8px;
  padding: 2px 4px 2px 10px;
  transition: border-color var(--duration-fast) var(--ease-out);
}
.fbh-footer-search:focus-within {
  border-color: var(--color-primary);
}
.fbh-footer-search input[type="search"] {
  font-family: var(--font-sans);
  font-size: 13px;
  line-height: 1.4;
  color: var(--color-text-primary);
  background: transparent;
  border: 0;
  outline: none;
  width: 130px;
  padding: 6px 0;
  -webkit-appearance: none;
  appearance: none;
}
.fbh-footer-search input[type="search"]::placeholder {
  color: var(--color-text-muted);
}
.fbh-footer-search input[type="search"]::-webkit-search-cancel-button {
  -webkit-appearance: none;
}
.fbh-footer-search button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  flex: 0 0 auto;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--color-text-muted);
  cursor: pointer;
  padding: 0;
  transition: background-color var(--duration-fast) var(--ease-out),
              color var(--duration-fast) var(--ease-out);
}
.fbh-footer-search button:hover {
  background: var(--color-primary);
  color: var(--color-text-on-brand);
}

/* the bottom bar stacks on phones - let the field take the full width there */
/* it now sits at the bottom of the Contact column, so it takes the column's
   width rather than a fixed one */
.fbh-footer-search {
  width: 100%;
  max-width: 260px;
  margin-top: 4px;
}
.fbh-footer-search input[type="search"] {
  width: 100%;
  min-width: 0;
}

@media (max-width: 767px) {
  .fbh-footer-search {
    max-width: 320px;
  }
}


/* ==========================================================================
   53. MOBILE POLISH - breadcrumb overflow, card buttons, button padding
   --------------------------------------------------------------------------
   a) .fbh-proj-crumb was flex-wrap:nowrap with white-space:nowrap on its
      links, so a long service name (Ajnad: "WordPress Development .
      Localization") pushed past the container edge instead of folding. What
      that looked like on a phone was a breadcrumb with no padding on the
      right. Letting it wrap below 600px keeps the hero padding intact.

   b) A portfolio card is a <div> whose title link is stretched over the whole
      card via ::after. That made every tap - including one on "View Case
      Study" - register on the title. The affordance is now a real <a> to the
      same URL, lifted above the overlay, so the press and hover state land on
      the control the visitor actually tapped.

   c) Buttons get a little more room left and right on phones. The pair of
      buttons in the CTA rows must stay on one line, so the wrap is pinned off
      for any container holding two buttons - down to 361px, below which a
      fold is the lesser evil.
   ========================================================================== */

/* a */
@media (max-width: 600px) {
  .fbh-proj-crumb {
    flex-wrap: wrap;
    row-gap: 6px;
  }
  .fbh-proj-crumb a,
  .fbh-proj-crumb .fbh-badge {
    white-space: normal;
  }
}

/* b */
.fbh-pgrid-card .fbh-pgrid-more {
  position: relative;
  z-index: 2;
}

/* c */
@media (max-width: 767px) {
  .elementor-widget-button .elementor-button.elementor-button.elementor-button {
    padding-left: 22px;
    padding-right: 22px;
    white-space: nowrap;
  }
}
@media (max-width: 767px) and (min-width: 361px) {
  .e-con:has(> .elementor-widget-button + .elementor-widget-button),
  .e-con-inner:has(> .elementor-widget-button + .elementor-widget-button) {
    --flex-wrap: nowrap;
    flex-wrap: nowrap;
  }
}
@media (max-width: 480px) {
  .elementor-widget-button .elementor-button.elementor-button.elementor-button {
    padding-left: 16px;
    padding-right: 16px;
  }
}
@media (max-width: 380px) {
  .elementor-widget-button .elementor-button.elementor-button.elementor-button {
    padding-left: 13px;
    padding-right: 13px;
    font-size: 13px;
  }
}
