/* -------------------------------------------------------------------------
 * TrySoft overrides.
 *
 * Layered on top of the base template stylesheet, so this file must stay
 * last in the <head> cascade (see STYLESHEETS in app/layout.tsx). Nothing in
 * styles.css is edited directly, which keeps the template updatable.
 * ---------------------------------------------------------------------- */

:root {
  --accent: #6D3BF5;
  --accent-2: #8A63FF;

  /* The template's red brand token. It drives link hovers, underlines, icons
     and accents across every page -- some of them with !important, which no
     amount of per-rule overriding can outrank -- so it is repointed at the
     accent here, once, instead of being fought rule by rule. */
  --brand: var(--accent);
  /* Distance from the hero card's edge to the copy and to the header pill.
     A share of the viewport, not a leftover from a centred container, so the
     content keeps hugging the card at every width. */
  --hero-gutter: 4.6%;
}

/* ============================ Home hero ============================== */

.section-hero.hero-video {
  display: flex;
  align-items: center;
  /* A little air above the card rather than butting against the viewport. The
     header pill's own top padding is raised to match, so it keeps its place
     inside the card. */
  padding: 20px 16px 16px;
  min-height: 100vh;
}

/* The card is inset on all four sides: the template left the bottom edge open
   for the "scroll for more" tab, which this layout does not use. */
.section-hero.hero-video .hero-image {
  inset: 20px 16px 16px;
  background-image: none;
  background-color: #000;
  overflow: hidden;
}

/* The video is deliberately not full-bleed. It occupies the right of the card
   and its left edge is masked away, so the copy sits on flat black rather than
   on a washed-out overlay. */
.section-hero.hero-video .hero-image video {
  position: absolute;
  top: 0;
  right: 0;
  width: 64%;
  height: 100%;
  border-radius: 0;
  object-fit: cover;
  /* Crops from the right, which walks the vortex core out to ~77% across the
     card and leaves the source's darker edge against the mask. */
  object-position: left center;
  -webkit-mask-image: linear-gradient(
    90deg,
    rgba(0, 0, 0, 0) 0%,
    rgba(0, 0, 0, 0.35) 14%,
    rgb(0, 0, 0) 36%
  );
  mask-image: linear-gradient(
    90deg,
    rgba(0, 0, 0, 0) 0%,
    rgba(0, 0, 0, 0.35) 14%,
    rgb(0, 0, 0) 36%
  );
}

.section-hero.hero-video .container {
  z-index: 1;
}

.section-hero.hero-video .content-wrap {
  padding: 160px 0 120px;
  text-align: left;
  max-width: 860px;
}

.section-hero.hero-video .content-wrap .title {
  margin-bottom: 24px;
  color: var(--white);
  font-size: clamp(38px, 5.1vw, 80px);
  line-height: 1.06;
  letter-spacing: -0.03em;
}

.section-hero.hero-video .content-wrap .text {
  margin-bottom: 32px;
  max-width: 520px;
  color: rgba(255, 255, 255, 0.72);
  font-size: 16px;
  line-height: 26px;
}

.section-hero.hero-video .content-wrap .bot-btns {
  justify-content: flex-start;
  gap: 12px;
}

/* Primary CTA ----------------------------------------------------------
   Same construction as the template's .tf-btn -- identical inset edges and
   the same layered drop shadow -- only the fill is the accent. It reads as
   the purple member of the existing button set, not a different style. -- */
.tf-btn.btn-accent {
  background:
    radial-gradient(62.56% 62.56% at 28.14% -10.42%, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 100%),
    linear-gradient(180deg, var(--accent-2) 0%, var(--accent) 100%);
  box-shadow:
    0 -3px 0 0 rgba(43, 12, 112, 0.55) inset,
    0 1px 0 0 rgba(255, 255, 255, 0.3) inset,
    0 2.77px 2.21px 0 rgba(0, 0, 0, 0.12),
    0 6.65px 5.32px 0 rgba(0, 0, 0, 0.13),
    0 12.52px 10.02px 0 rgba(0, 0, 0, 0.13),
    0 22.34px 17.87px 0 rgba(0, 0, 0, 0.14),
    0 41.78px 33.42px 0 rgba(0, 0, 0, 0.15),
    0 100px 80px 0 rgba(0, 0, 0, 0.15);
}

.tf-btn.btn-accent:hover {
  background:
    radial-gradient(62.56% 62.56% at 50% -13%, rgba(255, 255, 255, 0.7) 0%, rgba(255, 255, 255, 0) 100%),
    linear-gradient(180deg, var(--accent-2) 0%, var(--accent) 100%);
}

/* ---- Photo hero (about) ------------------------------------------------
   Same black card, but the media is a bottom-anchored render on the right
   rather than a full-bleed video. ---------------------------------------- */
/*
 * "contain" rather than "cover": the card is far wider than the render is, so
 * cover would crop the top of the building by an amount that changes with the
 * viewport. Contained, the whole render is always visible and simply scales
 * with the card height -- and because the render is black-backed on a black
 * card, the leftover space beside it is invisible.
 *
 * The 62% box keeps the building clear of the copy on narrower desktops, where
 * a full-width box would slide it left into the headline.
 */
/*
 * The render is cropped to the building itself (no transparent or black margin
 * baked in), so pinning it to the card's bottom-right corner leaves no gap on
 * either side. max-width is what keeps it off the copy when the card turns
 * tall: sized by height alone it would widen past the headline.
 */
.section-hero.hero-video.hero-photo .hero-image img {
  position: absolute;
  top: auto;
  right: 0;
  bottom: 0;
  width: auto;
  height: 100%;
  max-width: 54%;
  border-radius: 0;
  object-fit: contain;
  object-position: right bottom;
}

/* Keeps the copy clear of the render. */
.section-hero.hero-video.hero-photo .content-wrap {
  max-width: 44%;
}

@media (max-width: 991px) {
  /* No room for copy beside the building, so it drops behind the text. */
  .section-hero.hero-video.hero-photo .hero-image img {
    right: 0;
    height: 100%;
    max-width: 100%;
    opacity: 0.5;
    object-position: center bottom;
  }

  .section-hero.hero-video.hero-photo .content-wrap {
    max-width: none;
  }
}

/* ---- Inner pages -------------------------------------------------------
   Same card, same left-aligned copy, just not a full viewport tall. ---- */
.section-hero.hero-video.hero-inner {
  min-height: 0;
}

.section-hero.hero-video.hero-inner .content-wrap {
  padding: 220px 0 120px;
}

.section-hero.hero-video.hero-inner .content-wrap .title {
  font-size: clamp(34px, 4.2vw, 64px);
}

/* v2 pages float the next section's image up into the hero, so those keep the
   deep bottom padding the overlap depends on. */
.section-hero.hero-video.v2 .content-wrap {
  padding-bottom: 446px;
}

.section-hero.hero-video .breadcrumbs {
  justify-content: flex-start;
  margin-top: 20px;
  color: rgba(255, 255, 255, 0.6);
}

.section-hero.hero-video .breadcrumbs .link1 {
  color: rgba(255, 255, 255, 0.85);
}

@media (max-width: 991px) {
  .section-hero.hero-video.hero-inner .content-wrap {
    padding: 170px 0 80px;
  }
}

/* ============================== Team ================================= */

/* The unfilled team slot: an empty frame where the portrait will go. */
.team-item .image.is-empty {
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: transparent;
}

/* ======================== Section badges ============================= */

/* Every section badge carries the accent rather than the template red.
   Applied once, here, instead of per section. */
.heading-section .heading-sub {
  color: var(--accent);
  background:
    radial-gradient(62.56% 62.56% at 28.14% -10.42%, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 100%),
    linear-gradient(0deg, #F1EDFE, #F1EDFE);
  box-shadow:
    0 -3px 0 0 #E4DCFB inset,
    0 1px 0 0 rgba(255, 255, 255, 0.7) inset,
    0 3px 3px 0 rgba(0, 0, 0, 0.08);
}

.heading-section .heading-sub::before {
  background-color: var(--accent);
}

/* ============================ Process ================================ */

/* Icon tiles carry the accent and its glow instead of the template red. */
.section-process .process-card .icon {
  background: linear-gradient(180deg, var(--accent-2) 0%, var(--accent) 100%);
  box-shadow:
    0 3.44px 5.57px 0 rgba(0, 0, 0, 0.09),
    0 22.91px 37.08px 0 rgba(109, 59, 245, 0.16),
    0 76px 123px 0 rgba(109, 59, 245, 0.05),
    0 5.05px 8.18px 0 rgba(109, 59, 245, 0.1),
    0 16.98px 27.47px 0 rgba(109, 59, 245, 0.05),
    0 56px 83px 0 rgba(109, 59, 245, 0.25),
    0 14px 34px 0 rgba(109, 59, 245, 0.25),
    0 1px 2px 0 rgba(109, 59, 245, 0.4),
    0 -3px 0 0 rgba(0, 0, 0, 0.06) inset,
    0 1px 0 0 rgba(255, 255, 255, 0.6) inset;
}

/* =========================== Features ================================ */

/* The centre tile and every pulse that travels out of it run on the accent. */
.features-center {
  background:
    linear-gradient(180deg, var(--accent) 0%, var(--accent-2) 100%),
    radial-gradient(62.56% 62.56% at 28.14% -10.42%, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 100%);
  box-shadow:
    0 -3px 0 0 rgba(0, 0, 0, 0.06) inset,
    0 1px 0 0 rgba(255, 255, 255, 0.6) inset,
    0 3.44px 5.57px 0 rgba(0, 0, 0, 0.09),
    0 22.91px 37.08px 0 rgba(109, 59, 245, 0.16),
    0 76px 123px 0 rgba(109, 59, 245, 0.05),
    0 5.05px 8.18px 0 rgba(109, 59, 245, 0.1),
    0 16.98px 27.47px 0 rgba(109, 59, 245, 0.05),
    0 56px 83px 0 rgba(109, 59, 245, 0.25),
    0 14px 34px 0 rgba(109, 59, 245, 0.25),
    0 1px 2px 0 rgba(109, 59, 245, 0.4);
}

/* This asset is transparent artwork rather than a full-bleed tile of its own,
   so the CSS gradient above becomes the tile and the mark is inset within it. */
.features-center.has-wordmark img {
  width: auto;
  height: 48%;
  max-width: 60%;
  border-radius: 0;
}

/* Pulses running up and down the bracket lines. */
.side-line-main .link-break-line .item.top {
  background: radial-gradient(circle at top right, var(--accent) 0%, transparent 90%);
}

.side-line-main .link-break-line .item.bottom {
  background: radial-gradient(circle at bottom right, var(--accent) 0%, transparent 90%);
}

/* Pulses shooting horizontally out of the tile. */
.side-line-main .simu-electric.left {
  background: linear-gradient(to right, var(--accent) 0%, transparent 100%);
}

.side-line-main .simu-electric.right {
  background: linear-gradient(to left, var(--accent) 0%, transparent 100%);
}

/* ============================= Tools ================================= */

/* The old centre asset was a dark tile with the mark baked in. The mark is now
   transparent white artwork, so the tile is drawn here in the accent. */
/* ---- AI tool logos ------------------------------------------------------
   The template's tool assets were pre-baked 104px tiles with the logo and a
   grey rounded background inside the SVG. The real vendor logos are bare
   glyphs on a 24x24 viewBox with a 1em intrinsic size, so without this they
   would render at 16px on no background. The tile is drawn here instead. */
.tool-wrap .img-item {
  width: 92px;
  height: 92px;
  padding: 22px;
  border-radius: 10px;
  background: #F7F7F8;
  object-fit: contain;
}

/* ElevenLabs only ships a wordmark (175x24), so a square tile would shrink it
   to an illegible sliver. It gets a wider tile and keeps the same height. */
.tool-wrap .img-item[src*="elevenlabs"] {
  width: 138px;
  padding: 22px 18px;
}

@media (max-width: 991px) {
  .tool-wrap .img-item {
    width: 72px;
    height: 72px;
    padding: 16px;
  }

  .tool-wrap .img-item[src*="elevenlabs"] {
    width: 108px;
    padding: 16px 14px;
  }
}

/* The template shrinks individual tiles at this breakpoint; keep one size for
   all of them so the ring stays even. */
@media (max-width: 767px) {
  .tool-wrap .img-item,
  .tool-wrap .img-item-2,
  .tool-wrap .img-item-3,
  .tool-wrap .img-item-4,
  .tool-wrap .img-item-5,
  .tool-wrap .img-item-6 {
    width: 54px;
    height: 54px;
    padding: 11px;
    border-radius: 8px;
  }

  .tool-wrap .img-item[src*="elevenlabs"] {
    width: 82px;
    padding: 11px 9px;
  }
}

/* The dots travelling the connector lines. Their colour is a presentation
   attribute on each <circle>, which a CSS fill overrides -- so this catches
   all of them without touching the markup on every page. */
.tool-wrap .side-line circle {
  fill: var(--accent);
}

/* The two horizontal connectors are 2px and 3px tall, so an r=4 dot was being
   clipped by the SVG viewport into a dash while the tall diagonals rendered
   theirs whole. Letting the SVGs overflow makes all six dots identical. */
.tool-wrap .side-line svg {
  overflow: visible;
}

.tool-wrap .image-center.has-wordmark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 204px;
  height: 70px;
  padding: 0 22px;
  background:
    radial-gradient(62.56% 62.56% at 28.14% -10.42%, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 100%),
    linear-gradient(180deg, var(--accent-2) 0%, var(--accent) 100%);
}

.tool-wrap .image-center.has-wordmark img {
  width: 100%;
  height: auto;
}

@media (max-width: 767px) {
  .tool-wrap .image-center.has-wordmark {
    width: 100px;
    height: 36px;
    padding: 0 10px;
    border-radius: 6px;
  }
}

/* ============================ Contact ================================ */

/* Icon tiles on the three detail cards, accent instead of near-black. */
.box-contact-item .icon {
  background:
    linear-gradient(180deg, var(--accent-2) 0%, var(--accent) 100%),
    radial-gradient(62.56% 62.56% at 28.14% -10.42%, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 100%);
  box-shadow:
    0 -3px 0 0 rgba(43, 12, 112, 0.55) inset,
    0 1px 0 0 rgba(255, 255, 255, 0.3) inset,
    0 2.77px 2.21px 0 rgba(0, 0, 0, 0.12),
    0 3px 3px 0 rgba(0, 0, 0, 0.14),
    0 12.52px 10.02px 0 rgba(0, 0, 0, 0.13),
    0 22.34px 17.87px 0 rgba(0, 0, 0, 0.14),
    0 41.78px 33.42px 0 rgba(0, 0, 0, 0.15);
}

/* ============================= Footer ================================ */

/* The old asset was a dark tile with the mark baked in. The mark is now
   transparent white artwork, so the tile is drawn here -- same accent
   gradient and glow as the features tile. */
footer .footer-content .footer-logo {
  align-items: center;
  justify-content: center;
  width: 80px;
  height: 80px;
  border-radius: 20px;
  background:
    radial-gradient(62.56% 62.56% at 28.14% -10.42%, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 100%),
    linear-gradient(180deg, var(--accent-2) 0%, var(--accent) 100%);
  box-shadow:
    0 -3px 0 0 rgba(0, 0, 0, 0.06) inset,
    0 1px 0 0 rgba(255, 255, 255, 0.6) inset,
    0 3.44px 5.57px 0 rgba(0, 0, 0, 0.09),
    0 14px 34px 0 rgba(109, 59, 245, 0.25),
    0 1px 2px 0 rgba(109, 59, 245, 0.4);
}

footer .footer-content .footer-logo img {
  width: auto;
  height: 46%;
}

/* The background wordmark, sized to span the same 1296px band the old image
   occupied and to track the viewport below that. */
footer .footer-image .footer-wordmark {
  font-weight: 600;
  font-size: min(190px, 14.7vw);
  line-height: 1.05;
  letter-spacing: -0.03em;
  text-align: center;
  white-space: nowrap;
  color: #E3E2E2;
  -webkit-user-select: none;
  user-select: none;
}

/* Social badges carry the accent instead of the template's near-black. */
.tf-social-1 a .social-item {
  background:
    radial-gradient(62.56% 62.56% at 28.14% -10.42%, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 100%),
    linear-gradient(180deg, var(--accent-2) 0%, var(--accent) 100%);
  box-shadow:
    0 -3px 0 0 rgba(0, 0, 0, 0.22) inset,
    0 1px 0 0 rgba(255, 255, 255, 0.3) inset,
    0 2.77px 2.21px 0 rgba(0, 0, 0, 0.12),
    0 3px 3px 0 rgba(0, 0, 0, 0.14);
}

.tf-social-1 a:hover {
  color: var(--accent);
}

/* The glyph sits on the accent badge, so tinting it on hover made it vanish
   into its own background. The template colours it on hover from two places,
   hence the extra specificity here. */
.tf-social-1 a .social-item .icon,
.tf-social-1 a:hover .social-item .icon {
  color: #FFFFFF;
}

/* ============================== 404 ================================== */

/* The 404 is a full-page state: the header, footer and scroll-top button all
   step aside so nothing competes with it. The floating contact widgets stay,
   since reaching someone is still useful from a dead end. */
body.is-404 {
  background-color: #EFE1FB;
}

/*
 * Hidden two ways on purpose. :has() matches the server-rendered markup on the
 * very first paint, so the header never flashes before hydration; the body
 * class is the fallback for engines without :has(). The floating widgets are
 * appended to <body> by their own scripts, hence the id/class selectors.
 */
body:has(.page-404) .tf-header,
body:has(.page-404) footer,
body:has(.page-404) #goTop,
body:has(.page-404) .offcanvas-menu,
body:has(.page-404) .whatsapp-btn,
body:has(.page-404) #el-call-wrap,
body:has(.page-404) #el-modal-overlay,
body.is-404 .tf-header,
body.is-404 footer,
body.is-404 #goTop,
body.is-404 .offcanvas-menu,
body.is-404 .whatsapp-btn,
body.is-404 #el-call-wrap,
body.is-404 #el-modal-overlay {
  display: none !important;
}

.page-404 {
  position: relative;
  display: flex;
  min-height: 100vh;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 48px 20px 64px;
  background-color: #EFE1FB;
  overflow: hidden;
}

.page-404__oops {
  margin: 0;
  color: #0B0B0B;
  font-size: clamp(36px, 5vw, 72px);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.1;
}

/* The digits and the face share one box so the face always lands on the zero,
   whatever the viewport does to the type size. */
.page-404__stage {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: min(1100px, 100%);
  margin: clamp(8px, 3vh, 40px) 0;
}

.page-404__digits {
  color: #D3A7F2;
  font-size: clamp(150px, 32vw, 440px);
  font-weight: 800;
  line-height: 0.86;
  letter-spacing: 0.02em;
  pointer-events: none;
  user-select: none;
}

/*
 * The face is sized to sit on the middle zero rather than across all three
 * digits. pointer-events are off because an <svg> box swallows clicks over its
 * whole rect, transparent or not -- with them on it covered the Go Home link.
 * The pointer is tracked on window, so nothing is lost by switching them off.
 */
.page-404__face {
  position: absolute;
  top: 50%;
  left: 50%;
  width: clamp(180px, 30vw, 400px);
  transform: translate(-50%, -50%);
  overflow: visible;
  pointer-events: none;
}

.page-404__home {
  position: relative;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding-bottom: 6px;
  border-bottom: 2px solid #0B0B0B;
  color: #0B0B0B;
  font-size: clamp(18px, 2vw, 26px);
  font-weight: 500;
  transition: opacity 0.25s ease;
}

.page-404__home:hover {
  color: #0B0B0B;
  opacity: 0.62;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

@media (max-width: 767px) {
  .page-404 {
    padding: 32px 16px 48px;
  }
}

/* The face tracks the pointer; honour a request for less motion by holding it
   still (the tweens are pointer-driven, so this simply parks them). */
@media (prefers-reduced-motion: reduce) {
  .page-404__face g {
    transform: none !important;
  }
}

/* ====================== Service hero carousel ======================== */

/* Copy keeps the left side of the card; the stage owns the right. */
.section-hero.hero-carousel .content-wrap {
  max-width: 46%;
}

/* Full card: a "cover" slide needs the whole width, and a "subject" slide is
   held to the right by object-position rather than by the stage. */
.section-hero.hero-carousel .svh-stage {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  overflow: hidden;
}

/*
 * Every slide is parked off to the right with no transition. Becoming active
 * slides it in from there; leaving slides it out to the left. Because parking
 * is instant and invisible, the next slide always arrives from the right --
 * including on the wrap from the last service back to the first, so the motion
 * is always right to left.
 */
.section-hero.hero-carousel .svh-slide {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border-radius: 0;
  opacity: 0;
  transform: translateX(110%);
  transition: none;
  pointer-events: none;
}

/*
 * Trimmed cut-out. Boxed into the right half rather than spanning the card:
 * contained inside the full width, the widest artwork (cloud) would slide left
 * into the headline on narrower desktops. The vertical padding keeps it off
 * the card edges.
 */
.section-hero.hero-carousel .svh-slide[data-fit="subject"] {
  top: 8%;
  bottom: 8%;
  left: auto;
  right: 0;
  width: 52%;
  object-fit: contain;
  object-position: right bottom;
}

/*
 * Composed artwork. Boxed to the right like the cut-outs rather than covering
 * the card -- full bleed put dense code straight behind the headline. The mask
 * dissolves its left edge so the box has no visible seam against the card.
 */
.section-hero.hero-carousel .svh-slide[data-fit="cover"] {
  left: auto;
  right: 0;
  width: 56%;
  object-fit: cover;
  object-position: right center;
  -webkit-mask-image: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, rgb(0, 0, 0) 26%);
  mask-image: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, rgb(0, 0, 0) 26%);
}

.section-hero.hero-carousel .svh-slide.is-active,
.section-hero.hero-carousel .svh-slide.is-leaving {
  transition:
    transform 0.8s cubic-bezier(0.22, 1, 0.36, 1),
    opacity 0.8s ease;
}

.section-hero.hero-carousel .svh-slide.is-active {
  opacity: 1;
  transform: translateX(0);
}

.section-hero.hero-carousel .svh-slide.is-leaving {
  opacity: 0;
  transform: translateX(-110%);
}

/* ---- Rotating copy ------------------------------------------------------
   Same parking model as the slides: waiting items sit to the right, the live
   one is in place, and the outgoing one leaves to the left. The incoming copy
   is held back a beat so the old text clears before the new text lands. */
.svh-copy {
  display: grid;
}

.svh-copy__item {
  grid-area: 1 / 1;
  opacity: 0;
  transform: translateX(48px);
  transition: none;
  pointer-events: none;
}

.svh-copy__item.is-active {
  opacity: 1;
  transform: none;
  pointer-events: auto;
  transition:
    transform 0.7s cubic-bezier(0.22, 1, 0.36, 1) 0.14s,
    opacity 0.6s ease 0.14s;
}

.svh-copy__item.is-leaving {
  opacity: 0;
  transform: translateX(-48px);
  transition:
    transform 0.45s cubic-bezier(0.4, 0, 1, 1),
    opacity 0.35s ease;
}

/* ---- Pagination tabs --------------------------------------------------- */

.svh-tabs {
  display: flex;
  justify-content: space-between;
  gap: 32px;
  margin: 26px 0 8px;
  /* The WhatsApp and call widgets are fixed to the right edge (~60px wide at
     right: 24px), so the last tab needs that lane kept free. */
  padding-right: 96px;
  overflow-x: auto;
  scrollbar-width: none;
}

.svh-tabs::-webkit-scrollbar {
  display: none;
}

.svh-tab {
  position: relative;
  flex-shrink: 0;
  padding: 10px 2px 16px;
  border: 0;
  background: none;
  color: #0B0B0F;
  font-size: 16px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: color 0.25s ease;
}

.svh-tab:hover {
  color: var(--accent);
}

.svh-tab:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  border-radius: 6px;
}

/* The underline doubles as the timer: it grows from the centre over the
   slide's dwell time, and its animationend is what advances the carousel. */
.svh-tab__bar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  border-radius: 2px;
  background: #0B0B0F;
  transform: scaleX(0);
  transform-origin: center;
}

.svh-tab.is-active .svh-tab__bar {
  animation: svh-progress 5s linear forwards;
}

.svh[data-paused] .svh-tab.is-active .svh-tab__bar {
  animation-play-state: paused;
}

@keyframes svh-progress {
  from {
    transform: scaleX(0);
  }
  to {
    transform: scaleX(1);
  }
}

@media (max-width: 991px) {
  .section-hero.hero-carousel .content-wrap {
    max-width: none;
  }

  /* No room beside the copy, so the visual drops behind it. */
  .section-hero.hero-carousel .svh-stage {
    width: 100%;
    opacity: 0.35;
  }

  .svh-tabs {
    justify-content: flex-start;
    gap: 24px;
    padding-right: 84px;
  }

  .svh-tab {
    font-size: 15px;
  }
}

/* No autoplay under reduced motion -- with no animation there is no
   animationend -- and slides swap in place instead of travelling. */
@media (prefers-reduced-motion: reduce) {
  .svh-tab.is-active .svh-tab__bar {
    animation: none;
    transform: scaleX(1);
  }

  .section-hero.hero-carousel .svh-slide,
  .section-hero.hero-carousel .svh-slide.is-active,
  .section-hero.hero-carousel .svh-slide.is-leaving,
  .svh-copy__item,
  .svh-copy__item.is-active,
  .svh-copy__item.is-leaving {
    transition: opacity 0.2s ease;
    transform: none;
  }
}

/* ======================== Service list grid ========================== */

/*
 * Narrower than the site container. At the default 1320px this section runs
 * edge to edge on a typical screen, which also puts the last column under the
 * floating contact widgets; holding it to ~68% leaves a margin on both sides.
 */
.section-service-list > .container {
  width: clamp(320px, 80vw, 1400px);
  max-width: 100%;
}

.srv-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px;
}

/*
 * Notched card. The surface, the notch and the corner tile are three layers:
 * the surface clips the colour wash, the notch paints the page colour back
 * over the bottom-right corner (outline included, hence the overhang), and the
 * tile sits in the space that leaves. A single element could not do this --
 * clipping the wash would also clip the notch's overhang.
 */
.srv-card {
  --srv-notch: 78px;
  --srv-tile: 58px;
  --srv-radius: 16px;
  --srv-cut: 14px;
  --srv-line: #E4E1EE;
  /* Diameter of the hover wash: must clear the card's diagonal from corner to
     corner, or the fill stops short of the far edge. */
  --srv-wash: 1600px;

  position: relative;
  z-index: 0;
  display: flex;
  flex-direction: column;
  padding: 30px 30px 26px;
  min-height: 300px;
  color: #0B0B0F;
  transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}

.srv-card:hover,
.srv-card:focus-visible {
  transform: translateY(-6px);
}

.srv-card:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  border-radius: var(--srv-radius);
}

/* ---- surface ----
   Two rounded panels, top band and left band; their union is the card with the
   bottom-right corner cut away, and because they are real elements the cut
   corners can carry a radius. The outline is four 1px drop-shadows on their
   shared parent: a filter traces the union's silhouette, so the hairline turns
   every corner of the notch, which a box-shadow ring could not. */
.srv-card__bg {
  position: absolute;
  inset: 0;
  z-index: -1;
  filter:
    drop-shadow(1px 0 0 var(--srv-line))
    drop-shadow(-1px 0 0 var(--srv-line))
    drop-shadow(0 1px 0 var(--srv-line))
    drop-shadow(0 -1px 0 var(--srv-line));
  transition: filter 0.45s ease;
}

.srv-card:hover .srv-card__bg,
.srv-card:focus-visible .srv-card__bg {
  filter: drop-shadow(0 16px 28px rgba(75, 40, 180, 0.3));
}

.srv-card__panel {
  position: absolute;
  top: 0;
  left: 0;
  background: #FFFFFF;
  overflow: hidden;
}

/* Full width, stopping short of the notch. */
.srv-card__panel--a {
  right: 0;
  height: calc(100% - var(--srv-notch));
  border-radius: var(--srv-radius) var(--srv-radius) var(--srv-cut) 0;
}

/* Full height, stopping short of the notch. */
.srv-card__panel--b {
  bottom: 0;
  width: calc(100% - var(--srv-notch));
  border-radius: var(--srv-radius) 0 var(--srv-cut) var(--srv-radius);
}

/*
 * The wash floods from the cut corner. Both copies are circles CENTRED on the
 * card's bottom-right corner -- hence the --srv-wash/2 offsets, plus the notch
 * in whichever axis that panel stops short. Centred, not merely touching: a
 * circle anchored by its box corner is tangent to that point, and its far edge
 * then sweeps back across the card as an arc instead of covering it.
 *
 * The radius therefore has to exceed the card's diagonal. Sized in px because
 * the two panels differ in size and the circles must not.
 */
.srv-card__wash {
  --half: calc(var(--srv-wash) / 2);

  position: absolute;
  width: var(--srv-wash);
  height: var(--srv-wash);
  border-radius: 50%;
  background: radial-gradient(
    circle at center,
    #5A26E0 0%,
    var(--accent) 45%,
    var(--accent-2) 100%
  );
  opacity: 0;
  transform: scale(0.12);
  transform-origin: center;
  transition:
    transform 0.62s cubic-bezier(0.22, 1, 0.36, 1),
    opacity 0.3s ease;
}

.srv-card__panel--a .srv-card__wash {
  right: calc(-1 * var(--half));
  bottom: calc(-1 * var(--half) - var(--srv-notch));
}

.srv-card__panel--b .srv-card__wash {
  right: calc(-1 * var(--half) - var(--srv-notch));
  bottom: calc(-1 * var(--half));
}

.srv-card:hover .srv-card__wash,
.srv-card:focus-visible .srv-card__wash {
  opacity: 1;
  transform: scale(1);
}

/* ---- content ---- */
.srv-card__icon {
  display: flex;
  margin-bottom: 26px;
  color: #12121A;
  transition: color 0.35s ease;
}

.srv-card__title {
  margin: 0 0 10px;
  font-size: 18px;
  font-weight: 700;
  line-height: 1.3;
  transition: color 0.35s ease;
}

.srv-card__text {
  margin: 0 0 26px;
  /* Keeps the last lines clear of the cut corner. */
  padding-right: 8px;
  color: var(--secondary);
  font-size: 13.5px;
  line-height: 1.62;
  transition: color 0.35s ease;
}

.srv-card__more {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: auto;
  padding-bottom: 4px;
  width: -moz-max-content;
  width: max-content;
  border-bottom: 1px solid currentColor;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  transition: color 0.35s ease, gap 0.35s ease;
}

.srv-card:hover .srv-card__icon,
.srv-card:hover .srv-card__title,
.srv-card:hover .srv-card__text,
.srv-card:hover .srv-card__more,
.srv-card:focus-visible .srv-card__icon,
.srv-card:focus-visible .srv-card__title,
.srv-card:focus-visible .srv-card__text,
.srv-card:focus-visible .srv-card__more {
  color: #FFFFFF;
}

.srv-card:hover .srv-card__more {
  gap: 12px;
}

/* ---- the tile in the cut ---- */
.srv-card__go {
  position: absolute;
  right: 0;
  bottom: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--srv-tile);
  height: var(--srv-tile);
  border: 1px solid var(--srv-line);
  border-radius: 14px;
  background: #FFFFFF;
  color: #12121A;
  transition:
    background 0.4s ease,
    border-color 0.4s ease,
    color 0.4s ease,
    transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}

.srv-card:hover .srv-card__go,
.srv-card:focus-visible .srv-card__go {
  border-color: #0B0B0F;
  background: #0B0B0F;
  color: #FFFFFF;
  transform: scale(1.08);
}

@media (max-width: 1199px) {
  .srv-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 767px) {
  .srv-grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 18px;
  }

  .srv-card {
    padding: 24px 24px 22px;
  }

  .srv-card {
    --srv-notch: 66px;
    --srv-tile: 50px;
  }
}

/* Touch devices have no hover, so the wash would only ever appear mid-tap. */
@media (hover: none) {
  .srv-card:hover {
    transform: none;
  }

  .srv-card:hover .srv-card__bg {
    filter:
      drop-shadow(1px 0 0 var(--srv-line))
      drop-shadow(-1px 0 0 var(--srv-line))
      drop-shadow(0 1px 0 var(--srv-line))
      drop-shadow(0 -1px 0 var(--srv-line));
  }

  .srv-card:hover .srv-card__wash {
    opacity: 0;
    transform: scale(0.18);
  }

  .srv-card:hover .srv-card__icon,
  .srv-card:hover .srv-card__title,
  .srv-card:hover .srv-card__more {
    color: #0B0B0F;
  }

  .srv-card:hover .srv-card__text {
    color: var(--secondary);
  }

  .srv-card:hover .srv-card__go {
    border-color: var(--srv-line);
    background: #FFFFFF;
    color: #12121A;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .srv-card,
  .srv-card__bg,
  .srv-card__wash,
  .srv-card__go,
  .srv-card__more {
    transition-duration: 0.01ms;
  }

  .srv-card:hover,
  .srv-card:focus-visible {
    transform: none;
  }

  .srv-card:hover .srv-card__go,
  .srv-card:focus-visible .srv-card__go {
    transform: none;
  }
}

/* ====================== In-development notice ======================== */

.wip-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  max-width: 720px;
  margin: 0 auto;
  padding: 56px 40px 48px;
  border: 1px solid #E7E3F5;
  border-radius: 28px;
  background: #FFFFFF;
  box-shadow: 0 24px 60px rgba(17, 12, 46, 0.07);
  text-align: center;
}

.wip-badge {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 22px;
  padding: 7px 16px;
  border-radius: 999px;
  background: #F1EDFE;
  color: var(--accent);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* A slow pulse rather than a spinner: nothing is loading, work is ongoing. */
.wip-badge__pulse {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  animation: wip-pulse 2s ease-in-out infinite;
}

@keyframes wip-pulse {
  0%,
  100% {
    opacity: 1;
    box-shadow: 0 0 0 0 rgba(109, 59, 245, 0.5);
  }
  50% {
    opacity: 0.7;
    box-shadow: 0 0 0 7px rgba(109, 59, 245, 0);
  }
}

.wip-title {
  margin: 0 0 14px;
  color: #0B0B0F;
  font-size: clamp(26px, 3vw, 40px);
  font-weight: 700;
  line-height: 1.18;
  letter-spacing: -0.02em;
}

.wip-text {
  margin: 0 0 32px;
  max-width: 520px;
  color: var(--secondary);
  font-size: 16px;
  line-height: 1.65;
}

.wip-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
}

.wip-rail {
  position: relative;
  width: 220px;
  height: 4px;
  margin-top: 40px;
  border-radius: 999px;
  background: #EEEAF8;
  overflow: hidden;
}

.wip-rail__fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: 38%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--accent-2), var(--accent));
  animation: wip-slide 2.6s ease-in-out infinite;
}

@keyframes wip-slide {
  0% {
    transform: translateX(-110%);
  }
  100% {
    transform: translateX(320%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .wip-badge__pulse,
  .wip-rail__fill {
    animation: none;
  }
}

@media (max-width: 575px) {
  .wip-card {
    padding: 40px 24px 36px;
    border-radius: 22px;
  }

  .wip-actions {
    width: 100%;
    flex-direction: column;
  }

  .wip-actions > * {
    justify-content: center;
  }
}

/* ========================= Contact form states ======================= */

.form-optional {
  color: var(--neutral-400);
  font-weight: 400;
}

/* Only shown after the server rejects a field, so it never nags while typing. */
.form-contact [aria-invalid="true"] {
  border-color: #E4574C !important;
}

.form-error {
  margin: 0 0 16px;
  padding: 12px 16px;
  border-radius: 10px;
  background: #FDECEA;
  color: #B3261E;
  font-size: 14px;
  line-height: 1.5;
}

.form-contact button[type="submit"]:disabled {
  opacity: 0.7;
  cursor: progress;
}

/* Success state replaces the fields rather than sitting above them: the form is
   done, and leaving it filled invites a duplicate submission. */
.form-sent {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.form-sent__mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 62px;
  height: 62px;
  margin-bottom: 22px;
  border-radius: 50%;
  background: linear-gradient(180deg, var(--accent-2) 0%, var(--accent) 100%);
  color: #FFFFFF;
  box-shadow: 0 12px 28px rgba(109, 59, 245, 0.3);
}

.form-sent__text {
  margin: 10px 0 26px;
  max-width: 380px;
  color: var(--secondary);
  font-size: 15px;
  line-height: 1.6;
}

/* ========================== Service page ============================= */

/* Shared section heading: a purple dotted eyebrow over a solid dark title,
   which is the pattern across all three sections in the reference. */
.sv-head {
  max-width: 780px;
  margin: 0 auto 56px;
}

.sv-eyebrow {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 16px;
  color: var(--accent);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.sv-head .sv-eyebrow {
  justify-content: center;
}

.sv-eyebrow::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  flex-shrink: 0;
}

.sv-title {
  margin: 0 0 16px;
  color: #0B0B0F;
  font-size: clamp(30px, 3.4vw, 50px);
  font-weight: 700;
  line-height: 1.14;
  letter-spacing: -0.02em;
}

.sv-lede {
  margin: 0;
  color: var(--secondary);
  font-size: 17px;
  line-height: 1.6;
}

/* ---- Capability rail --------------------------------------------------- */

.capability-rail {
  display: grid;
  grid-template-columns: repeat(8, minmax(0, 1fr));
  gap: 0 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.capability {
  position: relative;
  text-align: center;
}

.capability-ring {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 76px;
  height: 76px;
  margin: 0 auto 18px;
  border-radius: 50%;
  border: 1px dashed rgba(109, 59, 245, 0.45);
  background: #FFFFFF;
  color: var(--accent);
  box-shadow: 0 6px 24px rgba(109, 59, 245, 0.1);
}

/* Connector between one ring and the next, with the travelling dot from the
   reference sitting at its midpoint. Drawn from the ring so it always lands on
   the ring's vertical centre, whatever the label below wraps to. */
.capability:not(:last-child) .capability-ring::before {
  content: "";
  position: absolute;
  top: 50%;
  left: calc(100% + 1px);
  width: calc(100% + 12px);
  height: 1px;
  border-top: 1px dashed rgba(109, 59, 245, 0.4);
}

.capability:not(:last-child) .capability-ring::after {
  content: "";
  position: absolute;
  top: 50%;
  left: calc(150% + 7px);
  width: 7px;
  height: 7px;
  margin-top: -3.5px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 10px rgba(109, 59, 245, 0.7);
}

.capability-name {
  margin: 0 0 10px;
  color: #0B0B0F;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.capability-rule {
  display: block;
  width: 22px;
  height: 2px;
  margin: 0 auto 12px;
  border-radius: 2px;
  background: var(--accent);
}

.capability-text {
  margin: 0;
  color: var(--secondary);
  font-size: 13px;
  line-height: 1.55;
}

@media (max-width: 1199px) {
  .capability-rail {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 40px 12px;
  }

  /* The connector would dangle at the end of each wrapped row. */
  .capability:nth-child(4n) .capability-ring::before,
  .capability:nth-child(4n) .capability-ring::after {
    display: none;
  }
}

@media (max-width: 767px) {
  .capability-rail {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 32px 12px;
  }

  .capability .capability-ring::before,
  .capability .capability-ring::after {
    display: none;
  }

  .capability-ring {
    width: 62px;
    height: 62px;
  }
}

/* ---- Software services grid -------------------------------------------- */

.sv-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px;
}

.sv-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: 32px;
  border: 1px solid #ECEAF2;
  border-radius: 18px;
  background: #FFFFFF;
  transition: transform 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease;
}

.sv-card:hover {
  transform: translateY(-4px);
  border-color: rgba(109, 59, 245, 0.35);
  box-shadow: 0 18px 40px rgba(17, 12, 46, 0.08);
}

.sv-card__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  margin-bottom: 22px;
  border-radius: 14px;
  background: #F1EDFE;
  color: var(--accent);
}

.sv-card__title {
  margin: 0 0 10px;
  color: #0B0B0F;
  font-size: 19px;
  font-weight: 700;
  line-height: 1.3;
}

.sv-card__text {
  margin: 0 0 24px;
  color: var(--secondary);
  font-size: 14px;
  line-height: 1.6;
}

/* Pushed to the bottom so the arrows line up across cards of unequal height. */
.sv-card__go {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  margin-top: auto;
  border-radius: 50%;
  background: linear-gradient(180deg, var(--accent-2) 0%, var(--accent) 100%);
  color: #FFFFFF;
  transition: transform 0.25s ease, box-shadow 0.25s ease;
}

.sv-card__go:hover {
  color: #FFFFFF;
  transform: translateX(3px);
  box-shadow: 0 8px 20px rgba(109, 59, 245, 0.35);
}

@media (max-width: 991px) {
  .sv-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 575px) {
  .sv-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .sv-card {
    padding: 24px;
  }
}

/* ---- Custom software (dark) -------------------------------------------- */

.section-custom-software {
  padding: 110px 0;
  background: #08070C;
  color: #FFFFFF;
  overflow: hidden;
}

.cs-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: 60px;
  align-items: center;
}

.cs-title {
  margin: 0 0 18px;
  font-size: clamp(28px, 3.2vw, 46px);
  font-weight: 700;
  line-height: 1.16;
  letter-spacing: -0.02em;
}

.cs-accent {
  color: var(--accent-2);
}

.cs-lede {
  margin: 0 0 32px;
  max-width: 460px;
  color: rgba(255, 255, 255, 0.62);
  font-size: 16px;
  line-height: 1.65;
}

.cs-cta {
  gap: 10px;
}

.cs-traits {
  display: flex;
  flex-wrap: wrap;
  margin: 44px 0 0;
  padding: 0;
  list-style: none;
}

.cs-traits li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 20px;
  color: rgba(255, 255, 255, 0.72);
  font-size: 12px;
  line-height: 1.35;
  max-width: 150px;
}

.cs-traits li:first-child {
  padding-left: 0;
}

.cs-traits li + li {
  border-left: 1px solid rgba(255, 255, 255, 0.12);
}

.cs-trait__icon {
  color: var(--accent-2);
  flex-shrink: 0;
}

/* ---- The stack diagram ------------------------------------------------- */

.cs-stack {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  padding: 10px 0;
}

/* Each layer sits slightly wider than the one above, which is what reads as
   depth without needing a 3D transform. */
.cs-layer {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  width: calc(62% + var(--i) * 7%);
  min-height: 74px;
  padding: 18px 26px;
  border: 1px solid rgba(139, 92, 246, 0.28);
  border-radius: 18px;
  background:
    linear-gradient(180deg, rgba(30, 22, 54, 0.9) 0%, rgba(12, 9, 22, 0.9) 100%);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.45), 0 0 0 1px rgba(255, 255, 255, 0.02) inset;
  color: #FFFFFF;
  font-size: 15px;
  font-weight: 500;
}

/* Vertical connector down to the next layer. */
.cs-layer:not(:last-child)::after {
  content: "";
  position: absolute;
  top: calc(100% + 1px);
  left: 50%;
  width: 1px;
  height: 17px;
  background: linear-gradient(180deg, rgba(139, 92, 246, 0.8), rgba(139, 92, 246, 0.15));
}

.cs-layer__icon {
  display: flex;
  color: var(--accent-2);
}

/* Side chips, tethered to their layer with a dashed lead line. */
.cs-chip {
  position: absolute;
  top: 50%;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 8px 13px;
  transform: translateY(-50%);
  border: 1px solid rgba(139, 92, 246, 0.22);
  border-radius: 11px;
  background: rgba(16, 12, 28, 0.92);
  color: rgba(255, 255, 255, 0.8);
  font-size: 12px;
  white-space: nowrap;
}

.cs-chip svg {
  color: var(--accent-2);
}

.cs-chip--left {
  right: calc(100% + 42px);
}

.cs-chip--right {
  left: calc(100% + 42px);
}

.cs-chip--low {
  top: auto;
  bottom: -6px;
}

.cs-chip::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 34px;
  border-top: 1px dashed rgba(139, 92, 246, 0.45);
}

.cs-chip--left::after {
  left: calc(100% + 4px);
}

.cs-chip--right::after {
  right: calc(100% + 4px);
}

@media (max-width: 1199px) {
  .cs-layout {
    grid-template-columns: minmax(0, 1fr);
    gap: 56px;
  }

  .cs-stack {
    max-width: 560px;
    margin: 0 auto;
  }

  .cs-layer {
    width: calc(70% + var(--i) * 6%);
  }
}

/* No room to hang chips beside the stack, and stacked they would double its
   height for no gain. */
@media (max-width: 767px) {
  .section-custom-software {
    padding: 70px 0;
  }

  .cs-chip {
    display: none;
  }

  .cs-layer {
    width: calc(84% + var(--i) * 4%);
    min-height: 62px;
    padding: 14px 18px;
    font-size: 14px;
  }

  .cs-traits li {
    padding: 0 14px;
  }
}

/* ====================== Header over the hero ========================= */

/* The pill now sits inside .container on every route; on the light pages it
   still resolves to the same centred pill it was before. */
.tf-header .container {
  padding-left: 12px;
  padding-right: 12px;
}

.tf-header.header-overlay .header-inner {
  max-width: none;
  width: -moz-max-content;
  width: max-content;
  margin-left: 0;
  margin-right: auto;
  gap: 28px;
  padding: 6px 6px 6px 20px;
  background: rgba(255, 255, 255, 0.92);
  border: 1px solid rgba(255, 255, 255, 0.7);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
}

/* The wordmark is dark artwork on a light pill, so no knockout. Height is
   pinned because the asset is 1280x374 rather than the old 120x30. */
.tf-header.header-overlay .logo-site img {
  height: 30px;
  width: auto;
}

.tf-header.header-overlay {
  padding-top: 44px;
}

.tf-header.header-overlay .nav-menu-main {
  gap: 24px;
}

.tf-header.header-overlay .item-link {
  font-size: 15px;
  color: var(--primary);
}

.tf-header.header-overlay .tf-btn {
  padding: 9px 20px;
  font-size: 15px;
}

.tf-header.header-overlay .item-link.active {
  color: var(--primary);
}

.tf-header.header-overlay .item-link:hover {
  color: var(--accent);
}

/* Underline tracks whatever colour the link currently is. */
.tf-header.header-overlay .item-link::before {
  background-color: currentColor;
}

/* Sub-menus keep the light panel, so their links stay dark. */
.tf-header.header-overlay .sub-menu .item-link {
  color: var(--primary);
}

.tf-header.header-overlay .sub-menu .item-link:hover,
.tf-header.header-overlay .sub-menu .item-link.active {
  color: var(--accent);
}

.tf-header.header-overlay .mobile-menu {
  color: var(--white);
}

/* Pull the pill and the hero copy onto the same left edge, a little inside
   the rounded card. Both rules move together on purpose. */
@media (min-width: 992px) {
  .section-hero.hero-video > .container,
  .tf-header.header-overlay .container {
    width: 100%;
    max-width: none;
  }

  .section-hero.hero-video > .container {
    padding-left: max(24px, var(--hero-gutter));
    padding-right: max(24px, var(--hero-gutter));
  }

  /* The header has no 16px section padding of its own, so it makes up the
     difference to land on the hero copy's left edge. */
  .tf-header.header-overlay .container {
    padding-left: calc(15px + max(24px, var(--hero-gutter)));
    padding-right: calc(15px + max(24px, var(--hero-gutter)));
  }
}

@media (max-width: 991px) {
  /* The template already gives the pill its own 32px gutter below lg. */
  .tf-header .container {
    padding-left: 0;
    padding-right: 0;
  }

  .section-hero.hero-video {
    min-height: 640px;
  }

  .section-hero.hero-video .content-wrap {
    padding: 150px 0 90px;
  }

  /* Too narrow to keep the copy clear of the video, so it goes full width and
     drops behind the text instead of beside it. */
  .section-hero.hero-video .hero-image video {
    width: 100%;
    opacity: 0.55;
    -webkit-mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.4) 0%, rgb(0, 0, 0) 55%);
    mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.4) 0%, rgb(0, 0, 0) 55%);
  }
}

@media (max-width: 767px) {
  .section-hero.hero-video .hero-image {
    border-radius: 24px;
  }

  .section-hero.hero-video .content-wrap {
    padding: 130px 0 72px;
  }

  .section-hero.hero-video .content-wrap .bot-btns {
    flex-direction: row;
    flex-wrap: wrap;
  }
}
