/* =========================================================
   W3Era SEO — custom CSS
   -------------------------------------------------------
   ONLY effects Elementor's controls cannot express. Everything else
   (padding, margin, gaps, font sizes/weights, colours, gradients on
   containers, border radii, box shadows, card hover lift, the featured
   pricing card scale, image hover zoom, all responsive stacking) is
   configured in Elementor and deliberately absent from this file.

   Breakpoints match the original stylesheet: 1080 / 991 / 767.
   ========================================================= */

/* ---------------------------------------------------------
   0. Theme integration
   Astra still emits its own .ast-container box around the content area.
   Elementor owns page width here (each section is a boxed 1200px
   container), so the theme wrapper must not add a second max-width or
   the full-bleed hero and dark bands stop reaching the viewport edges.
   --------------------------------------------------------- */
.elementor-page #content .ast-container,
.elementor-page #primary,
.elementor-page .entry-content {
  max-width: 100%;
  width: 100%;
  padding-left: 0;
  padding-right: 0;
  margin-left: 0;
  margin-right: 0;
}
.elementor-page #content .ast-container { display: block; }

/* Safety net: the Elementor header/footer templates replace Astra's chrome
   entirely, but if those templates were ever unpublished Astra's own header
   would take back over — and it prints the site title beside the logo, which
   the source design does not have. */
.ast-site-identity .site-title,
.ast-site-identity .site-description { display: none; }
.ast-site-identity .custom-logo-link img { height: 46px; width: auto; }

/* The source stylesheet opens with `*{margin:0}`, so no paragraph carries a
   default bottom margin and all spacing comes from explicit rules. Astra adds
   ~1.75em below every <p>, which stacks on top of the margins set per widget in
   Elementor and inflates the gap after every Text Editor. Reset it so the
   Elementor values are the only ones in play. */
.elementor-widget-text-editor p:last-child,
.elementor-widget-text-editor > .elementor-widget-container > p:only-child {
  margin-bottom: 0;
}
.elementor-widget-text-editor ul { margin-bottom: 0; }

:root {
  --w3-green-start: #0ea968;
  --w3-green-end: #22c55e;
  --w3-gradient-primary: linear-gradient(135deg, #0ea968, #22c55e);
  /* The 4-stop radial mesh. Elementor's background overlay accepts a single
     gradient, so the mesh has to live here. */
  --w3-gradient-mesh:
    radial-gradient(circle at 15% 20%, rgba(14, 169, 104, .26), transparent 45%),
    radial-gradient(circle at 85% 10%, rgba(37, 99, 235, .2), transparent 45%),
    radial-gradient(circle at 65% 90%, rgba(6, 182, 212, .16), transparent 50%),
    radial-gradient(circle at 20% 88%, rgba(132, 204, 22, .13), transparent 45%);
}

/* ---------------------------------------------------------
   1. Gradient-filled text
   Heading and Counter colour controls are solid-colour only, so the
   two-tone section titles and the dark stats-bar numbers need this.
   The <span> lives inside the Heading widget's own text, so the copy
   stays editable in Elementor.
   --------------------------------------------------------- */
.text-gradient,
.stat-num .elementor-counter-number-wrapper {
  background: var(--w3-gradient-primary);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* ---------------------------------------------------------
   2. .eyebrow — the 6px gradient dot before the label.
   Pseudo-elements have no Elementor control; the pill's background,
   radius, padding and typography are all set in Elementor.
   --------------------------------------------------------- */
.eyebrow::before {
  content: '';
  width: 6px;
  height: 6px;
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--w3-gradient-primary);
}

/* ---------------------------------------------------------
   3. Animated radial mesh overlay (.page-banner, .hero-slider .slide,
   .mesh-bg). Two things Elementor can't do: a 4-stop layered radial
   gradient, and animating background-position.

   Elementor 4.x paints a container's Background Overlay on the element's
   own ::before, so the mesh goes on ::after to sit alongside — not
   instead of — the dark scrim configured in Elementor.
   --------------------------------------------------------- */
.page-banner::after,
.hero-slider .slide::after,
.mesh-bg::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: var(--w3-gradient-mesh);
  background-size: 170% 170%;
  animation: w3MeshDrift 24s ease-in-out infinite alternate;
}

/* Stacking order, matching the source's single background shorthand
   (`linear-gradient(scrim), var(--gradient-mesh)` puts the scrim on top):
     background image (the element)  →  mesh (::after)  →  scrim (::before)  →  content.
   Without this the mesh would sit over the scrim and wash the photo out. */
.page-banner::after,
.hero-slider .slide::after,
.mesh-bg::after { z-index: 0; }

.page-banner::before,
.hero-slider .slide::before { z-index: 1; }

.page-banner > .e-con-inner,
.hero-slider .slide > .e-con-inner,
.mesh-bg > .e-con-inner {
  position: relative;
  z-index: 2;
}

@keyframes w3MeshDrift {
  0%   { background-position: 0% 0%; }
  100% { background-position: 100% 45%; }
}

/* ---------------------------------------------------------
   4. Hero slider — absolute stacking + cross-fade.
   Elementor free has no slider, and Pro's Slides widget cannot host the
   per-slide counters, glow icon and second button this design needs. The
   three slides are ordinary Elementor containers; this rule only stacks
   them, and custom.js toggles .is-active.
   --------------------------------------------------------- */
.hero-slider {
  position: relative;
}
.hero-slider .slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity .9s ease;
}
.hero-slider .slide.is-active {
  opacity: 1;
  visibility: visible;
}
/* The first slide also sits in the normal flow so the stage keeps its height. */
.hero-slider .slide:first-child {
  position: relative;
}

/* Floating stat cards. Only the looping float is here — the absolute offsets
   are set through Elementor's position controls, because Elementor emits its
   own top/left at a specificity no class selector can override. Elementor's
   animations are entrance-only, so the infinite float has to be CSS. */
.hero-slider .slide-stat-card { animation: w3FloatY 4.5s ease-in-out infinite; }
.hero-slider .stat-card-2     { animation-delay: 1.4s; }

@keyframes w3FloatY {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-12px); }
}

/* Prev/next arrows and dot strip, injected by custom.js. */
.hero-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 5;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .1);
  border: 1px solid rgba(255, 255, 255, .25);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all .25s ease;
}
.hero-nav:hover { background: var(--w3-gradient-primary); border-color: transparent; }
.hero-prev { left: 28px; }
.hero-next { right: 28px; }

.hero-dots {
  position: absolute;
  bottom: 28px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 10px;
  z-index: 5;
}
.hero-dots button {
  width: 10px;
  height: 10px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, .35);
  cursor: pointer;
  transition: all .3s ease;
}
.hero-dots button.is-active {
  background: var(--w3-gradient-primary);
  width: 28px;
  border-radius: 6px;
}

/* ---------------------------------------------------------
   5. .service-card — gradient border on hover.
   Elementor's border-colour control is solid-colour only; a gradient
   border needs the mask-composite technique.
   --------------------------------------------------------- */
.service-card { position: relative; }
.service-card::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 16px;
  padding: 2px;
  background: var(--w3-gradient-primary);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: 0;
  transition: opacity .35s ease;
  pointer-events: none;
}
.service-card:hover::after { opacity: 1; }

/* ---------------------------------------------------------
   6. Card link arrow nudges on *card* hover — a child transform driven
   by a parent's hover state, which Elementor doesn't expose.
   --------------------------------------------------------- */
.card:hover .card-link .elementor-button-icon {
  transform: translateX(4px);
}
.card .card-link .elementor-button-icon {
  transition: transform .25s ease;
}

/* ---------------------------------------------------------
   7. .timeline-step — the vertical connector line between step numbers.
   --------------------------------------------------------- */
.timeline-step { position: relative; }
.timeline-step::before {
  content: '';
  position: absolute;
  left: 29px;
  top: 64px;
  bottom: 0;
  width: 2px;
  background: #e6eae8;
}
.timeline-step:last-child::before { display: none; }

/* ---------------------------------------------------------
   8. Portfolio thumb — image zoom on card hover.
   The thumb is a container background (the design layers a scrim and a
   centred icon over it), and Elementor has no hover-scale for
   background images.
   --------------------------------------------------------- */
.portfolio-thumb { transition: transform .5s ease; }
.portfolio-card:hover .portfolio-thumb { transform: scale(1.08); }

/* ---------------------------------------------------------
   9. .price — the smaller "/mo" suffix inside the Heading widget.
   The suffix is an inline <span> in the widget's own editable text, so
   only its size/weight/colour need a rule.
   --------------------------------------------------------- */
.price .elementor-heading-title span {
  font-size: 15px;
  font-weight: 500;
  color: #667085;
}
.pricing-card.featured .price .elementor-heading-title span {
  color: rgba(255, 255, 255, .7);
}

/* ---------------------------------------------------------
   10. Breadcrumb inside the page banner Text Editor widget.
   --------------------------------------------------------- */
.breadcrumb {
  display: flex;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
}
.breadcrumb a:hover      { color: #fff; }
.breadcrumb .sep         { opacity: .5; }
.breadcrumb .current     { color: var(--w3-green-end); }

/* ---------------------------------------------------------
   11. Contact Form 7 fields.
   Elementor's Form widget is Pro-only, so the two forms are Contact Form 7
   rendered through Elementor's native shortcode widget. That markup belongs
   to CF7, not Elementor, so its controls cannot reach it — these are the
   source's .form-group / .form-control / .btn rules, scoped to .wpcf7.
   When Elementor Pro is installed, 21-header-footer.php swaps in native Form
   widgets and this whole block can be deleted.
   --------------------------------------------------------- */
/* CF7 wraps its own markup in <p> and <br>; those paragraphs inherit Astra's
   ~1.75em bottom margin and open a gap between every label and its input. */
.wpcf7 form p { margin: 0; }
.wpcf7 form br { display: none; }
.wpcf7 .wpcf7-form-control-wrap { display: block; }

.wpcf7 .form-group { margin-bottom: 22px; }
.wpcf7 .form-group label {
  display: block;
  font-size: 13.5px;
  font-weight: 600;
  margin-bottom: 8px;
  color: #23262b;
}
.wpcf7 .form-control,
.wpcf7 input[type="text"],
.wpcf7 input[type="email"],
.wpcf7 input[type="tel"],
.wpcf7 select,
.wpcf7 textarea {
  width: 100%;
  padding: 14px 18px;
  border: 1px solid #e6eae8;
  border-radius: 8px;
  font-family: inherit;
  font-size: 14.5px;
  background: #f5f8f7;
  color: #23262b;
  transition: all .25s ease;
}
.wpcf7 .form-control:focus,
.wpcf7 input:focus,
.wpcf7 select:focus,
.wpcf7 textarea:focus {
  outline: none;
  border-color: var(--w3-green-start);
  background: #fff;
  box-shadow: 0 0 0 4px rgba(14, 169, 104, .1);
}
.wpcf7 textarea { resize: vertical; min-height: 140px; }

/* .btn.btn-primary.btn-block on the submit control */
.wpcf7 input[type="submit"],
.wpcf7 .btn-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding: 15px 32px;
  border: none;
  border-radius: 999px;
  font-family: inherit;
  font-weight: 600;
  font-size: 15px;
  color: #fff;
  background: var(--w3-gradient-primary);
  box-shadow: 0 10px 24px rgba(14, 169, 104, .32);
  cursor: pointer;
  transition: all .3s ease;
}
.wpcf7 input[type="submit"]:hover,
.wpcf7 .btn-primary:hover {
  transform: translateY(-3px);
  box-shadow: 0 16px 32px rgba(14, 169, 104, .4);
}

/* The footer newsletter form inherits the dark-panel treatment. */
.footer-newsletter .wpcf7 .form-control,
.footer-newsletter .wpcf7 input[type="email"] {
  background: rgba(255, 255, 255, .06);
  border-color: rgba(255, 255, 255, .1);
  color: #fff;
  margin-bottom: 12px;
}
.footer-newsletter .wpcf7 input[type="email"]::placeholder {
  color: rgba(255, 255, 255, .4);
}

/* CF7's own response text, restyled to match .form-note */
.wpcf7 form .wpcf7-response-output {
  margin: 14px 0 0;
  padding: 12px 16px;
  border: none;
  border-radius: 8px;
  font-size: 14px;
  background: rgba(14, 169, 104, .09);
  color: var(--w3-green-start);
}
.wpcf7 form.invalid .wpcf7-response-output,
.wpcf7 form.unaccepted .wpcf7-response-output {
  background: rgba(220, 38, 38, .08);
  color: #b91c1c;
}
.wpcf7-not-valid-tip { font-size: 13px; margin-top: 6px; }

/* ---------------------------------------------------------
   12. Custom cursor — dot + lerped ring that grows over interactive
   elements. No Elementor equivalent. Desktop pointers only.
   --------------------------------------------------------- */
body.has-custom-cursor,
body.has-custom-cursor a,
body.has-custom-cursor button,
body.has-custom-cursor input,
body.has-custom-cursor textarea,
body.has-custom-cursor select { cursor: none; }

.cursor-dot,
.cursor-ring {
  position: fixed;
  top: 0;
  left: 0;
  pointer-events: none;
  z-index: 99999;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  will-change: transform;
  opacity: 0;
}
.cursor-dot {
  width: 8px;
  height: 8px;
  background: var(--w3-gradient-primary);
  transition: opacity .2s ease;
}
.cursor-ring {
  width: 38px;
  height: 38px;
  border: 1.5px solid rgba(14, 169, 104, .5);
  transition: width .25s ease, height .25s ease, border-color .25s ease,
              background .25s ease, opacity .2s ease;
}
.cursor-dot.is-visible,
.cursor-ring.is-visible { opacity: 1; }
.cursor-ring.is-hovering {
  width: 64px;
  height: 64px;
  border-color: var(--w3-green-end);
  background: rgba(34, 197, 94, .08);
}
@media (hover: none), (pointer: coarse) {
  .cursor-dot, .cursor-ring { display: none !important; }
}

/* ---------------------------------------------------------
   13. Responsive edge cases outside Elementor's device controls
   --------------------------------------------------------- */

/* .stat-item:nth-child(2) loses its divider once the bar is 2-up. */
@media (max-width: 1080px) {
  .stats-bar .stat-item:nth-child(2) { border-right: none !important; }
}

@media (max-width: 767px) {
  .stats-bar .stat-item { border-right: none !important; }
  /* .hero-prev/.hero-next { display:none } — dots and swipe remain. */
  .hero-prev, .hero-next { display: none; }
  .hero-slider .stat-card-1,
  .hero-slider .stat-card-2 { position: static; margin: 12px 0 0; }

  /* Deliberate fix, not a reproduction: the source's .slide-tag and .eyebrow
     are inline-flex with no wrapping, so "AWARD-WINNING DIGITAL MARKETING
     AGENCY" (~406px at 13px + 1px letter-spacing) overflows any viewport
     narrower than ~450px. The original hides the overflow with
     body{overflow-x:hidden}, which clips the text instead. Allowing the pill
     to shrink and wrap keeps the label readable on small phones. */
  .eyebrow, .slide-tag {
    max-width: 100%;
    text-align: center;
  }
  .eyebrow .elementor-heading-title,
  .slide-tag .elementor-heading-title {
    white-space: normal;
    overflow-wrap: break-word;
  }
}

/* ---------------------------------------------------------
   14. Sticky header + shadow on scroll.
   Elementor's sticky is a Pro Motion Effect; this is the free equivalent.
   --------------------------------------------------------- */
.w3-site-header {
  position: sticky;
  top: 0;
  z-index: 1000;
  background: rgba(255, 255, 255, .92);
  backdrop-filter: blur(10px);
  transition: box-shadow .25s ease;
}
.w3-site-header.is-scrolled {
  box-shadow: 0 8px 24px rgba(35, 38, 43, .08);
}
