/* ============================================================================
   VKV GROUP — UX layer (Module 33)
   Loaded LAST, after vkv-premium.css, so it wins without editing earlier files
   (delete this one file to revert every change in it).

   Scope, in order:
     1. Clean surfaces — remove the lined / grid-sheet appearance
     2. Banner + hero presence (all public pages)
     3. 35px section rhythm, collapsed so gaps never double
     4. Hero: Digital Service Ecosystem + first-screen lead form
     5. Pricing Plans — premium cards
   Functional borders (buttons, inputs, cards, focus rings) are untouched.
   ========================================================================== */

/* ---- 1. Clean surfaces: no grid overlay, no section seams ---------------- */
/* The lined appearance came from three places: a repeating grid image on
   alternating sections, a 1px seam on their top and bottom edges, and a
   hairline under the network background. All three go. */
/* Clean surfaces, part 2: the source grid rule was deleted from
   vkv-premium.css in Module 33, so these guards only cover a stale minified
   build still being served. */
.section-alt::after { content: none !important; background-image: none !important; }
.section-alt { border-block: 0 !important; box-shadow: none !important; }
.vkv-network-background::after { content: none !important; }

/* Decorative rules and dividers: gone. (An <hr> inside prose keeps a soft
   spacing role but paints nothing.) */
hr, .hairline, .divider-gold {
  border: 0 !important; height: 0 !important; background: none !important;
  margin-block: 10px !important;
}

/* Accidental separator lines on stacked content blocks. Card, form, button and
   focus borders are deliberately NOT in this list. */
.hero-meta, .channel-links, .post-author, .ty-next, .legal-related,
.contact-trust, .footer-contact-bar, .footer-legal-bar, .footer-band,
.testimonial figcaption { border-top-color: transparent !important; border-bottom-color: transparent !important; }
.footer-band { border-bottom: 0 !important; }
.process-step:not(:last-child)::after { background: none !important; }

/* The soft light bed on every section is kept, but lowered so it reads as
   atmosphere rather than a panel edge. */
.section::before { opacity: 0.55; }

/* ---- 1b. Sticky header ---------------------------------------------------
   Module 39: the header is pinned for the whole scroll so the menu and CTAs are
   always one tap away. `top: 0` with the util bar scrolling away above it keeps
   the nav flush to the viewport edge; a scrolled state deepens the backdrop so
   content passing underneath never muddies the labels. No JS is required — the
   `.is-stuck` class is a progressive enhancement only. */
body:not(.admin-body) .site-header {
  /* Module 39: sticky is declared HERE, in the same rule that owns the header's
     stacking context, so the ambient-particle block further down this file
     cannot overwrite it. */
  position: sticky; top: 0; z-index: 50;
  background: rgba(8, 16, 38, 0.86);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  transition: background 260ms ease, box-shadow 260ms ease;
}
body:not(.admin-body) .site-header.is-stuck {
  background: rgba(7, 13, 31, 0.96);
  box-shadow: 0 10px 30px -18px rgba(3, 8, 22, 0.9);
}
/* Anchor targets must clear the pinned header. */
body:not(.admin-body) { scroll-padding-top: calc(var(--header-h, 72px) + 12px); }

/* ---- 2. Banner system: premium corporate, 1920×700 reference ----------
   Module 42. One banner treatment for every public page.

   PROPORTION: the reference is 1920×700 (≈36.45% of width). `aspect-ratio`
   alone would give 700px at 1920 but only 117px at 320 — unusable. The ratio
   therefore sets a CLAMPED MIN height, so the composition holds the reference
   proportion on desktop and grows to fit content on narrow screens. Nothing
   overflows and nothing is cropped.

   PALETTE: deep navy ground, electric cyan, a restrained magenta/violet depth
   note, gold reserved for the accent and the frame. */
:root {
  --hero-pad: clamp(56px, 3.4vw + 34px, 96px);
  --hero-pad-bottom: clamp(48px, 3vw + 30px, 84px);
}

main > .hero,
main > section[class*="-hero"],
main .hero { padding-block: var(--hero-pad) var(--hero-pad-bottom); }

.hero, .home-hero, .page-hero, .service-hero,
main > section[class*="-hero"] {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  min-height: clamp(360px, 36.45vw, 700px);
  display: flex; align-items: center;
  background:
    radial-gradient(118% 120% at 82% -18%, rgba(30, 74, 156, 0.85) 0%, transparent 56%),
    radial-gradient(75% 90% at 96% 42%, rgba(0, 198, 232, 0.20) 0%, transparent 58%),
    radial-gradient(70% 85% at 12% 96%, rgba(138, 74, 220, 0.16) 0%, transparent 60%),
    radial-gradient(60% 70% at 4% 8%, rgba(201, 162, 75, 0.12) 0%, transparent 58%),
    linear-gradient(174deg, #0A1636 0%, #070F26 58%, #050A1B 100%);
  /* Module 45: the inset gold glow went with the perimeter frame — together
     they made the banner read as a bordered box rather than a scene. */
}
@media (max-width: 767.98px) {
  .hero, .home-hero, .page-hero, .service-hero,
  main > section[class*="-hero"] { min-height: 0; }
}
/* Banner content must clear the gold frame and the motion layers. */
.hero > .container,
main > section[class*="-hero"] > .container { position: relative; z-index: 2; }

/* Depth sweep — the futuristic cue. Module 45 softens it: the previous stops
   produced hard gradient edges that read as a pale triangular wedge across the
   banner rather than as light. Lower opacities, wider transitions and a
   stronger mask keep it as atmosphere. */
.hero::after,
main > section[class*="-hero"]::after {
  content: ""; position: absolute; inset: -30% -10% auto -10%; height: 150%;
  z-index: -1; pointer-events: none;
  background:
    conic-gradient(from 208deg at 74% 16%,
      rgba(0, 208, 255, 0.10) 0deg,
      rgba(0, 208, 255, 0) 60deg,
      rgba(228, 199, 126, 0.08) 110deg,
      rgba(228, 199, 126, 0) 180deg,
      rgba(150, 90, 235, 0.07) 250deg,
      rgba(150, 90, 235, 0) 330deg);
  -webkit-mask-image: radial-gradient(58% 50% at 74% 20%, #000 0%, transparent 82%);
          mask-image: radial-gradient(58% 50% at 74% 20%, #000 0%, transparent 82%);
  filter: blur(18px);
  opacity: 0.85;
}
/* Vignette: keeps the content column legible over every layer above. */
.hero::before,
main > section[class*="-hero"]::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(86% 72% at 42% 44%, transparent 0%, rgba(4, 9, 22, 0.46) 100%),
    linear-gradient(180deg, rgba(4, 9, 22, 0.30) 0%, transparent 26%, rgba(4, 9, 22, 0.38) 100%);
  opacity: 1;
}

/* Type hierarchy (Module 45): a wider headline step, a calmer sub-line and
   deliberate rhythm between eyebrow → headline → sub → actions, so the left
   column reads as one composed block rather than four stacked items. */
.hero-title, .page-hero h1, .service-hero h1,
main > section[class*="-hero"] h1 {
  font-size: clamp(2.1rem, 1.4rem + 2.9vw, 3.75rem);
  line-height: 1.06; letter-spacing: -0.025em; text-wrap: balance;
  margin: 0;
}
.hero-sub, .page-hero .hero-sub, .page-hero > .container > p,
main > section[class*="-hero"] > .container > p {
  font-size: clamp(1rem, 0.95rem + 0.34vw, 1.18rem);
  line-height: 1.68; max-width: 56ch;
  color: #C4CFE4;
  margin: 18px 0 0;
}
.hero .eyebrow, .page-hero .eyebrow,
main > section[class*="-hero"] .eyebrow {
  font-size: 0.74rem; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--gold-400, #E4C77E);
  display: inline-block; margin: 0 0 16px;
}
.hero-actions { margin-top: 30px; gap: 14px; flex-wrap: wrap; }
.hero-actions .btn { min-height: 48px; }

/* Inner banners: proportional, capped, never tall. */
main > section[class*="-hero"] {
  min-height: min(30vw, 320px);
  display: flex; align-items: center;
}
main > section[class*="-hero"] > .container { width: min(100% - 2.5rem, var(--container)); }

/* ---- 2b. Animated benefit underline ------------------------------------
   A travelling rule under each hero benefit line. It lives on a pseudo-element
   of an inline-block span, so it cannot shift text or change the strip height.

   Module 37 also fixes the strip layout itself: the four benefits were laid out
   in a row that wrapped unpredictably, so the fourth item overlapped the second
   at mid widths. An auto-fit grid gives each benefit its own cell — four across
   when there is room, two, then one, with no overlap at any width. */
.trust-inner {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 14px clamp(18px, 2.5vw, 40px);
  align-items: start;
}
.trust-item {
  display: flex; align-items: flex-start; gap: 9px;
  margin: 0; min-width: 0;
}
.trust-check { flex: none; line-height: 1.5; }
.trust-underline {
  position: relative; display: inline-block;
  padding-bottom: 7px; min-width: 0;
}
.trust-underline::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  border-radius: 2px; pointer-events: none;
  background:
    linear-gradient(90deg, transparent 0%, rgba(228, 199, 126, 0.95) 45%, rgba(228, 199, 126, 0.95) 55%, transparent 100%) no-repeat,
    linear-gradient(90deg, rgba(234, 240, 251, 0.14), rgba(234, 240, 251, 0.14));
  background-size: 58% 100%, 100% 100%;
  animation: vkv-underline-travel 4.6s cubic-bezier(0.45, 0, 0.55, 1) infinite;
}
.trust-item:nth-child(2) .trust-underline::after { animation-delay: 0.5s; }
.trust-item:nth-child(3) .trust-underline::after { animation-delay: 1s; }
.trust-item:nth-child(4) .trust-underline::after { animation-delay: 1.5s; }
@keyframes vkv-underline-travel {
  0%, 100% { background-position: -20% 0, 0 0; }
  50%      { background-position: 120% 0, 0 0; }
}

/* ---- 2c. Banner motion layer -------------------------------------------
   Module 39. Two additive motion layers inside every banner, both CSS-only and
   both behind the content: a slow drifting particle field (same language as the
   page background, tuned brighter for the banner) and one wide light beam that
   sweeps across on a long cycle. No canvas, no per-frame JS, no imagery. */
.hero > .hero-motion,
main > section[class*="-hero"] > .hero-motion {
  position: absolute; inset: 0; z-index: -1; pointer-events: none; overflow: hidden;
}
.hero-motion span { position: absolute; inset: 0; will-change: background-position, opacity, transform; }
.hero-motion .hm-dots {
  background-image:
    radial-gradient(rgba(228, 199, 126, 0.55) 1.1px, transparent 1.4px),
    radial-gradient(rgba(120, 220, 255, 0.5) 1.4px, transparent 1.8px);
  background-size: 112px 112px, 186px 186px;
  opacity: 0.22;
  animation: vkv-hm-drift 68s linear infinite, vkv-hm-blink 9s ease-in-out infinite;
}
.hero-motion .hm-beam {
  background: linear-gradient(104deg,
    transparent 38%, rgba(0, 208, 255, 0.10) 47%,
    rgba(255, 255, 255, 0.07) 50%, rgba(228, 199, 126, 0.10) 53%, transparent 62%);
  animation: vkv-hm-sweep 13s cubic-bezier(0.5, 0, 0.5, 1) infinite;
}
/* Running light lines — thin rails whose highlight travels left to right. */
.hero-motion .hm-lines {
  background-image:
    linear-gradient(90deg, transparent, rgba(0, 208, 255, 0.5) 12%, rgba(0, 208, 255, 0) 30%),
    linear-gradient(90deg, transparent, rgba(228, 199, 126, 0.45) 14%, rgba(228, 199, 126, 0) 34%),
    linear-gradient(90deg, transparent, rgba(150, 190, 255, 0.34) 10%, rgba(150, 190, 255, 0) 28%);
  background-repeat: no-repeat;
  background-size: 62% 1px, 48% 1px, 40% 1px;
  background-position: -62% 27%, -48% 58%, -40% 79%;
  opacity: 0.85;
  animation: vkv-hm-rails 11s linear infinite;
}
/* Glowing pointer nodes, blinking out of phase. */
.hero-motion .hm-nodes {
  background-image:
    radial-gradient(circle, rgba(255, 244, 214, 0.95) 0%, rgba(228, 199, 126, 0.5) 38%, transparent 68%),
    radial-gradient(circle, rgba(190, 240, 255, 0.9) 0%, rgba(0, 208, 255, 0.45) 38%, transparent 68%),
    radial-gradient(circle, rgba(255, 244, 214, 0.85) 0%, rgba(228, 199, 126, 0.4) 38%, transparent 68%),
    radial-gradient(circle, rgba(205, 180, 255, 0.85) 0%, rgba(150, 90, 235, 0.4) 38%, transparent 68%);
  background-repeat: no-repeat;
  background-size: 7px 7px, 6px 6px, 5px 5px, 6px 6px;
  background-position: 22% 27%, 61% 58%, 78% 34%, 40% 79%;
  animation: vkv-hm-nodes 4.2s ease-in-out infinite;
}
/* Faint glowing diagonal paths, slow parallax. */
.hero-motion .hm-paths {
  background-image:
    linear-gradient(72deg, transparent 49.7%, rgba(0, 208, 255, 0.10) 50%, transparent 50.3%),
    linear-gradient(-68deg, transparent 49.7%, rgba(228, 199, 126, 0.09) 50%, transparent 50.3%);
  background-size: 340px 340px, 480px 480px;
  opacity: 0.6;
  animation: vkv-hm-paths 46s linear infinite;
}
@keyframes vkv-hm-rails {
  0%   { background-position: -62% 27%, -48% 58%, -40% 79%; }
  100% { background-position: 162% 27%, 148% 58%, 140% 79%; }
}
@keyframes vkv-hm-nodes {
  0%, 100% { opacity: 0.35; }
  25%      { opacity: 1; }
  55%      { opacity: 0.45; }
  75%      { opacity: 0.9; }
}
@keyframes vkv-hm-paths { to { background-position: 340px -340px, -480px -480px; } }

/* ---- 2c-ii. Banner perimeter frame REMOVED (Module 45) -----------------
   The animated gold perimeter is gone from the banner entirely: no frame
   element, no running border, no perimeter glow. It read as a hard lining box
   around the hero rather than a premium edge, and the rotating conic gradient
   behind it was fragile — in any engine where mask compositing did not apply it
   painted as a solid wedge across the banner.

   The hero now relies on its gradient composition and the motion layers alone.
   `.hero-frame` is no longer emitted by vkv-ux.js; this rule only neutralises
   any cached markup still carrying it. */
.hero-frame { display: none !important; }

@keyframes vkv-hm-drift { to { background-position: 112px -112px, -186px -93px; } }
@keyframes vkv-hm-blink { 0%, 100% { opacity: 0.22; } 50% { opacity: 0.11; } }
@keyframes vkv-hm-sweep {
  0%, 100% { transform: translateX(-38%); opacity: 0; }
  18%      { opacity: 1; }
  82%      { opacity: 1; }
  99%      { transform: translateX(38%); opacity: 0; }
}

/* ---- 2d. Hero headline motion ------------------------------------------
   The two banner lines rise and fade in on load, one after the other, with a
   single gold light passing across the second line's accent. Transform and
   opacity only — nothing reflows, and the text is fully present to crawlers and
   screen readers whether or not the animation runs. */
.hero-title-anim { display: grid; gap: 0.12em; }
.hero-line { display: block; opacity: 0; animation: vkv-line-in 900ms cubic-bezier(0.22, 1, 0.36, 1) forwards; }
.hero-line-1 { animation-delay: 120ms; }
.hero-line-2 { animation-delay: 320ms; }
@keyframes vkv-line-in {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}
.hero-line-2 .text-gold {
  background: linear-gradient(100deg,
    #C9A24B 0%, #E4C77E 38%, #FFF4D6 50%, #E4C77E 62%, #C9A24B 100%);
  background-size: 260% 100%;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  animation: vkv-gold-pass 7s ease-in-out infinite 1.2s;
}
@keyframes vkv-gold-pass {
  0%, 100% { background-position: 130% 0; }
  50%      { background-position: -30% 0; }
}

/* ---- 2e. Banner lead form ----------------------------------------------
   The banner becomes a two-column composition: copy left, a compact enquiry
   card right. The card is deliberately narrow and quiet so it supports the
   headline rather than competing with it. Below 980px it drops under the copy
   at full width. */
/* The two-column banner is switched on by a CLASS added by vkv-ux.js, not by
   `:has()`. `:has()` is unsupported in older Safari/Firefox builds still in the
   wild, and when it fails the whole rule is dropped — the form silently stacked
   under the copy at full width. A class works everywhere. */
/* Banner composition: the copy column takes the larger share and the enquiry
   card is held to a comfortable width, so the two read as one balanced layout
   rather than two competing blocks. */
.has-banner-lead > .container {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(320px, 0.7fr);
  gap: clamp(28px, 3.5vw, 64px);
  align-items: center;
}
.has-banner-lead .hero-inner,
.home-hero.has-banner-lead .hero-inner,
.hero.has-banner-lead .hero-inner {
  /* Must out-specify the centred single-column rule in §4, which also targets
     .home-hero .hero-inner — without the extra class the copy stayed centred
     while the form sat beside it. */
  max-width: none; margin-inline: 0; text-align: left;
}
.home-hero.has-banner-lead .hero-actions,
.hero.has-banner-lead .hero-actions { justify-content: flex-start; }
.home-hero.has-banner-lead .hero-sub,
.hero.has-banner-lead .hero-sub { margin-inline: 0; }

.banner-lead {
  position: relative; z-index: 3;
  padding: 20px 18px 18px; border-radius: 16px;
  background: linear-gradient(168deg, rgba(23, 38, 79, 0.94) 0%, rgba(9, 18, 43, 0.96) 100%);
  border: 1px solid rgba(228, 199, 126, 0.26);
  box-shadow: 0 26px 54px -22px rgba(3, 8, 22, 0.8), inset 0 1px 0 rgba(255, 255, 255, 0.07);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
}
.banner-lead-title { font-size: 1.12rem; line-height: 1.25; margin: 0; letter-spacing: -0.01em; }
.banner-lead-sub { margin: 6px 0 14px; font-size: 0.82rem; line-height: 1.5; color: var(--text-muted, #A9B6CE); }
.banner-lead .form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 9px 10px; }
.banner-lead .form-grid > .field-wide,
.banner-lead .form-grid > .consent-field { grid-column: 1 / -1; }
.banner-lead .form-actions { margin-top: 12px; }
.banner-lead .form-actions .btn-gold { width: 100%; justify-content: center; min-height: 42px; }
/* The secondary WhatsApp action is already in the banner CTA row above. */
.banner-lead .form-actions .btn-outline { display: none; }
.banner-lead textarea { min-height: 66px; }
.banner-lead .consent { font-size: 0.72rem; line-height: 1.45; }

/* Placeholder-only mode: labels stay in the DOM for assistive tech and for the
   error-summary logic, but are visually hidden. */
.lead-form-ph label:not(.consent) {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
.lead-form-ph input:not([type="checkbox"]),
.lead-form-ph select,
.lead-form-ph textarea {
  min-height: 40px; padding: 9px 12px; font-size: 0.88rem; border-radius: 9px;
}
.lead-form-ph ::placeholder { color: rgba(169, 182, 206, 0.8); opacity: 1; }

@media (max-width: 980px) {
  .has-banner-lead > .container { grid-template-columns: minmax(0, 1fr); }
  .banner-lead { max-width: 520px; }
}
@media (max-width: 480px) {
  .banner-lead .form-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ---- 2f. First-visit consent gate --------------------------------------
   Layered dialogs, not a page blocker: the site renders underneath and the
   BODY is never permanently covered — the gate removes itself on acceptance and
   never returns (localStorage). The terms panel itself scrolls, so the modal
   can never exceed the viewport. */
.consent-gate { position: fixed; inset: 0; z-index: 200; }
.consent-gate[hidden] { display: none; }
.consent-backdrop { position: absolute; inset: 0; background: rgba(4, 9, 22, 0.72); backdrop-filter: blur(3px); }
.consent-modal {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  padding: clamp(14px, 3vw, 32px);
}
.consent-modal[hidden] { display: none; }
.consent-panel {
  position: relative; width: min(100%, 680px);
  max-height: min(84vh, 720px);
  display: flex; flex-direction: column;
  border-radius: 18px; overflow: hidden;
  background: linear-gradient(168deg, #16264F 0%, #0A1428 100%);
  border: 1px solid rgba(228, 199, 126, 0.32);
  box-shadow: 0 40px 90px -30px rgba(2, 6, 18, 0.9);
  animation: vkv-modal-in 320ms cubic-bezier(0.22, 1, 0.36, 1);
}
.consent-modal-sm .consent-panel { width: min(100%, 460px); }
@keyframes vkv-modal-in {
  from { opacity: 0; transform: translateY(12px) scale(0.985); }
  to   { opacity: 1; transform: none; }
}
.consent-head { padding: 22px 24px 12px; flex: none; }
.consent-head h2 { margin: 6px 0 0; font-size: clamp(1.2rem, 1rem + 0.8vw, 1.6rem); line-height: 1.2; }
.consent-body {
  padding: 0 24px; overflow-y: auto; flex: 1 1 auto;
  font-size: 0.88rem; line-height: 1.65; color: #D4DCEC;
}
.consent-body-sm { overflow: visible; padding-bottom: 4px; font-size: 0.94rem; }
.consent-body h3 {
  margin: 18px 0 6px; font-size: 0.78rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--gold-400, #E4C77E);
}
.consent-body p { margin: 0 0 10px; }
.consent-actions {
  flex: none; display: flex; flex-wrap: wrap; gap: 10px; justify-content: flex-end;
  padding: 16px 24px 20px;
  background: linear-gradient(180deg, transparent, rgba(4, 9, 22, 0.5));
}
.consent-actions .btn { min-height: 44px; }
@media (max-width: 520px) {
  .consent-actions { flex-direction: column-reverse; }
  .consent-actions .btn { width: 100%; justify-content: center; }
}

/* ---- 3. Corporate spacing scale ----------------------------------------
   Module 37 replaces the forced literal 35px on every edge. That rule gave a
   dense four-card section exactly as much room as a full FAQ block, which is
   what made some sections feel cramped and others empty.

   The scale is proportional instead, and fluid: one step for standard sections,
   a tighter step for strips (trust bar, CTA band, newsletter) whose content is
   a single line. Vertical MARGINS are zero throughout — spacing is padding
   only, so two adjacent sections can never sum into a double gap and no margin
   collapse has to be relied on. */
:root {
  --space-section: clamp(44px, 2.4vw + 30px, 72px);   /* standard section */
  --space-strip:   clamp(26px, 1.2vw + 18px, 38px);   /* one-line strips  */
  --space-block:   clamp(20px, 1vw + 14px, 32px);     /* inner blocks     */
}

body:not(.admin-body) main > section,
body:not(.admin-body) main > div > section,
body:not(.admin-body) main .section {
  margin-block: 0;
  padding-block: var(--space-section);
}

/* Strips carry one line of content, so they take the tighter step. */
body:not(.admin-body) .trust-strip,
body:not(.admin-body) .newsletter-band,
body:not(.admin-body) main .cta-band {
  margin-block: 0;
  padding-block: var(--space-strip);
}

/* A section nested inside a section contributes nothing vertically — the
   parent already owns the rhythm. */
body:not(.admin-body) main .section .section,
body:not(.admin-body) main section section { padding-block: 0; margin-block: 0; }

.section-head { margin-bottom: var(--space-block); }
.section-head p { margin-top: 10px; }

.site-footer { margin-top: var(--space-section); }

/* Heroes own the first-screen padding. */
body:not(.admin-body) main > .hero,
body:not(.admin-body) main > section.hero,
body:not(.admin-body) main > section[class*="-hero"] {
  margin-block: 0;
  padding-top: var(--hero-pad);
  padding-bottom: var(--hero-pad-bottom);
}

@media (max-width: 767.98px) {
  :root { --hero-pad: 56px; --hero-pad-bottom: 44px; }
  main > section[class*="-hero"] { min-height: 0; }
}

/* ---- 4. Home hero: matches the premium About-page banner ----------------
   Module 34: the ecosystem ring and the in-hero lead form were removed, so all
   of their CSS is gone with them. What remains is one centred column of copy
   and CTAs — the same composition the About banner uses — at hero scale. */
.home-hero .hero-inner,
.about-hero .hero-inner {
  position: relative; z-index: 3;
  max-width: 62ch; margin-inline: auto; text-align: center;
}
.home-hero .hero-sub,
.about-hero .hero-sub { margin-inline: auto; }
.home-hero .hero-actions,
.about-hero .hero-actions { justify-content: center; }

/* ---- 5. Pricing Plans — premium cards ----------------------------------- */
.pricing-grid {
  grid-template-columns: repeat(auto-fit, minmax(272px, 1fr));
  gap: 18px !important;
}
.pricing-card {
  gap: 14px; padding: 30px 26px 26px; border-radius: 18px; overflow: hidden;
  background: linear-gradient(168deg, rgba(23, 38, 79, 0.62) 0%, rgba(10, 22, 51, 0.92) 100%);
  border: 1px solid rgba(234, 240, 251, 0.10);
}
/* A single gold light sweep across the top edge — the premium tell. */
.pricing-card::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 2px;
  background: linear-gradient(90deg, transparent, rgba(228, 199, 126, 0.75), transparent);
  opacity: 0.5; transition: opacity 320ms ease;
}
.pricing-card:hover::before { opacity: 1; }
.pricing-card:hover { transform: translateY(-6px); }

.pricing-name {
  font-size: 1.08rem; line-height: 1.3; margin: 0;
  letter-spacing: -0.01em;
}
.pricing-price { display: grid; gap: 2px; margin: 6px 0 0; }
.pricing-from {
  font-size: 0.68rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--slate-400, #8A97B1);
}
.pricing-amount {
  font-family: var(--font-display, Sora, sans-serif);
  font-size: clamp(1.85rem, 1.6rem + 0.9vw, 2.3rem); font-weight: 700;
  line-height: 1.05; color: #FFFFFF; letter-spacing: -0.02em;
}
.pricing-star { color: var(--gold-400, #E4C77E); font-size: 0.55em; vertical-align: super; margin-left: 2px; }
.pricing-unit { font-size: 0.84rem; color: var(--text-muted, #A9B6CE); line-height: 1.5; }
.pricing-actions { margin-top: auto; padding-top: 18px; display: flex; flex-wrap: wrap; gap: 10px; }
.pricing-actions .btn { flex: 1 1 auto; justify-content: center; }

/* Recommended plan: lifted, gold-framed, with a legible flag. */
.pricing-card.is-featured {
  border-color: rgba(228, 199, 126, 0.46);
  background: linear-gradient(168deg, rgba(36, 52, 94, 0.72) 0%, rgba(10, 22, 51, 0.95) 100%);
}
.pricing-card.is-featured::before { opacity: 1; height: 3px; }
.pricing-flag {
  top: 16px; left: auto; right: 16px;
  padding: 5px 11px; border-radius: 999px;
  font-size: 0.66rem; letter-spacing: 0.12em; text-transform: uppercase; font-weight: 700;
  background: linear-gradient(135deg, #E4C77E, #C9A24B); color: #0A1633;
  box-shadow: 0 6px 16px rgba(201, 162, 75, 0.32);
}
.pricing-card.is-featured .pricing-name { padding-right: 92px; }

/* Bundles + disclaimer read as one quiet block under the cards. */
.pricing-bundles {
  margin-top: 22px; padding: 22px; border-radius: 16px;
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid rgba(234, 240, 251, 0.09);
}
.pricing-bundles-title { font-size: 1rem; margin: 0 0 14px; }
.pricing-bundle-list { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.pricing-bundle {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 13px 16px; border-radius: 12px;
  background: rgba(10, 22, 51, 0.6); border: 1px solid rgba(234, 240, 251, 0.08);
}
.pricing-bundle-label { font-size: 0.9rem; }
.pricing-bundle-price { font-family: var(--font-display, Sora, sans-serif); font-weight: 700; color: #FFFFFF; }
.pricing-note { margin-top: 16px; font-size: 0.8rem; color: var(--slate-400, #8A97B1); }

@media (max-width: 600px) {
  .pricing-card { padding: 26px 20px 22px; }
  .pricing-card.is-featured .pricing-name { padding-right: 0; }
  .pricing-flag { position: static; display: inline-block; margin-bottom: 4px; }
}

/* ---- 6. Global ambient particle field ----------------------------------
   Premium dots with depth: three fixed layers of different dot size, opacity
   and drift speed, so the field has parallax without a second canvas engine.
   Pure CSS (background-position + opacity only — no per-frame JS, no repaint
   of content), injected once into <body> by vkv-ux.js and pinned behind
   everything. Blink comes from the slow opacity cycle on each layer, offset so
   they never pulse in unison. */
.vkv-dots {
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  overflow: hidden; contain: strict;
}
.vkv-dots span {
  position: absolute; inset: 0;
  background-repeat: repeat;
  will-change: background-position, opacity;
}
/* far layer — small, faint, slow */
.vkv-dots .d1 {
  background-image: radial-gradient(rgba(228, 199, 126, 0.5) 1px, transparent 1.2px);
  background-size: 96px 96px; opacity: 0.16;
  animation: vkv-drift-a 150s linear infinite, vkv-blink-a 11s ease-in-out infinite;
}
/* mid layer — cool tone, opposite direction */
.vkv-dots .d2 {
  background-image: radial-gradient(rgba(150, 190, 255, 0.55) 1.2px, transparent 1.5px);
  background-size: 148px 148px; opacity: 0.13;
  animation: vkv-drift-b 105s linear infinite, vkv-blink-b 8.5s ease-in-out infinite;
}
/* near layer — largest and brightest, fastest drift */
.vkv-dots .d3 {
  background-image: radial-gradient(rgba(255, 255, 255, 0.6) 1.6px, transparent 2px);
  background-size: 230px 230px; opacity: 0.10;
  animation: vkv-drift-c 72s linear infinite, vkv-blink-c 6.5s ease-in-out infinite;
}
@keyframes vkv-drift-a { to { background-position: 96px -96px; } }
@keyframes vkv-drift-b { to { background-position: -148px -74px; } }
@keyframes vkv-drift-c { to { background-position: 115px -230px; } }
@keyframes vkv-blink-a { 0%, 100% { opacity: 0.16; } 50% { opacity: 0.07; } }
@keyframes vkv-blink-b { 0%, 100% { opacity: 0.13; } 45% { opacity: 0.05; } }
@keyframes vkv-blink-c { 0%, 100% { opacity: 0.10; } 60% { opacity: 0.04; } }

/* Content sits above the field. Without this the fixed layer would cover the
   page instead of sitting behind it. */
body:not(.admin-body) .util-bar,
body:not(.admin-body) main,
body:not(.admin-body) .site-footer,
body:not(.admin-body) .mobile-cta-bar { position: relative; z-index: 1; }
/* .site-header is NOT listed above — it is sticky (§1b) and this later rule
   would silently overwrite that with `position: relative` at equal
   specificity, un-pinning the header. */
/* .floating-stack is deliberately NOT in the list above: it must stay
   position:fixed, and `body:not(.admin-body) .floating-stack` would out-specify
   the fixed rule in §16 (specificity beats source order). It is body-scoped
   there instead. */

/* ---- 7. "Ready for better results?" (base) ------------------------------
   Superseded by §14 below, which owns the final clearance values. */
.cta-band { overflow: hidden; }

/* ---- 8. Fixed phone + WhatsApp: subtle pulse ---------------------------
   An expanding ring behind each button, not a scale on the button itself, so
   the hit target never moves and nothing reflows. The two are offset in time so
   they read as attention rather than a blinking pair. */
.floating-btn { position: relative; }
.floating-call::after,
.floating-whatsapp::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; z-index: -1;
  animation: vkv-pulse-ring 2.6s cubic-bezier(0.24, 0.6, 0.3, 1) infinite;
}
.floating-call::after  { box-shadow: 0 0 0 0 rgba(228, 199, 126, 0.55); }
.floating-whatsapp::after { box-shadow: 0 0 0 0 rgba(37, 211, 102, 0.55); animation-delay: 1.3s; }
@keyframes vkv-pulse-ring {
  0%   { box-shadow: 0 0 0 0 currentColor; opacity: 0.5; }
  70%  { box-shadow: 0 0 0 16px currentColor; opacity: 0; }
  100% { box-shadow: 0 0 0 0 currentColor; opacity: 0; }
}
.floating-call  { --pulse: rgba(228, 199, 126, 0.5); }
.floating-whatsapp { --pulse: rgba(37, 211, 102, 0.5); }
.floating-call::after, .floating-whatsapp::after { color: var(--pulse); }

/* ---- 9. Process sequences: same-line number, blink + runner ------------
   Module 37. Applies to EVERY genuine "How We Work" / process sequence on the
   site — all of them share the `.process > .process-step` markup with a
   `.process-num` and a `.process-title`. Unrelated numbered content (pricing,
   stats, lists) does not use these classes and is untouched.

   1. NUMBER AND HEADING ON ONE LINE. The step is a grid with a fixed first
      column, so "01" and its heading sit on the same row and the description
      aligns under the heading. Previously the chip was a block and the heading
      wrapped to the next line.
   2. Blinking nodes, staggered per step.
   3. A runner dot travelling 01 → 02 → 03 → 04, looping continuously. */
.process { position: relative; container-type: inline-size; }
.process-step {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas: "num title" ". desc";
  align-items: center;
  column-gap: 12px; row-gap: 6px;
}
.process-num {
  grid-area: num;
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  flex: none; margin: 0;
}
.process-title {
  grid-area: title;
  margin: 0; align-self: center; line-height: 1.25;
}
.process-desc { grid-area: desc; margin: 0; }

/* Node blink — a ring, so the chip itself never changes size. */
.process-num::after {
  content: ""; position: absolute; inset: -3px; border-radius: 50%;
  pointer-events: none; background: none;
  box-shadow: 0 0 0 0 rgba(228, 199, 126, 0.5);
  animation: vkv-node-blink 3.4s ease-in-out infinite;
}
.process-step:nth-child(2) .process-num::after { animation-delay: 0.45s; }
.process-step:nth-child(3) .process-num::after { animation-delay: 0.9s; }
.process-step:nth-child(4) .process-num::after { animation-delay: 1.35s; }
.process-step:nth-child(5) .process-num::after { animation-delay: 1.8s; }
@keyframes vkv-node-blink {
  0%, 100% { box-shadow: 0 0 0 0 rgba(228, 199, 126, 0.5); }
  55%      { box-shadow: 0 0 0 8px rgba(228, 199, 126, 0); }
}

/* The runner dot. Horizontal layouts get it travelling left→right along the
   number row; stacked layouts get top→bottom, so the 01→04 cue reads correctly
   in both directions rather than being switched off on mobile. */
.process::after {
  content: ""; position: absolute; pointer-events: none; z-index: 2;
  width: 8px; height: 8px; border-radius: 50%;
  background: radial-gradient(circle, #FFF3D6 0%, rgba(228, 199, 126, 0.9) 45%, rgba(228, 199, 126, 0) 72%);
  box-shadow: 0 0 12px rgba(228, 199, 126, 0.85);
}
@media (min-width: 900px) {
  .process::after {
    top: 16px; left: 0;
    animation: vkv-runner-x 7s cubic-bezier(0.5, 0, 0.5, 1) infinite;
  }
  @keyframes vkv-runner-x {
    0%   { transform: translateX(0); opacity: 0; }
    6%   { opacity: 1; }
    94%  { opacity: 1; }
    100% { transform: translateX(calc(100cqw - 8px)); opacity: 0; }
  }
}
@media (max-width: 899.98px) {
  .process::after {
    left: 16px; top: 0;
    animation: vkv-runner-y 7s cubic-bezier(0.5, 0, 0.5, 1) infinite;
  }
  @keyframes vkv-runner-y {
    0%   { transform: translateY(0); opacity: 0; }
    6%   { opacity: 1; }
    94%  { opacity: 1; }
    100% { transform: translateY(calc(100cqh - 8px)); opacity: 0; }
  }
}

/* ---- 10. Contact — "Get in touch" alignment + compact premium form ------ */
/* Every contact box aligns on the same grid: icon, title, value, note — each at
   the same vertical position across all four cards, all left-aligned. */
.contact-cards { align-items: stretch; }
.contact-cards .card { display: flex; }
.contact-cards .card-body {
  display: flex; flex-direction: column; align-items: flex-start;
  gap: 8px; padding: 22px 20px; text-align: left; width: 100%;
}
.contact-cards .service-icon { margin: 0 0 4px; flex: none; }
.contact-cards .card-title {
  margin: 0; font-size: 0.82rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--slate-400, #8A97B1);
}
.contact-cards .card-text {
  margin: 0; font-size: 1rem; line-height: 1.45; font-weight: 600;
  color: #EAF0FB; text-align: left; word-break: break-word;
}
.contact-cards .card-text a { color: inherit; }
.contact-cards .contact-sub {
  margin: auto 0 0; padding-top: 6px;
  font-size: 0.8rem; line-height: 1.5; color: var(--slate-400, #8A97B1);
}
.contact-trust {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 8px 24px; margin-top: 22px;
}
.contact-trust-item { display: flex; align-items: flex-start; gap: 8px; margin: 0; }

/* Compact form: the panel, controls and gaps all tighten. Every field, label,
   validation message and hidden security input is untouched — this is padding,
   type scale and column layout only. The grid container is .form-grid (the
   partial's own wrapper); .field-wide items still span the full width. */
.form-tabs { padding: 18px 18px 20px; border-radius: 16px; }
.form-tabs .tab-list { gap: 6px; margin-bottom: 14px; }
.form-tabs .tab { padding: 8px 14px; font-size: 0.85rem; }
.form-intro { font-size: 0.86rem; margin: 0 0 12px; }
.form-grid { display: grid; gap: 10px 12px; }
@media (min-width: 640px) {
  .form-grid:not(.form-grid-1) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .form-grid:not(.form-grid-1) > .field-wide { grid-column: 1 / -1; }
}
.form-grid .field { margin: 0; }
.form-grid label:not(.consent) {
  font-size: 0.76rem; letter-spacing: 0.04em; margin-bottom: 4px; display: block;
}
.form-grid input:not([type="checkbox"]), .form-grid select {
  min-height: 40px; padding: 8px 12px; font-size: 0.9rem; border-radius: 9px;
}
/* Module 42: every public enquiry Message field renders about two visible
   lines — compact, still freely typable and user-resizable. The `rows="2"`
   attribute on the control does the sizing; this only removes the old
   min-height floor that was overriding it. */
.form-grid textarea {
  padding: 9px 12px; font-size: 0.9rem; border-radius: 9px;
  min-height: 0; height: auto; line-height: 1.45; resize: vertical;
}
.form-tabs .form-actions { margin-top: 12px; }
.form-tabs .form-actions .btn { min-height: 42px; }
.form-grid .consent { font-size: 0.78rem; line-height: 1.5; }
.form-grid .field-error { font-size: 0.74rem; margin: 3px 0 0; }

/* ---- 11. Header alignment -----------------------------------------------
   Desktop only. header.css switches to the off-canvas menu at ≤980px by
   hiding .primary-nav and .header-cta — an unscoped display:flex here would
   defeat that and push the nav off-screen (it did: 470px of overflow at 430px
   wide). The desktop rules are therefore gated above that breakpoint, and
   .nav-toggle is left entirely to header.css. */
@media (min-width: 981px) {
  .header-inner {
    display: flex; align-items: center; gap: clamp(12px, 1.6vw, 28px);
    min-height: var(--header-h, 72px);
  }
  .header-inner .brand { display: inline-flex; align-items: center; flex: none; }
  .primary-nav { display: flex; align-items: center; margin-inline: auto; }
  .nav-list { display: flex; align-items: center; gap: clamp(4px, 0.8vw, 16px); margin: 0; padding: 0; }
  .nav-item { display: flex; align-items: center; }
  .nav-link { display: inline-flex; align-items: center; line-height: 1; padding-block: 10px; }
  .header-cta { display: flex; align-items: center; gap: 8px; flex: none; }
  .header-cta .btn {
    display: inline-flex; align-items: center; gap: 7px;
    min-height: 38px; padding: 0 14px; line-height: 1; white-space: nowrap;
  }
  .header-pill-ico { display: inline-flex; align-items: center; }
}
/* Below the breakpoint only the brand + burger remain, so the row just needs
   to stay centred and spread. */
@media (max-width: 980px) {
  .header-inner { display: flex; align-items: center; gap: 12px; min-height: 64px; }
  .header-inner .brand { display: inline-flex; align-items: center; }
}
.util-bar-inner { display: flex; align-items: center; justify-content: space-between; gap: 16px; min-height: var(--util-h, 40px); flex-wrap: wrap; }
.util-contact { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.util-contact-item { display: inline-flex; align-items: center; gap: 6px; margin: 0; }
.util-tag { display: inline-flex; align-items: center; gap: 7px; margin: 0; }

/* ---- 12. Content cards: OUTSIDE running border + inner hover shadow -----
   Module 39 moves the animated frame OUTSIDE the box and swaps the outer
   directional shadow for a subtle animated INNER shadow.

   The frame sits at `inset: -5px` — a ring around the card, clear of its own
   edge — and a single illuminated segment travels the full perimeter via a
   rotating conic gradient clipped to a 1.5px band. Because the ring is an
   absolutely-positioned pseudo-element it adds no size and cannot shift
   layout; the 5px it occupies is already inside the grid gap.

   On hover the card gains an inset shadow that deepens as it settles, giving
   the surface real depth instead of an outer glow. Each card is given its own
   random phase by vkv-ux.js, so the set animates independently.

   Applied from a fixed selector list — never blanket-applied. Form and button
   borders are not in that list. */
.vkv-anim-box {
  position: relative;
  transition: box-shadow 460ms cubic-bezier(0.22, 1, 0.36, 1),
              transform 460ms cubic-bezier(0.22, 1, 0.36, 1);
}
/* Resting ring: dark, quiet, outside the card. */
.vkv-anim-box::before {
  content: ""; position: absolute; inset: -5px;
  border-radius: calc(var(--card-radius, 16px) + 5px);
  pointer-events: none; z-index: 0;
  box-shadow: inset 0 0 0 1px rgba(10, 20, 44, 0.6);
}
/* ---- 12. Content cards: even gold edge + inner hover shadow ------------
   Module 45 removes the travelling perimeter arc. A conic gradient clipped to
   a thin band is only ever bright along part of its sweep, so at any instant it
   showed as a short bright segment sitting on ONE corner — read as a stray
   corner line on the service cards rather than as a running border. It also
   depended on mask compositing, and degraded badly where that was unsupported.

   What replaces it is quieter and correct on every engine: an EVEN gold edge on
   all four sides, a soft gold outer glow, and on hover a deepening inner shadow
   plus a brighter edge. Geometry is unchanged — the ring still sits at
   `inset: -5px`, adds no size, and cannot shift layout. */
.vkv-anim-box::after {
  content: ""; position: absolute; inset: -5px;
  border-radius: calc(var(--card-radius, 16px) + 5px);
  pointer-events: none; z-index: 0;
  box-shadow: inset 0 0 0 1px rgba(228, 199, 126, 0.26);
  opacity: 1;
  transition: box-shadow 420ms ease;
}
.vkv-anim-box:hover::after,
.vkv-anim-box:focus-within::after {
  box-shadow:
    inset 0 0 0 1px rgba(228, 199, 126, 0.62),
    0 0 22px -8px rgba(228, 199, 126, 0.45);
}
@property --run-angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

/* Hover: the card surface takes a subtle animated inner shadow. No outer glow
   beyond the edge, no size change. */
.vkv-anim-box:hover,
.vkv-anim-box:focus-within {
  transform: translateY(-2px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.07),
    inset 0 14px 34px -16px rgba(2, 6, 18, 0.92),
    inset 0 -14px 34px -18px rgba(2, 6, 18, 0.78);
  animation: vkv-inner-settle 620ms cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes vkv-inner-settle {
  from { box-shadow: inset 0 0 0 rgba(2, 6, 18, 0); }
}
@supports not ((-webkit-mask-composite: xor) or (mask-composite: exclude)) {
  .vkv-anim-box::after { opacity: 1; }
}

/* ---- 13. Industries we serve: premium button hover ----------------------
   Same language as the cards, at chip scale. Border and background shift, a
   gold wash rises from the bottom, the icon lifts — all on transforms and
   colour, so the grid never reflows. */
.industry {
  position: relative; overflow: hidden;
  transition: transform 380ms cubic-bezier(0.22, 1, 0.36, 1),
              border-color 380ms ease, box-shadow 380ms ease;
}
.industry::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; z-index: 0;
  background: linear-gradient(0deg, rgba(228, 199, 126, 0.16) 0%, transparent 72%);
  opacity: 0; transition: opacity 380ms ease;
}
.industry > * { position: relative; z-index: 1; }
.industry:hover,
.industry:focus-within {
  transform: translateY(-3px);
  border-color: rgba(228, 199, 126, 0.55);
  box-shadow:
    0 2px 6px rgba(3, 8, 22, 0.4),
    0 16px 30px -12px rgba(3, 8, 22, 0.7);
}
.industry:hover::before,
.industry:focus-within::before { opacity: 1; }
.industry-icon { transition: transform 380ms cubic-bezier(0.22, 1, 0.36, 1), color 380ms ease; }
.industry:hover .industry-icon { transform: translateY(-2px) scale(1.06); color: var(--gold-400, #E4C77E); }

/* ---- 14. "Ready for better results?" — guaranteed clearance -------------
   Module 37: the band now has its own inner gutter and the action row a
   guaranteed top gap, so the buttons cannot touch the card edge or the text
   above them at any width. */
main .cta-band {
  padding-inline: clamp(22px, 3vw, 52px);
  overflow: hidden;
}
main .cta-band > * { position: relative; z-index: 2; max-width: 100%; }
main .cta-band h2 { margin-bottom: 10px; }
main .cta-band p { margin-bottom: 0; }
.cta-actions {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 14px; margin-top: clamp(20px, 2vw, 28px); width: 100%;
}
.cta-actions .btn {
  flex: 0 1 auto; max-width: 100%;
  justify-content: center; text-align: center; white-space: nowrap;
  padding-inline: clamp(16px, 2vw, 30px);
}
@media (max-width: 560px) {
  .cta-actions { flex-direction: column; align-items: stretch; }
  .cta-actions .btn { width: 100%; white-space: normal; }
}

/* ---- 15. About leadership: full portrait, no crop or distortion ---------
   Module 37: the frame was cropping the supplied portraits (they are square
   assets of differing pixel sizes in a taller frame). A square frame with
   `object-fit: contain` shows each portrait COMPLETE at its true aspect ratio —
   no cropping, no stretching, no alteration of the approved image. The tinted
   backdrop fills any letterbox so the card still reads as one solid unit. */
.leader-photo {
  aspect-ratio: 1 / 1; width: 100%; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background:
    radial-gradient(70% 70% at 50% 30%, rgba(36, 52, 94, 0.85) 0%, rgba(10, 22, 51, 0.95) 100%);
}
.leader-photo img {
  width: 100%; height: 100%;
  object-fit: contain; object-position: center;
  display: block;
}
.leader-body { padding: 18px 18px 20px; }
.leader-name { margin: 0 0 2px; }
.leader-title { margin: 0; color: var(--gold-400, #E4C77E); font-size: 0.88rem; }

/* ---- 16. Floating contact: pinned right, aligned, never overlapping -----
   One flex column anchored to the right edge, bottom-aligned, with a fixed gap
   so the Call and WhatsApp buttons can never sit on top of each other. The
   mobile CTA bar offset is preserved. */
body:not(.admin-body) .floating-stack {
  position: fixed;
  right: clamp(12px, 1.6vw, 22px);
  left: auto;
  bottom: calc(clamp(14px, 2vw, 24px) + var(--floating-offset, 0px));
  display: flex; flex-direction: column; align-items: flex-end;
  gap: 12px; z-index: 60;
}
.floating-stack.has-mobile-bar { --floating-offset: 64px; }
.floating-stack.has-chat { --floating-offset: 72px; }
.floating-btn {
  position: relative;
  width: 52px; height: 52px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  /* Module 42: gold rim + glow, a periodic blink and a gentle scale pulse.
     Animating transform/box-shadow only, so the layout box never moves and no
     horizontal overflow is possible (the stack is right-anchored). */
  border: 1px solid rgba(228, 199, 126, 0.55);
  animation: vkv-float-pulse 3.4s cubic-bezier(0.4, 0, 0.3, 1) infinite;
}
.floating-whatsapp { animation-delay: 1.7s; }
@keyframes vkv-float-pulse {
  0%, 100% { transform: scale(1);
             box-shadow: 0 0 0 0 rgba(228, 199, 126, 0.42),
                         0 10px 24px -10px rgba(2, 6, 18, 0.85),
                         0 0 16px -4px rgba(228, 199, 126, 0.30); }
  42%      { transform: scale(1.06);
             box-shadow: 0 0 0 10px rgba(228, 199, 126, 0),
                         0 12px 26px -10px rgba(2, 6, 18, 0.88),
                         0 0 26px 0 rgba(228, 199, 126, 0.55); }
  60%      { transform: scale(1); }
}
@media (max-width: 430px) {
  .floating-btn { width: 48px; height: 48px; }
  .floating-stack { gap: 10px; }
}

/* ---- 17. Premium section treatment (Module 39) --------------------------
   Typography, hierarchy and card presentation only — no approved copy changes.
   Covers the four named sections: Ready for better results, Why Choose Us,
   How We Work, Industries We Serve. */
.section-head .eyebrow {
  display: inline-block; margin-bottom: 10px;
  font-size: 0.72rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--gold-400, #E4C77E);
  /* Short kickers like "How we work" were wrapping onto two lines inside the
     narrow centred column, which read as a mistake. */
  white-space: nowrap;
}
.section-head h2 {
  font-size: clamp(1.5rem, 1.1rem + 1.5vw, 2.2rem);
  line-height: 1.16; letter-spacing: -0.018em; text-wrap: balance; margin: 0;
}
.section-head p {
  font-size: clamp(0.94rem, 0.9rem + 0.2vw, 1.04rem);
  line-height: 1.65; max-width: 62ch; margin-inline: auto; color: var(--text-muted, #A9B6CE);
}
.section-head.center { text-align: center; }

/* Ready for better results — the page's closing statement, so it gets the most
   presence: a wider gold frame, a deeper ground and a larger headline. */
main .cta-band {
  border-radius: 20px;
  background:
    radial-gradient(110% 130% at 82% -20%, rgba(38, 60, 116, 0.75) 0%, transparent 58%),
    radial-gradient(80% 100% at 6% 110%, rgba(201, 162, 75, 0.16) 0%, transparent 62%),
    linear-gradient(168deg, #132348 0%, #0A1428 100%);
  border: 1px solid rgba(228, 199, 126, 0.34);
  box-shadow: 0 30px 70px -34px rgba(2, 6, 18, 0.88);
  text-align: center;
}
main .cta-band h2 {
  font-size: clamp(1.6rem, 1.2rem + 1.7vw, 2.4rem);
  line-height: 1.14; letter-spacing: -0.02em; text-wrap: balance;
}
main .cta-band p {
  margin-inline: auto; max-width: 62ch;
  font-size: clamp(0.94rem, 0.9rem + 0.2vw, 1.05rem); line-height: 1.6;
}

/* Why Choose VKV Group — even card heights, clear title/body separation. */
.why-grid, .why-choose-grid { align-items: stretch; }
.why-card, .why-item {
  display: flex; flex-direction: column; gap: 8px;
  padding: 22px 20px; border-radius: 16px;
}
.why-card h3, .why-item h3 {
  margin: 0; font-size: 1.02rem; line-height: 1.3; letter-spacing: -0.01em;
}
.why-card p, .why-item p {
  margin: 0; font-size: 0.9rem; line-height: 1.6; color: var(--text-muted, #A9B6CE);
}

/* How We Work — the number chip reads as a premium marker, not a bullet. */
.process-num {
  font-family: var(--font-display, Sora, sans-serif);
  font-weight: 700; font-size: 0.92rem; letter-spacing: 0.02em;
  width: 38px; height: 38px; border-radius: 50%;
  color: var(--gold-400, #E4C77E);
  background: radial-gradient(circle at 34% 28%, rgba(255, 255, 255, 0.16) 0%, transparent 52%),
              linear-gradient(158deg, #22325C 0%, #101C3C 100%);
  border: 1px solid rgba(228, 199, 126, 0.42);
}
.process-title { font-size: 1.02rem; letter-spacing: -0.01em; }
.process-desc { font-size: 0.9rem; line-height: 1.6; color: var(--text-muted, #A9B6CE); }

/* Industries We Serve — even chips on one rhythm. */
.industries-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 12px;
}
.industry {
  display: flex; align-items: center; gap: 12px;
  padding: 16px 18px; border-radius: 14px; min-height: 68px;
}
.industry-title { font-size: 0.94rem; line-height: 1.35; font-weight: 600; }

/* ---- 18. Success in Numbers (Module 42) --------------------------------
   Every statistic sits in ONE horizontal desktop row — including 7+ Years of
   Experience, which must not be pushed to a second line — and each stat stacks
   its value ABOVE its label.

   The Google rating follows that same stacked shape: "5★" on its own line with
   "Rating on Google" beneath it. It is deliberately NOT one horizontal phrase,
   so the previous `order: -1` + full-width break are removed — that break was
   exactly what pushed 7+ onto a second row. `white-space: nowrap` on the label
   keeps "Rating on Google" from splitting mid-phrase. */
.stat-grid {
  display: flex; flex-wrap: wrap; justify-content: center;
  align-items: flex-start;
  gap: clamp(14px, 2vw, 40px);
}
.stat {
  flex: 0 1 auto; min-width: 0; text-align: center; padding-inline: 4px;
  display: flex; flex-direction: column; align-items: center;
}
.stat-value {
  display: block;
  font-family: var(--font-display, Sora, sans-serif); font-weight: 700;
  font-size: clamp(1.5rem, 1.1rem + 1.3vw, 2.4rem); line-height: 1.05;
  letter-spacing: -0.02em; color: #FFFFFF; white-space: nowrap;
}
.stat-label {
  display: block; margin-top: 4px;
  font-size: clamp(0.72rem, 0.66rem + 0.2vw, 0.82rem);
  line-height: 1.4; color: var(--slate-400, #8A97B1); white-space: nowrap;
}
/* The rating: same stacked shape as every other stat, gold value, inline in
   the row — no order override, no full-width break. */
.stat-rating { order: 0; flex: 0 1 auto; display: flex; flex-direction: column; align-items: center; margin-bottom: 0; }
.stat-rating .stat-value { font-size: clamp(1.5rem, 1.1rem + 1.3vw, 2.4rem); color: var(--gold-400, #E4C77E); }
.stat-rating .stat-label { margin-top: 4px; font-size: clamp(0.72rem, 0.66rem + 0.2vw, 0.82rem); color: #EAF0FB; white-space: nowrap; }
@media (max-width: 560px) {
  .stat { flex: 1 1 40%; }
  .stat-label { white-space: normal; }
  .stat-rating .stat-label { white-space: nowrap; }
}

/* ---- 19. Global gold box language (Module 42) --------------------------
   Every genuine content box carries the banner's gold treatment: a four-side
   gold border, a gold outer glow, and the running perimeter light from §12.
   Applied through .vkv-anim-box, which vkv-ux.js assigns from a fixed selector
   list — so form controls and buttons keep their own borders.

   Hierarchy is preserved: featured pricing and the CTA band keep their stronger
   frames (declared more specifically); this is the shared base. */
.vkv-anim-box {
  border: 1px solid rgba(228, 199, 126, 0.30);
  box-shadow:
    0 0 0 1px rgba(228, 199, 126, 0.06),
    0 18px 40px -26px rgba(228, 199, 126, 0.30),
    0 22px 44px -28px rgba(2, 6, 18, 0.8);
}
.vkv-anim-box:hover,
.vkv-anim-box:focus-within { border-color: rgba(228, 199, 126, 0.58); }
/* The banner enquiry card and the tabbed contact panel are boxes too. */
.banner-lead, .form-tabs {
  border: 1px solid rgba(228, 199, 126, 0.30);
  box-shadow:
    0 18px 40px -26px rgba(228, 199, 126, 0.28),
    0 24px 50px -30px rgba(2, 6, 18, 0.82);
}

/* ---- 20. Step-by-step sequence pointer (Module 44) ---------------------
   ONE reusable mechanism for the three sequenced sections: Why Choose Us,
   How We Work, Industries We Serve. vkv-ux.js tags each section
   `data-vkv-sequence`, marks its items `.seq-item`, and moves a single
   `.is-active` class along them on a timer — that is the whole engine. One
   class change every 1.8s, no geometry maths, no per-frame work, nothing
   generated per item, so it cannot conflict with the existing gold box borders
   (those animate their own pseudo-elements; this only adds colour and a glow).

   The active item gets a gold ring and a small lift, plus a pulsing pointer
   head. The pointer is an inset pseudo-element and the lift is a transform, so
   nothing reflows and there is no layout shift.

   Reading order is DOM order, which for these grids is exactly the visual
   left-to-right, top-to-bottom order — the sequence never crosses or moves
   diagonally. */
[data-vkv-sequence] .seq-item {
  position: relative;
  transition: border-color 520ms ease, box-shadow 520ms ease, transform 520ms cubic-bezier(0.22, 1, 0.36, 1);
}
[data-vkv-sequence] .seq-item.is-active {
  border-color: rgba(228, 199, 126, 0.72);
  box-shadow:
    0 0 0 1px rgba(228, 199, 126, 0.30),
    0 0 26px -6px rgba(228, 199, 126, 0.42),
    0 18px 36px -22px rgba(2, 6, 18, 0.85);
  transform: translateY(-2px);
}
/* Pointer head: a glowing dot that arrives at the active item and pulses. */
[data-vkv-sequence] .seq-item::before {
  content: ""; position: absolute; top: 10px; right: 10px;
  width: 9px; height: 9px; border-radius: 50%;
  pointer-events: none; z-index: 4;
  background: radial-gradient(circle, #FFF6DA 0%, rgba(228, 199, 126, 0.95) 42%, rgba(228, 199, 126, 0) 72%);
  opacity: 0; transform: scale(0.6);
  transition: opacity 320ms ease, transform 320ms ease;
}
[data-vkv-sequence] .seq-item.is-active::before {
  opacity: 1;
  animation: vkv-seq-pulse 1.8s ease-in-out infinite;
}
@keyframes vkv-seq-pulse {
  0%   { transform: scale(0.6);  box-shadow: 0 0 0 0 rgba(228, 199, 126, 0.55); }
  35%  { transform: scale(1);    box-shadow: 0 0 0 7px rgba(228, 199, 126, 0); }
  100% { transform: scale(0.85); box-shadow: 0 0 0 0 rgba(228, 199, 126, 0); }
}
/* How We Work: the active step's number chip lights up. */
[data-vkv-sequence] .process-step.is-active .process-num {
  color: #0A1428;
  background: linear-gradient(158deg, #FFF3D2 0%, #E4C77E 62%, #C9A24B 100%);
  border-color: rgba(255, 246, 214, 0.9);
  box-shadow: 0 0 22px -4px rgba(228, 199, 126, 0.75);
}
/* Industries: the active chip's icon brightens. */
[data-vkv-sequence] .industry.is-active .industry-icon {
  color: var(--gold-400, #E4C77E); transform: translateY(-2px) scale(1.06);
}
/* Why Choose: the active card's title takes the accent. */
[data-vkv-sequence] .why-card.is-active .card-title { color: var(--gold-400, #E4C77E); }

@media (max-width: 767.98px) {
  /* The pointer head would crowd a narrow card; the gold ring carries the cue. */
  [data-vkv-sequence] .seq-item::before { display: none; }
}

/* ---- Reduced motion: every addition above stops, nothing disappears ----- */
@media (prefers-reduced-motion: reduce) {
  .vkv-dots span,
  .vkv-anim-box::after,
  .hero-motion span,
  .hero-line,
  .hero-line-2 .text-gold,
  .consent-panel,
  .trust-underline::after,
  .process-num::after,
  .process::after,
  .floating-call::after,
  .floating-whatsapp::after,
  .floating-btn,
  [data-vkv-sequence] .seq-item.is-active::before { animation: none !important; }
  /* The JS sequence also stops advancing, so no item is left mid-highlight. */
  [data-vkv-sequence] .seq-item.is-active { transform: none; }
  .hero-line { opacity: 1; }
  .hero-line-2 .text-gold { -webkit-text-fill-color: currentColor; color: var(--gold-400, #E4C77E); }
  .process::after, .floating-call::after, .floating-whatsapp::after { opacity: 0; }
  .vkv-anim-box:hover, .industry:hover { transform: none; animation: none; }
}
