/* ==========================================================================
   Eco Bonheur - design system for WordPress
   --------------------------------------------------------------------------
   Source of truth: html/assets/css/ in the project repository.

   This file carries ONLY what Elementor cannot express natively:

     1. @font-face   subsetting and variable weight ranges, which Elementor
                     Custom Fonts cannot describe.
     2. Tokens       the custom properties every other layer reads.
     3. Surfaces     .surface-* reassigns text, border, link and focus colour
                     as one measured-accessible set. Reproducing that with
                     Elementor widget settings would take six separate controls
                     per section and drift the moment one was missed.

   Everything else - buttons, forms, cards, accordions, containers, grid,
   spacing, the type scale - is native Elementor, driven by Global Colours and
   Global Typography. Do not add a rule here for anything a native control
   already exposes.

   Enqueued from inc/eco-bonheur.php, after elementor-frontend.
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. FONTS - self-hosted variable WOFF2, latin + latin-ext.
   Latin critical path is 62 KB for both families.
   Paths are relative to this file: assets/css/ -> ../../fonts/
   -------------------------------------------------------------------------- */

@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../../fonts/archivo-latin-roman.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../../fonts/archivo-latin-ext-roman.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Archivo";
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url("../../fonts/archivo-latin-italic.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Archivo";
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url("../../fonts/archivo-latin-ext-italic.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Source Sans 3";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../../fonts/sourcesans3-latin-roman.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Source Sans 3";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../../fonts/sourcesans3-latin-ext-roman.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Source Sans 3";
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url("../../fonts/sourcesans3-latin-italic.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Source Sans 3";
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url("../../fonts/sourcesans3-latin-ext-italic.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --------------------------------------------------------------------------
   2-3. TOKENS AND SURFACES - carried verbatim from tokens.css
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   1. PRIMITIVES
   -------------------------------------------------------------------------- */

:root {
  /* Brand blue - sampled from the existing logo asset.
     Logo-Bleu-125x50.png is a single flat colour: #246DB1. Do not alter. */
  --eb-blue-50:  #ECF4FB;
  --eb-blue-100: #D5E6F6;
  --eb-blue-200: #AACDEE;
  --eb-blue-300: #6FAAE2;
  --eb-blue-400: #3487D6;
  --eb-blue-500: #246DB1; /* ← the logo blue. The brand anchor. */
  --eb-blue-600: #1F5D96;
  --eb-blue-700: #184977;
  --eb-blue-800: #123759;
  --eb-blue-900: #10283F;

  /* Blue tuned for text on light surfaces (AA at body size on white, ivory
     AND sand - the raw logo blue fails on sand at 4.11:1). */
  --eb-blue-ink:        #2266A6;
  --eb-blue-ink-strong: #184876;

  /* Ocean & stone */
  --eb-navy:      #102F43;
  --eb-navy-deep: #0B2231;
  --eb-mineral:      #4E8098; /* decorative only - see README */
  --eb-mineral-ink:  #40697D; /* the text-safe mineral */
  --eb-mineral-soft: #E6EDF1;

  /* Vegetation */
  --eb-sage:      #8FAF9A;    /* decorative only */
  --eb-sage-soft: #E3EBE5;
  --eb-olive:      #68795A;
  --eb-olive-ink:  #59674D;   /* the text-safe olive */
  --eb-olive-soft: #EFF3EC;

  /* Sand, ivory, architecture */
  --eb-sand:      #E8E0D1;
  --eb-sand-deep: #DBD1BC;
  --eb-ivory:     #F7F5EF;
  --eb-white:     #FFFFFF;

  /* Ink & stone neutrals (warm, never pure grey) */
  --eb-charcoal:  #27302D;
  --eb-graphite:  #5C6663;   /* secondary text - AA on white, ivory, sand */
  --eb-stone-100: #E4E0D5;   /* hairline on ivory */
  --eb-stone-200: #D5D0C2;   /* standard border */
  --eb-stone-400: #8E8A80;   /* form-control border - 3.44:1 on white */

  /* Feedback - kept natural, never candy */
  --eb-success-ink:     #2C6A4B;
  --eb-success-surface: #EAF2ED;
  --eb-success-border:  #BCD4C6;
  --eb-warning-ink:     #7E5510;
  --eb-warning-surface: #FBF1DF;
  --eb-warning-border:  #E4D0A6;
  --eb-error-ink:       #9E3327;
  --eb-error-surface:   #FBEDEA;
  --eb-error-border:    #E7C3BC;
  --eb-info-ink:        #2266A6;
  --eb-info-surface:    #E9F1F8;
  --eb-info-border:     #C2D8EA;

  /* Shadow base - navy-tinted, never black */
  --eb-shadow-rgb: 16 47 67;
}

/* --------------------------------------------------------------------------
   2. SEMANTIC COLOUR - default (warm ivory) environment
   -------------------------------------------------------------------------- */

:root {
  --color-brand:        var(--eb-blue-500);
  --color-brand-hover:  var(--eb-blue-600);
  --color-brand-active: var(--eb-blue-700);
  --color-brand-ink:    var(--eb-blue-ink);

  --color-text:           var(--eb-charcoal);
  --color-text-secondary: var(--eb-graphite);
  --color-text-inverse:   var(--eb-ivory);

  --color-surface:       var(--eb-white);
  --color-surface-page:  var(--eb-ivory);
  --color-surface-sunken: var(--eb-ivory);

  --color-border-subtle: var(--eb-stone-100);
  --color-border:        var(--eb-stone-200);
  --color-border-strong: var(--eb-stone-400);

  --color-link:        var(--eb-blue-ink);
  --color-link-hover:  var(--eb-blue-700);

  --color-focus-ring:  var(--eb-blue-600);
  --color-focus-halo:  var(--eb-white);

  /* Sustainability accent. Only ever this token - never a stray green. */
  --color-eco:      var(--eb-olive-ink);
  --color-eco-soft: var(--eb-olive-soft);

  /* Section accent. Overridden per service family (see §3). */
  --color-accent:      var(--eb-blue-ink);
  --color-accent-soft: var(--eb-blue-50);

  --color-success: var(--eb-success-ink);
  --color-warning: var(--eb-warning-ink);
  --color-error:   var(--eb-error-ink);
  --color-info:    var(--eb-info-ink);

  /* Button colours - resolved per surface so a button is always legible
     against whatever it sits on. */
  --btn-primary-bg:          var(--eb-blue-500);
  --btn-primary-bg-hover:    var(--eb-blue-600);
  --btn-primary-bg-active:   var(--eb-blue-700);
  --btn-primary-text:        var(--eb-white);
  --btn-secondary-text:      var(--eb-charcoal);
  --btn-secondary-border:    var(--eb-stone-400);
  --btn-secondary-bg-hover:  var(--eb-white);
}

/* --------------------------------------------------------------------------
   3. SURFACES
   Apply to a <section> (or any block). Sets background AND every colour that
   depends on it, including `color` itself.
   -------------------------------------------------------------------------- */

.surface-page,
.surface-white,
.surface-sand,
.surface-mist,
.surface-eco,
.surface-navy,
.surface-brand {
  background-color: var(--surface-bg);
  color: var(--color-text);
}

/* Warm ivory - the default environment for most of the site. */
.surface-page {
  --surface-bg: var(--eb-ivory);
  --color-surface: var(--eb-white);
  --color-border-subtle: var(--eb-stone-100);
  --color-border: var(--eb-stone-200);
}

/* White - for long-form reading and dense content. */
.surface-white {
  --surface-bg: var(--eb-white);
  --color-surface: var(--eb-white);
  --color-surface-sunken: var(--eb-ivory);
  --color-border-subtle: #EDEAE1;
  --color-border: var(--eb-stone-200);
}

/* Sand - a warm band used to break rhythm. Note: the raw logo blue is NOT
   legible here at body size, so links and accents shift to the ink variants. */
.surface-sand {
  --surface-bg: var(--eb-sand);
  --color-surface: var(--eb-ivory);
  --color-border-subtle: #D6CCB6;
  --color-border: #CBBFA6;
  --color-border-strong: #9A8F76;
  --color-link: var(--eb-blue-ink);
  --color-accent: var(--eb-blue-ink);
  --color-accent-soft: var(--eb-ivory);
  --btn-secondary-border: #9A8F76;
  --btn-secondary-bg-hover: var(--eb-ivory);
}

/* Mist - pale mineral blue. Cleaning contexts. */
.surface-mist {
  --surface-bg: var(--eb-blue-50);
  --color-surface: var(--eb-white);
  --color-border-subtle: #DCE8F3;
  --color-border: #C8DAEB;
  --color-accent: var(--eb-mineral-ink);
  --color-accent-soft: var(--eb-white);
}

/* Eco - the sustainability environment. Olive on near-ivory, nothing louder. */
.surface-eco {
  --surface-bg: var(--eb-olive-soft);
  --color-surface: var(--eb-white);
  --color-border-subtle: #DFE6DA;
  --color-border: #CBD6C4;
  --color-accent: var(--eb-olive-ink);
  --color-accent-soft: var(--eb-white);
}

/* Deep navy - footer and high-impact moments.
   The primary button inverts to ivory here: a brand-blue fill on navy has only
   2.58:1 separation from its background and would read as a smudge. */
.surface-navy {
  --surface-bg: var(--eb-navy);
  --color-text: var(--eb-ivory);
  --color-text-secondary: #B9C9D4;
  --color-surface: var(--eb-navy-deep);
  --color-surface-sunken: var(--eb-navy-deep);
  --color-border-subtle: rgb(255 255 255 / 0.10);
  --color-border: rgb(255 255 255 / 0.18);
  --color-border-strong: rgb(255 255 255 / 0.38);
  --color-link: #A9CBEA;
  --color-link-hover: var(--eb-white);
  --color-focus-ring: #A9CBEA;
  --color-focus-halo: var(--eb-navy);
  --color-accent: #8FAF9A;
  --color-accent-soft: rgb(255 255 255 / 0.08);
  --color-eco: #A8C4B2;

  --btn-primary-bg: var(--eb-ivory);
  --btn-primary-bg-hover: var(--eb-white);
  --btn-primary-bg-active: var(--eb-sand);
  --btn-primary-text: var(--eb-navy);
  --btn-secondary-text: var(--eb-ivory);
  --btn-secondary-border: rgb(255 255 255 / 0.45);
  --btn-secondary-bg-hover: rgb(255 255 255 / 0.10);
}

/* Brand blue - used once per page at most, for a single conversion moment.
   Only white and ivory clear AA here; there is no "muted" text on this
   surface, so hierarchy comes from size and weight instead. */
.surface-brand {
  --surface-bg: var(--eb-blue-500);
  --color-text: var(--eb-white);
  --color-text-secondary: var(--eb-ivory);
  --color-surface: var(--eb-blue-600);
  --color-border-subtle: rgb(255 255 255 / 0.16);
  --color-border: rgb(255 255 255 / 0.28);
  --color-border-strong: rgb(255 255 255 / 0.5);
  --color-link: var(--eb-white);
  --color-link-hover: var(--eb-white);
  --color-focus-ring: var(--eb-white);
  --color-focus-halo: var(--eb-blue-700);
  --color-accent: var(--eb-white);
  --color-accent-soft: rgb(255 255 255 / 0.12);
  --color-eco: var(--eb-white);

  --btn-primary-bg: var(--eb-white);
  --btn-primary-bg-hover: var(--eb-ivory);
  --btn-primary-bg-active: var(--eb-blue-50);
  --btn-primary-text: var(--eb-blue-700);
  --btn-secondary-text: var(--eb-white);
  --btn-secondary-border: rgb(255 255 255 / 0.55);
  --btn-secondary-bg-hover: rgb(255 255 255 / 0.12);
}

/* --------------------------------------------------------------------------
   4. SERVICE FAMILIES
   Three families, one design system. The distinction is deliberately faint:
   an eyebrow colour, a rule, an icon stroke. Never a different look.
   -------------------------------------------------------------------------- */

[data-family="cleaning"]     { --color-accent: var(--eb-mineral-ink); --color-accent-soft: var(--eb-blue-50); }
[data-family="maintenance"]  { --color-accent: var(--eb-blue-ink-strong); --color-accent-soft: var(--eb-sand); }
[data-family="property"]     { --color-accent: var(--eb-blue-ink); --color-accent-soft: var(--eb-ivory); }
[data-family="sustainability"] { --color-accent: var(--eb-olive-ink); --color-accent-soft: var(--eb-olive-soft); }

.surface-navy[data-family],
.surface-navy [data-family],
.surface-brand[data-family],
.surface-brand [data-family] {
  --color-accent: currentColor;
}

/* --------------------------------------------------------------------------
   5. TYPOGRAPHY
   -------------------------------------------------------------------------- */

:root {
  --font-display: "Archivo", "Helvetica Neue", Arial, sans-serif;
  --font-body: "Source Sans 3", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  --weight-regular:  400;
  --weight-medium:   500;
  --weight-semibold: 600;
  --weight-bold:     700;

  /* Fluid scale. Lower bound = 360px viewport, upper bound ≈ 1560px. */
  --text-display:  clamp(2.75rem, 2.10rem + 2.90vw, 5.00rem);   /*  44 → 80 */
  --text-h1:       clamp(2.25rem, 1.90rem + 1.55vw, 3.50rem);   /*  36 → 56 */
  --text-h2:       clamp(1.75rem, 1.55rem + 0.90vw, 2.50rem);   /*  28 → 40 */
  --text-h3:       clamp(1.375rem, 1.29rem + 0.38vw, 1.625rem); /*  22 → 26 */
  --text-h4:       clamp(1.125rem, 1.09rem + 0.17vw, 1.25rem);  /*  18 → 20 */
  --text-lead:     clamp(1.1875rem, 1.12rem + 0.34vw, 1.375rem);/*  19 → 22 */
  --text-body:     clamp(1.0625rem, 1.03rem + 0.16vw, 1.125rem);/*  17 → 18 */
  --text-small:    0.9375rem;                                   /*  15     */
  --text-caption:  0.8125rem;                                   /*  13     */
  --text-button:   1rem;                                        /*  16     */

  --leading-display: 1.02;
  --leading-h1:      1.08;
  --leading-h2:      1.15;
  --leading-h3:      1.25;
  --leading-h4:      1.35;
  --leading-lead:    1.5;
  --leading-body:    1.65;
  --leading-tight:   1.3;

  --tracking-display: -0.028em;
  --tracking-h1:      -0.022em;
  --tracking-h2:      -0.016em;
  --tracking-h3:      -0.010em;
  --tracking-normal:   0;
  --tracking-eyebrow:  0.10em;
  --tracking-button:   0.005em;

  /* Line length. Prose should never exceed --measure. */
  --measure:        68ch;
  --measure-narrow: 46ch;
  --measure-wide:   78ch;
}

/* --------------------------------------------------------------------------
   6. SPACE
   4px base. Section rhythm is fluid.
   -------------------------------------------------------------------------- */

:root {
  --space-3xs: 0.25rem;  /*   4 */
  --space-2xs: 0.5rem;   /*   8 */
  --space-xs:  0.75rem;  /*  12 */
  --space-sm:  1rem;     /*  16 */
  --space-md:  1.5rem;   /*  24 */
  --space-lg:  2rem;     /*  32 */
  --space-xl:  3rem;     /*  48 */
  --space-2xl: 4rem;     /*  64 */
  --space-3xl: 6rem;     /*  96 */
  --space-4xl: 8rem;     /* 128 */

  --section-y:       clamp(3.5rem, 2.40rem + 4.60vw, 7.50rem);  /* 56 → 120 */
  --section-y-tight: clamp(2.5rem, 1.90rem + 2.50vw, 4.50rem);  /* 40 →  72 */
  --section-y-loose: clamp(4.5rem, 3.00rem + 6.30vw, 10rem);    /* 72 → 160 */
}

/* --------------------------------------------------------------------------
   7. LAYOUT
   -------------------------------------------------------------------------- */

:root {
  --container-xs: 40rem;   /*  640 - long-form prose            */
  --container-sm: 52rem;   /*  832 - narrow editorial           */
  --container-md: 64rem;   /* 1024 - forms, focused content     */
  --container-lg: 75rem;   /* 1200 - the default                */
  --container-xl: 84rem;   /* 1344 - wide media compositions    */

  --gutter: clamp(1.25rem, 0.90rem + 1.50vw, 2.5rem); /* 20 → 40 */
  --grid-gap: clamp(1.25rem, 1.00rem + 1.20vw, 2rem); /* 20 → 32 */
  --grid-gap-row: clamp(2rem, 1.60rem + 1.80vw, 3.5rem);

  /* Breakpoints are documented here for reference; media queries must state
     the value literally because custom properties are not valid in @media. */
  --bp-xs:  30em;   /*  480 */
  --bp-sm:  40em;   /*  640 */
  --bp-md:  48em;   /*  768 */
  --bp-lg:  64em;   /* 1024 */
  --bp-xl:  80em;   /* 1280 */
  --bp-2xl: 90em;   /* 1440 */

  --header-height: 4.5rem;
}

@media (min-width: 64em) {
  :root { --header-height: 5.5rem; }
}

/* --------------------------------------------------------------------------
   8. BORDERS, RADII, ELEVATION
   -------------------------------------------------------------------------- */

:root {
  --border-hairline: 1px;
  --border-thick: 2px;

  /* Directional arrow, used as a mask so its colour stays tokenised.
     Same path as the prototype's inline SVG. */
  --eb-arrow-right: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E");
  --border-rule: 3px;      /* accent rules above headings */

  --radius-xs: 2px;
  --radius-sm: 3px;
  --radius-md: 4px;   /* buttons, inputs - slightly rounded, never a pill */
  --radius-lg: 8px;   /* cards, media */
  --radius-xl: 12px;  /* large media only */
  --radius-pill: 999px; /* tags and status chips only */

  --shadow-xs: 0 1px 2px rgb(var(--eb-shadow-rgb) / 0.06);
  --shadow-sm: 0 1px 3px rgb(var(--eb-shadow-rgb) / 0.07),
               0 1px 2px rgb(var(--eb-shadow-rgb) / 0.04);
  --shadow-md: 0 4px 14px rgb(var(--eb-shadow-rgb) / 0.08);
  --shadow-lg: 0 14px 36px rgb(var(--eb-shadow-rgb) / 0.12);

  --focus-width: 3px;
  --focus-offset: 2px;
}

/* --------------------------------------------------------------------------
   9. MOTION
   Motion confirms an action or eases a change of state. Nothing decorative.
   -------------------------------------------------------------------------- */

:root {
  /* Stronger than the CSS built-ins, which are too weak to read as
     intentional. ease-in is never used: it delays the first few frames, which
     is exactly when the user is watching. */
  --ease-out:    cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);

  --dur-press:  140ms;  /* press feedback             */
  --dur-fast:   120ms;  /* colour, opacity, borders   */
  --dur-base:   200ms;  /* buttons, links, hovers     */
  --dur-slow:   300ms;  /* disclosure, mobile nav     */
  --dur-exit:   180ms;  /* exits are faster than entrances */
  --dur-reveal: 560ms;  /* content entrance, once     */

  --lift: -2px;        /* the only translate a hover may use */
  --press: 0.985;      /* the only scale a press may use     */
  --image-zoom: 1.03;  /* the only scale a hover may use     */
}

/* Reduced motion keeps opacity and colour, which aid comprehension, and drops
   everything that moves. It is fewer and gentler, not zero. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-press: 1ms;
    --dur-slow: 1ms;
    --dur-exit: 1ms;
    --dur-reveal: 1ms;
    --lift: 0px;
    --press: 1;
    --image-zoom: 1;
  }
}

/* --------------------------------------------------------------------------
   10. Z-INDEX
   -------------------------------------------------------------------------- */

:root {
  --z-base: 1;
  --z-sticky: 100;
  --z-header: 200;
  --z-dropdown: 300;
  --z-drawer: 400;
  --z-skip-link: 500;
}


/* --------------------------------------------------------------------------
   4. SITE HEADER
   Built as Elementor containers and widgets. Only the rules below are here,
   because each one reaches something no widget control exposes:
   descendant links inside a Text Editor, and a 44px tap target on a phone
   number set in caption-sized type.
   -------------------------------------------------------------------------- */

.eb-header-utility { font-size: var(--text-caption); }

/* The phone number is one of the most-tapped things on the site. It gets a
   full 44px target even though the type is deliberately small. */
.eb-header-utility a[href^="tel:"] {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* The Text Editor wraps content in <p>; the strip is a single line. */
.eb-header-utility p { margin: 0; }

.eb-header-bar-outer {
  background-color: var(--color-surface-page);
  border-bottom: var(--border-hairline) solid var(--color-border-subtle);
}

/* Elementor ships `.elementor-widget-image a img[src$=".svg"] { width: 48px }`
   for linked SVGs, at a higher specificity than a plain class selector. The
   logo is a theme-served SVG inside a link, so it needs to outrank that rule
   rather than merely restate a width. */
/* The logo must hold its width rather than be squeezed by the nav and CTA
   beside it; without this, max-width:100% resolves against a shrinking flex
   item and the mark quietly gets smaller as the viewport narrows. */
.eb-header-logo { flex-shrink: 0; }

.eb-header-logo a { display: block; width: 176px; max-width: 100%; }

/* Below 480 the bar carries the logo and the menu toggle only - the quote
   button is hidden there, as in the prototype - so the mark comes down to keep
   the row on one line. */
@media (max-width: 479px) {
  .eb-header-logo a { width: 140px; }
}

.eb-header-logo.elementor-widget-image a img[src$=".svg"],
.eb-header-logo img {
  width: 100%;
  height: auto;
}


/* --------------------------------------------------------------------------
   5. SURFACES AND LINKS

   The surface classes above already reassign --color-link for each background.
   This rule is what makes Elementor honour them.

   Elementor's kit styles anchors with `.elementor-kit-12 a`, a direct type
   selector, which beats the colour a surface passes down by inheritance. On
   .surface-navy that would put brand-ink links on navy - a contrast failure,
   and exactly the drift the surface system exists to prevent. Scoping under
   .elementor raises specificity above the kit rule without touching any
   individual widget.
   -------------------------------------------------------------------------- */

.elementor [class*="surface-"] a { color: var(--color-link); }
.elementor [class*="surface-"] a:hover { color: var(--color-link-hover); }

/* Buttons carry their own colours and must not inherit the link colour. */
.elementor [class*="surface-"] .elementor-button { color: inherit; }

/* Block-level links.

   Some components make an entire container the anchor - a ledger row, a
   service row, a sidebar sibling. Those are not text links: colouring them
   like one turns a whole block of copy blue. They take the surface's text
   colour and signal interactivity through their own hover treatment instead.

   Listed explicitly rather than matched by pattern, so adding a new one is a
   deliberate act. Specificity (0,3,0) clears the link rule above at (0,2,1). */
.elementor [class*="surface-"] .eb-ledger-row,
.elementor [class*="surface-"] .eb-service-link,
.elementor [class*="surface-"] .eb-sibling-link {
  color: var(--color-text);
}

/* Elementor binds each text widget's DEFAULT colour to a global - for example
   `.elementor-widget-text-editor { color: var(--e-global-color-text) }`. That
   is set on the widget itself, so it defeats the colour a surface passes down
   by inheritance, and text on a dark surface renders in the light-surface ink.
   Letting these widgets inherit inside a surface restores the intended
   behaviour without touching a single widget's own settings. */
/* :where() keeps this at (0,2,0) - high enough to beat Elementor's own
   (0,1,0) widget default, low enough that any component rule below can still
   override it. Written without :where() it was (0,4,0) and quietly overrode
   every component that tried to set its own colour on a surface. This rule is
   a floor, not a ceiling. */
.elementor [class*="surface-"] :where(
  .elementor-widget-text-editor,
  .elementor-widget-heading .elementor-heading-title,
  .elementor-widget-icon-list .elementor-icon-list-text
) {
  color: inherit;
}


/* --------------------------------------------------------------------------
   6. SITE FOOTER
   Built as Elementor containers. On a surface section, colour comes from the
   surface; everything else comes from Elementor controls.
   -------------------------------------------------------------------------- */

.eb-footer p { margin: 0; }

/* Column labels. Typography is the Eyebrow global, set on the widget; only the
   colour is here, because it has to follow the surface rather than a fixed
   global. */
/* These must outrank the surface widget rule in section 5, which is (0,3,0).
   Scoping through .surface-navy matches that weight, and this block sits later
   in the file, so the intended muted tone wins deterministically rather than by
   luck. Without it every line here flattens to full-strength ivory and the
   links stop standing out. */
.eb-footer.surface-navy .eb-footer-heading,
.eb-footer.surface-navy .eb-footer-blurb,
.eb-footer.surface-navy .eb-footer-note,
.eb-footer.surface-navy .eb-footer-address,
.eb-footer.surface-navy .eb-footer-colophon {
  color: var(--color-text-secondary);
}

.eb-footer .eb-footer-blurb { max-width: 32ch; }

.eb-footer .eb-footer-logo img { width: 160px; height: auto; max-width: 100%; }

/* Footer links: a full 44px target at small type, and an underline that only
   appears on hover. The Nav Menu widget cannot express the tap target and the
   surface-aware colour together. */
.eb-footer .eb-footer-menu .elementor-item,
.eb-footer .eb-footer-legal .elementor-item,
.eb-footer .eb-footer-contact a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: var(--text-small);
  color: var(--color-text);
  text-decoration: none;
  border-bottom: var(--border-hairline) solid transparent;
  transition: color var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out);
}

.eb-footer .eb-footer-menu .elementor-item:hover,
.eb-footer .eb-footer-legal .elementor-item:hover,
.eb-footer .eb-footer-contact a:hover {
  color: var(--color-link-hover);
  border-bottom-color: currentColor;
}

/* The nav widget adds its own vertical padding; the 44px target replaces it. */
.eb-footer .eb-footer-menu .elementor-nav-menu--main .elementor-item { padding: 0; }

.eb-footer .eb-footer-bottom {
  border-top: var(--border-hairline) solid var(--color-border-subtle);
  font-size: var(--text-caption);
}

.eb-footer .eb-footer-legal .elementor-nav-menu { gap: var(--space-md); }


/* --------------------------------------------------------------------------
   7. SERVICE LINK - the Loop Item used by every service listing.

   The design system's rule for listing services: "a rule, a title, a line of
   copy. No card, no shadow, no box." Elementor supplies the structure and the
   type; the parts below are the ones no widget control reaches - a hairline
   that belongs to the row, a sweeping accent rule drawn with a pseudo-element,
   and a directional arrow appended to the title.
   -------------------------------------------------------------------------- */

.eb-service-link {
  position: relative;
  border-top: var(--border-hairline) solid var(--color-border);
  text-decoration: none;
  color: inherit;
}

/* The sweeping rule.

   The prototype animated `width` from 0 to 100%, which the design phase
   recorded as a known inefficiency (site.css:292): width is a layout property,
   so every frame costs a reflow. scaleX with a left origin is compositor-only
   and visually identical. Applied here rather than carried forward. */
.eb-service-link::before {
  content: "";
  position: absolute;
  top: calc(var(--border-hairline) * -1);
  left: 0;
  width: 100%;
  height: var(--border-thick);
  background-color: var(--color-accent);
  transform: scaleX(0);
  transform-origin: left center;
}

/* Decorative hover, gated so it cannot stick on touch - a named rule of the
   design system. */
@media (hover: hover) and (pointer: fine) {
  .eb-service-link:hover::before { transform: scaleX(1); }
  .eb-service-link:hover .eb-service-link-title .elementor-heading-title { color: var(--color-link); }
  .eb-service-link:hover .eb-service-link-title .elementor-heading-title::after { translate: 4px 0; }
}

@media (prefers-reduced-motion: no-preference) {
  .eb-service-link::before { transition: transform var(--dur-slow) var(--ease-out); }
  .eb-service-link-title .elementor-heading-title {
    transition: color var(--dur-base) var(--ease-out);
  }
  .eb-service-link-title .elementor-heading-title::after {
    transition: translate var(--dur-base) var(--ease-out);
  }
}

/* Title, with the arrow pushed to the far edge. */
.eb-service-link-title .elementor-heading-title {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-sm);
  color: var(--color-text);
}

/* The arrow is masked rather than embedded as a coloured SVG, so its colour
   still comes from --color-accent and follows whatever surface it sits on. */
.eb-service-link-title .elementor-heading-title::after {
  content: "";
  flex: none;
  width: 0.85em;
  height: 0.85em;
  align-self: center;
  background-color: var(--color-accent);
  -webkit-mask: var(--eb-arrow-right) center / contain no-repeat;
          mask: var(--eb-arrow-right) center / contain no-repeat;
}

.eb-service-link .eb-service-link-desc {
  color: var(--color-text-secondary);
  max-width: 48ch;
}

/* The list closes with a hairline under the final row. */
.elementor-loop-container > *:last-child .eb-service-link {
  border-bottom: var(--border-hairline) solid var(--color-border);
}


/* --------------------------------------------------------------------------
   8. SINGLE — SERVICE
   Theme Builder template for the 21 service pages (children of the three
   hubs). Elementor supplies the containers, the dynamic bindings and the type;
   the rules below are the parts it cannot express.
   -------------------------------------------------------------------------- */

/* Breadcrumbs. Elementor Pro's own Breadcrumbs widget delegates to Yoast SEO,
   which is not installed, so the trail is a shortcode reading the page tree.
   The separator is a rotated border rather than a glyph, so it never gets read
   aloud or copied with the text. */
.eb-breadcrumbs {
  font-size: var(--text-caption);
  color: var(--color-text-secondary);
}

.eb-breadcrumbs ol {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.eb-breadcrumbs li { display: flex; align-items: center; gap: 0.35rem; }

.eb-breadcrumbs li + li::before {
  content: "";
  width: 5px;
  height: 5px;
  border-right: 1.5px solid currentColor;
  border-top: 1.5px solid currentColor;
  rotate: 45deg;
  opacity: 0.6;
}

.eb-breadcrumbs a {
  color: inherit;
  text-decoration-color: color-mix(in srgb, currentColor 30%, transparent);
}

.eb-breadcrumbs a:hover { color: var(--color-link); }

.eb-breadcrumbs [aria-current="page"] {
  color: var(--color-text);
  font-weight: var(--weight-semibold);
}

/* The page title is set tighter than the H1 global: a service name is short,
   and at this size the standard heading leading opens too much air. */
.eb-page-head-title .elementor-heading-title {
  font-size: clamp(2.25rem, 1.75rem + 2.2vw, 3.5rem);
  line-height: 1.06;
  max-width: 16ch;
}

.eb-page-head-lead { color: var(--color-text-secondary); }

/* Title and lead sit side by side only where there is room for both to keep
   their measure; below that they stack. */
.eb-page-head-grid > * { width: 100%; }

@media (min-width: 64em) {
  .eb-page-head-grid > *:first-child { width: 52%; }
  .eb-page-head-grid > *:last-child  { width: 40%; }
}

/* The sidebar tracks the reader down long service copy. Offset by the header
   so a sticky aside never slides under it. */
@media (min-width: 64em) {
  .eb-article-aside {
    position: sticky;
    top: calc(var(--header-height, 88px) + var(--space-md));
  }
}

.eb-aside-block {
  padding: var(--space-md);
  background-color: var(--color-surface);
  border: var(--border-hairline) solid var(--color-border-subtle);
  border-radius: var(--radius-md);
}

.eb-aside-title .elementor-heading-title { color: var(--color-text-secondary); }

/* Sibling services: a left rule that fills on hover, and a full 44px target
   even though the type is small. */
.eb-sibling-link {
  min-height: 44px;
  padding-left: var(--space-xs);
  border-left: var(--border-thick) solid transparent;
  text-decoration: none;
  justify-content: flex-start;
  align-items: center;
}

.eb-sibling-link .elementor-heading-title { color: var(--color-text); }

@media (hover: hover) and (pointer: fine) {
  .eb-sibling-link:hover { border-left-color: var(--color-border-strong); }
  .eb-sibling-link:hover .elementor-heading-title { color: var(--color-link); }
}

@media (prefers-reduced-motion: no-preference) {
  .eb-sibling-link,
  .eb-sibling-link .elementor-heading-title {
    transition: border-color var(--dur-base) var(--ease-out),
                color var(--dur-base) var(--ease-out);
  }
}

.eb-sibling-nav .elementor-loop-container { gap: var(--space-3xs); }

.eb-aside-contact p { margin: 0; }
.eb-aside-contact p + p {
  margin-top: var(--space-2xs);
  font-size: var(--text-small);
  color: var(--color-text-secondary);
}

/* Post content: constrain the measure so long copy stays readable. Elementor
   has no measure control - it sizes containers, not line length.

   This has to outrank Elementor's own
   `.elementor.elementor .e-con > .elementor-widget { max-width: 100% }`,
   which is (0,4,0) and was silently winning - the prose column ran to the full
   62% of the container, about 90 characters, instead of the 68 intended.
   Mirroring Elementor's selector shape and adding our class takes this to
   (0,5,0), so it wins on weight rather than on load order. */
.elementor.elementor .e-con > .elementor-widget.eb-prose-content {
  max-width: var(--measure);
}

/* Vertical rhythm. The parent theme resets `* { margin: 0 }` and Elementor's
   kit spacing only reaches widget output, so raw post content arrives with no
   margins at all - every heading sat flush against the paragraph above it.
   These are the prototype's .prose rules, which are the design system's
   answer and the reason a measure was set here in the first place. */

.eb-prose-content > * + * { margin-top: var(--space-md); }

.eb-prose-content h2 { margin-top: var(--space-xl); }
.eb-prose-content h3,
.eb-prose-content h4 { margin-top: var(--space-lg); }

.eb-prose-content h2 + *,
.eb-prose-content h3 + *,
.eb-prose-content h4 + * { margin-top: var(--space-sm); }

/* Lists inside post content. This is the only place on the site that renders
   prose lists - every other list is a widget - so the design system's list
   treatment lives with the prose rather than as a component. The marker is an
   accent dot, not the browser's disc. */

.eb-prose-content ul,
.eb-prose-content ol {
  display: grid;
  gap: var(--space-2xs);
  padding-left: var(--space-md);
  margin-bottom: 0;
}

/* The gap owns the rhythm, so the parent theme's `li { margin: .35em 0 }` has
   to go - left in, it stacks on top of the gap and doubles the spacing. */
.eb-prose-content li { margin: 0; }

.eb-prose-content ul > li {
  list-style: none;
  position: relative;
  padding-left: var(--space-sm);
}

.eb-prose-content ul > li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.72em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background-color: var(--color-accent);
}

.eb-prose-content ol { list-style: decimal; }


/* ==========================================================================
   9. HOME PAGE
   Sections are Elementor containers; the rules below are the compositions the
   blueprint named as justified custom CSS, plus the few properties no widget
   control exposes.
   ========================================================================== */

/* --------------------------------------------------------------------------
   HERO
   Elementor holds the background image so an editor can swap it. The crop and
   the scrims stay here: background-position only offers keyword presets, and
   the scrims are measured, not decorative.
   -------------------------------------------------------------------------- */

.eb-hero { position: relative; overflow: hidden; }

/* Art direction. At narrow widths a centre-right crop loses the working
   subject entirely and leaves a wall, so the frame moves left to keep the
   action in shot. Elementor's background-position control offers only keyword
   presets, which cannot express these measured values. */
.eb-hero { background-position: 34% 50%; }
@media (min-width: 48em) { .eb-hero { background-position: 50% 50%; } }
@media (min-width: 64em) { .eb-hero { background-position: 62% 50%; } }

/* Top scrim, for the header that sits over the photograph.
   The lower scrim protects the text block, but the header sits in the top band
   where that layer is weakest. Measured against this photograph, white nav text
   reached only 1.88:1 there. 55% navy over the top band brings the worst case
   under the luminance ceiling white text needs for AA, and fades out before it
   touches the composition. */
.eb-hero::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 16rem;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(to bottom,
    rgb(16 47 67 / 0.66) 0%,
    rgb(16 47 67 / 0.55) 55%,
    rgb(16 47 67 / 0) 100%);
}

/* Lower scrim, carrying the headline and lead. */
.eb-hero::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 70%;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(to top,
    rgb(16 47 67 / 0.82) 0%,
    rgb(16 47 67 / 0.55) 45%,
    rgb(16 47 67 / 0) 100%);
}

/* Content sits above both scrims. The hero's child is a boxed container,
   which Elementor renders as `.e-con` - not `.e-con-inner`, which is the
   wrapper *inside* it. Targeting the wrong one leaves the whole hero sitting
   under the scrim and everything reads washed out. */
.eb-hero > .e-con { position: relative; z-index: 2; }

.eb-hero-content { max-width: 40rem; }
.eb-hero-title .elementor-heading-title { max-width: 22ch; }
.eb-hero-lead { max-width: 46ch; }

/* --------------------------------------------------------------------------
   SECONDARY BUTTON
   Elementor ships one button style; the design system has two. The outline
   variant reads its colours from the surface, so it inverts correctly on the
   navy hero and the navy CTA band without a second set of settings.
   -------------------------------------------------------------------------- */

.eb-btn-secondary .elementor-button {
  background-color: transparent;
  color: var(--color-text);
  border: var(--border-hairline) solid var(--color-border-strong);
}

.eb-btn-secondary .elementor-button:hover,
.eb-btn-secondary .elementor-button:focus {
  background-color: var(--color-accent-soft);
  border-color: currentColor;
  color: var(--color-text);
}

/* --------------------------------------------------------------------------
   FACT BAND
   Hairlines between the columns, never around them.
   -------------------------------------------------------------------------- */

.eb-fact-band-inner {
  border-top: var(--border-hairline) solid var(--color-border);
  border-bottom: var(--border-hairline) solid var(--color-border);
}

.eb-fact + .eb-fact { border-left: var(--border-hairline) solid var(--color-border); }

@media (max-width: 479px) {
  .eb-fact + .eb-fact {
    border-left: 0;
    border-top: var(--border-hairline) solid var(--color-border);
  }
}

/* The fix carried over from the prototype: each column stretches so the
   separators run full height, but a stretched flex column hands its spare
   height to the gaps, which pushed each note away from its label. Packing the
   content to the start keeps the label and its note together at every width. */
.eb-fact { justify-content: flex-start; }

.eb-fact-note { color: var(--color-text-secondary); }

/* --------------------------------------------------------------------------
   AUDIENCE FORK
   -------------------------------------------------------------------------- */

.eb-route-media img {
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius-lg);
  width: 100%;
  height: auto;
}

.eb-route-lead { max-width: 42ch; }

.eb-route-links p {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs) var(--space-md);
  margin: 0;
}

.eb-route-links a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  text-decoration: none;
  border-bottom: var(--border-hairline) solid transparent;
}

.eb-route-links a:hover { border-bottom-color: currentColor; }

/* --------------------------------------------------------------------------
   SERVICE LEDGER - the signature composition
   A list of families beside one sticky image that changes with the row under
   the pointer. Degrades to a plain list with no image if scripting is off.
   -------------------------------------------------------------------------- */

.eb-ledger-row {
  position: relative;
  border-top: var(--border-hairline) solid var(--color-border);
  text-decoration: none;
  color: inherit;
}

.eb-ledger-list > .eb-ledger-row:last-child {
  border-bottom: var(--border-hairline) solid var(--color-border);
}

/* Same sweeping rule as the service link, and the same reason for scaleX
   rather than width: it is compositor-only and does not reflow. */
.eb-ledger-row::before {
  content: "";
  position: absolute;
  top: calc(var(--border-hairline) * -1);
  left: 0;
  width: 100%;
  height: var(--border-thick);
  background-color: var(--color-accent);
  transform: scaleX(0);
  transform-origin: left center;
}

.eb-ledger-row .eb-ledger-row-note { color: var(--color-text-secondary); max-width: 52ch; }

@media (hover: hover) and (pointer: fine) {
  .eb-ledger-row:hover::before,
  .eb-ledger-row:focus-visible::before { transform: scaleX(1); }
  .eb-ledger-row:hover .eb-ledger-row-title .elementor-heading-title { color: var(--color-link); }
}

@media (prefers-reduced-motion: no-preference) {
  .eb-ledger-row::before { transition: transform var(--dur-slow) var(--ease-out); }
  .eb-ledger-row-title .elementor-heading-title { transition: color var(--dur-base) var(--ease-out); }
}

/* The frame holds every image stacked; only the active one is shown. */
.eb-ledger-frame {
  position: relative;
  aspect-ratio: 1 / 1;
  border-radius: var(--radius-lg);
  overflow: hidden;
}

@media (min-width: 64em) {
  .eb-ledger-frame { position: sticky; top: calc(var(--header-height, 88px) + var(--space-xl)); }
}

.eb-ledger-frame .eb-ledger-img {
  position: absolute;
  inset: 0;
  opacity: 0;
}

.eb-ledger-frame .eb-ledger-img.is-active { opacity: 1; }

.eb-ledger-frame .eb-ledger-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (prefers-reduced-motion: no-preference) {
  .eb-ledger-frame .eb-ledger-img { transition: opacity var(--dur-slow) var(--ease-out); }
}

/* No pointer, no swap: the frame is decorative, so it is hidden rather than
   left showing an image that no longer relates to anything. */
@media (max-width: 1023px) {
  .eb-ledger-frame { display: none; }
}

/* --------------------------------------------------------------------------
   PROOF
   One named reference set as editorial type, not a testimonial card.
   -------------------------------------------------------------------------- */

.eb-quote-text p {
  max-width: 34ch;
  margin: 0;
}

.eb-quote-attrib { color: var(--color-text-secondary); }

.eb-proof-line + .eb-proof-line { border-top: var(--border-hairline) solid var(--color-border); }

.eb-proof-desc { color: var(--color-text-secondary); }

/* --------------------------------------------------------------------------
   SUSTAINABILITY
   -------------------------------------------------------------------------- */

.eb-cert-strip {
  padding-top: var(--space-md);
  border-top: var(--border-hairline) solid var(--color-border);
}

.eb-cert-marks img { max-width: 320px; height: auto; }

.eb-cert-note { color: var(--color-text-secondary); max-width: 46ch; }

.eb-feature-media img {
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border-radius: var(--radius-lg);
  width: 100%;
  height: auto;
}

/* An arrow that travels on hover, masked so its colour follows the surface. */
.eb-link-arrow p { margin: 0; }

.eb-link-arrow a {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  min-height: 44px;
  font-weight: var(--weight-semibold);
  text-decoration: none;
}

.eb-link-arrow a::after {
  content: "";
  width: 0.85em;
  height: 0.85em;
  background-color: currentColor;
  -webkit-mask: var(--eb-arrow-right) center / contain no-repeat;
          mask: var(--eb-arrow-right) center / contain no-repeat;
}

@media (hover: hover) and (pointer: fine) {
  .eb-link-arrow a:hover::after { translate: 4px 0; }
}

@media (prefers-reduced-motion: no-preference) {
  .eb-link-arrow a::after { transition: translate var(--dur-base) var(--ease-out); }
}

/* --------------------------------------------------------------------------
   HOW IT WORKS - four numbered steps
   Replaced the offset stair on 17 August 2026: the four steps now sit on one
   baseline, each opened by an accent rule and a step number, so the sequence
   is carried by the numbering rather than by a stagger.

   The columns are the Elementor grid container itself (4 / 2 / 1 across the
   1024 and 480 breakpoints) and the step number's typography is the Step
   number global set on the widget. Only what Elementor controls cannot
   express lives here: the rule, and the two colours that have to follow the
   surface rather than a fixed global.
   -------------------------------------------------------------------------- */

.eb-process-step::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  height: var(--border-thick);
  background-color: var(--color-accent);
  opacity: 0.35;
}

.eb-process-number { color: var(--color-accent); }

.eb-process-note { color: var(--color-text-secondary); }

/* --------------------------------------------------------------------------
   CTA BAND
   -------------------------------------------------------------------------- */

.eb-cta-text { color: var(--color-text-secondary); max-width: 46ch; }
