/* ==========================================================================
   Orbixedge brand layer
   Loaded after style.css, so it wins on specificity ties.

   style.css used to repeat a magenta/red/purple gradient in ~26 places. That
   palette predated the logo and had nothing to do with it - the mark is blue,
   the site was hot pink. Every brand colour is a token here now; style.css
   references those tokens directly, and the remap block below still catches
   the selectors it cannot reach cleanly. Change the palette in one place.

   Utilities (.flex-center, .text-gradient, .eyebrow, .ox-card) and the design
   tokens live at the top of this file. Palette matches brand/README.md.
   ========================================================================== */

:root {
  /* --- brand -----------------------------------------------------------
     Each brand colour is declared once, as bare channels, and the hex-style
     token is derived from it. Anything that needs the colour at partial
     opacity writes rgb(var(--ox-<name>-rgb) / <alpha>) rather than a literal
     rgba(), so a change here reaches every tint, glow, ring and scrim too.
     Before this there were 38 places carrying these numbers by hand, and a
     palette change reached none of them.

     The hues come from the footer's water - glacier blue rather than the
     royal azure this started as. The luminances deliberately do NOT: the
     water's brightest cyan (#47B3FA) scores 2.31:1 on white, which is under
     the 3:1 floor even for large text, so lifting it straight out of the
     shader would have washed out the hero heading and every accent link.
     These are hue-shifted at or below the old luminance instead, and the
     accent actually gains contrast (3.49:1 -> 3.87:1). */
  --ox-blue-bright-rgb:  18 135 210;   /* #1287D2  3.87:1 on white */
  --ox-blue-deep-rgb:    10  79 134;   /* #0A4F86  8.48:1 */
  --ox-navy-rgb:         10  43  68;   /* #0A2B44 14.56:1 */
  --ox-cyan-rgb:         63 200 240;   /* #3FC8F0  glints, never text */
  --ox-ink-rgb:          13  58  86;   /* #0D3A56 11.95:1 */

  --ox-blue-bright: rgb(var(--ox-blue-bright-rgb));
  --ox-blue-deep:   rgb(var(--ox-blue-deep-rgb));
  --ox-navy:        rgb(var(--ox-navy-rgb));
  --ox-cyan:        rgb(var(--ox-cyan-rgb));
  --ox-ink:         rgb(var(--ox-ink-rgb));
  --ox-slate:       #557285;

  /* --- surfaces ------------------------------------------------------- */
  --ox-surface:       #FFFFFF;
  --ox-surface-muted: #F1F7FA;
  --ox-surface-dark:  #06202F;
  --ox-border:        #DDE9EF;

  /* --- text ----------------------------------------------------------- */
  --ox-text:      var(--ox-navy);
  --ox-text-soft: #41606F;
  --ox-text-dim:  #75909D;

  /* --- the gradients ---------------------------------------------------
     The originals read
       linear-gradient(90deg, magenta 0%, red 0%, purple 100%)
     - two stops both at 0%, so the magenta never rendered at all. Fixed
     here as a genuine two-stop ramp. */
  --ox-gradient:      linear-gradient(90deg,  var(--ox-blue-bright) 0%, var(--ox-blue-deep) 100%);
  --ox-gradient-diag: linear-gradient(135deg, var(--ox-blue-bright) 0%, var(--ox-blue-deep) 100%);
  --ox-gradient-deep: linear-gradient(135deg, var(--ox-ink) 0%, var(--ox-blue-deep) 55%, var(--ox-blue-bright) 100%);

  /* --- elevation ------------------------------------------------------ */
  --ox-ring:     0 0 0 3px rgb(var(--ox-blue-bright-rgb) / 0.18);
  --ox-shadow-s: 0 1px 2px rgb(var(--ox-navy-rgb) / 0.06), 0 2px 8px rgb(var(--ox-navy-rgb) / 0.05);
  --ox-shadow-m: 0 2px 4px rgb(var(--ox-navy-rgb) / 0.06), 0 12px 28px rgb(var(--ox-navy-rgb) / 0.09);
  --ox-shadow-l: 0 4px 10px rgb(var(--ox-navy-rgb) / 0.08), 0 24px 56px rgb(var(--ox-navy-rgb) / 0.14);
  --ox-glow:     0 8px 24px rgb(var(--ox-blue-deep-rgb) / 0.28);

  /* --- radii ---------------------------------------------------------- */
  --ox-r-xs: 10px;
  --ox-r-sm: 8px;
  --ox-r-md: 14px;
  --ox-r-lg: 22px;
  --ox-r-pill: 999px;

  /* --- motion -------------------------------------------------------- */
  --ox-transition:      0.18s ease;
  --ox-transition-slow: 0.5s cubic-bezier(0.22, 0.61, 0.36, 1);

  /* --- rhythm ------------------------------------------------------------
     Vertical padding every full-width section shares, replacing the
     100px / 80px / 90px / 70px / 60px values scattered through style.css. */
  --ox-section-y: clamp(3.5rem, 7vw, 6rem);

  /* --- type scale ------------------------------------------------------
     The page currently uses 17 unrelated font sizes up to 75px. This is a
     1.25 ratio scale to replace them section by section. */
  --ox-t-xs:   0.8125rem;   /* 13 */
  --ox-t-sm:   0.9375rem;   /* 15 */
  --ox-t-base: 1.0625rem;   /* 17 */
  --ox-t-lg:   1.3125rem;   /* 21 */
  --ox-t-xl:   1.625rem;    /* 26 */
  --ox-t-2xl:  2.0625rem;   /* 33 */
  --ox-t-3xl:  2.625rem;    /* 42 */
  --ox-t-4xl:  3.25rem;     /* 52 */

  /* --- spacing scale --------------------------------------------------- */
  --ox-s-1: 0.5rem;
  --ox-s-2: 1rem;
  --ox-s-3: 1.5rem;
  --ox-s-4: 2.5rem;
  --ox-s-5: 4rem;
  --ox-s-6: 6rem;
}

/* ==========================================================================
   Utilities
   The handful of patterns that were re-declared in a dozen places each -
   flex centring, gradient-clipped text, the small caps "eyebrow" label and
   the bordered card box. Compose with these instead of repeating the rule.
   ========================================================================== */

.flex-center {
  display: flex;
  align-items: center;
  justify-content: center;
}

.text-gradient {
  background: var(--ox-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: var(--ox-blue-deep); /* fallback where clip is unsupported */
}

.eyebrow {
  display: inline-block;
  margin: 0 0 var(--ox-s-1);
  font-size: var(--ox-t-xs);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ox-blue-deep);
}

.ox-card {
  border: 1px solid var(--ox-border);
  border-radius: var(--ox-r-lg);
  background: var(--ox-surface);
  box-shadow: var(--ox-shadow-m);
}

/* ==========================================================================
   Remap the old palette
   Grouped by what the colour was doing, not by selector order.
   ========================================================================== */

/* --- primary actions ------------------------------------------------- */
.global_btn span:nth-child(1) button,
.global_btn span:nth-child(1) a.btn,
.form_div form input[type="submit"],
.form_wrapper form input[type="submit"],
.popup_content form input[type="submit"],
.contact_form_card .btn-submit,
.schedule_btn button,
.menu_wrapper button#menuBtn,
.support_inner ul li button,
.tab_wrapper ul#pills-tab li.nav-item button.active,
section.sec_9 div#v-tabs button.active,
/* the three that already looked right, listed so the shape below reaches
   them too and there is one description of "primary" rather than four */
.side-menu__cta,
.lead-modal__submit,
.cxa_submit {
  background: var(--ox-gradient);
  border-color: transparent;

  /* One shape for one role. An audit of 73 buttons found this single role
     rendering eight different ways - radii of 0, 2, 6, 10, 50 and 999px,
     four font sizes, and weights from 300 to 600 - because each button was
     skinned where it happened to live rather than by what it is.

     Deliberately NOT a full .ox-btn class system: that only pays off once the
     115 existing selectors are deleted, which means touching 92 buttons in 14
     Blade files. Keeping both would add a layer, not remove one. The colour
     and hover bugs those selectors caused are already fixed; what was left was
     shape, and shape can be stated once, here, with no markup change. */
  border-radius: var(--ox-r-pill);
  font-weight: 600;
  font-size: var(--ox-t-sm);
  letter-spacing: 0.005em;
  /* The modal's submit had no colour rule at all, so it fell through to the
     browser default for input[type=submit] - black text on the gradient.
     Set here rather than on that one button, so every primary action states
     its own foreground instead of relying on one inherited by accident. */
  color: #fff;

  /* And the hover foreground, because Bootstrap's `.btn:hover` reads
     `color: var(--bs-btn-hover-color)`. A plain `.btn` with no variant class
     - .btn-submit is one - never sets that variable, so the declaration
     resolved to nothing and the label fell back to black the moment you
     hovered it. Naming the variables fixes it at the source rather than
     out-specifying Bootstrap on every button. */
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: transparent;
  --bs-btn-hover-border-color: transparent;
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: transparent;
  --bs-btn-active-border-color: transparent;
}

.contact_form_card .btn-submit:hover,
.schedule_btn button:hover {
  box-shadow: var(--ox-glow);
}

/* --- one hover language ------------------------------------------------
   The site had four, three of them off-brand:

     .btn-dark        -> #424649   Bootstrap's grey
     .btn-primary     -> #0b5ed7   Bootstrap's blue, not ours
     .packages_box    -> #0D0C13   near-black
     .footer-btn      -> color:#000

   Bootstrap paints its hovers from --bs-btn-hover-* custom properties, so
   those are re-pointed at the tokens rather than fought with selectors.
   The rule everywhere now: a filled button brightens and lifts, an outline
   button fills with brand. Nothing turns grey or black. */

.btn-dark {
  --bs-btn-bg: var(--ox-navy);
  --bs-btn-border-color: var(--ox-navy);
  --bs-btn-hover-bg: var(--ox-ink);
  --bs-btn-hover-border-color: var(--ox-ink);
  --bs-btn-hover-color: #fff;
  --bs-btn-active-bg: var(--ox-ink);
  --bs-btn-active-border-color: var(--ox-ink);
}

.btn-primary {
  --bs-btn-bg: var(--ox-blue-deep);
  --bs-btn-border-color: var(--ox-blue-deep);
  --bs-btn-hover-bg: var(--ox-blue-bright);
  --bs-btn-hover-border-color: var(--ox-blue-bright);
  --bs-btn-hover-color: #fff;
  --bs-btn-active-bg: var(--ox-blue-bright);
  --bs-btn-active-border-color: var(--ox-blue-bright);
}

/* filled: brighten and lift, never change hue */
.global_btn span:nth-child(1) button:hover,
.global_btn span:nth-child(1) a.btn:hover,
.form_div form input[type="submit"]:hover,
.form_wrapper form input[type="submit"]:hover,
.popup_content form input[type="submit"]:hover,
.schedule_btn button:hover,
.global_btn span:nth-child(1) button:focus-visible,
.global_btn span:nth-child(1) a.btn:focus-visible {
  filter: brightness(1.08);
  box-shadow: var(--ox-glow);
}

/* Outline: was a black border and black text.

   The second header button has to follow the hero behind it - navy on the
   light home hero, white on the dark hero every inner page opens with.
   style.css did that with `color: #000 !important`, which is exactly why the
   token colour could not reach it. Scoped with :not(.page-home) instead, so
   the two cases separate on their own and nothing needs !important. */
.global_btn span:nth-child(2) button,
.global_btn span:nth-child(2) a.btn {
  color: var(--ox-navy);
  border-color: rgb(var(--ox-navy-rgb) / 0.28);
  /* the same shape as primary - these two stand side by side in the header,
     so a pill next to a 6px rectangle reads as a mistake */
  border-radius: var(--ox-r-pill);
  font-weight: 600;
  font-size: var(--ox-t-sm);
}

body:not(.page-home) header.main_header .global_btn span:nth-child(2) button,
body:not(.page-home) header.main_header .global_btn span:nth-child(2) a.btn {
  color: #fff;
  border-color: rgb(255 255 255 / 0.55);
}
body:not(.page-home) header.main_header .global_btn span:nth-child(2) button:hover,
body:not(.page-home) header.main_header .global_btn span:nth-child(2) button:focus-visible {
  color: #fff;
  background: rgb(255 255 255 / 0.14);
  border-color: #fff;
}
.global_btn span:nth-child(2) button:hover,
.global_btn span:nth-child(2) a.btn:hover,
.global_btn span:nth-child(2) button:focus-visible {
  color: var(--ox-blue-deep);
  border-color: var(--ox-blue-bright);
  background: rgb(var(--ox-blue-bright-rgb) / 0.06);
}

/* the footer's inverted button kept pure black text on white */
.footer-btn button:hover,
.footer-btn button:focus-visible {
  color: var(--ox-blue-deep);
  background: #fff;
}

/* every interactive control eases the same way */
.global_btn button,
.global_btn a.btn,
.packages_box button,
.footer-btn button {
  transition: background var(--ox-transition), color var(--ox-transition),
              border-color var(--ox-transition), box-shadow var(--ox-transition),
              filter var(--ox-transition);
}

/* --- brand-coloured surfaces ----------------------------------------- */
section.sec_3,
section.sec_7,
section.choose_sec:not(.no_bg),
.subscribe_inner,
.request_inner ul,
.form_div {
  background: var(--ox-gradient-diag);
}

/* --- small brand accents --------------------------------------------- */
.global_inner h6,
.contact_dual_header .contact_tag {
  background: var(--ox-gradient);
}

/* style.css narrows every <p> in the About block to `width: 85%` with a 20px
   top margin. That was meant for the body copy, but the eyebrow is a <p> now
   too, so the label inside the pill was being squeezed to 85% - which is what
   wrapped "About company" onto two lines and pushed it out of the pill. */
section.sec_8 .global_inner.black span p {
  width: auto;
  margin: 0;
}

.global_inner span {
  width: max-content;
  max-width: 100%;
  height: auto;
  min-height: 40px;
  white-space: nowrap;
  box-shadow: 0 -5px 14px rgb(var(--ox-blue-bright-rgb) / 0.30),
              0 10px 22px rgb(var(--ox-blue-deep-rgb) / 0.26),
              0 0 28px rgb(var(--ox-cyan-rgb) / 0.24);
}

/* "View More" under the FAQ list. Was 18px black text on nothing, which read
   as a stray line of copy rather than a control - the only thing marking it as
   clickable was the cursor. A ghost pill on the brand tokens instead, centred
   rather than a full-width block. Defined here and removed from style.css, so
   there is no specificity fight between the two files. */
#seeMoreBtn.see-more {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin: var(--ox-s-4) auto 0;
  padding: 0.65rem 1.5rem;
  width: auto;
  font-size: var(--ox-t-sm);
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--ox-blue-deep);
  background: var(--ox-surface);
  border: 1px solid var(--ox-border);
  border-radius: var(--ox-r-pill);
  box-shadow: var(--ox-shadow-s);
  cursor: pointer;
  transition: color var(--ox-transition), border-color var(--ox-transition),
              background var(--ox-transition), box-shadow var(--ox-transition);
}

/* the column is not a flex container, so centre it the old-fashioned way */
.custom-accordion + #seeMoreBtn.see-more,
#seeMoreBtn.see-more { display: flex; width: fit-content; }

#seeMoreBtn.see-more:hover {
  color: var(--ox-blue-bright);
  border-color: rgb(var(--ox-blue-bright-rgb) / 0.45);
  background: rgb(var(--ox-blue-bright-rgb) / 0.05);
  box-shadow: var(--ox-shadow-m);
}
#seeMoreBtn.see-more:focus-visible {
  outline: none;
  box-shadow: var(--ox-ring);
}

.see-more__chev {
  flex: none;
  transition: transform var(--ox-transition);
}
/* one SVG that turns over, rather than swapping the glyph on every click */
#seeMoreBtn.see-more[aria-expanded="true"] .see-more__chev {
  transform: rotate(180deg);
}

@media (prefers-reduced-motion: reduce) {
  .see-more__chev { transition: none; }
}

/* --- focus ------------------------------------------------------------ */
.contact_form_card .form-control:focus {
  border-color: var(--ox-blue-bright);
  box-shadow: var(--ox-ring);
}

/* --- footer -----------------------------------------------------------
   Was a magenta -> red -> purple ramp, which fought the logo sitting on it.

   Ambient water: a small WebGL shader (custom.js -> initFooterWater) paints a
   rolling water surface with light glints onto .footer_wave. No media file, no
   library. It runs only while the footer is on screen and draws one still frame
   for reduced-motion; the gradient here is the fallback when WebGL is absent. */
footer.main_folder {
  position: relative;
  overflow: hidden;
  /* What sits behind the water canvas, and what a browser without WebGL gets
     instead of it. This used to be --ox-gradient-deep, whose last stop is
     --ox-blue-bright (#2B87FF) across the bottom half - a bright azure that
     flashed on every load before the first WebGL frame landed, and that no-GL
     visitors saw permanently. These stops approximate the shader's own output
     before the scrim above dims it, so the handover is invisible.
     Deliberately not the token: --ox-gradient-deep is used elsewhere. */
  background: linear-gradient(180deg, #16324a 0%, #22688c 52%, #143f57 100%);
}

.footer_wave {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  display: block;
  pointer-events: none;
}

/* A mark adrift on the water, behind everything. It sits between the canvas
   and the scrim in paint order, so the same haze that keeps the copy readable
   also sinks it back - it should register as something floating out there, not
   as a second logo competing with the wordmark below.

   The bob, sway and roll come from custom.js, not from a CSS animation: the
   ripples it pushes into the fluid have to break as it dips, and a keyframe
   animation on its own clock would drift out of phase within seconds. */
/* Marks adrift on the footer's water. They paint between the canvas and the
   readability scrim, so the same haze that keeps the copy legible also sinks
   them back - they should register as things floating out there, not as extra
   logos competing with the wordmark.

   Each one's spot and size come from --x/--y/--s set on the element in
   footer.blade.php. Nothing here touches transform: custom.js owns that for
   the bob and roll, so the position has to live in left/top. */
.footer_drift {
  position: absolute;
  left: var(--x);
  /* the starting point only; custom.js carries each mark up from here and
     wraps it round, so --y seeds the scatter rather than fixing it */
  top: var(--y);
  width: calc(var(--s, 1) * clamp(96px, 12vw, 200px));
  height: auto;
  aspect-ratio: 1;
  /* Above the readability scrim, below the content. At z-index 0 the scrim
     painted over these and knocked the white back to a flat grey - they looked
     like dark cut-outs instead of something pale floating on the water. The
     container is z-index 1 as well and comes later in the DOM, so the copy
     still wins over them. */
  z-index: 1;
  /* --o is the mark's own weight, --fade is written by custom.js as it
     wraps off one edge and returns from the other. Composed rather than
     set outright, so the script's fade and the breakpoint below do not
     overwrite each other. */
  opacity: calc(var(--o, 0.2) * var(--fade, 1));
  pointer-events: none;
  user-select: none;
  /* No will-change. Combined with the z-index above it promoted each mark to
     its own compositing layer, and the WebGL canvas underneath then stopped
     compositing at all - the water vanished and the footer fell back to a flat
     gradient. These are five small images; the transform animates fine without
     the hint. Confirmed by toggling it live: water back, marks unchanged. */
  /* No drop-shadow. The mark is a solid silhouette, so a dark rim around it
     came out about as strong as the pale fill and the whole thing turned to
     mud - it read as a dark cut-out rather than something light on the water.
     The ripples each mark pushes into the fluid do the "it is in the water"
     work instead, and they do it better. */
}

@media (max-width: 991px) {
  /* the columns stack, so the footer is far taller and much narrower - the
     marks would otherwise crowd the copy */
  .footer_drift {
    width: calc(var(--s, 1) * clamp(74px, 22vw, 132px));
    opacity: calc(var(--o, 0.2) * var(--fade, 1) * 0.85);
  }
}

/* Nothing drifts for a reader who asked for stillness. The script never enters
   its float loop either; this only tidies the resting state. */
@media (prefers-reduced-motion: reduce) {
  .footer_drift { transform: none !important; }
}

/* readability scrim over the water, under the content */
footer.main_folder::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(4, 12, 32, 0.30) 0%, rgba(4, 12, 32, 0.52) 100%);
}

footer.main_folder > .container {
  position: relative;
  z-index: 1;
}

/* ==========================================================================
   Accessibility floor
   ========================================================================== */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 3px solid var(--ox-blue-bright);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ==========================================================================
   Buttons
   One button system, replacing the ad-hoc gradient buttons scattered through
   style.css. Two roles only: primary (the one action) and ghost (everything
   else). More than two weights of button on a page and none of them read as
   the main action.
   ========================================================================== */

.btn-ox {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.95rem 1.75rem;
  border: 1px solid transparent;
  border-radius: var(--ox-r-pill);
  font-size: var(--ox-t-base);
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}

.btn-ox--primary {
  background: var(--ox-gradient);
  color: #fff;
  box-shadow: var(--ox-glow);
}

.btn-ox--primary:hover {
  color: #fff;
  transform: translateY(-1px);
  box-shadow: 0 12px 30px rgb(var(--ox-blue-deep-rgb) / 0.34);
}

.btn-ox--ghost {
  background: transparent;
  color: var(--ox-navy);
  border-color: var(--ox-border);
}

.btn-ox--ghost:hover {
  color: var(--ox-blue-deep);
  border-color: var(--ox-blue-bright);
  background: var(--ox-surface-muted);
}

/* ==========================================================================
   Hero
   Was: a 90px headline flanked by two columns of the same three stock images
   repeated on both sides, with an email subscribe box as the primary action.
   Now: one clear action, and proof instead of decoration.
   ========================================================================== */

.hero {
  position: relative;
  padding: clamp(9rem, 14vw, 13rem) 0 clamp(4rem, 7vw, 6.5rem);
  overflow: hidden;
  background: var(--ox-surface);
}

.hero__glow {
  position: absolute;
  top: -28%;
  left: 50%;
  width: min(1100px, 120vw);
  aspect-ratio: 1;
  transform: translateX(-50%);
  background: radial-gradient(circle at 50% 50%,
              rgb(var(--ox-blue-bright-rgb) / 0.16) 0%,
              rgb(var(--ox-cyan-rgb) / 0.09) 38%,
              transparent 68%);
  pointer-events: none;
  /* a very slow drift so the backdrop is never quite still */
  animation: heroGlowDrift 26s ease-in-out infinite alternate;
  will-change: transform;
}

@keyframes heroGlowDrift {
  0%   { transform: translateX(-50%) translate(-2%, -1%) scale(1);    }
  50%  { transform: translateX(-50%) translate(3%,  2%)  scale(1.09); }
  100% { transform: translateX(-50%) translate(-1%, -2%) scale(1.03); }
}

.hero__inner {
  position: relative;
  max-width: 62rem;
  margin: 0 auto;
  text-align: center;
}

.hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.65rem;
  margin: 0 0 var(--ox-s-3);
  padding: 0.4rem 1rem 0.4rem 0.4rem;
  border: 1px solid var(--ox-border);
  border-radius: var(--ox-r-pill);
  background: var(--ox-surface);
  box-shadow: var(--ox-shadow-s);
  font-size: var(--ox-t-sm);
  color: var(--ox-text-soft);
}

.hero__eyebrow span {
  padding: 0.3rem 0.75rem;
  border-radius: var(--ox-r-pill);
  background: var(--ox-gradient);
  color: #fff;
  font-weight: 600;
  font-size: var(--ox-t-xs);
  letter-spacing: 0.02em;
}

.hero__title {
  margin: 0 0 var(--ox-s-3);
  font-size: clamp(2.6rem, 6vw, 4.5rem);
  line-height: 1.05;
  letter-spacing: -0.03em;
  font-weight: 600;
  color: var(--ox-navy);
  text-transform: none;
}

/* The keyword-bearing H1 runs to three lines. At the short headline's 4.5rem
   that pushed the buttons and the proof line below the fold on a 900px-tall
   screen, which is the one thing the hero has to avoid. */
.hero__title--long {
  font-size: clamp(2.1rem, 4.6vw, 3.4rem);
}

.hero__accent {
  display: block;
  /* line-height 1.05 on the title is fine for the solid navy line, but it
     clips the descenders of this gradient-clipped line (background-clip:text
     paints nothing outside the box). Pad the box out, pull the layout back. */
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
  line-height: 1.12;
  background: linear-gradient(90deg, var(--ox-blue-bright), var(--ox-blue-deep));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.hero__lede {
  max-width: 42rem;
  margin: 0 auto var(--ox-s-4);
  font-size: var(--ox-t-lg);
  line-height: 1.6;
  color: var(--ox-text-soft);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ox-s-2);
  justify-content: center;
  margin-bottom: var(--ox-s-4);
}

.hero__proof {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ox-s-1) var(--ox-s-4);
  justify-content: center;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--ox-t-sm);
  color: var(--ox-text-dim);
}

.hero__proof strong {
  color: var(--ox-navy);
  font-weight: 700;
}

/* --- entrance -----------------------------------------------------------
   The hero content rises in on load, one line after another. Pure CSS, runs
   once, and holds still for prefers-reduced-motion. */
@keyframes heroRise {
  from { opacity: 0; transform: translateY(13px); }
  to   { opacity: 1; transform: translateY(0); }
}

.hero__eyebrow,
.hero__title,
.hero__lede,
.hero__actions,
.hero__proof {
  animation: heroRise 0.62s cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
.hero__eyebrow { animation-delay: 0.06s; }
.hero__title   { animation-delay: 0.14s; }
.hero__lede    { animation-delay: 0.23s; }
.hero__actions { animation-delay: 0.32s; }
.hero__proof   { animation-delay: 0.41s; }

@media (prefers-reduced-motion: reduce) {
  .hero__glow { animation: none; }
  .hero__eyebrow,
  .hero__title,
  .hero__lede,
  .hero__actions,
  .hero__proof {
    animation: none;
    opacity: 1;
    transform: none;
  }
}

/* ==========================================================================
   Client strip
   Typographic, not logos - see includes/clients.php for why.
   ========================================================================== */

.client_strip {
  padding: var(--ox-s-4) 0;
  background: var(--ox-surface-muted);
  border-block: 1px solid var(--ox-border);
}

.client_strip__label {
  margin: 0 0 var(--ox-s-2);
  text-align: center;
  font-size: var(--ox-t-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ox-text-dim);
}

.client_strip__list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ox-s-3) var(--ox-s-5);
  justify-content: center;
  margin: 0;
  padding: 0;
  list-style: none;
}

.client_strip__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
}

.client_strip__name {
  font-size: var(--ox-t-lg);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ox-navy);
}

.client_strip__sector {
  font-size: var(--ox-t-xs);
  color: var(--ox-text-dim);
}

/* ==========================================================================
   Gradient-clipped text
   style.css paints several elements with `background-clip: text` over the old
   magenta ramp - stat numbers, section eyebrows, service labels, post links.
   Remapped in one block rather than nine.
   ========================================================================== */

.counter_wrapper ul li h3,
.global_inner span h5,
.global_inner span p,
.post-box h5,
.post-box__kicker,
.post_box a,
.choose_wrapper ul li h4 span,
.industries_icon ul li h4 span,
.image_tab h4 span {
  background: var(--ox-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: var(--ox-blue-deep);

  /* background-clip:text paints the gradient only inside the background
     positioning area - the padding box - so any glyph ink outside it simply is
     not painted. style.css sets letter-spacing:-1px on these, and letter
     spacing applies after the LAST character too, which pulls the box's right
     edge about 1-2px inside the final glyph. The tail of that glyph then had
     no gradient to show through and read as a chopped-off letter ("Our Story",
     "About Company", "Featured Services"...).

     Widening the padding box fixes it; the equal negative margin hands the
     width straight back, so layout, centring and line breaks are untouched. */
  padding-right: 0.3em;
  margin-right: -0.3em;
}

/* style.css sets the section eyebrow to line-height:14px on a 14px font, so
   background-clip:text shaves the caps and the descenders off ("Our Story",
   "About Company"...). Give the glyphs room. */
.global_inner span h5 {
  line-height: 1.5;
  /* right side keeps the background-box widening from the rule above */
  padding: 0.12em 0.3em 0.12em 0;
}

/* The same eyebrow, as a <p>. It was an <h5> printed immediately before the
   section's own <h2>, so every section it appeared in ran h5 -> h2 - axe and
   Lighthouse both flag that, and this site gates releases on those scores. It
   is a label, not a heading. The h5 selectors stay for the pages that have not
   been converted yet. */
.global_inner span p {
  margin: 0;
  font-size: 14px;
  line-height: 1.5;
  font-weight: 500 !important;
  letter-spacing: -1px;
  text-transform: capitalize;
  padding: 0.12em 0.3em 0.12em 0;
}

.tab_wrapper button.nav-link.active,
#pills-tab button.nav-link.active {
  background: var(--ox-gradient-diag);
  border-color: transparent;
}

/* ==========================================================================
   Typography
   style.css sets 60px on four different section headings and 30px on six
   others, with no relationship between them, then overrides each one again at
   two breakpoints. Everything below collapses that onto the scale and lets
   clamp() handle the breakpoints, so a heading is one declaration instead of
   three.
   ========================================================================== */

.global_inner h2,
.counter_inner h2,
h2.normal,
h1.border-txt {
  font-size: clamp(2rem, 3.6vw, var(--ox-t-3xl));
  line-height: 1.12;
  letter-spacing: -0.025em;
  font-weight: 600;
  color: var(--ox-navy);
}

.counter_wrapper ul li h3 {
  font-size: clamp(2.2rem, 4vw, var(--ox-t-4xl));
  line-height: 1;
  letter-spacing: -0.03em;
  font-weight: 700;
}

.post-box h3,
.packages_box h1,
.packages_box__price {
  font-size: clamp(1.5rem, 2.4vw, var(--ox-t-xl));
  line-height: 1.2;
  letter-spacing: -0.02em;
  font-weight: 600;
  color: var(--ox-navy);
}

.schedule_inner h2,
section.contact_us_sec h4,
.request_inner ul li h3,
.support_inner ul li h4,
.subscribe p {
  font-size: clamp(1.35rem, 2vw, var(--ox-t-lg));
  line-height: 1.3;
  letter-spacing: -0.015em;
  font-weight: 600;
}

/* body copy: one measure, one colour, everywhere */
.global_inner p,
.counter_inner p,
.post-box p {
  font-size: var(--ox-t-base);
  line-height: 1.65;
  color: var(--ox-text-soft);
}

/* section intros should not run the full container width */
.global_inner p {
  max-width: 46rem;
  margin-inline: auto;
}

/* ==========================================================================
   Section rhythm
   Was 80 / 100 / 30 / 180px picked per section. One scale, and it breathes
   down on small screens instead of staying at desktop values.
   ========================================================================== */

section.sec_2,
section.sec_4,
section.sec_5,
section.sec_6,
section.sec_7,
section.sec_8,
section.sec_9,
section.why_choose {
  padding-block: clamp(3.5rem, 7vw, var(--ox-s-6));
}

/* ==========================================================================
   Services (sec_5)
   A row list rather than a card grid. Five cards across left ~250px each, so
   one-line and two-line titles pushed everything below them out of step; rows
   share one grid template, so alignment is structural.

   Note: style.css has `ul { margin: 0 !important; padding: 0 !important }`,
   so every gap here is set with padding on non-ul elements or on the wrapper.
   ========================================================================== */

.services {
  background: var(--ox-surface-dark);
  color: #fff;
}

/* --- heading block ---------------------------------------------------- */
.services__head {
  max-width: 46rem;
  margin-inline: auto;
  text-align: center;
}

.services__eyebrow {
  display: inline-block;
  margin: 0 0 var(--ox-s-2);
  padding: 0.35rem 0.9rem;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: var(--ox-r-pill);
  font-size: var(--ox-t-xs);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ox-blue-bright);
}

.services__heading {
  margin: 0 0 var(--ox-s-2);
  font-size: clamp(1.9rem, 3.4vw, var(--ox-t-3xl));
  line-height: 1.15;
  letter-spacing: -0.025em;
  font-weight: 600;
  color: #fff;
}

.services__intro {
  margin: 0;
  font-size: var(--ox-t-base);
  line-height: 1.65;
  color: rgba(255, 255, 255, 0.62);
}

/* --- the list --------------------------------------------------------- */
.services__listwrap {
  margin-top: clamp(2.5rem, 5vw, var(--ox-s-5));
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}

.services__row {
  display: grid;
  grid-template-columns: 3.5rem minmax(11rem, 15rem) minmax(0, 1fr) auto;
  align-items: start;
  gap: var(--ox-s-3);
  padding: var(--ox-s-3) var(--ox-s-2);
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
  transition: background 0.18s ease;
}

.services__row:hover { background: rgba(255, 255, 255, 0.035); }

.services__num {
  font-size: var(--ox-t-sm);
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--ox-blue-bright);
  padding-top: 0.2rem;
}

.services__name {
  margin: 0;
  font-size: var(--ox-t-lg);
  line-height: 1.25;
  letter-spacing: -0.015em;
  font-weight: 600;
  color: #fff;
}

.services__body {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.services__desc {
  margin: 0;
  font-size: var(--ox-t-sm);
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.66);
}

.services__points {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 0.5rem;
}

.services__points li {
  padding: 0.25rem 0.7rem;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: var(--ox-r-pill);
  font-size: var(--ox-t-xs);
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.55);
}

.services__link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding-top: 0.2rem;
  font-size: var(--ox-t-sm);
  font-weight: 600;
  color: var(--ox-blue-bright);
  text-decoration: none;
  white-space: nowrap;
}

.services__link svg { transition: transform 0.15s ease; }
.services__row:hover .services__link { color: #fff; }
.services__row:hover .services__link svg { transform: translateX(3px); }

/* --- narrower screens -------------------------------------------------- */
@media (max-width: 991px) {
  .services__row {
    grid-template-columns: 2.75rem minmax(0, 1fr);
    gap: 0.5rem var(--ox-s-2);
    padding-block: var(--ox-s-3);
  }
  .services__name  { grid-column: 2; }
  .services__body  { grid-column: 2; }
  .services__link  { grid-column: 2; justify-self: start; padding-top: 0.35rem; }
  .services__num   { grid-row: 1 / span 3; }
}

@media (max-width: 575px) {
  .services__row  { grid-template-columns: 1fr; }
  .services__num  { grid-row: auto; }
  .services__name,
  .services__body,
  .services__link { grid-column: 1; }
}

/* ==========================================================================
   Process cards (sec_2)
   The three stock photos are gone - one of them was the same picture used
   again further down the page. The step number carries the sequence instead.
   ========================================================================== */

.post-box {
  position: relative;
  padding: 0;                       /* .post-box__body carries the padding now */
  border: 1px solid var(--ox-border);
  border-radius: var(--ox-r-lg);
  background: var(--ox-surface);
  box-shadow: var(--ox-shadow-s);
  height: 100%;
  overflow: hidden;                 /* clip the full-bleed photo to the radius */
  display: flex;
  flex-direction: column;
  transition: box-shadow 0.2s ease, transform 0.2s ease;
}

.post-box:hover {
  transform: translateY(-3px);
  box-shadow: var(--ox-shadow-m);
}

/* the text column below the photo - a flex column so the button can sink to
   the bottom and line up across all three cards regardless of copy length */
.post-box__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: var(--ox-s-4) var(--ox-s-3) var(--ox-s-3);
}

.post-box h5,
.post-box p.post-box__kicker {
  margin: 0 0 0.4rem;
  font-size: var(--ox-t-xs);
  font-weight: 700 !important;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  line-height: 1.4;
}

.post-box h3 { margin: 0 0 0.35rem; }

/* the one-line "what this step produces" note, right under the title */
.post-box__note {
  margin: 0 0 0.9rem;
  font-size: var(--ox-t-xs);
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--ox-text-dim);
}

.post-box p {
  margin: 0 0 var(--ox-s-3);
  font-size: var(--ox-t-sm);
  line-height: 1.6;
  color: var(--ox-text-soft);
}

.post-box button {
  margin-top: auto;                 /* pin to the bottom of the card */
  align-self: flex-start;
  padding: 0.7rem 1.4rem;
  border: 1px solid var(--ox-border);
  border-radius: var(--ox-r-pill);
  background: transparent;
  font-size: var(--ox-t-sm);
  font-weight: 600;
  color: var(--ox-navy);
  cursor: pointer;
  transition: all 0.15s ease;
}

.post-box button:hover {
  border-color: var(--ox-blue-bright);
  color: var(--ox-blue-deep);
  background: var(--ox-surface-muted);
}

/* ==========================================================================
   Schedule card
   ========================================================================== */

.schedule_card {
  display: flex;
  flex-direction: column;
  gap: var(--ox-s-2);
  height: 100%;
  padding: var(--ox-s-4);
  border: 1px solid var(--ox-border);
  border-radius: var(--ox-r-lg);
  background: var(--ox-surface);
  box-shadow: var(--ox-shadow-m);
}

.schedule_card .card_icon {
  display: grid;
  place-items: center;
  width: 3.5rem;
  height: 3.5rem;
  border-radius: var(--ox-r-md);
  background: var(--ox-gradient-diag);
}

.schedule_card .card_icon img { width: 60%; height: auto; }

.schedule_card h3 {
  margin: var(--ox-s-1) 0 0;
  font-size: var(--ox-t-xl);
  line-height: 1.2;
  letter-spacing: -0.02em;
  font-weight: 600;
  color: var(--ox-navy);
}

.schedule_note {
  margin: 0;
  font-size: var(--ox-t-sm);
  line-height: 1.65;
  color: var(--ox-text-soft);
}

.schedule_btn { margin-top: auto; padding-top: var(--ox-s-2); }

.schedule_btn button {
  padding: 0.95rem 1.75rem;
  border: none;
  border-radius: var(--ox-r-pill);
  font-size: var(--ox-t-base);
  font-weight: 600;
  color: #fff;
}

/* Once the schedule card and the form stack (below col-md), the .row gives
   them no vertical gap - the old .schedule_card margin-bottom collapsed away
   inside the flex column. Space the second card off the first directly. */
@media (max-width: 767.98px) {
  .contact_section_dual .row.mt-5 > [class*="col-"] + [class*="col-"] {
    margin-top: clamp(1.5rem, 5vw, 2rem);
  }
}

/* ==========================================================================
   Contact page - primary block (pages/contact.blade.php, .cxa)
   The form is the first thing after the hero now, with a support rail beside
   it. Self-contained classes so it does not collide with the shared
   .contact_form_card / .schedule_card used by the homepage CTA.
   ========================================================================== */

.cxa {
  padding: clamp(2.5rem, 6vw, 4.5rem) 0 var(--ox-section-y);
  background: var(--ox-surface-muted);
}

/* pull the form card up so it overlaps the dark hero a little */
.cxa .container { margin-top: clamp(-3.5rem, -6vw, -2rem); }

/* --- the form card --- */
.cxa_form {
  padding: clamp(1.5rem, 4vw, 2.75rem);
  border: 1px solid var(--ox-border);
  border-radius: var(--ox-r-lg);
  background: var(--ox-surface);
  box-shadow: var(--ox-shadow-m);
}

.cxa_form > h2 {
  margin: 0 0 0.35rem;
  font-size: clamp(1.4rem, 2.4vw, var(--ox-t-xl));
  line-height: 1.2;
  letter-spacing: -0.02em;
  font-weight: 600;
  color: var(--ox-navy);
}

.cxa_form__lede {
  margin: 0 0 clamp(1.5rem, 4vw, 2rem);
  font-size: var(--ox-t-sm);
  line-height: 1.6;
  color: var(--ox-text-soft);
}

.cxa_grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(1rem, 2.5vw, 1.35rem);
}

.cxa_field { display: flex; flex-direction: column; gap: 0.4rem; }
.cxa_field--full { grid-column: 1 / -1; }

.cxa_field label {
  font-size: var(--ox-t-xs);
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--ox-navy);
}
.cxa_field label span { color: var(--ox-blue-bright); }

.cxa_field input,
.cxa_field select,
.cxa_field textarea {
  width: 100%;
  padding: 0.8rem 0.95rem;
  border: 1px solid var(--ox-border);
  border-radius: var(--ox-r-sm);
  background: var(--ox-surface);
  font: inherit;
  font-size: var(--ox-t-sm);
  color: var(--ox-navy);
  transition: border-color var(--ox-transition), box-shadow var(--ox-transition);
  -webkit-appearance: none;
  appearance: none;
}

.cxa_field textarea { resize: vertical; min-height: 7rem; line-height: 1.6; }

.cxa_field select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%234A5A85' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.95rem center;
  padding-right: 2.4rem;
}

.cxa_field input::placeholder,
.cxa_field textarea::placeholder { color: var(--ox-text-dim); }

.cxa_field input:focus,
.cxa_field select:focus,
.cxa_field textarea:focus {
  outline: none;
  border-color: var(--ox-blue-bright);
  box-shadow: var(--ox-ring);
}

.cxa_submit {
  margin-top: clamp(1.5rem, 4vw, 2rem);
  width: 100%;
  padding: 0.95rem 1.5rem;
  border: 0;
  border-radius: var(--ox-r-pill);
  background: var(--ox-gradient);
  font-size: var(--ox-t-base);
  font-weight: 600;
  color: #fff;
  cursor: pointer;
  transition: transform var(--ox-transition), box-shadow var(--ox-transition);
}
.cxa_submit:hover { transform: translateY(-1px); box-shadow: var(--ox-glow); }

.cxa_privacy {
  margin: 0.9rem 0 0;
  font-size: var(--ox-t-xs);
  color: var(--ox-text-dim);
  text-align: center;
}
.cxa_privacy a { color: var(--ox-text-soft); text-decoration: underline; }

/* --- the support rail --- */
.cxa_rail {
  position: sticky;
  top: 2rem;
  display: flex;
  flex-direction: column;
  gap: var(--ox-s-3);
}

/* the person photo sits in the card's own padding box, so the copy gets a
   right inset on wide rails and the image tucks into the bottom corner */
.cxa_rail__call {
  position: relative;
  overflow: hidden;
  padding: clamp(1.35rem, 3vw, 1.85rem);
  border-radius: var(--ox-r-lg);
  background: var(--ox-gradient-diag);
  box-shadow: var(--ox-glow);
  color: #fff;
}

.cxa_rail__callcopy {
  position: relative;
  z-index: 2;                       /* above the photo and its overlay */
  /* keep the copy on the opaque side of the overlay, where contrast holds */
  max-width: min(21rem, 68%);
}

/* The photo is texture, not a subject: it fills the card and the brand
   gradient sits over it, so the copy keeps full contrast. */
.cxa_rail__shot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 72% 58%;         /* keep the keyboard on the card's open right */
  z-index: 0;
  pointer-events: none;
}

.cxa_rail__call::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  /* opaque where the copy sits, thinner on the right so the laptop reads */
  background: linear-gradient(102deg,
              rgb(var(--ox-blue-deep-rgb) / 0.97) 0%,
              rgb(var(--ox-blue-deep-rgb) / 0.93) 40%,
              rgb(var(--ox-blue-bright-rgb) / 0.58) 76%,
              rgb(var(--ox-blue-bright-rgb) / 0.38) 100%);
}

.cxa_rail__badge {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0 0 0.7rem !important;
  padding: 0.3rem 0.7rem;
  border-radius: var(--ox-r-pill);
  background: rgba(255, 255, 255, 0.16);
  font-size: var(--ox-t-xs);
  font-weight: 600;
  color: #fff !important;
  white-space: nowrap;           /* a wrapped pill reads as a broken chip */
}
.cxa_dot {
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  background: #7CF0B4;
  box-shadow: 0 0 0 3px rgba(124, 240, 180, 0.25);
}

.cxa_rail__call h3,
.cxa_rail__call h2 {
  margin: 0 0 0.5rem;
  font-size: var(--ox-t-lg);
  line-height: 1.25;
  letter-spacing: -0.015em;
  font-weight: 600;
  color: #fff;
}
.cxa_rail__call p {
  margin: 0 0 1.15rem;
  font-size: var(--ox-t-sm);
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.86);
}
.cxa_rail__cta {
  display: inline-flex;
  align-items: center;
  padding: 0.7rem 1.3rem;
  border: 0;
  border-radius: var(--ox-r-pill);
  background: #fff;
  font-size: var(--ox-t-sm);
  font-weight: 600;
  color: var(--ox-blue-deep);
  cursor: pointer;
  transition: transform var(--ox-transition), box-shadow var(--ox-transition);
}
.cxa_rail__cta:hover { transform: translateY(-1px); box-shadow: 0 10px 24px rgba(4, 12, 40, 0.28); }

/* --- what happens after you send the form --- */
.cxa_steps {
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: cxastep;
}
.cxa_steps li {
  display: flex;
  gap: 0.9rem;
  padding: 0 0 1.05rem;
}
.cxa_steps li:last-child { padding-bottom: 0; }

.cxa_steps__n {
  position: relative;
  flex: none;
  display: grid;
  place-items: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 50%;
  background: var(--ox-surface);
  border: 1px solid var(--ox-border);
  font-size: var(--ox-t-xs);
  font-weight: 700;
  color: var(--ox-blue-deep);
}
/* the connector between the step markers */
.cxa_steps li:not(:last-child) .cxa_steps__n::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  width: 1px;
  height: calc(1.05rem + 0.4rem);
  transform: translateX(-50%);
  background: var(--ox-border);
}

.cxa_steps h4,
.cxa_steps h3 {
  margin: 0 0 0.15rem;
  font-size: var(--ox-t-sm);
  font-weight: 600;
  color: var(--ox-navy);
}
.cxa_steps p {
  margin: 0;
  font-size: var(--ox-t-sm);
  line-height: 1.5;
  color: var(--ox-text-soft);
}

/* style.css sets `ul { padding: 0 !important }`, so the card's horizontal
   padding has to live on the rows, not on the list. */
.cxa_channels {
  margin: 0;
  list-style: none;
  border: 1px solid var(--ox-border);
  border-radius: var(--ox-r-lg);
  background: var(--ox-surface);
  box-shadow: var(--ox-shadow-s);
}
.cxa_channels li {
  display: flex;
  gap: 0.95rem;
  padding: clamp(1rem, 2.5vw, 1.15rem) clamp(1.1rem, 3vw, 1.5rem);
}
.cxa_channels li + li { border-top: 1px solid var(--ox-border); }

.cxa_channels__ico {
  flex: none;
  display: grid;
  place-items: center;
  width: 2.6rem;
  height: 2.6rem;
  border-radius: var(--ox-r-md);
  background: var(--ox-surface-muted);
  color: var(--ox-blue-deep);
}
.cxa_channels__ico svg { width: 1.3rem; height: 1.3rem; }

.cxa_channels h4,
.cxa_channels h3 {
  margin: 0 0 0.15rem;
  font-size: var(--ox-t-base);
  font-weight: 600;
  color: var(--ox-navy);
}
.cxa_channels li p {
  margin: 0 0 0.4rem;
  font-size: var(--ox-t-sm);
  line-height: 1.5;
  color: var(--ox-text-soft);
}
.cxa_channels__link {
  padding: 0;
  border: 0;
  background: none;
  font-size: var(--ox-t-sm);
  font-weight: 600;
  color: var(--ox-blue-deep);
  cursor: pointer;
}
.cxa_channels__link:hover { color: var(--ox-blue-bright); }

.cxa_rail__note {
  margin: 0;
  font-size: var(--ox-t-xs);
  text-align: center;
  color: var(--ox-text-dim);
}

@media (max-width: 991.98px) {
  .cxa_rail { position: static; }
  .cxa .container { margin-top: clamp(-2.5rem, -5vw, -1.5rem); }
}

@media (max-width: 575.98px) {
  .cxa_grid { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Featured services (sec_6)
   Three more stock desk photos removed. An icon states the category without
   pretending to be a picture of the team.
   ========================================================================== */

.post_box {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  height: 100%;
  padding: var(--ox-s-3);
  border: 1px solid var(--ox-border);
  border-radius: var(--ox-r-lg);
  background: var(--ox-surface);
  overflow: hidden;                 /* clip the full-bleed photo header to the radius */
  transition: box-shadow 0.2s ease, transform 0.2s ease, border-color 0.2s ease;
}

.post_box:hover {
  transform: translateY(-3px);
  border-color: transparent;
  box-shadow: var(--ox-shadow-m);
}

.post_box h3 {
  margin: 0;
  font-size: var(--ox-t-lg);
  line-height: 1.25;
  letter-spacing: -0.015em;
  font-weight: 600;
  color: var(--ox-navy);
}

.post_box p {
  margin: 0;
  font-size: var(--ox-t-sm);
  line-height: 1.6;
  color: var(--ox-text-soft);
}

.post_box a {
  margin-top: auto;
  padding-top: var(--ox-s-2);
  font-size: var(--ox-t-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-decoration: none;
}

/* the three cards were bottom-aligned against a row of unequal photos;
   with the photos gone they should simply be equal-height columns */
.parent_post {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: var(--ox-s-3);
  align-items: stretch;
  width: min(100%, 72rem);
  margin-inline: auto;
}

/* style.css pins each card to flex: 0 0 30%, which fights the grid */
.parent_post .post_box { flex: initial; border: 1px solid var(--ox-border); transition: transform 0.3s ease, box-shadow 0.3s ease; }

@media (min-width: 992px) {
  .parent_post .post_box:nth-child(2) {
    transform: scale(1.08);
    z-index: 2;
    box-shadow: 0 20px 40px rgba(0, 0, 0, 0.08);
    border-color: var(--ox-blue-deep);
  }
}

.sec_6 .row.align-items-end { align-items: stretch !important; }

.post_box { text-align: left; }

/* ==========================================================================
   Logo sizing
   The SVGs carry their own intrinsic width and nothing in style.css constrains
   them, so on a 375px viewport the header logo rendered nearly full-bleed.
   ========================================================================== */

.logo img,
.footer_inner img,
.f_logo img {
  max-width: 100%;
  height: auto;
}

.logo img { width: 190px; }

@media (max-width: 991px) {
  .logo img { width: 160px; }
}

@media (max-width: 575px) {
  .logo img { width: 140px; }
}

/* ==========================================================================
   Dark sections
   style.css sets `section.sec_5 { background:#000 }` and the same on sec_9.
   That is element+class, so it outranks a plain `.services` rule - the brand
   dark was being written and then silently discarded.

   Pure black is the wrong dark for a blue brand: it has no hue, so it reads as
   a hole punched in the page rather than the same system turned down. The
   brand dark is navy, which keeps the blue family intact.
   ========================================================================== */

section.sec_5,
section.sec_9 {
  background: var(--ox-surface-dark);
}

/* a hairline at each edge so the band reads as deliberate, not as a gap */
section.sec_5 { border-block: 1px solid rgba(255, 255, 255, 0.06); }

/* the remaining hard-coded blacks, all element+class in style.css so they
   outrank a plain class rule the same way sec_5 did */
section.header-top,
section.form_sec {
  background: var(--ox-surface-dark);
}

.request_inner ul li .global_btn.left span:nth-child(1) button {
  background: var(--ox-navy);
}

/* "Watch Our Success Stories" sits on the brand gradient and its buttons are
   white outlines. Filling them with navy on hover put a dark block on a blue
   ground - muddy, and the opposite of what an outline button on colour should
   do. It inverts instead: white fill, brand text. */
.success_big ul {
  flex-wrap: wrap;
  gap: var(--ox-s-2);
  align-items: center;
}

.success_big ul > li:nth-child(1) {
  flex: 1 1 18rem;
  min-width: 0;
}

.success_big ul > li:nth-child(2) {
  flex: 0 0 auto;
  margin-right: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.625rem;
}

/* the narrower cards carry the same tags in a <span> rather than a list */
.success_big > span {
  display: flex;
  flex-wrap: wrap;
  gap: 0.625rem;
}

/* gap does the spacing now; these margins only pushed the row off-centre.
   Matching style.css's own specificity, including its mobile override. */
.success_big ul li:nth-child(2) button.btn,
.success_big ul li button,
.success_big ul li .btn,
.success_big > span button,
.success_big > span .btn {
  margin: 0;
}

/* The card headings were <h2>s under the section's own <h2>. As <h3>s they no
   longer match style.css's `.success_big h2`, so the type comes from here. */
.success_big ul li h3,
.success_big h3 {
  margin: 0;
  font-size: clamp(1.35rem, 2.2vw, 1.75rem);
  line-height: 1.25;
  font-weight: 600;
  color: #fff;
}

.success_big button,
.success_big .btn {
  color: #fff;
  border-color: rgb(255 255 255 / 0.6);
  transition: background var(--ox-transition), color var(--ox-transition),
              border-color var(--ox-transition);
}
.success_big button:hover,
.success_big .btn:hover,
.success_big button:focus-visible {
  background: #fff;
  border-color: #fff;
  color: var(--ox-blue-deep);
}

/* `.packages_box button.btn.active` used to be filled navy here. With the
   featured plan now carrying the only filled button, a second solid button in
   the first card made two of the three look like the recommendation. The
   `.active` class stays in the markup - it is Bootstrap tab plumbing, not a
   visual state - so it simply gets the same outline treatment as the rest. */

/* ==========================================================================
   Dark-section text
   The type scale sets .global_inner h2 to navy, which is right on every light
   section and invisible on the two navy ones - navy on navy. Overriding per
   dark section rather than per heading, so a new heading in these sections
   inherits the correct colour instead of repeating the bug.
   ========================================================================== */

/* Every dark or saturated surface, listed once. `.choose_sec` carries a
   `.no_bg` modifier on the inner pages that turns the section white while
   keeping the class - services-inner has one of each - so a class name alone
   is not proof a surface is dark. Every other selector here was checked
   across all pages and is dark wherever it appears.

   Every dark or saturated surface, listed once. The type scale sets headings
   to navy, which is right on white and invisible on these - and patching it
   per section is how the same bug reappeared three times (sec_5, sec_9, the
   footer). Anything added to a surface below inherits the right colour. */
.sec_5, .sec_9, .sec_7, .choose_sec, .header-top, .form_sec, .main_folder {
  --on-dark: 1;
}

section.sec_5 :is(h1,h2,h3,h4,h5,h6),
section.sec_9 :is(h1,h2,h3,h4,h5,h6),
section.sec_7 :is(h1,h2,h3,h4,h5,h6),
section.choose_sec:not(.no_bg) :is(h1,h2,h3,h4,h5,h6),
section.form_sec :is(h1,h2,h3,h4,h5,h6),
footer.main_folder :is(h1,h2,h3,h4,h5,h6) {
  color: #fff;
}

section.sec_5 :is(p, li, span),
section.sec_9 :is(p, li, span),
section.sec_7 :is(p, li),
section.choose_sec:not(.no_bg) :is(p, li),
section.form_sec :is(p, li),
footer.main_folder :is(p, li) {
  color: rgba(255, 255, 255, 0.72);
}

/* links on dark keep their own treatment */
section.sec_5 a:not(.btn-ox):not(.services__link),
section.sec_9 a:not(.btn-ox),
footer.main_folder a {
  color: rgba(255, 255, 255, 0.82);
}

footer.main_folder a:hover { color: #fff; }

/* ==========================================================================
   Container gutters
   style.css sets `.container { max-width: 1620px !important }` with only the
   12px bootstrap padding, so at most widths the content runs to within 12px of
   the viewport edge. The max-width is left alone - the galleries are built for
   it - but the gutter is made real.
   ========================================================================== */

.container {
  padding-inline: clamp(1rem, 4vw, 3rem);
}

/* ==========================================================================
   Packages toggle
   The Monthly/Yearly switch sits under #packageTabs, not the .tab_wrapper the
   earlier remap targeted, so it kept the magenta gradient.
   ========================================================================== */

/* style.css wins this one with
   `.mainactive_cta ul#packageTabs li.nav-item button.nav-link.active`
   - specificity (1,4,3). Matched rather than reached for !important. */
.mainactive_cta ul#packageTabs li.nav-item button.nav-link.active {
  background: var(--ox-gradient);
  border-color: transparent;
  color: #fff;
}

/* the inactive half of the Monthly/Yearly switch was plain black */
.mainactive_cta ul#packageTabs li.nav-item button.nav-link {
  color: var(--ox-navy);
  transition: color var(--ox-transition), background var(--ox-transition);
}
.mainactive_cta ul#packageTabs li.nav-item button.nav-link:not(.active):hover {
  color: var(--ox-blue-deep);
  background: rgb(var(--ox-blue-bright-rgb) / 0.07);
}

/* ==========================================================================
   Orbit diagram
   Replaces circle.webp. Everything that was pixels is now text or vector, so
   it is selectable, indexable, crisp at any density, and follows the palette.
   ========================================================================== */

.orbit {
  position: relative;
  width: min(100%, 26rem);
  margin-inline: auto;
  aspect-ratio: 1;
  display: grid;
  place-items: center;
}

.orbit__ring {
  position: absolute;
  inset: 8%;
  border-radius: 50%;
  border: 1px solid transparent;
  background:
    linear-gradient(var(--ox-surface), var(--ox-surface)) padding-box,
    var(--ox-gradient-diag) border-box;
}

.orbit__center {
  position: relative;
  width: 68%;
  text-align: center;
}

.orbit__eyebrow {
  margin: 0 0 0.35rem;
  font-size: var(--ox-t-xs);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ox-blue-deep);
}

.orbit__title {
  margin: 0 0 0.5rem;
  font-size: var(--ox-t-lg);
  line-height: 1.2;
  letter-spacing: -0.015em;
  font-weight: 600;
  color: var(--ox-navy);
}
.orbit__title span { display: block; }

.orbit__body {
  margin: 0;
  font-size: var(--ox-t-xs);
  line-height: 1.55;
  color: var(--ox-text-soft);
}

/* the four nodes sit centred on the ring where it crosses each 45° diagonal.
   The ring is inset 8%, so its radius is 42% of the orbit and the crossing
   point is 42% / sqrt(2) = 20.302% from the edge. --node-inset backs that off
   by half a node so the node's centre lands on the line - resize with
   --node-size alone and the placement stays correct. */
.orbit__node {
  --node-size: 18%;
  --node-inset: calc(20.302% - var(--node-size) / 2);
  position: absolute;
  display: grid;
  place-items: center;
  width: var(--node-size);
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--ox-surface);
  box-shadow: var(--ox-shadow-m);
  color: var(--ox-blue-deep);
}

.orbit__node svg { width: 46%; height: 46%; }

/* --- hub variant: every node is a link to a service ------------------- */
.orbit--hub .orbit__node {
  text-decoration: none;
  transition: transform var(--ox-transition), box-shadow var(--ox-transition);
}
.orbit--hub .orbit__node:hover,
.orbit--hub .orbit__node:focus-visible {
  transform: scale(1.07);
  box-shadow: var(--ox-shadow-l);
}
.orbit--hub .orbit__node:focus-visible {
  outline: 2px solid var(--ox-blue-bright);
  outline-offset: 3px;
}

.orbit__link {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  margin-top: 0.15rem;
  font-size: var(--ox-t-sm);
  font-weight: 600;
  color: var(--ox-blue-deep);
  text-decoration: none;
}
.orbit__link:hover { color: var(--ox-blue-bright); }
.orbit__link svg { transition: transform var(--ox-transition); }
.orbit__link:hover svg { transform: translateX(2px); }

/* filled node, matching the one accent the original had */
.orbit__node--tl {
  top: var(--node-inset);
  left: var(--node-inset);
  background: var(--ox-gradient-diag);
  color: #fff;
}

.orbit__node--tr { top: var(--node-inset);    right: var(--node-inset); }
.orbit__node--bl { bottom: var(--node-inset); left: var(--node-inset);  }
.orbit__node--br { bottom: var(--node-inset); right: var(--node-inset); }

@media (max-width: 767px) {
  .orbit { width: min(100%, 20rem); }
  .orbit__body { display: none; }   /* too tight to read at this size */
}

/* the portrait is only 153x219 in the source, so it is capped near its native
   size rather than blown up into a blur */
/* .card_icon is position:absolute in style.css - it floats in the card's top
   corner and takes no space in the flow, so the portrait has to clear it. */
.schedule_portrait {
  display: grid;
  place-items: center;
  margin: calc(56px + var(--ox-s-2)) 0 var(--ox-s-1);
}

.schedule_portrait img {
  width: min(100%, 168px);
  height: auto;
  border-radius: 50% 50% 48% 48% / 46% 46% 54% 54%;
  background: var(--ox-surface-muted);
}

/* ==========================================================================
   Why our solutions work
   Was a heading, a paragraph and a stock meeting photo - the same photo that
   already appeared in the process cards above. The photo proved nothing, so it
   is replaced by the thing that actually answers the question: what runs
   before a release reaches the client's users.
   ========================================================================== */

.whywork {
  background: var(--ox-surface-muted);
}

.whywork__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: clamp(2rem, 5vw, var(--ox-s-5));
  /* the photo column is ~290px taller than the copy; centring it dropped the
     heading a long way down the section. Both columns start at the top. */
  align-items: start;
}

.whywork__eyebrow {
  display: inline-block;
  margin: 0 0 var(--ox-s-2);
  padding: 0.35rem 0.9rem;
  border: 1px solid var(--ox-border);
  border-radius: var(--ox-r-pill);
  background: var(--ox-surface);
  font-size: var(--ox-t-xs);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ox-blue-deep);
}

.whywork__lede {
  max-width: 34rem;
  margin: 0 0 var(--ox-s-4);
  font-size: var(--ox-t-base);
  line-height: 1.65;
  color: var(--ox-text-soft);
}

.whywork__points {
  display: grid;
  gap: var(--ox-s-3);
}

/* The number used to sit in its own 2.5rem track with a 1rem gap, so every
   point started 56px in while "01" only filled ~20px of it. That left a dead
   strip down the left and a hard step off the heading above. The number is
   part of the heading line now: heading, lede and all four points share one
   left edge. */
.whywork__points li {
  padding-left: 0;
}

.whywork__num {
  margin-right: 0.55rem;
  font-size: var(--ox-t-sm);
  font-weight: 700;
  letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
  color: var(--ox-blue-bright);
}

.whywork__points h3 {
  margin: 0 0 0.25rem;
  font-size: var(--ox-t-base);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ox-navy);
}

.whywork__points p {
  margin: 0;
  font-size: var(--ox-t-sm);
  line-height: 1.6;
  color: var(--ox-text-soft);
}

/* --- the release panel ------------------------------------------------- */
.pipeline {
  border: 1px solid var(--ox-border);
  border-radius: var(--ox-r-lg);
  background: var(--ox-surface);
  box-shadow: var(--ox-shadow-l);
  overflow: hidden;
}

.pipeline__bar {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.75rem var(--ox-s-2);
  border-bottom: 1px solid var(--ox-border);
  background: var(--ox-surface-muted);
}

.pipeline__dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #D7DEEC;
}

.pipeline__label {
  margin-left: auto;
  font-size: var(--ox-t-xs);
  font-weight: 600;
  color: var(--ox-text-dim);
}

.pipeline__steps { padding: 0.35rem 0; }

.pipeline__steps li {
  display: grid;
  grid-template-columns: 1.5rem minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.7rem;
  padding: 0.7rem var(--ox-s-2);
}

.pipeline__steps li + li { border-top: 1px solid var(--ox-surface-muted); }

.pipeline__tick {
  position: relative;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 50%;
  background: var(--ox-gradient-diag);
}

/* the tick itself, drawn rather than shipped as an icon file */
.pipeline__tick::after {
  content: "";
  position: absolute;
  left: 36%;
  top: 24%;
  width: 26%;
  height: 46%;
  border: 2px solid #fff;
  border-top: 0;
  border-left: 0;
  transform: rotate(42deg);
}

.is-live .pipeline__tick {
  background: var(--ox-surface);
  border: 2px solid var(--ox-blue-bright);
}

.is-live .pipeline__tick::after {
  border-color: var(--ox-blue-bright);
}

.pipeline__step {
  font-size: var(--ox-t-sm);
  font-weight: 600;
  color: var(--ox-navy);
}

.pipeline__meta {
  font-size: var(--ox-t-xs);
  color: var(--ox-text-dim);
  white-space: nowrap;
}

.is-live .pipeline__meta {
  font-weight: 700;
  color: var(--ox-blue-deep);
}

.pipeline__scores {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  padding: 0;
  border-top: 1px solid var(--ox-border);
  background: var(--ox-border);
}

.pipeline__scores div {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.1rem;
  padding: var(--ox-s-2) 0.5rem;
  background: var(--ox-surface);
}

.pipeline__scores strong {
  font-size: var(--ox-t-xl);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--ox-blue-deep);
}

.pipeline__scores span {
  font-size: var(--ox-t-xs);
  color: var(--ox-text-dim);
  text-align: center;
}

.whywork__caption {
  margin: var(--ox-s-2) 0 0;
  text-align: center;
  font-size: var(--ox-t-xs);
  color: var(--ox-text-dim);
}

/* --- the photo the release panel sits on -------------------------------
   The section used to be a flat photograph on the left and a wall of text on
   the right. The photo stays - it is the team the copy is about - but the
   release panel now overlaps its lower edge, so the two read as one object
   instead of two columns of unrelated content. */
.whywork__photo {
  margin: 0;
  border-radius: var(--ox-r-lg);
  overflow: hidden;
  background: var(--ox-surface-muted);
  box-shadow: var(--ox-shadow-m);
}

.whywork__photo picture {
  display: block;
  line-height: 0;
}

.whywork__photo img {
  display: block;
  width: 100%;
  height: auto;
  /* a 3/4 portrait made this column 467px taller than the copy beside it,
     leaving a dead strip down the bottom left. A table scene reads better
     landscape anyway. */
  aspect-ratio: 16 / 10;
  object-fit: cover;
  object-position: 50% 42%;
}

.whywork__visual .pipeline {
  position: relative;
  z-index: 1;
  margin: -5rem 1.25rem 0;
}

@media (max-width: 767px) {
  .whywork__photo img { aspect-ratio: 4 / 3; }
  .whywork__visual .pipeline { margin: -3rem 0.5rem 0; }
}

@media (max-width: 991px) {
  .whywork__grid { grid-template-columns: minmax(0, 1fr); }
  .whywork__visual { order: -1; }
}

.pipeline__gateslabel {
  margin: 0;
  padding: 0.6rem var(--ox-s-2) 0;
  border-top: 1px solid var(--ox-border);
  font-size: var(--ox-t-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ox-text-dim);
}

.pipeline__gateslabel + .pipeline__scores { border-top: 0; }

/* ==========================================================================
   Process card photos
   A full-bleed photo header - it runs to the card edge and the card's own
   overflow:hidden clips it to the rounded top corners. A fixed aspect ratio
   keeps the three headers the same height whatever the source crop is.
   ========================================================================== */

.card-shot {
  margin: 0;
  overflow: hidden;
  background: var(--ox-surface-muted);
}

.card-shot picture {
  display: block;
  line-height: 0;
}

.card-shot img {
  display: block;
  margin: 0;                      /* style.css floats .post-box img right */
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;          /* holds the space before the file lands */
  object-fit: cover;
  transition: transform 0.55s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.card-col:hover .card-shot img { transform: scale(1.045); }

/* A centred paragraph of this length is hard to track back to - every line
   starts in a different place. Left-aligned, with the eyebrow and button
   keeping their own alignment. */
.post-box { text-align: left; }
.post-box h5,
.post-box p.post-box__kicker { text-align: left; }

/* style.css insets only the paragraph by 30px, so the copy did not line up
   with the heading, the eyebrow or the diagram above it. One left edge. */
.post-box p { padding-inline: 0; }
.post-box button { margin-left: 0; }

/* Stacked on phones the three cards are still one grid row, so Bootstrap
   stretches them all to the tallest - which strands the bottom-pinned button
   in a gap on the shorter cards. Let each card take its own height there. */
@media (max-width: 575.98px) {
  .process-section .row { align-items: flex-start; }
}

/* ==========================================================================
   Featured service cards - product shots
   The three service photos, each in a 16:9 frame so the cards keep a common
   top edge. The sources are only ~370px wide, so they are never asked to
   render larger than the card and the frame does the cropping.
   ========================================================================== */

/* full-bleed photo header: negative margins cancel the card's padding on the
   top and both sides, the card's overflow:hidden clips it to the rounded
   corners. Same treatment as the process cards' .card-shot. */
.post_box__shot {
  position: relative;
  margin: calc(var(--ox-s-3) * -1) calc(var(--ox-s-3) * -1) var(--ox-s-2);
  border: 0;
  border-radius: 0;
  overflow: hidden;
  background: var(--ox-surface-muted);
  line-height: 0;
}

.post_box__shot picture {
  display: block;
  line-height: 0;
}

.post_box__shot img {
  display: block;
  margin: 0;                      /* style.css adds 20px under .post_box img */
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  transition: transform 0.55s cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* a whisper of brand over the photo, so three unrelated stock shots still
   read as one set */
.post_box__shot::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(160deg, rgb(var(--ox-blue-bright-rgb) / 0.10), rgb(var(--ox-blue-deep-rgb) / 0.04) 55%, transparent);
  pointer-events: none;
}

.post_box:hover .post_box__shot img { transform: scale(1.05); }

/* the shot is the card's lead element now, so the old icon spacing goes */
.post_box { text-align: left; }
.post_box h3 { margin-top: 0; }

/* ==========================================================================
   Inner-page navigation
   style.css sets `.menu ul li a { color:#fff }` and then darkens it again per
   page - `body.page-home`, `body.page-refund-policy`, and two more. Those body
   classes are added by JavaScript on DOMContentLoaded (assets/js/custom.js).

   Two consequences: any page not on that list rendered white links on the
   light banner - about, services, contact-us and blog were all at a 1.16
   contrast ratio, i.e. invisible - and even the listed pages flash white
   before the script runs.

   Every header on the site is light now, so dark is the correct default and
   the allow-list is no longer load-bearing. New pages inherit it.
   ========================================================================== */

.menu ul li a,
.side-menu ul li a {
  color: var(--ox-navy);
}

.menu ul li a:hover,
.side-menu ul li a:hover {
  color: var(--ox-blue-deep);
}

/* The page you are on. Keyed off aria-current, not a class: the attribute is
   what a screen reader announces, so one hook serves both and they cannot fall
   out of step. An underline rather than a colour swap - every header on the
   site is light now, but an accent rule survives a dark one too. */
.menu ul li a[aria-current="page"] {
  color: var(--ox-blue-deep);
  font-weight: 600;
}
.menu ul li a[aria-current="page"]::after {
  content: "";
  display: block;
  height: 2px;
  margin-top: 4px;
  border-radius: 2px;
  background: var(--ox-cyan);
}

/* the two existing overrides set #000 / black; bring them onto the token so
   the nav is one colour everywhere rather than two near-blacks */
body.page-home .menu ul li a,
body.page-refund-policy .menu ul li a,
body.page-terms-and-conditions .menu ul li a,
body.page-privacy-policy .menu ul li a {
  color: var(--ox-navy);
}

/* banner text on the inner pages: white was meant for a dark banner that no
   longer exists */
section.inner-banner .global_inner h2,
section.inner-banner .global_inner p,
section.inner-banner h1,
section.inner-banner p {
  color: var(--ox-navy);
}

section.inner-banner .global_inner p,
section.inner-banner p {
  color: var(--ox-text-soft);
}

/* ==========================================================================
   Light cards inside dark sections
   The dark-surface rules above colour every descendant, but some of those
   sections hold white cards - .choose_wrapper on services-inner sits on the blue
   gradient and its list items are white. Their text was being painted white
   too, i.e. white on white. Text inside a card follows the card, not the
   section behind it.
   ========================================================================== */

section.choose_sec .choose_wrapper ul li :is(p, span, li) {
  color: var(--ox-text-soft);
}

section.choose_sec .choose_wrapper ul li :is(h1, h2, h3, h4, h5, h6) {
  color: var(--ox-navy);
}

/* ==========================================================================
   Inner-page hero (section.global_sec)
   Used by about, services, services-inner, blog, blog-inner and contact-us.

   It was painted with shade-bg.webp - a black field with a purple glow on the
   left and a blue one on the right, straight from the old palette. Replaced
   with a gradient in brand colours: same dark hero, no raster, and it scales
   to any width instead of stretching a 1600px image.
   ========================================================================== */

section.global_sec {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  height: auto;
  min-height: clamp(27rem, 62vh, 39rem);
  display: flex;
  align-items: center;
  padding-block: clamp(8.5rem, 15vh, 11rem) clamp(3.5rem, 8vh, 6rem);
  background-color: var(--ox-surface-dark);
  background-image:
    radial-gradient(60% 120% at 5% 0%,    rgb(var(--ox-blue-bright-rgb) / 0.40) 0%, transparent 60%),
    radial-gradient(52% 115% at 97% 100%, rgb(var(--ox-cyan-rgb) / 0.26) 0%, transparent 58%),
    radial-gradient(82% 150% at 84% 2%,   rgb(var(--ox-blue-deep-rgb) / 0.52)  0%, transparent 64%),
    linear-gradient(180deg, transparent 56%, rgba(4, 8, 24, 0.55) 100%);
  background-repeat: no-repeat;
}

/* faint dot grid so the flat gradient reads as a surface, not a wash */
section.global_sec::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: radial-gradient(rgba(255, 255, 255, 0.55) 1px, transparent 1px);
  background-size: 44px 44px;
  opacity: 0.045;
  -webkit-mask-image: radial-gradient(78% 78% at 50% 24%, #000 0%, transparent 74%);
          mask-image: radial-gradient(78% 78% at 50% 24%, #000 0%, transparent 74%);
}

/* hairline at the foot so the band ends deliberately */
section.global_sec::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgb(var(--ox-cyan-rgb) / 0.35), transparent);
}

body.page-blog-inner section.global_sec {
  height: auto;
  min-height: clamp(30rem, 72vh, 44rem);
}

/* --- the label above the heading -------------------------------------
   Was <h1 class="border-txt"> rendered as a 42px ghost-outline sitting
   behind the h2 - muddy on the dark field and adding noise, not weight.
   Now a crisp eyebrow chip, matching the home hero. */
section.global_sec .border-txt,
section.global_sec .global_inner > h6:first-child,
section.global_sec .col-md-8 > h6:first-child,
section.global_sec .global_inner.position-relative:has(+ .design_circle)::before {
  position: static;
  z-index: auto;
  top: auto;
  left: auto;
  opacity: 1;
  -webkit-text-stroke: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0 0 1.4rem;
  padding: 0.55rem 1.05rem 0.55rem 0.62rem;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: var(--ox-r-pill);
  background: rgba(255, 255, 255, 0.06);
  font-size: 0.8125rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ox-cyan);
}

section.global_sec .border-txt::before,
section.global_sec .global_inner > h6:first-child::before,
section.global_sec .col-md-8 > h6:first-child::before {
  content: "";
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--ox-cyan);
  box-shadow: 0 0 12px var(--ox-cyan);
}

/* services-inner has no label in the markup - generate one */
section.global_sec .global_inner.position-relative:has(+ .design_circle)::before {
  content: "What we build";
}

/* the descriptive heading: a real page hero, not a section sub-head */
section.global_sec .global_inner h1:not(.border-txt) {
  margin: 10px 0;
}

section.global_sec .global_inner h2,
section.global_sec .global_inner h1:not(.border-txt),
section.global_sec .col-md-8 > h2 {
  font-size: clamp(2.3rem, 4.8vw, 3.75rem);
  line-height: 1.08;
  letter-spacing: -0.03em;
  font-weight: 700;
  max-width: 22ch;
  text-wrap: balance;
  text-shadow: 0 2px 44px rgb(var(--ox-blue-deep-rgb) / 0.32);
}

section.global_sec .col-md-8 > h2 {
  max-width: 26ch;
}

/* the intro copy in the right-hand column, given a quiet rule so it
   reads as a deck rather than loose body text */
section.global_sec .global_inner:not(.position-relative) p {
  max-width: 34rem;
  padding-left: 1.3rem;
  border-left: 2px solid rgb(var(--ox-cyan-rgb) / 0.55);
  font-size: 1.0625rem;
  line-height: 1.72;
  color: rgba(255, 255, 255, 0.74);
}

/* :not(.border-txt) - the About hero's label is a <p> now, and this rule for
   the hero deck copy would otherwise repaint it as body text. */
section.global_sec .col-md-8 > p:not(.border-txt),
section.global_sec .global_inner.position-relative > p:not(.border-txt) {
  max-width: 44rem;
  font-size: 1.0625rem;
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.74);
}

@media (max-width: 991px) {
  section.global_sec {
    min-height: 0;
  }

  section.global_sec .global_inner:not(.position-relative) p {
    margin-top: 1.5rem;
  }
}

@media (max-width: 575px) {
  section.global_sec .global_inner h2,
  section.global_sec .global_inner h1:not(.border-txt),
  section.global_sec .col-md-8 > h2 {
    font-size: clamp(1.95rem, 8.5vw, 2.4rem);
    max-width: none;
  }
}

/* ==========================================================================
   Header and hero text over that dark hero
   The nav is navy by default now, which is right on every light header and
   wrong on these six pages, where the header floats over the dark hero.
   `:has()` keys off the hero actually being present, so it does not depend on
   the JavaScript body class - no flash of the wrong colour on load, and a new
   page using this hero is handled without adding it to a list.
   ========================================================================== */

body:has(section.global_sec) .menu ul li a {
  color: rgba(255, 255, 255, 0.86);
}

body:has(section.global_sec) .menu ul li a:hover {
  color: #fff;
}

/* Same problem, same fix, for the logo itself. `.parent-head` is positioned
   absolute, so the header floats over whatever section comes first. On the six
   pages that open with the dark hero the navy wordmark (#0A1E5A) sat on the
   navy field and effectively disappeared - the nav links were corrected here
   but the logo was missed.

   Both marks ship in the markup and CSS picks one, so there is no flash of the
   wrong logo and no dependence on the JavaScript body class. Dark stays the
   default: white is only correct where the hero is dark, and on the home page
   and the policy pages - which open on a light background - a white logo would
   be just as invisible as the navy one is here. */

.logo__img--light {
  display: none;
}

body:has(section.global_sec) .logo__img--dark {
  display: none;
}

body:has(section.global_sec) .logo__img--light {
  display: inline-block;
}

section.global_sec :is(h1, h2, h3, h4, h5, h6) {
  color: #fff;
}

section.global_sec :is(p, li) {
  color: rgba(255, 255, 255, 0.76);
}

/* the small eyebrow above the hero heading */
section.global_sec .global_inner h5,
section.global_sec .global_inner h6 {
  color: var(--ox-cyan);
}

/* the drawn laptop, still in use on the about page */
.journey_img .laptop svg {
  display: block;
  width: 100%;
  height: auto;
}

/* the home page runs the photographed version: a cut-out render with its own
   soft shadow, so it needs no frame - just room to breathe and a slow lift on
   hover to match the cards above it */
.journey_img picture {
  display: block;
  line-height: 0;
}

.journey_img img {
  display: block;
  width: 100%;
  height: auto;
  transition: transform 0.6s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.journey_img:hover img { transform: translateY(-6px); }

/* Nothing on this page needs to move for a pointer that is only passing
   through. */
@media (prefers-reduced-motion: reduce) {
  .card-shot img,
  .post_box__shot img,
  .journey_img img {
    transition: none;
  }

  .card-col:hover .card-shot img,
  .post_box:hover .post_box__shot img,
  .journey_img:hover img {
    transform: none;
  }
}

/* ==========================================================================
   Consultation card (includes/accordian.php)
   The card was a mark, a heading and a button with a lot of empty space under
   it. The booking widget shows the thing the button does - pick a day, pick a
   slot - and the footer pills carry the real terms as text rather than
   decoration.
   ========================================================================== */

.schedule_inner .booking {
  margin: var(--ox-s-3) 0 var(--ox-s-3);
  border-radius: var(--ox-r-md);
}

.schedule_inner .booking svg {
  display: block;
  width: 100%;
  height: auto;
}

/* the same booking widget as the consultation card, sized for this one.
   The meta pills went with it - the widget's footer already says
   30 minutes / Free / Online, and two copies of the same terms in one card
   read as filler. */
.schedule_card .booking {
  margin-top: var(--ox-s-1);
  border: 1px solid var(--ox-border);
  border-radius: var(--ox-r-md);
  overflow: hidden;
}

.schedule_card .booking svg {
  display: block;
  width: 100%;
  height: auto;
}

/* .schedule_inner is centred, so the widget needs a real width to sit in */
.schedule_inner .booking {
  width: min(100%, 21rem);
  margin-inline: auto;
  border: 1px solid var(--ox-border);
  overflow: hidden;
}

/* ==========================================================================
   Featured blog card
   The card used to be a single raster - stock photo, old magenta gradient, and
   the previous template's pink logo burnt into the pixels, so neither the
   colour nor the branding could be corrected in CSS. Drawn instead.
   ========================================================================== */

.image_tab--brand {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 1.3rem;
  min-height: 33rem;
  padding: 3.4rem 1.6rem 1.6rem;
  border-radius: var(--ox-r-lg);
  overflow: hidden;
  background:
    radial-gradient(95% 55% at 88% 0%, rgb(var(--ox-cyan-rgb) / 0.30) 0%, transparent 58%),
    var(--ox-gradient-deep);
}

/* a soft orbit ring, echoing the mark, low in the corner for depth */
.image_tab--brand::after {
  content: "";
  position: absolute;
  right: -30%;
  bottom: -36%;
  width: 82%;
  aspect-ratio: 1;
  border-radius: 50%;
  border: 1.5px solid rgba(255, 255, 255, 0.10);
  pointer-events: none;
}

/* ---- the concept-to-scale figure ---------------------------------------- */
.image_tab--brand .tab_viz {
  position: relative;
  z-index: 1;
  margin: 0;
  display: grid;
  gap: 0.85rem;
}

.tab_viz__win {
  border-radius: 12px;
  overflow: hidden;
  background: #fff;
  box-shadow: 0 26px 44px -18px rgba(3, 10, 35, 0.6);
}

.tab_viz__bar {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 8px 12px;
  background: #eef1f7;
  border-bottom: 1px solid #e3e7f1;
}

.tab_viz__bar i {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #ccd4e4;
}

.tab_viz__bar span {
  margin-left: 8px;
  height: 12px;
  flex: 1;
  max-width: 130px;
  border-radius: 4px;
  background: #dee4ef;
}

.tab_viz__plot {
  padding: 13px 14px 11px;
}

.tab_viz__plot svg {
  display: block;
  width: 100%;
  height: 72px;
}

.tab_viz__legend {
  display: flex;
  justify-content: space-between;
  margin-top: 8px;
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #8894b0;
}

/* concept -> build -> ship -> scale */
.tab_viz__steps {
  display: flex;
  align-items: stretch;
  margin: 0;
  padding: 0;
  list-style: none;
}

.tab_viz__steps li {
  flex: 1;
  text-align: center;
  padding: 0.5rem 0.2rem;
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.66);
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-right-width: 0;
}

.tab_viz__steps li:first-child {
  border-radius: var(--ox-r-pill) 0 0 var(--ox-r-pill);
}

.tab_viz__steps li.is-on {
  color: #fff;
  background: var(--ox-gradient);
  border-color: transparent;
  border-right-width: 1px;
  border-radius: 0 var(--ox-r-pill) var(--ox-r-pill) 0;
  box-shadow: 0 8px 20px -6px rgb(var(--ox-blue-deep-rgb) / 0.55);
}

/* one entry point, many instances */
.tab_viz__nodes {
  display: flex;
  align-items: center;
  gap: 6px;
}

.tab_viz__nodes b {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.13);
  border: 1px solid rgba(255, 255, 255, 0.24);
}

.tab_viz__nodes b::before {
  content: "";
  width: 11px;
  height: 11px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.55);
}

.tab_viz__nodes b.is-lb {
  background: #fff;
  border-color: #fff;
}

.tab_viz__nodes b.is-lb::before {
  background: var(--ox-blue-deep);
  border-radius: 50%;
}

.tab_viz__nodes span {
  flex: 1;
  height: 2px;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0.45), rgba(255, 255, 255, 0.08));
}

.image_tab--brand .image_content p {
  margin-bottom: 0.9rem;
}

.image_tab__badge {
  position: absolute;
  top: var(--ox-s-3);
  left: var(--ox-s-3);
  display: grid;
  place-items: center;
  width: 4rem;
  height: 4rem;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.14);
  border: 1px solid rgba(255, 255, 255, 0.28);
  backdrop-filter: blur(2px);
}

.image_tab--brand .image_content {
  position: static;
  width: 100%;
}

.image_tab--brand .image_content p {
  font-size: var(--ox-t-sm);
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.82);
}

/* the headline beside the card broke mid-word ("Enterprise-Ready") on
   narrow columns - the markup now uses a non-breaking hyphen; balance the
   remaining lines */
.blog_sec_content .global_inner h2.normal {
  text-wrap: balance;
}

.image_tab--brand .image_content ul {
  flex-wrap: wrap;
  gap: 0.5rem;
}

/* A translucent white fill measured 2.84:1 against the bright end of the
   gradient - under the 4.5 AA needs for small bold text. A navy scrim holds
   5.74 at the bright end and 11.62 at the deep end, so the tags stay legible
   wherever they land on the ramp. */
.image_tab--brand .image_content ul li {
  margin: 0;
  padding: 0.3rem 0.8rem;
  border-radius: var(--ox-r-pill);
  background: rgba(7, 18, 51, 0.30);
  border: 1px solid rgba(255, 255, 255, 0.22);
  color: #fff;
  font-size: var(--ox-t-xs);
  font-weight: 600;
}

/* ==========================================================================
   Two legacy colours the earlier passes missed
   The first sweeps matched five known hex values. #e82861 (blog filter pills)
   and #a70dcd (FAQ list items) were never on that list, so they survived. The
   sweep is hue-based now - see src note - and these were the only two left.
   ========================================================================== */

.tab_wrapper ul#pills-tab li.nav-item button {
  border-color: var(--ox-border);
  color: var(--ox-navy);
}

.tab_wrapper ul#pills-tab li.nav-item button:hover {
  border-color: var(--ox-blue-bright);
  color: var(--ox-blue-deep);
  background: var(--ox-surface-muted);
}

.custom-accordion .accordion-body ul.content-list li:first-child {
  color: var(--ox-blue-deep);
  border-bottom-color: var(--ox-border);
}

/* ==========================================================================
   Subscribe panel submit
   style.css gave this `color: red` and no background, so it rendered as the
   browser's default grey button with red text, sitting on the blue panel.
   On a coloured surface the action reads best as a solid light pill.
   ========================================================================== */

.subscribe_inner input[type="submit"] {
  width: auto;
  min-width: 11rem;
  height: auto;
  padding: 0.85rem 1.6rem;
  border: 0;
  border-radius: var(--ox-r-pill);
  background: #fff;
  color: var(--ox-blue-deep);
  font-size: var(--ox-t-base);
  font-weight: 600;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.subscribe_inner input[type="submit"]:hover {
  transform: translateY(-1px);
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.18);
}

/* the email field on that panel, so it matches */
.subscribe_inner input[type="email"] {
  border: 1px solid rgba(255, 255, 255, 0.4);
  border-radius: var(--ox-r-pill);
  padding-inline: 1.1rem;
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
}

.subscribe_inner input[type="email"]::placeholder {
  color: rgba(255, 255, 255, 0.7);
}

/* ==========================================================================
   Form feedback

   New in the Laravel version: submissions are validated server side now, so a
   rejected lead form has to explain itself instead of silently bouncing the
   visitor back to the page.
   ========================================================================== */

.form_errors {
  margin: 0 0 1.25rem;
  padding: 0.9rem 1.1rem;
  border: 1px solid #F2B8B5;
  border-left: 3px solid #C5221F;
  border-radius: var(--ox-r-md, 10px);
  background: #FDF3F2;
  color: #8C1D18;
  font-size: 0.9rem;
}

.form_errors ul {
  margin: 0 !important;
  padding: 0 !important;
  list-style: none;
}

.form_errors li + li {
  margin-top: 0.35rem;
}

.lead_status {
  display: inline-block;
  margin: 0 0 1rem;
  padding: 0.55rem 1.1rem;
  border-radius: var(--ox-r-pill, 999px);
  background: rgb(var(--ox-blue-bright-rgb) / 0.12);
  color: var(--ox-blue-deep);
  font-weight: 600;
}

/* ==========================================================================
   Lead modal (partials/lead-modal.blade.php)
   Behind every "Talk to Sales" / "Request a Demo" / "Contact ..." button and
   the newsletter boxes - collects name + email (phone / message optional)
   before the lead is filed.
   ========================================================================== */

/* a soft, slightly darkened backdrop reads more considered than a flat wash */
.modal-backdrop.show {
  background: #050f2b;
  opacity: 0.62;
  -webkit-backdrop-filter: blur(5px);
  backdrop-filter: blur(5px);
}

.lead-modal .modal-content {
  border: 0;
  border-radius: var(--ox-r-lg, 16px);
  overflow: hidden;
  box-shadow: 0 30px 70px rgba(4, 14, 45, 0.35);
}

/* rise and settle rather than bootstrap's flat drop */
.lead-modal.fade .modal-dialog {
  transform: translateY(18px) scale(0.97);
  transition: transform 0.28s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.28s ease;
}
.lead-modal.show .modal-dialog {
  transform: translateY(0) scale(1);
}

/* --- branded header band --- */
.lead-modal .modal-header {
  position: relative;
  display: block;
  padding: 1.5rem 1.7rem 1.35rem;
  border-bottom: 0;
  background: var(--ox-gradient-diag);
  color: #fff;
}

.lead-modal__mark {
  display: grid;
  place-items: center;
  width: 2.35rem;
  height: 2.35rem;
  margin: 0 0 0.85rem;
  border-radius: var(--ox-r-md, 12px);
  background: rgba(255, 255, 255, 0.16);
}
.lead-modal__mark img { width: 1.15rem; height: auto; }

.lead-modal .modal-title {
  margin: 0;
  font-size: 1.45rem;
  line-height: 1.2;
  letter-spacing: -0.02em;
  font-weight: 600;
  color: #fff;
}

.lead-modal__badge {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0.7rem 0 0;
  padding: 0.28rem 0.7rem;
  border-radius: var(--ox-r-pill, 999px);
  background: rgba(255, 255, 255, 0.16);
  font-size: var(--ox-t-xs, 0.8125rem);
  font-weight: 600;
  color: #fff;
  white-space: nowrap;
}
.lead-modal__dot {
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  background: #7CF0B4;
  box-shadow: 0 0 0 3px rgba(124, 240, 180, 0.25);
}

.lead-modal .modal-header .btn-close {
  position: absolute;
  top: 1.15rem;
  right: 1.15rem;
  margin: 0;
  padding: 0.5rem;
  border-radius: 50%;
  background-color: rgba(255, 255, 255, 0.16);
  filter: invert(1) grayscale(1) brightness(2.4);
  opacity: 0.9;
  transition: background-color var(--ox-transition, 0.18s ease);
}
.lead-modal .modal-header .btn-close:hover {
  background-color: rgba(255, 255, 255, 0.3);
  opacity: 1;
}

.lead-modal .modal-body {
  padding: 1.4rem 1.7rem 1.7rem;
}

.lead-modal .modal-body > p {
  margin: 0 0 1.3rem;
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--ox-text-soft, #4b5563);
}

/* name and phone share a row so the modal stays short enough to read at once */
.lead-modal__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.85rem;
}

.lead-modal__field {
  display: block;
  margin: 0 0 1.05rem;
}

.lead-modal__field > span {
  display: block;
  margin: 0 0 0.45rem;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ox-navy, #0b1b3f);
}

.lead-modal__field > span em {
  font-style: normal;
  font-weight: 400;
  color: var(--ox-text-dim, #8a94a6);
}

.lead-modal__field input,
.lead-modal__field textarea {
  width: 100%;
  padding: 0.75rem 1rem;
  border: 1px solid var(--ox-border, #d7dbe3);
  border-radius: var(--ox-r-md, 10px);
  background: var(--ox-surface, #fff);
  font-size: 0.95rem;
  font-family: inherit;
  color: var(--ox-navy, #0b1b3f);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.lead-modal__field input {
  height: 48px;
  padding-block: 0;
}

.lead-modal__field textarea {
  resize: vertical;
  min-height: 76px;
}

.lead-modal__field input:focus,
.lead-modal__field textarea:focus {
  outline: 0;
  border-color: var(--ox-blue-bright);
  box-shadow: 0 0 0 3px rgb(var(--ox-blue-bright-rgb) / 0.15);
}

.lead-modal__submit {
  width: 100%;
  min-height: 52px;
  margin-top: 0.5rem;
  border: 0;
  border-radius: var(--ox-r-pill, 999px);
  background: var(--ox-gradient);
  font-size: 1rem;
  font-weight: 600;
  color: #fff;
  cursor: pointer;
  transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.lead-modal__submit:hover {
  transform: translateY(-1px);
  box-shadow: var(--ox-glow, 0 8px 24px rgb(var(--ox-blue-deep-rgb) / 0.28));
}

/* on phones a centred box floats; a sheet anchored to the bottom edge reads
   as native and puts the fields nearer the keyboard */
@media (max-width: 575.98px) {
  .lead-modal .modal-dialog {
    margin: 0;
    min-height: 100%;
    align-items: flex-end;
  }
  .lead-modal .modal-content {
    border-radius: var(--ox-r-lg, 16px) var(--ox-r-lg, 16px) 0 0;
  }
  .lead-modal__row { grid-template-columns: 1fr; gap: 0; }
  .lead-modal .modal-header { padding: 1.3rem 1.3rem 1.2rem; }
  .lead-modal .modal-body { padding: 1.2rem 1.3rem 1.5rem; }
}

@media (prefers-reduced-motion: reduce) {
  .lead-modal.fade .modal-dialog { transition: none; transform: none; }
}

/* ==========================================================================
   Services index - approach band (pages/services/index.blade.php)
   Scoped to its own class on purpose: .sec_8 is shared with the home and
   about pages, which use it for something else entirely.
   ========================================================================== */

.svc_approach {
  padding: var(--ox-section-y) 0;
  background: var(--ox-surface);
}

.svc_approach__head { margin-bottom: clamp(2rem, 5vw, 3.25rem); }

.svc_approach__eyebrow {
  margin: 0 0 0.6rem;
  font-size: var(--ox-t-xs);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  background: var(--ox-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: var(--ox-blue-deep);
}

.svc_approach h2 {
  margin: 0;
  font-size: clamp(1.9rem, 3.6vw, var(--ox-t-3xl));
  line-height: 1.15;
  letter-spacing: -0.025em;
  font-weight: 600;
  color: var(--ox-navy);
}
.svc_approach h2 span { display: block; }

.svc_approach__lede {
  margin: 0;
  font-size: var(--ox-t-base);
  line-height: 1.65;
  color: var(--ox-text-soft);
}

.svc_pillars {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(1rem, 2.2vw, 1.5rem);
  margin: 0;
  list-style: none;
}

.svc_pillars li {
  display: flex;
  flex-direction: column;
  padding: clamp(1.35rem, 2.6vw, 1.75rem);
  border: 1px solid var(--ox-border);
  border-radius: var(--ox-r-lg);
  background: var(--ox-surface);
  box-shadow: var(--ox-shadow-s);
  transition: transform var(--ox-transition), box-shadow var(--ox-transition);
}
.svc_pillars li:hover {
  transform: translateY(-3px);
  box-shadow: var(--ox-shadow-m);
}

.svc_pillars__ico {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  margin-bottom: var(--ox-s-2);
  border-radius: var(--ox-r-md);
  background: var(--ox-surface-muted);
  color: var(--ox-blue-deep);
}
.svc_pillars__ico svg { width: 1.4rem; height: 1.4rem; }

.svc_pillars h3 {
  margin: 0 0 0.45rem;
  font-size: var(--ox-t-base);
  line-height: 1.3;
  letter-spacing: -0.01em;
  font-weight: 600;
  color: var(--ox-navy);
}

.svc_pillars p {
  margin: 0;
  font-size: var(--ox-t-sm);
  line-height: 1.6;
  color: var(--ox-text-soft);
}

@media (max-width: 991.98px) {
  .svc_pillars { grid-template-columns: repeat(2, 1fr); }
  .svc_approach__head > [class*="col-"] + [class*="col-"] { margin-top: var(--ox-s-2); }
}

@media (max-width: 767.98px) {
  /* let the heading wrap naturally rather than at our chosen point */
  .svc_approach h2 span { display: inline; }
}

@media (max-width: 575.98px) {
  .svc_pillars { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Testimonial avatars
   Every one of the twenty cards showed the same stock portrait of one woman,
   over twenty different names - Ahmed Khan and Lin Chen included. Initials are
   honest, legible at 45px, and cost no request.
   ========================================================================== */

.user .user__avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 45px;
  height: 45px;
  border-radius: 50%;
  background: var(--ox-gradient-diag);
  color: #fff;
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: 1;
}

/* ==========================================================================
   Testimonials on phones
   style.css unrolls the marquee into a 6000px stack of 24 cards below 768px -
   an endless scroll. Keep the desktop feel instead: one full-width column,
   ~2.5 cards tall, rolling upward on a loop.
   ========================================================================== */

@media (max-width: 767px) {
  section.sec_10 { padding: 3rem 0; }

  .testimonial-slider {
    display: block;
    position: relative;
    height: clamp(430px, 74vh, 600px);
    overflow: hidden;
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 42px, #000 calc(100% - 42px), transparent 100%);
    mask-image: linear-gradient(to bottom, transparent 0, #000 42px, #000 calc(100% - 42px), transparent 100%);
  }

  /* show one column (6 reviews, printed twice) and roll it up */
  .slider-track { display: none !important; }
  .slider-track:first-child {
    display: flex !important;
    flex-direction: column;
    animation: scrollUp 34s linear infinite !important;
    animation-delay: 0s !important;
    will-change: transform;
  }
  .slider-track:first-child .card-item[aria-hidden="true"] { display: block; }

  .testimonial-slider:active .slider-track { animation-play-state: paused; }

  .card-item { margin: 0 0 12px; padding: 20px; }
  .card-item p {
    display: -webkit-box;
    -webkit-line-clamp: 6;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
}

/* reduced motion: no auto-scroll - a scrollable panel of the six reviews */
@media (max-width: 767px) and (prefers-reduced-motion: reduce) {
  .slider-track:first-child { animation: none !important; }
  .slider-track:first-child .card-item[aria-hidden="true"] { display: none; }
  .testimonial-slider {
    height: auto;
    max-height: 82vh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    -webkit-mask-image: none;
    mask-image: none;
  }
}

/* ==========================================================================
   Link-style CTAs
   Several controls that only ever navigated are <a class="btn"> now, so
   `route()` can generate the href and the markup is honest. The rules that
   sized and skinned them keyed off `button` in the selector - widened to
   the anchor here rather than duplicated across style.css.
   ========================================================================== */

.global_btn span a.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 50px;
  padding: 0 20px;
  font-size: 16px;
  font-weight: 300;
  text-transform: capitalize;
  text-decoration: none;
}

.global_btn span:nth-child(2) a.btn {
  background: transparent;
  color: var(--ox-navy);
  border: 1px solid var(--ox-border);
}

/* Two-CTA rows (Talk to Sales / Request a Demo). style.css only spaced the
   spans horizontally (margin-right), so once they wrapped on a narrow screen
   the buttons stacked flush against each other. Flex + gap spaces them both
   ways. */
.global_btn.left {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.global_btn.left span {
  margin: 0;
}

/* "Read Article" on the blog index - was .blog_post button.btn */
.blog_post a.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 80%;
  min-height: 50px;
  margin: 10px 0 0;
  border: 1px solid #000;
  font-size: 18px;
  font-weight: 500;
  color: #000;
  text-decoration: none;
}

/* ==========================================================================
   Contact page - "We're here to help" card
   style.css hangs a 451px portrait off .request_inner ul::before at
   right:-100px. There is room for that on a wide screen; below the desktop
   grid it just crashes out of the blue card, so it is dropped and the copy
   gets the full width instead of the 60% it shares with the image.
   ========================================================================== */

@media (max-width: 991px) {
  .request_inner ul::before {
    display: none;
  }

  .request_inner ul {
    width: 100%;
    height: auto;
    padding: clamp(1.5rem, 5vw, 2.25rem) !important;
  }

  .request_inner ul li {
    width: 100%;
  }
}

/* ==========================================================================
   Service detail page (services/show.blade.php)
   Every grid on this page was pinned to fixed-percent columns with no wrap
   fallback, so the whole thing broke apart below the desktop width. These
   classes are unique to this page, so they're targeted directly.
   ========================================================================== */

/* hero feature pills - wrap, never run off the edge */
.design_circle ul {
  flex-wrap: wrap;
  row-gap: 10px;
}

/* style.css pulls .image_sec up by 80px so the strip tucks under the hero.
   On these pages the hero ends with the feature pills, and that pull-up was
   landing straight on top of them - 6px of clearance at 1440px and negative as
   soon as the title wrapped to a third line. The pills reserve the height the
   strip takes, so the overlap stays a design detail instead of a collision.
   The three values track the three .image_sec margins below. */
.design_circle {
  margin-bottom: 88px;
}

/* the step number in the process list. It was an <h5> printed before the
   step's own <h3>, which ran the heading levels backwards on all seven service
   pages; as a <p> it also needs its weight back from
   style.css's `p { font-weight: 300 !important }`. */
section.choose_sec.no_bg .choose_wrapper ul li p.step_num {
  margin: 0 0 15px;
  font-size: 26px;
  line-height: 30px;
  font-weight: 400 !important;
  color: var(--ox-navy);
}

@media (max-width: 991px) {
  /* the -80px pull-up is a desktop overlap trick */
  section.image_sec { margin-top: -40px; }
  .design_circle { margin-bottom: 48px; }

  /* Why Choose / Process: 3 fixed columns -> 2 fluid */
  .choose_wrapper ul { justify-content: flex-start; gap: 18px; }
  .choose_wrapper ul li { flex: 1 1 calc(50% - 9px); margin: 0; }

  /* Industries: 6 tiny columns -> 4 */
  .industries_icon ul { justify-content: center; gap: 14px; }
  .industries_icon ul li { flex: 1 1 calc(25% - 11px); margin: 0; }

  /* Brand logos: one non-wrapping row -> wrap */
  ul.brand_logo {
    flex-wrap: wrap;
    gap: 26px 42px;
    justify-content: center;
  }

  /* consultancy form: 3 side-by-side inputs -> stacked */
  .form_wrapper form span { flex-wrap: wrap; }
  .form_wrapper form span input { flex: 1 1 100%; }
}

@media (max-width: 767px) {
  section.image_sec { margin-top: 0; }
  .design_circle { margin-bottom: 0; }

  .choose_wrapper ul li { flex-basis: 100%; padding: 24px; }
  .choose_wrapper ul li span h3 { font-size: 22px; line-height: 1.25; letter-spacing: -0.5px; }

  .industries_icon ul li { flex-basis: calc(50% - 7px); height: 120px; }
  .industries_icon ul li p { font-size: 15px; line-height: 1.3; }

  ul.brand_logo { gap: 22px 30px; }
  ul.brand_logo li img { max-height: 30px; width: auto; }

  /* the submit button was width:12% - about 40px wide, unusable on a phone */
  .form_wrapper form input[type="submit"] {
    width: 100%;
    max-width: 260px;
    height: 52px;
  }

  h1.border-txt { font-size: 40px; line-height: 1.1; top: -20px; }
}

/* ==========================================================================
   Stats counter (sec_4 - about + home)
   style.css just stacked the three stats into a bland left-aligned column on
   phones. Presented as a single bordered strip with divided columns it reads
   as a deliberate stats bar and takes a third of the height.
   ========================================================================== */

@media (max-width: 767px) {
  /* the card lives on .counter_wrapper (a div) - `ul { padding: 0 !important }`
     in style.css would eat any padding put on the ul */
  .counter_wrapper {
    margin-top: clamp(1.25rem, 5vw, 1.75rem);
    padding: clamp(1rem, 4vw, 1.5rem) 0.5rem;
    border: 1px solid var(--ox-border);
    border-radius: var(--ox-r-lg);
    background: var(--ox-surface);
    box-shadow: var(--ox-shadow-s);
  }

  .counter_wrapper ul {
    display: flex;
    flex-wrap: nowrap;
    gap: 0;
    width: 100%;
  }

  .counter_wrapper ul li {
    position: relative;
    flex: 1 1 0;
    min-width: 0;
    margin: 0;
    padding: 0 0.35rem;
    text-align: center;
  }

  .counter_wrapper ul li + li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 10%;
    height: 80%;
    border-left: 1px solid var(--ox-border);
  }

  .counter_wrapper ul li h3 {
    margin: 0 0 0.3rem;
    font-size: clamp(1.65rem, 8.5vw, 2.15rem);
    line-height: 1.05;
    text-align: center;
  }

  .counter_wrapper ul li p {
    font-size: clamp(0.78rem, 3.2vw, 0.9rem);
    line-height: 1.25;
    text-align: center;
  }
}

/* ==========================================================================
   Responsive fixes
   ========================================================================== */

/* Phantom horizontal scroll on phones came from two places: AOS slides
   elements in from +/-100px on the x-axis, and the off-canvas mobile menu
   parks itself at right:-350px. style.css clips this with `overflow-x:
   hidden !important`, which turns <html> into a scroll container and can
   break `position: sticky` (the #v-tabs work rail). `clip` on the x-axis
   with `visible` on the y-axis hides the overflow without ever creating a
   scroll container, so sticky keeps working. The selectors mirror the
   !important ones in style.css so this actually wins. */
html,
html.fontawesome-i2svg-active.fontawesome-i2svg-complete,
body,
body.page-home {
  overflow-x: clip !important;
}

/* keep the reveal, drop the sideways travel below the desktop grid so it
   can never push the layout wider than the screen */
@media (max-width: 991px) {
  [data-aos="fade-left"],
  [data-aos="fade-right"],
  [data-aos="fade-down-left"],
  [data-aos="fade-down-right"],
  [data-aos="fade-up-left"],
  [data-aos="fade-up-right"] {
    transform: none !important;
  }
}

/* --- Packages --------------------------------------------------------------
   style.css made the tab-pane a non-wrapping flexbox and pinned each card to
   flex: 0 0 30%, so three price cards were crushed side by side on every
   phone. The panes hold a normal Bootstrap .row now - let it lay out. */
.tab-pane.fade.show.active {
  display: block;
}

.tab-pane .col-lg-4,
.tab-pane .col-sm-6,
.tab-pane.fade.show.active .col-md-4 {
  flex: 0 0 auto;
}

/* ==========================================================================
   Packages
   Was three identical #F9F9F9 cards on a grey section - grey on grey, so they
   barely separated from the background, and nothing said which plan to pick.
   White cards lift off the section, and the middle one is marked as the
   recommendation, which is the one thing a pricing table has to do.
   ========================================================================== */
.packages_box {
  position: relative;
  margin-top: 0;
  padding: clamp(1.75rem, 4.5vw, 3.125rem) clamp(1.35rem, 3.5vw, 2.5rem);
  height: 100%;
  display: flex;
  flex-direction: column;
  background: var(--ox-surface);
  border: 1px solid var(--ox-border);
  border-radius: var(--ox-r-lg);
  box-shadow: var(--ox-shadow-s);
  transition: transform var(--ox-transition), box-shadow var(--ox-transition),
              border-color var(--ox-transition);
}

.packages_box:hover {
  transform: translateY(-4px);
  box-shadow: var(--ox-shadow-m);
  border-color: rgb(var(--ox-blue-bright-rgb) / 0.35);
}

.packages_box h2,
.packages_box h3 {
  color: var(--ox-navy);
}

/* The plan name used to be an <h2> sitting beside the section's own <h2>, and
   the price under it an <h1> - six of those on a page whose H1 is the hero.
   The name is an <h3> under the section heading now and the price is a plain
   block, so these two rules carry what the old tags were being styled for. */
.packages_box h3 {
  font-size: clamp(1.2rem, 1.8vw, 1.375rem);
  line-height: 1.2;
  font-weight: 600;
  margin: 0 0 0.625rem;
}

.packages_box > p {
  color: var(--ox-text-soft);
  line-height: 1.5;
  min-height: 3em;              /* keeps the three prices on one line */
}

/* the price, given the weight it deserves */
.packages_box h1,
.packages_box__price {
  font-size: clamp(2.1rem, 3.4vw, 2.9rem);
  line-height: 1.05;
  margin: var(--ox-s-3) 0 0;
  color: var(--ox-navy);
  letter-spacing: -0.03em;
  font-weight: 700;
}
.packages_box h1 span,
.packages_box__price span {
  font-size: var(--ox-t-sm);
  font-weight: 500;
  color: var(--ox-text-dim);
  letter-spacing: 0;
}

/* a rule between the price and what you get for it */
.packages_box ul {
  border-top: 1px solid var(--ox-border);
  margin-top: var(--ox-s-3) !important;
  padding-top: var(--ox-s-3) !important;
}
.packages_box ul li {
  color: var(--ox-text-soft);
  line-height: 1.45;
  align-items: flex-start;
}

/* The button sits on the floor of every card, so all three line up.
   `.btn.active` is matched explicitly: that class is Bootstrap tab plumbing
   left on the first card, and Bootstrap's own .active state paints it black.
   The --bs-btn-active-* variables are re-pointed for the same reason. */
.packages_box button,
.packages_box button.btn.active {
  --bs-btn-active-bg: transparent;
  --bs-btn-active-border-color: rgb(var(--ox-navy-rgb) / 0.22);
  --bs-btn-active-color: var(--ox-blue-deep);
  margin-top: auto;
  width: 100%;
  height: auto;
  padding: 0.85rem 1.25rem;
  font-size: var(--ox-t-sm);
  font-weight: 600;
  border-radius: var(--ox-r-pill);
  border: 1px solid rgb(var(--ox-navy-rgb) / 0.22);
  color: var(--ox-blue-deep);
  background: transparent;
}
/* was #0D0C13 - near-black, and the only place on the site that did that */
.packages_box button:hover,
.packages_box button:focus-visible {
  background: rgb(var(--ox-blue-bright-rgb) / 0.07);
  border-color: var(--ox-blue-bright);
  color: var(--ox-blue-deep);
}

/* the recommended plan */
.packages_box.is-featured {
  border-color: transparent;
  box-shadow: 0 0 0 2px var(--ox-blue-bright), var(--ox-shadow-m);
}
.packages_box.is-featured:hover {
  box-shadow: 0 0 0 2px var(--ox-blue-bright), var(--ox-shadow-l);
}
.packages_box__flag {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translate(-50%, -50%);
  padding: 0.34rem 0.9rem;
  font-size: var(--ox-t-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #fff;
  background: var(--ox-gradient);
  border-radius: var(--ox-r-pill);
  box-shadow: var(--ox-glow);
  white-space: nowrap;
}
.packages_box.is-featured button,
.packages_box.is-featured button.btn.active {
  --bs-btn-active-bg: transparent;
  --bs-btn-active-color: #fff;
  background: var(--ox-gradient);
  border-color: transparent;
  color: #fff;
}
.packages_box.is-featured button:hover,
.packages_box.is-featured button:focus-visible {
  background: var(--ox-gradient);
  filter: brightness(1.08);
  box-shadow: var(--ox-glow);
  color: #fff;
}

/* the tick: was a 14x10 PNG repeated on every row */
.packages_box ul li img { display: none; }
.packages_box ul li::before {
  content: "";
  flex: none;
  width: 1.15em;
  height: 1.15em;
  margin-right: 0.6rem;
  border-radius: 50%;
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231287D2' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / 0.72em no-repeat,
    rgb(var(--ox-blue-bright-rgb) / 0.10);
}

/* the intro line under "Our Packages": .text-center centred the text but the
   block itself sat left because style.css gave it width:100%, which cancels
   auto side margins. */
.global_inner.black.text-center.full p {
  width: auto;
  max-width: 46rem;
  margin-left: auto;
  margin-right: auto;
}

/* the Monthly / Yearly switch can overflow its white pill on narrow screens */
@media (max-width: 400px) {
  .mainactive_cta ul#packageTabs {
    width: 100%;
    padding: 8px !important;
  }

  .mainactive_cta ul#packageTabs li.nav-item {
    flex: 1 1 0;
  }

  .mainactive_cta ul#packageTabs li.nav-item button {
    width: 100%;
    font-size: 1rem;
  }
}


/* ==========================================================================
   About page
   The hero used to be <h1 class="border-txt">About Us</h1> with the real
   headline below it as an <h2> - the H1 was a two-word label with no search
   value. The label is a <p> chip now and the headline is the H1, which is the
   shape the .global_sec rules above were already written for.
   ========================================================================== */

/* style.css line 2340 is `p { font-weight: 300 !important }`, so the chip
   needs its weight back now that it is a paragraph rather than a heading. */
section.global_sec p.border-txt {
  font-weight: 700 !important;
}

section.global_sec .global_sec__cta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 1.6rem;
}

/* .btn-ox--ghost is drawn for a light section - navy text on a pale border,
   i.e. invisible on the hero gradient. */
section.global_sec .btn-ox--ghost {
  color: #fff;
  border-color: rgba(255, 255, 255, 0.3);
  background: rgba(255, 255, 255, 0.07);
}

section.global_sec .btn-ox--ghost:hover,
section.global_sec .btn-ox--ghost:focus-visible {
  color: #fff;
  border-color: rgba(255, 255, 255, 0.55);
  background: rgba(255, 255, 255, 0.14);
}

/* --- the three-step methodology, under the About section heading -------
   style.css sets `ul { margin: 0 !important; padding: 0 !important }`, so the
   list gets its top margin with !important and the rest lives on the items. */
.method_list {
  display: grid;
  gap: var(--ox-s-2);
  margin-top: var(--ox-s-3) !important;
  list-style: none;
}

.method_list li {
  padding-left: 1.1rem;
  border-left: 2px solid rgb(var(--ox-blue-bright-rgb) / 0.45);
}

.method_list h3 {
  margin: 0 0 0.25rem;
  font-size: var(--ox-t-base);
  line-height: 1.35;
  letter-spacing: -0.01em;
  font-weight: 600;
  color: var(--ox-navy);
}

.method_list p {
  margin: 0;
  font-size: var(--ox-t-sm);
  line-height: 1.6;
  color: var(--ox-text-soft);
}

/* --- closing call to action (About and Services) ---------------------------------------------
   The page ran from the client quotes straight into the FAQ, so its strongest
   moment had nothing to act on. One band, and deliberately no second form -
   the FAQ card below it already carries the booking widget. */
section.page_cta {
  padding-block: clamp(2.75rem, 6vw, 4.25rem);
}

section.page_cta .page_cta__actions {
  display: flex;
  justify-content: center;
  margin-top: var(--ox-s-3);
}
