/* ==========================================================================
   PAGE-LEVEL MESH — one continuous drifting dot grid behind the ENTIRE page,
   instead of per-section .section-mesh backgrounds.

   Composition only: every value comes from tokens.css, and the drift reuses the
   `mesh-wave` keyframes already defined in components.css.

   Pairs with: no .section-mesh / .section--light / .section--brand on any
   <section>, so all sections are transparent and the mesh reads as one field.
   ========================================================================== */

/* The mesh layer itself. Fixed, so it stays one continuous field while the page
   scrolls over it. Sits at z-index 0; page content is lifted to 1 below. */
.page-mesh {
  position: fixed;
  inset: -80px;
  background-image:
    radial-gradient(circle, rgba(252, 252, 252, 0.10) 1px, transparent 1.5px),
    radial-gradient(circle, rgba(252, 252, 252, 0.10) 1px, transparent 1.5px);
  background-size: 28px 28px, 28px 28px;
  background-position: 0 0, 14px 14px;
  animation: mesh-wave 14s ease-in-out infinite;
  will-change: transform;
  pointer-events: none;
  z-index: 0;
}
@media (prefers-reduced-motion: reduce) { .page-mesh { animation: none; } }

/* Dark shade bleeding in from both viewport edges. Two linear gradients on one
   fixed layer rather than pseudo-elements, so it stays a single paint and can't
   inherit the mesh's drift animation. Sits above the mesh (later in the DOM, same
   z-index) but below all content, and never eats a click.

   Mixed from --color-bg. Because that IS the page's base colour, a high alpha
   here doesn't darken the page so much as mask the dot mesh — the texture fades
   out toward both edges. Alpha and reach are the two dials. */
.page-edge {
  --edge-alpha: 85%;
  --edge-reach: 4%;
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    linear-gradient(to right,
      color-mix(in srgb, var(--color-bg) var(--edge-alpha), transparent) 0%,
      transparent var(--edge-reach)),
    linear-gradient(to left,
      color-mix(in srgb, var(--color-bg) var(--edge-alpha), transparent) 0%,
      transparent var(--edge-reach));
}

/* Lift all page content above the mesh layer. */
main, #footer { position: relative; z-index: 1; }

/* --- Minimal header (replaces the kit's #navbar pill) ----------------------
   Logo pinned left, the single CTA pinned right, on the container's own gutters
   so both line up with the hero copy underneath. No background: it reads as part
   of the hero rather than as a bar.

   Absolute, not fixed, and #hero is its containing block — it belongs to the hero
   and scrolls away with it instead of following the page. That also sidesteps the
   overlap problem a fixed version had: the white "Byte" would pass over the
   off-white trust band and the light cards below. */
#hero { position: relative; }
.hero-bar {
  position: absolute; top: var(--space-6); left: 0; right: 0; z-index: 10;
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-6);
  max-width: var(--container-max); margin-inline: auto;
  padding-inline: var(--space-6);
  /* the bar spans the full width, so let clicks through the empty middle */
  pointer-events: none;
}
.hero-bar > * { pointer-events: auto; }

/* --- Backgroundless sections ---------------------------------------------
   Sections inherit the page background; only cards, carousel slides, the
   value strip and the navbar keep a surface of their own. */
main > section { background-color: transparent; }

/* --- Reveal on scroll -----------------------------------------------------
   .reveal-up and --reveal-delay are applied by js/reveal.js, never in the
   markup — so if the script or IntersectionObserver is unavailable, nothing is
   ever hidden.

   --ease-reveal is a softer sibling of the system's --ease-out: same shape, but
   it decelerates over a longer tail, which is what makes a slow entrance read as
   a glide rather than a slide-and-stop. */
:root { --ease-reveal: cubic-bezier(0.16, 0.84, 0.24, 1); }

.reveal-up {
  opacity: 0;
  transform: translateY(22px);
  transition:
    opacity 1s var(--ease-reveal) var(--reveal-delay, 0ms),
    transform 1s var(--ease-reveal) var(--reveal-delay, 0ms);
  will-change: opacity, transform;   /* reveal.js clears this once it has run */
}
.reveal-up.is-visible {
  opacity: 1;
  transform: none;
}
@media (prefers-reduced-motion: reduce) {
  .reveal-up {
    opacity: 1; transform: none; transition: none; will-change: auto;
  }
}


/* --- Small additions the kit doesn't ship ---------------------------------- */

/* 2-up card grid (components.css only ships --2-4 and --3). Used by the
   "Two ways to work with us" pair. */
@media (min-width: 768px) { .card-grid--2 { grid-template-columns: repeat(2, 1fr); } }

/* Logo + label lockups in the hero trust bar. The logo sits tight against its
   label, inside the same flex item, so the bar's `·` dividers still fall between
   items rather than between a logo and its own text.

   Sizes are ALSO set as width/height attributes and an inline style on each <img>:
   these badge files are big raster assets (the Clutch one is 860x283), and with
   base.css's `img { max-width:100%; height:auto }` an unstyled render blows them
   up to container width. Belt and braces so that can't happen again. */
.trust-badge { display: inline-flex; align-items: center; gap: var(--space-3); }
.trust-badge__logo {
  display: block; width: auto; flex: 0 0 auto;
  height: 24px; max-height: 24px; max-width: 110px;
}

/* --- Hero: copy left, 3D embed right ---------------------------------------
   One column on mobile (copy first, embed under it), two from 1024px up. */
.hero-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-12);
  align-items: center;
}
@media (min-width: 1024px) {
  .hero-grid { grid-template-columns: 1.05fr 0.95fr; gap: var(--space-16); }
}

/* From tablet up the hero gets deeper top padding than the other sections, so
   the headline clears the absolute header with room to spare. Expressed as
   nav height + a gap (152px) rather than a literal, same as it was originally.
   Mobile keeps the flat 60px from the mobile block at the end of this file. */
@media (min-width: 768px) {
  #hero { padding-top: calc(var(--navbar-height) + var(--space-20)); }
}

/* Isometric circuit board in the right column. The canvas sizes itself off its
   own clientWidth (see js/circuit-board.js), so it only needs a width here —
   the script sets the height to keep the board's aspect. */
.hero-visual {
  position: relative;
  min-width: 0;
  display: flex; align-items: center; justify-content: center;
}
/* Yellow bloom behind the board, so it reads as lit rather than pasted on.
   Sits under the canvas, and can't intercept a pointer. */
.hero-visual::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 58% 46% at 50% 55%,
    color-mix(in srgb, var(--color-primary) 18%, transparent) 0%,
    transparent 70%);
  pointer-events: none;
  z-index: 0;
}
.hero-circuit {
  position: relative;
  z-index: 1;
  display: block;
  width: 100%;
  max-width: 520px;
}

/* --- .steps-carousel--flat -------------------------------------------------
   Modifier for the section 2 and section 3 carousels. The --slide variant
   alternates dark / brand-yellow slides and colours its type for a light
   section; --flat pins every slide to the plain .card look instead — same
   --color-surface, same border, same type ramp — so the carousels read as the
   card decks they replaced.

   Selectors are chained with --slide to outrank the kit's own rules on
   specificity rather than relying on stylesheet order. */
.steps-carousel--slide.steps-carousel--flat .step,
.steps-carousel--slide.steps-carousel--flat .step:nth-child(odd),
.steps-carousel--slide.steps-carousel--flat .step:nth-child(even) {
  background-color: var(--color-bg);
  border: 1px solid var(--color-border);
}
.steps-carousel--slide.steps-carousel--flat .step:nth-child(odd) h3,
.steps-carousel--slide.steps-carousel--flat .step:nth-child(even) h3 { color: var(--color-text); }
.steps-carousel--slide.steps-carousel--flat .step:nth-child(odd) p,
.steps-carousel--slide.steps-carousel--flat .step:nth-child(even) p { color: var(--color-text-muted); }
.steps-carousel--slide.steps-carousel--flat .step:nth-child(odd) .card-icon,
.steps-carousel--slide.steps-carousel--flat .step:nth-child(even) .card-icon { color: var(--color-primary); }

/* Inactive dots are dark-on-dark from the same light-section assumption. */
.steps-carousel--slide.steps-carousel--flat .steps-dot { background-color: rgba(252, 252, 252, 0.2); }
.steps-carousel--slide.steps-carousel--flat .steps-dot.is-active { background-color: var(--color-primary); }

/* Large line-drawn carousel icons (sections 2 and 3). These are inline <svg>,
   not <iconify-icon>, so anime.js can animate their strokes (js/icon-trace.js) —
   a web component's shadow DOM would be out of reach. 120px tall, with the
   stroke thinned from Tabler's native 2 to 1.25 so it stays fine at that size. */
.card-icon--trace {
  display: block;
  width: 120px; height: 120px;
  margin: 0 0 var(--space-6);   /* left-aligned; mobile centres it */
  color: var(--color-primary);
}
.icon-trace {
  display: block;
  width: 100%; height: 100%;
  overflow: visible;
}
/* Tabler ships stroke-width="2" on inner <g>/<path> elements; override so the
   line reads correctly scaled up 5x. */
.icon-trace [stroke-width] { stroke-width: 1.25; }

/* In-section CTA — centred under the engagement cards. Distinct class from
   .section-cta, which is the final CTA section's own panel. */
.cta-row {
  margin-top: var(--space-12);
  text-align: center;
}
.cta-row p {
  margin-bottom: var(--space-5);
  color: var(--color-text-muted);
}

/* --- Section 3: transparent section, contained panel -----------------------
   The section itself is backgroundless — the mesh runs straight through it.
   The panel is the .container instead, so it's a bounded block with rounded
   corners rather than a full-bleed band.

   The width clamp is what keeps it off the viewport edges: .container's own
   horizontal padding becomes the panel's inner padding once it has a
   background, so the page gutter has to come from somewhere else. */
#nearshore { background: none; border: none; }

#nearshore > .container {
  width: min(100% - var(--space-12), var(--container-max));
  padding: var(--space-16) var(--space-10);
  background-color: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  /* Yellow bloom INSIDE the panel, rising off its bottom edge. A
     background-image, so it paints over the translucent background-colour the
     glass block sets and is clipped to the border-radius for free. Flatter and
     wider than the one on section 2's cards, since this panel is much larger. */
  background-image: radial-gradient(
    ellipse 60% 42% at 50% 100%,
    color-mix(in srgb, var(--color-primary) 14%, transparent) 0%,
    transparent 70%);
}

/* its intro paragraph reads centred */
#nearshore .section-intro { text-align: center; margin-inline: auto; }

/* --- Trust band section ----------------------------------------------------
   A short strip under the hero. It's the one section with a solid background:
   --color-surface sits one step above the page base, and the hairlines top and
   bottom keep the edges crisp where the dotted mesh resumes. Shallow padding so
   it reads as a band, not a full section. */
.section-trust {
  /* 80% alpha so the dot mesh reads faintly through the band. First declaration
     is the opaque fallback for anything without color-mix(). */
  background-color: var(--color-bg);
  background-color: color-mix(in srgb, var(--color-bg) 80%, transparent);
  border-top: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
  padding-block: var(--space-10);
}

/* Bare variant of the trust bar. components.css ships it in yellow
   (.trust-bar) and dark (.trust-bar--dark); this one has no surface at all —
   the badges and labels sit straight on the section.

   Type goes back to the dark-theme ramp, and the `·` dividers need no override:
   components.css already draws them white-on-dark. The logos switch to the grey
   artwork, since the untouched brand versions were only legible on a light bar. */
.trust-bar--bare {
  background: none;
  border: none;
  padding-inline: 0;
}
.trust-bar--bare .fit-trust-title { color: var(--color-text); }
.trust-bar--bare .fit-trust-item  { color: var(--color-text-muted); }

/* The bar holds two .fit-trust-title badges side by side, a pairing
   components.css's divider rules don't cover (they only know title+item and
   item+item). Draw that one divider here, matching the kit's own colour. */
.trust-bar--bare .fit-trust-title + .fit-trust-title::before {
  content: ""; position: absolute; left: calc(-1 * var(--space-8) / 2); top: 50%;
  transform: translateY(-50%); height: 1.4em; width: 1px;
  background-color: rgba(252, 252, 252, 0.18);
}

/* Footnote under the bar — outside it, so it's back on the dark page and takes
   the dark-theme type ramp. Centred to match the bar above it. */
.trust-footnote {
  margin-top: var(--space-4);
  text-align: center;
  font-size: var(--text-sm);
  color: var(--color-primary);
}
/* separator kept in the same yellow, just quieter, so it reads as punctuation */
.trust-footnote span { margin: 0 var(--space-2); opacity: 0.5; }

.trust-badge__star { color: var(--color-primary); font-size: var(--text-base); flex: 0 0 auto; }

/* --- Darker surfaces -------------------------------------------------------
   Everything with a background drops one rung down the token ramp
   (bg → surface → surface-2 → surface-3), so the whole page sits darker:

     cards, section-2 slides, panels, footer   --color-surface  → --color-bg
     section-3 slides                          --color-surface-2 → --color-surface

   Section 3's slides keep one rung of separation from their own panel, which is
   the only reason they don't drop all the way to --color-bg too.

   This rule must stay ABOVE .card--bare below, so the bare cards' `background:
   none` still wins on source order. */
.card { background-color: var(--color-bg); }


/* ==========================================================================
   NO HOVER EFFECTS
   Nothing on the page moves, lifts, flips or changes colour on hover. The
   card--invert / card--lift variants were dropped from the markup entirely
   (that's where the yellow flip and the -4px lift came from); what's left here
   neutralises the hover states baked into the remaining components.

   Deliberately kept: buttons and the modal close still respond on hover. That's
   affordance on an actual control, not decoration — without it they read as dead.
   ========================================================================== */

/* base card: no border-colour flash */
.card:hover { border-color: var(--color-border); }

/* Bare card: content with no chrome. `border: none` rather than a transparent
   colour, so the .card:hover border-colour rule above has nothing to act on.
   Padding drops to 0 so the text lines up with the grid column edge instead of
   sitting inset where a card's padding used to be — hence the wider grid gap. */
.card--bare { background: none; border: none; padding: 0; }

/* Split card: icon in a filled circle on the left, title + subtitle on the
   right. Used by the two engagement cards under "Two ways to work with us". */
.card--split {
  display: flex;
  align-items: flex-start;
  gap: var(--space-5);
  text-align: left;
}
.card--split__text { min-width: 0; }
.card--split h3 { margin-bottom: var(--space-2); }
.card--split p  { margin: 0; }

/* Dark disc, yellow rim, and the glow on the OUTSIDE — no `inset`, so it blooms
   off the circle into the card. 30% larger than it started (56 -> 73px, glyph
   30 -> 39px). Also overrides .card-icon's block display and bottom margin,
   which would otherwise break the row. */
.card-icon--circle {
  position: relative;            /* containing block for the injected .circle-orbit */
  flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: 73px; height: 73px;
  margin: 0;
  border-radius: 50%;
  background-color: var(--color-surface);
  /* No border: the spinning conic ring below IS the rim. A solid one underneath
     would sit there permanently and kill the trail effect. */
  box-shadow: 0 0 26px -4px color-mix(in srgb, var(--color-primary) 40%, transparent);
  color: var(--color-primary);
  font-size: 39px;
  line-height: 1;
}

/* Orbiting dot, injected by js/icon-trace.js. The wrapper spans the disc and is
   what anime.js spins; the dot is pinned to the top of it, so rotating the
   wrapper walks the dot around the rim. Its own centre sits on the border line
   (top: -3px on a 6px dot), so it runs along the rim rather than inside it. */
.circle-orbit {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.circle-orbit__dot {
  position: absolute;
  top: -3px; left: 50%;
  width: 6px; height: 6px;
  margin-left: -3px;
  border-radius: 50%;
  background-color: var(--color-primary);
  box-shadow:
    0 0 6px 1px color-mix(in srgb, var(--color-primary) 85%, transparent),
    0 0 14px 4px color-mix(in srgb, var(--color-primary) 40%, transparent);
}

/* The trail: a conic gradient masked down to a 2px ring, spinning inside the
   same wrapper as the dot. The dot sits at 0deg (12 o'clock) and the gradient
   is brightest as it approaches 360deg — i.e. immediately BEHIND the dot —
   fading to nothing about a quarter-turn back. Rotation is clockwise, so the
   lit part is always the arc the dot has just crossed. */
.circle-orbit__trail {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(from 0deg,
    transparent 0deg,
    transparent 100deg,
    color-mix(in srgb, var(--color-primary) 12%, transparent) 190deg,
    color-mix(in srgb, var(--color-primary) 40%, transparent) 285deg,
    color-mix(in srgb, var(--color-primary) 75%, transparent) 345deg,
    var(--color-primary) 360deg);
  /* keep only the outer 2px, turning the disc into a ring */
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));
}
#capabilities .card-grid--2 { gap: var(--space-10); }

/* molecular globe (section 5): no scale-up, no fill change on the nodes.
   Only the dedicated .hub-node__hover wrapper is reset — the positioning
   transform on .hub-node and the depth scale on .hub-node__depth must survive. */
.hub-node:hover .hub-node__hover { transform: none; }
.hub-node:hover .hub-node__dot {
  border-color: rgba(242, 183, 5, 0.45);
  background: var(--color-bg);
}
.hub-node--center:hover .hub-node__dot {
  background: rgba(242, 183, 5, 0.12);
  border-color: rgba(242, 183, 5, 0.6);
}

/* Testimonial cards (section 4) — four across, plain .card surface like the rest
   of the page. .trust-stars only inherits a colour inside .trust-bar, where the
   bar itself is yellow, so it needs setting here. The quote is the card's lead
   voice rather than muted body copy; the attribution is the quiet part. */
.trust-stars { color: var(--color-primary); }
.card--testimonial {
  display: flex; flex-direction: column; gap: var(--space-3);
  margin: 0;
}
.card.card--testimonial p {
  color: var(--color-text);
  font-size: var(--text-base);
  line-height: 1.6;
  margin: 0;
}
.card--testimonial footer { font-size: var(--text-sm); color: var(--color-text-muted); }

/* Marker-pen highlight on a phrase inside a quote. Painted at full width here
   so it's present without JS; js/quote-highlight.js collapses it and sweeps it
   back in when the section scrolls into view.

   A background-image rather than a background-colour, because only an image can
   be sized to a percentage — which is what the sweep animates. box-decoration-
   break: clone repaints it on every line, so a phrase that wraps still reads as
   one continuous highlight.

   Solid brand yellow, so the ink has to flip dark to stay legible — white on
   #F2B705 is about 1.7:1, dark ink on it is 10.4:1. The script crossfades the
   colour as the sweep passes, so the text is never dark-on-dark mid-animation. */
.q-hl {
  background-image: linear-gradient(var(--color-primary), var(--color-primary));
  background-repeat: no-repeat;
  background-size: 100% 100%;
  background-position: 0 0;
  color: var(--color-bg);
  border-radius: 3px;
  padding: 0.06em 0.18em;
  margin: 0 -0.18em;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

/* --- Final CTA + footer, matched to hire.bytenana.tech ---------------------
   Both are opaque dark panels where the page-wide dot mesh stops, same as
   .section-trust. This kit's components.css still ships the older off-white
   #footer, so the background and the type ramp are overridden here. */
.section-cta {
  position: relative; overflow: hidden;
  background-color: var(--color-bg);
  border-top: 1px solid var(--color-border);
}
.cta-content { min-width: 0; text-align: center; }
.cta-content .section-intro { margin-inline: auto; }
.cta-actions { margin-top: var(--space-10); }
.section-cta .form-microcopy { color: var(--color-text-dim); margin-top: var(--space-3); }

#footer { background-color: var(--color-bg); border-top: 1px solid var(--color-border); }
#footer .footer-brand .logo-byte { color: var(--color-text); }
#footer .footer-brand p { color: var(--color-text-muted); }
.footer-social { display: flex; flex-direction: column; gap: var(--space-2); }
.footer-social a { font-size: var(--text-sm); color: var(--color-text-muted); transition: color var(--t-fast) ease; }
/* Icon-only variant: sits in a row, 24px glyphs with a 44px tap target. */
.footer-social--icons { flex-direction: row; align-items: center; gap: var(--space-4); }
.footer-social--icons a {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; min-height: 44px; font-size: 24px;
}
@media (hover: hover) and (pointer: fine) {
  .footer-social a:hover { color: var(--color-primary); }
}


/* ==========================================================================
   GLASS PANELS
   Every surface goes translucent with a blurred backdrop, so the dot mesh and
   the edge shade read softly through the cards and panels.

   Declared last and as one block: it's the single place to tune the look, and
   being last it wins over the per-element background rules further up without
   any specificity games. .card--bare is excluded so the two engagement cards
   stay genuinely bare.
   ========================================================================== */
:root {
  --panel-alpha: 70%;
  --panel-blur: 12px;
}

.card:not(.card--bare),
.steps-carousel--slide.steps-carousel--flat .step,
.section-trust,
#nearshore > .container,   /* section 3's panel is the container, not the section */
.section-cta,
#footer {
  background-color: color-mix(in srgb, var(--color-bg) var(--panel-alpha), transparent);
  -webkit-backdrop-filter: blur(var(--panel-blur));
  backdrop-filter: blur(var(--panel-blur));
}

/* Section 3's slides carry no card at all — content straight on the panel.
   backdrop-filter and box-shadow have to go with the background: a blur or a
   drop shadow on a boxless element renders as a floating rectangle. */
#nearshore .steps-carousel--flat .step,
#nearshore .steps-carousel--flat .step:nth-child(odd),
#nearshore .steps-carousel--flat .step:nth-child(even) {
  background: none;
  border: none;
  box-shadow: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* Section 2's slides get a yellow bloom INSIDE the card, rising off the bottom
   edge. It's a background-image, so it paints over the translucent
   background-color set above and is clipped to the card's border-radius for
   free. Inactive slides sit at opacity 0, so only the visible one glows. */
#services-carousel .step {
  background-image: radial-gradient(
    ellipse 76.5% 49.5% at 50% 100%,
    color-mix(in srgb, var(--color-primary) 16%, transparent) 0%,
    transparent 72%);
}


/* ==========================================================================
   THANK-YOU INTERSTITIAL (thanks.html)
   ========================================================================== */
.thanks-wrap {
  position: relative; z-index: 1;      /* above the mesh and edge layers */
  min-height: 100svh;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--space-10);
  text-align: center;
}
.thanks-card {
  width: min(100%, 520px);
  padding: var(--space-12) var(--space-10);
  background-color: color-mix(in srgb, var(--color-bg) var(--panel-alpha), transparent);
  -webkit-backdrop-filter: blur(var(--panel-blur));
  backdrop-filter: blur(var(--panel-blur));
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}
.thanks-tick {
  display: inline-flex; align-items: center; justify-content: center;
  width: 56px; height: 56px;
  margin-bottom: var(--space-6);
  border-radius: 50%;
  background-color: var(--color-primary);
  color: var(--color-bg);
  font-size: var(--text-2xl); line-height: 1;
}
.thanks-card h1 { font-size: var(--text-4xl); }
.thanks-lead { margin-top: var(--space-4); color: var(--color-text-muted); }

/* The bar is decorative and duplicates the countdown text, so it's the one part
   that goes static under reduced motion. */
.thanks-progress {
  height: 3px; margin: var(--space-8) 0 var(--space-3);
  border-radius: 999px; overflow: hidden;
  background-color: var(--color-border);
}
.thanks-progress__fill {
  display: block; width: 100%; height: 100%;
  background-color: var(--color-primary);
  transform-origin: left center;
  animation: thanks-fill 3s linear forwards;
}
@keyframes thanks-fill { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@media (prefers-reduced-motion: reduce) {
  .thanks-progress__fill { animation: none; transform: scaleX(1); }
}

.thanks-countdown { font-size: var(--text-sm); color: var(--color-text-dim); }
.thanks-card .btn { margin-top: var(--space-6); }
.thanks-note { margin-top: var(--space-4); font-size: var(--text-xs); color: var(--color-text-dim); }


/* ==========================================================================
   MOBILE ONLY (< 768px)
   Everything below this line is scoped to the phone layout — the tablet and
   desktop rendering above is untouched.
   ========================================================================== */
@media (max-width: 767px) {

  /* 1. Header keeps the logo only; the CTA lives in the hero on mobile. */
  .hero-bar .btn { display: none; }

  /* 2. Every CTA spans its column — hero, the one under the engagement cards,
        and the final CTA. .btn is already an inline-flex with centred content,
        so full width centres the label too. Sizing the buttons rather than
        their wrappers, because the hero's wrapper carries display:flex as an
        inline style that a stylesheet can't override.
        (The header's Book a call is hidden on mobile — see 1 above.) */
  .hero-copy .btn,
  .cta-row .btn,
  .cta-actions .btn { width: 100%; }

  /* 3. Circuit board above the copy. .hero-grid is a single column here, so
        order alone reverses them. */
  .hero-visual { order: -1; }
  .hero-copy   { order: 0; }

  /* 4. Tighter section rhythm: 60px instead of the kit's 96px (--space-24),
        which desktop keeps. The hero picks this up too now that its inline
        padding-top is gone. */
  main > section { padding-block: 60px; }

  /* 5. Traced carousel icons centre in the card. Auto side margins work
        because .step-content is a plain block and the icon has a set width. */
  .card-icon--trace { margin-inline: auto; }

  /* 6. Section headings centre. Scoped to direct children of .container so the
        h3s inside cards and carousel slides keep their own alignment. */
  :is(#capabilities, #nearshore, #proof) > .container > :is(.section-label, h2) {
    text-align: center;
  }
}
