/* =========================================================================
   SoftCircles — Home page visual refresh
   Scope: content areas of index.html only (hero, trusted-by, case studies,
   "who we are" / accordion, stats, testimonials, blog cards, footer CTA).
   Nothing here touches markup, links, or navigation — pure presentational
   layer that sits on top of assets/css/app.min-v=13.css.
   ========================================================================= */

@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap");

:root {
  --sc-teal: #008066;
  --sc-teal-dark: #045c48;
  --sc-dark: #1c252b;
  --sc-yellow: #fec527;
  --sc-blue: #9dceca;
  --sc-pink: #fea388;
  --sc-gray: #eceded;
  --sc-quote-bg: #f6f5f4;
  --sc-shadow-sm: 0 6px 20px rgba(28, 37, 43, 0.06);
  --sc-shadow-md: 0 14px 40px rgba(28, 37, 43, 0.12);
  --sc-shadow-lg: 0 24px 60px rgba(28, 37, 43, 0.16);
  --sc-ease: cubic-bezier(0.22, 1, 0.36, 1);

  /* Exact values pulled from the Figma dev-mode export */
  --sc-brand-blue: #3aadd9;
  --sc-border: #e7e8ec;
  --sc-ink: #0e0e12;
  --sc-text-muted: #4b4d57;
  --sc-star: #f4b335;
  --sc-tag-blue: #e3f5fb;
  --sc-tag-lavender: #eaedff;
  --sc-mint: #e8fffa;
  --sc-mint-pill: #cdf5ed;
  --sc-verified-bg: #e5fffe;
  --sc-band-1: #f9f9f9;
  --sc-band-2: #f4f5f7;
  --sc-band-3: #f3f3f3;
  --sc-btn-fill: #f5f6f7;
  --sc-green-bright: #12b76a;
  /* One ramp for every filled green button on the site -- the .btn-warning
     CTAs and the "View case study" link. They are styled by separate rules in
     separate parts of this file, so holding the value once is what keeps them
     from drifting apart. Left to right, light to dark; a plain 90deg ramp,
     deliberately not a two-way sweep that lightens through the middle and
     reads as a sheen. */
  --sc-btn-gradient: linear-gradient(
    90deg,
    var(--sc-green-bright) 0%,
    var(--sc-teal) 55%,
    var(--sc-teal-dark) 100%
  );
  --sc-font-body: "Inter", "Poppins", sans-serif;
}

/* Prevent the horizontal scrollbar that full-bleed sections (e.g. the
   trusted-by band) can introduce when their 100vw width slightly exceeds
   the visible viewport (scrollbar-width rounding). */
body {
  overflow-x: hidden;
}

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

html {
  scroll-behavior: smooth;
}

::selection {
  background: var(--sc-teal);
  color: #fff;
}

/* -------------------------------------------------------------------------
   Hero
   ------------------------------------------------------------------------- */
main .container[data-background-change="#fff"] {
  position: relative;
}

.main-header {
  position: relative;
  z-index: 1;
  letter-spacing: -0.5px;
}

.main-header b {
  background: linear-gradient(100deg, var(--sc-teal) 0%, #04a37f 55%, var(--sc-teal-dark) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: var(--sc-teal);
}

.btn {
  transition:
    transform 0.28s var(--sc-ease),
    box-shadow 0.28s var(--sc-ease),
    background-color 0.2s ease,
    /* The green CTAs carry a gradient, and background-image is not an
       animatable property -- their hover state dims with filter instead, so
       filter has to be in this list for that change to ease rather than
       snap. */ filter 0.2s ease,
    color 0.2s ease;
}

.btn.btn-warning,
.btn.btn-dark,
.btn.btn-outline-dark {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

.btn.btn-warning::after,
.btn.btn-dark::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(120deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.35) 50%, rgba(255, 255, 255, 0) 100%);
  transform: translateX(-120%);
  transition: transform 0.6s var(--sc-ease);
}

.btn.btn-warning:hover,
.btn.btn-dark:hover,
.btn.btn-outline-dark:hover {
  transform: translateY(-3px);
  box-shadow: var(--sc-shadow-md);
}

.btn.btn-warning:hover::after,
.btn.btn-dark:hover::after {
  transform: translateX(120%);
}

.btn.btn-warning:active,
.btn.btn-dark:active,
.btn.btn-outline-dark:active {
  transform: translateY(-1px);
}

/* -------------------------------------------------------------------------
   Trusted-by band (two-column, divided)
   ------------------------------------------------------------------------- */
.sc-trustband {
  background: var(--sc-band-1);
  padding: 34px 0;
  /* Full-bleed: break out of the (narrower than viewport) page container
     so the band's background reaches both screen edges, while the
     nested .container inside keeps the text/logos aligned with the
     rest of the page content. */
  width: 100vw;
  position: relative;
  left: 50%;
  transform: translateX(-50%);
}

.sc-trustband-col {
  padding: 6px 24px;
}

.sc-trustband-divider {
  border-left: 1px solid rgba(28, 37, 43, 0.12);
}

.sc-trustband-label {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: #70747a;
  margin-bottom: 16px;
}

.sc-trustband-label b {
  color: var(--sc-dark);
}

.sc-trustband-logos {
  display: flex;
  align-items: center;
  gap: 48px;
  flex-wrap: wrap;
}

.sc-trustband-logos img {
  /* One shared height cap for every logo. The sources are a mix of 26px,
     36px and 40px tall art, which is what made the rows read as a jumble;
     capping the height and letting the width follow puts them all on one
     centre line at the same visual size without squashing anything. The
     inline width/height attributes stay as they are -- they still reserve
     the box before the image loads, which is what keeps CLS down. */
  max-height: 32px;
  width: auto;
  object-fit: contain;
  flex: 0 0 auto;
  filter: grayscale(0) opacity(1);
  transition: filter 0.3s ease, transform 0.3s var(--sc-ease);
}

.sc-trustband-logos img:hover {
  filter: grayscale(0) opacity(1);
  transform: translateY(-2px);
}

@media (max-width: 991px) {
  .sc-trustband-divider {
    border-left: none;
    border-top: 1px solid rgba(28, 37, 43, 0.12);
    margin-top: 20px;
    padding-top: 20px;
  }
}

/* -------------------------------------------------------------------------
   Trust-band logo carousel (every breakpoint)
   Each logo row is a seamless auto-scrolling strip. The loop is a
   translateX(-50%), which only reads as seamless while the track is at
   least twice as wide as the window it scrolls inside -- otherwise the
   second half runs out mid-cycle and an empty gap rotates through. Two
   copies (one in the markup, one `aria-hidden` duplicate) are enough at
   phone widths but not on desktop, where a column is only ~520px and the
   awards row holds just three logos. home-redesign.js therefore clones the
   row until the track clears 2x its container, and sets
   --sc-trustband-duration from the measured width so a 5-logo strip and a
   3-logo strip travel at the same ~50px/s instead of sharing one fixed
   duration.
   ------------------------------------------------------------------------- */
.sc-trustband-scroller {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 24px, #000 calc(100% - 24px), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 24px, #000 calc(100% - 24px), transparent 100%);
}

.sc-trustband-track {
  display: flex;
  align-items: center;
  width: max-content;
}

.sc-trustband-track .sc-trustband-logos {
  flex-wrap: nowrap;
  flex-shrink: 0;
  /* Same as the row's gap, so the spacing across the loop seam matches the
     spacing between two logos inside a single copy. */
  padding-right: 48px;
}

/* Covers the text badges on the service pages too, not just the <img> logos. */
.sc-trustband-track .sc-trustband-logos > * {
  flex: 0 0 auto;
}

@media (max-width: 767px) {
  .sc-trustband-logos {
    gap: 32px;
  }

  .sc-trustband-track .sc-trustband-logos {
    padding-right: 32px;
  }
}

@media (prefers-reduced-motion: no-preference) {
  .sc-trustband-track {
    animation: sc-trustband-marquee var(--sc-trustband-duration, 16s) linear infinite;
  }

  .sc-trustband-scroller:hover .sc-trustband-track {
    animation-play-state: paused;
  }
}

/* Reduced motion: nothing moves on its own -- a single static row the
   reader can scroll by hand. The duplicate copies only exist to feed the
   loop, so they come out. */
@media (prefers-reduced-motion: reduce) {
  .sc-trustband-scroller {
    overflow-x: auto;
  }

  .sc-trustband-track .sc-trustband-logos-dup {
    display: none;
  }

  .sc-trustband-track .sc-trustband-logos {
    padding-right: 0;
  }
}

@keyframes sc-trustband-marquee {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}

/* -------------------------------------------------------------------------
   Case study feature cards (SPEDPro / Real Madrid / Abloh)
   ------------------------------------------------------------------------- */
.zoom-img.color-reveal,
.zoom-img .color-reveal {
  box-shadow: var(--sc-shadow-sm);
  transition: box-shadow 0.4s var(--sc-ease), transform 0.4s var(--sc-ease);
}

a.link-article {
  display: block;
  color: inherit;
  text-decoration: none;
}

a.link-article:hover .color-reveal,
a.link-article:hover .zoom-img.color-reveal {
  box-shadow: var(--sc-shadow-lg);
  transform: translateY(-6px);
}

a.link-article .color-reveal::after {
  content: "\2197";
  position: absolute;
  right: 20px;
  bottom: 20px;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: #fff;
  color: var(--sc-dark);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  opacity: 0;
  transform: translate(8px, 8px) scale(0.8);
  transition: opacity 0.35s ease, transform 0.35s var(--sc-ease);
  z-index: 101;
}

a.link-article:hover .color-reveal::after {
  opacity: 1;
  transform: translate(0, 0) scale(1);
}

a.link-article > strong {
  display: inline-block;
  margin-top: 18px;
  font-size: 1.05rem;
  transition: color 0.25s ease, transform 0.25s var(--sc-ease);
}

a.link-article:hover > strong {
  color: var(--sc-teal);
  transform: translateX(4px);
}

/* -------------------------------------------------------------------------
   Services accordion ("positions")
   ------------------------------------------------------------------------- */
.positions {
  background: transparent;
  box-shadow: none;
}

.position {
  border-bottom: 1px solid rgba(28, 37, 43, 0.08);
  padding: 2px 4px;
}

.position:last-child {
  border-bottom: none;
}

.position-header h5 {
  transition: color 0.25s ease;
}

.position-header[aria-expanded="true"] h5 {
  color: var(--sc-teal);
}

.sc-explore-btn {
  display: inline-block;
  margin-top: 14px;
  padding: 8px 18px;
  font-size: 0.85rem;
}

.position-header .plus {
  transition: transform 0.3s ease;
}

.position-content h6 {
  animation: sc-fade-in 0.5s ease both;
}

@keyframes sc-fade-in {
  from {
    opacity: 0;
    transform: translateY(-6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* -------------------------------------------------------------------------
   Stats intro ("Real projects. Real numbers.") + stats row
   ------------------------------------------------------------------------- */
.sc-stats-intro {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 30px;
}

.sc-stats-intro h2 {
  font-size: 3.25rem;
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -0.52px;
  color: var(--sc-dark);
}

.sc-stats-intro-right {
  max-width: 380px;
  padding-top: 6px;
}

.sc-stats-intro-right p {
  font-family: var(--sc-font-body);
  color: var(--sc-text-muted);
  margin-bottom: 14px;
}

.sc-link-arrow {
  display: inline-block;
  color: var(--sc-ink);
  font-family: var(--sc-font-body);
  font-weight: 600;
  font-size: 0.9375rem;
  text-decoration: none;
  border-bottom: 2px solid var(--sc-ink);
  padding-bottom: 4px;
  transition: color 0.25s ease, border-color 0.25s ease, padding-right 0.25s ease;
}

.sc-link-arrow:hover {
  color: var(--sc-teal);
  border-color: var(--sc-teal);
  text-decoration: none;
  padding-right: 6px;
}

.sc-stats-row {
  display: flex;
  flex-wrap: wrap;
  border-top: 1px solid var(--sc-border);
  border-bottom: 1px solid var(--sc-border);
  margin-top: 40px;
}

.sc-stats-row-item {
  flex: 1 1 0;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 26px 24px;
  border-left: 1px solid var(--sc-border);
  transition: background-color 0.3s ease;
}

.sc-stats-row-item:first-child {
  border-left: none;
  padding-left: 0;
}

.sc-stats-row-item:hover {
  background-color: rgba(0, 128, 102, 0.04);
}

.sc-stats-row-item h2 {
  font-size: 1.625rem;
  line-height: 1.5;
  font-weight: 700;
  color: var(--sc-dark);
  margin: 0;
  white-space: nowrap;
}

.sc-stats-row-item span {
  font-family: var(--sc-font-body);
  color: var(--sc-text-muted);
  font-size: 0.84rem;
}

@media (max-width: 767px) {
  .sc-stats-row {
    flex-direction: column;
  }

  .sc-stats-row-item {
    border-left: none;
    border-top: 1px solid var(--sc-border);
    /* Desktop's horizontal padding (26px 24px) exists to space items apart
       side-by-side. Stacked vertically, that left padding is what was
       throwing the numbers out of alignment: `:first-child` resets its own
       padding-left to 0 for the desktop layout, but items 2 and 3 kept the
       24px left padding meant for a side-by-side row — so $10M sat flush
       left while 200+ and 1,000,000 sat indented under it. Reset every
       item's horizontal padding here so all three numbers share one left
       edge. */
    padding-left: 0;
    padding-right: 0;
  }

  .sc-stats-row-item:first-child {
    border-top: none;
  }
}

/* -------------------------------------------------------------------------
   Testimonials
   ------------------------------------------------------------------------- */
.random-quote {
  padding: 10px 0;
}

.random-quote .quote {
  position: relative;
  max-width: 900px;
  margin: 0 auto;
  padding: 46px 30px;
  border-radius: 18px;
  background: var(--sc-quote-bg);
  box-shadow: var(--sc-shadow-sm);
  transition: box-shadow 0.4s ease, transform 0.4s var(--sc-ease);
}

.random-quote .quote:hover {
  box-shadow: var(--sc-shadow-md);
  transform: translateY(-4px);
}

.random-quote .quote::before {
  content: "\201C";
  position: absolute;
  top: 4px;
  left: 26px;
  font-size: 84px;
  line-height: 1;
  font-family: Georgia, "Times New Roman", serif;
  color: var(--sc-teal);
  opacity: 0.25;
}

.quote-sm {
  background: transparent !important;
  padding: 0 !important;
  position: relative;
  z-index: 1;
}

/* -------------------------------------------------------------------------
   Blog / resources cards
   ------------------------------------------------------------------------- */
.resource-item .card {
  transition: transform 0.35s var(--sc-ease);
}

.resource-item .card:hover {
  transform: translateY(-6px);
}

.badge-blog {
  display: inline-block;
  color: var(--sc-teal) !important;
  font-weight: 600;
  letter-spacing: 0.2px;
}

.blog-card-title {
  transition: color 0.25s ease;
}

.resource-item .card:hover .blog-card-title {
  color: var(--sc-teal);
}

/* -------------------------------------------------------------------------
   Footer CTA banner ("Where there's smoke...")
   ------------------------------------------------------------------------- */
.bg-lightblue,
.bg-orange {
  position: relative;
}

.bg-lightblue h3,
.bg-orange h3 {
  letter-spacing: -0.4px;
}

.bg-lightblue .btn.btn-dark:hover {
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.28);
}

.bg-orange .btn.btn-outline-dark:hover {
  background-color: var(--sc-dark);
  color: #fff;
}

/* -------------------------------------------------------------------------
   Scroll-reveal utility (paired with home-redesign.js)
   ------------------------------------------------------------------------- */
.sc-reveal {
  opacity: 1;
  transform: none;
}

/* -------------------------------------------------------------------------
   Responsive tweaks
   ------------------------------------------------------------------------- */
@media (max-width: 991px) {
  main .container[data-background-change="#fff"]::before {
    width: 300px;
    height: 300px;
    top: -100px;
    right: -100px;
  }

  .sc-stats-intro h2 {
    font-size: 2rem;
  }

  .random-quote .quote {
    padding: 34px 20px;
  }
}

@media (max-width: 767px) {
  a.link-article .color-reveal::after {
    width: 36px;
    height: 36px;
    right: 12px;
    bottom: 12px;
    font-size: 16px;
  }
}

/* =========================================================================
   New Figma-aligned sections (real copy)
   ========================================================================= */

/* Trusted-by tweaks */
.sc-trust-title b {
  color: var(--sc-teal);
}

/* "Built for every stage of the journey" */
.sc-journey-band {
  background: var(--sc-gray);
  padding: 48px 40px;
}

.sc-journey-band h2 {
  font-weight: 700;
  font-size: 3.25rem;
  line-height: 0.9;
  letter-spacing: -0.42px;
  margin-bottom: 18px;
}

.sc-journey-band > .row > .col-lg-4 > p {
  color: var(--sc-text-muted);
  font-size: 0.97rem;
  line-height: 1.65;
  max-width: 420px;
}

.sc-journey-cards {
  display: flex;
  gap: 20px;
  height: 100%;
}

.sc-journey-card-item {
  flex: 1 1 0;
  border-radius: 20px;
  padding: 24px;
  min-height: 400px;
  /* Keep the card's portrait proportions (matches the ~267x400px it renders
     at in the normal 1264px container) as the container grows past 1685px,
     where .container switches to max-width:75vw and gets much wider — a
     fixed 400px height on that wider row made the cards look flat/short and
     the photos look "small". aspect-ratio scales height with width instead;
     min-height still floors it at narrower desktop widths (lg breakpoint). */
  aspect-ratio: 2 / 3;
  display: flex;
  flex-direction: column;
  position: relative;
  overflow: hidden;
  box-shadow: var(--sc-shadow-sm);
  transition: transform 0.35s var(--sc-ease), box-shadow 0.35s var(--sc-ease);
}

.sc-journey-card-item:hover {
  transform: translateY(-6px);
  box-shadow: var(--sc-shadow-md);
}

.sc-journey-card-item.sc-journey-light {
  background: linear-gradient(180deg, rgba(8, 10, 14, 0.15) 0%, rgba(6, 8, 12, 0.82) 100%),
    url(../img/home/journey-startups.webp) center/cover no-repeat;
  color: #fff;
}

/* Same light bottom-only gradient as .sc-journey-light — just enough to
   keep the icon/heading/text legible. The heavy full-card teal/navy tint
   + radial glow these two used before hid most of the photo underneath. */
.sc-journey-card-item.sc-journey-dark-1 {
  background: linear-gradient(180deg, rgba(8, 10, 14, 0.15) 0%, rgba(6, 8, 12, 0.82) 100%),
    url(../img/home/journey-scaleups.webp) center/cover no-repeat;
  color: #fff;
}

.sc-journey-card-item.sc-journey-dark-2 {
  background: linear-gradient(180deg, rgba(8, 10, 14, 0.15) 0%, rgba(6, 8, 12, 0.82) 100%),
    url(../img/home/journey-smbs.webp) center/cover no-repeat;
  color: #fff;
}

.sc-journey-icon {
  width: 42px;
  height: 42px;
  border-radius: 10px;
  background: #fff;
  color: var(--sc-teal);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.1rem;
  margin-bottom: 14px;
  position: relative;
  z-index: 1;
}

.sc-journey-card-item h5 {
  font-weight: 700;
  margin-top: auto;
  margin-bottom: 0;
  position: relative;
  z-index: 1;
}

/* Description text is hidden by default — only the icon (top) and the
   heading (pinned to the bottom) show. Hovering reveals the paragraph
   in the space between them, matching the industry-card interaction. */
.sc-journey-card-item p {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.85);
  position: relative;
  z-index: 1;
  opacity: 0;
  max-height: 0;
  overflow: hidden;
  transition: opacity 0.3s ease, max-height 0.3s ease, margin-bottom 0.3s ease;
}

.sc-journey-card-item:hover p {
  opacity: 1;
  max-height: 160px;
  margin-bottom: 14px;
}

@media (max-width: 991px) {
  .sc-journey-band {
    padding: 30px 22px;
  }

  .sc-journey-band h2 {
    font-size: 2.4rem;
  }

  .sc-journey-cards {
    flex-direction: column;
  }

  .sc-journey-card-item {
    min-height: 260px;
    /* Cards stack full-width here — the 2:3 desktop aspect-ratio would make
       them absurdly tall, so go back to a fixed height like before. */
    aspect-ratio: auto;
  }

  /* Touch devices have no :hover, so the desktop hover-reveal above would
     leave the paragraph permanently invisible — show it by default. */
  .sc-journey-card-item h5 {
    margin-top: 0;
  }

  .sc-journey-card-item p {
    opacity: 1;
    max-height: none;
    margin-bottom: 14px;
  }
}

@media (max-width: 767px) {
  .sc-journey-band h2 {
    font-size: 1.9rem;
    line-height: 1.05;
  }
}

/* Case study badges (SPEDPro tags/rating) */
.sc-case-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-top: 12px;
}

.sc-case-meta .sc-case-stat {
  font-family: var(--sc-font-body);
  font-size: 0.9rem;
  color: var(--sc-text-muted);
  flex-basis: 100%;
  margin-bottom: 4px;
}

.sc-case-meta .sc-tag {
  padding: 4px 12px;
  border-radius: 999px;
  border: 1px solid #ebebeb;
  background: transparent;
  font-family: var(--sc-font-body);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  color: #9a9a9a;
}

/* First tag (EdTech) is filled, per Figma — the rest stay outlined/muted */
.sc-case-meta .sc-tag:first-of-type {
  border-color: transparent;
  background: var(--sc-tag-lavender);
  color: var(--sc-dark);
}

.sc-case-rating-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-basis: 100%;
  margin-top: 6px;
}

.sc-case-meta .sc-rating {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 14px;
  border-radius: 999px;
  background: var(--sc-mint-pill);
  font-family: var(--sc-font-body);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  color: var(--sc-dark);
}

.sc-case-meta .sc-rating .fa {
  color: var(--sc-teal);
  font-size: 0.8rem;
}

.sc-case-meta .sc-case-stars .fa {
  color: var(--sc-star);
  font-size: 0.85rem;
  margin-right: 2px;
}

/* The image sits inside a.link-article (padding-bottom: 16px from the base
   framework) wrapping .color-reveal (margin-bottom: 16px) — 32px of space
   below the image before .sc-case-title-row's own margin-top even starts.
   .link-article is only used here on the page, so it's safe to zero both
   out and control the whole gap with margin-top below instead. */
.zoom-img > a.link-article {
  padding-bottom: 0;
}

.zoom-img > a.link-article .color-reveal {
  margin-bottom: 0;
}

/* Title row: SPEDPro heading (left) + "View case study" link (right) */
.sc-case-title-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 16px;
  margin-top: 16px;
}

a.sc-case-title {
  display: inline-block;
  color: inherit;
  text-decoration: none;
  font-size: 1.05rem;
  transition: color 0.25s ease, transform 0.25s var(--sc-ease);
}

a.sc-case-title:hover {
  color: var(--sc-teal);
  transform: translateX(4px);
}

a.sc-case-view-link {
  flex-shrink: 0;
  display: inline-block;
  font-family: var(--sc-font-body);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: #fff;
  /* background-color stays as the fallback beneath the gradient. */
  background-color: var(--sc-teal);
  background-image: var(--sc-btn-gradient);
  /* The transparent 1.5px border below is still part of the painted area
     (background-clip defaults to border-box), but a background is *sized* to
     the padding box by default -- so the gradient stopped 1.5px short on each
     side and background-repeat tiled it into the gap. That put the ramp's
     dark end (#045c48) against the left edge and its light end against the
     right, which read as a black hairline down the left of the button.
     Sizing the gradient to the border box instead makes one ramp span the
     whole button, edge to edge, with nothing left over to repeat. */
  background-origin: border-box;
  /* Was a solid teal border, which cut a hard flat edge around the gradient.
     Kept at the same width but transparent so the button's box size (and so
     the title row's alignment) is unchanged. */
  border: 1.5px solid transparent;
  padding: 0.55rem 1.3rem;
  border-radius: 10px;
  text-decoration: none;
  white-space: nowrap;
  /* background-color cannot carry the hover change -- the gradient is a
     background-image and paints over it, and background-image is not an
     animatable property. brightness() moves the whole ramp at once and does
     transition. */
  transition: filter 0.25s ease, transform 0.25s var(--sc-ease), box-shadow 0.25s ease;
}

a.sc-case-view-link:hover {
  color: #fff;
  /* Darkens, matching the .btn-warning CTAs -- every green button on the page
     should react the same way. */
  filter: brightness(0.94);
  text-decoration: none;
  transform: translateY(-2px);
  box-shadow: var(--sc-shadow-md);
}

/* This link had no focus ring at all: it is an <a>, so it never picked up
   Bootstrap's .btn focus styling, and nothing here replaced it -- a keyboard
   user tabbing through the card had nothing to follow. Same green ring the
   .btn-warning CTAs now use. */
a.sc-case-view-link:focus {
  box-shadow: 0 0 0 0.2rem rgba(0, 128, 102, 0.35);
}

/* -------------------------------------------------------------------------
   Featured case-study carousel (home page)
   Bootstrap 4.3.1 drives it: one case study on screen, the next sliding in
   every 5 seconds, paused while hovered. bootstrap.bundle.min.js is already
   on the page, so no new library.

   Everything is scoped under .sc-case-carousel; the other seven pages that
   load this stylesheet still render their case study as a static .zoom-img.
   ------------------------------------------------------------------------- */
.sc-case-header {
  /* Nothing sits to the left of the controls, so this row only has to push
     them to the right edge and leave the card below some air. */
  margin-bottom: 16px;
}

.sc-case-controls {
  display: flex;
  align-items: center;
  gap: 18px;
  margin-left: auto;
}

.sc-case-carousel .carousel-inner {
  /* The slide transition translates items by +/-100%, so the overflow has to
     be clipped. That also cuts the card's shadow and its 6px hover lift,
     hence the vertical padding to give them somewhere to land. */
  overflow: hidden;
  padding: 16px 0 34px;
  /* Bootstrap sizes .carousel-inner from whichever slide is active, and
     slide 1 carries a client rating row the other two have no rating data
     for -- so each advance shifted the rest of the page by ~43px. Stacking
     all three in one grid cell makes the box as tall as its tallest slide
     and the height stops moving. Grid does not disturb the transition:
     Bootstrap animates transform, which applies to grid items unchanged. */
  display: grid;
}

/* Bootstrap's float clearfix would become a grid item of its own here and
   add an empty row under the card. */
.sc-case-carousel .carousel-inner::after {
  display: none;
}

.sc-case-carousel .carousel-item {
  display: block;
  grid-area: 1 / 1;
  /* display no longer does the hiding, so visibility does -- and unlike
     opacity it keeps the off-screen slides out of the tab order and the
     accessibility tree. These are exactly the three states Bootstrap gives
     transforms to, so the outgoing and incoming slides are both on screen
     mid-transition and the animation is unaffected. */
  visibility: hidden;
}

.sc-case-carousel .carousel-item.active,
.sc-case-carousel .carousel-item.carousel-item-next,
.sc-case-carousel .carousel-item.carousel-item-prev {
  visibility: visible;
}

/* app.min-v=13.css:13677 carries a bare `.active { background:#1c252b;
   color:#fff }` -- written for the blog pagination dots, but unscoped, so it
   also matched whichever slide Bootstrap marks active and painted the whole
   card navy with white text. */
.sc-case-carousel .carousel-item.active {
  background: transparent;
  color: inherit;
}

/* Bootstrap absolutely positions .carousel-indicators across the bottom of
   the slide. These sit in the control row above the card instead, so the
   positioning and the 15% side margins come off -- but the class itself has
   to stay, because Carousel._setActiveIndicatorElement finds the container
   by `.carousel-indicators` and indexes its children to move .active. */
.sc-case-dots {
  position: static;
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.sc-case-dots button {
  width: 8px;
  height: 8px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: #c9cbd0;
  cursor: pointer;
  transition: width 0.25s var(--sc-ease), background-color 0.25s ease;
}

/* Beats the bare `.active` above on specificity, so the dot reads as teal
   rather than picking up the pagination rule's navy. */
.sc-case-dots button.active {
  width: 24px;
  border-radius: 999px;
  background: var(--sc-teal);
}

.sc-case-dots button:focus-visible,
.sc-case-header .sc-scroll-btn:focus-visible {
  outline: 2px solid var(--sc-teal);
  outline-offset: 2px;
}

/* All three banners are 2448x960. Pinning the ratio keeps every slide the
   same height before the lazy images have loaded, so the carousel does not
   resize as it advances. (Slide 1's markup carries width="600" height="600"
   on its fallback <img>, which would otherwise reserve a square box.) */
.sc-case-carousel .color-reveal img {
  width: 100%;
  aspect-ratio: 2448 / 960;
  object-fit: cover;
}

/* Belt-and-braces for the reveal layer: the markup no longer ships
   "show-color", and this makes sure a slide can never be left behind a flat
   colour block even if that class comes back. Higher specificity than
   app.min's `.color-reveal .layer.show-color { left: 0 }`. */
.sc-case-carousel .color-reveal .layer.show-color {
  left: 100%;
}

@media (max-width: 767px) {
  .sc-case-carousel .carousel-inner {
    padding: 12px 0 24px;
  }

  .sc-case-controls {
    gap: 14px;
  }
}

/* Hiring / staff-aug cards ("Skip the hiring bottleneck") */
.sc-hiring-card {
  border-radius: 18px;
  padding: 14px 22px;
  height: 100%;
  box-shadow: 0px 20px 40px -20px rgba(14, 14, 18, 0.25);
  transition: transform 0.35s var(--sc-ease), box-shadow 0.35s var(--sc-ease);
}

.sc-hiring-card:hover {
  transform: translateY(-6px);
}

.sc-hiring-card.sc-hiring-dark {
  background: var(--sc-ink);
  color: #fff;
}

.sc-hiring-card.sc-hiring-light {
  background: #fff;
  border: 1px solid var(--sc-border);
}

.sc-hiring-card h5 {
  font-weight: 700;
  letter-spacing: -0.15px;
  margin-bottom: 2px;
}

.sc-hiring-card .sc-hiring-exp {
  font-family: var(--sc-font-body);
  font-size: 0.75rem;
  opacity: 0.65;
  margin-bottom: 6px;
  display: block;
}

.sc-hiring-card.sc-hiring-light .sc-hiring-exp {
  color: var(--sc-text-muted);
  opacity: 1;
}

.sc-hiring-card .sc-tag {
  display: inline-block;
  padding: 4px 10px;
  border-radius: 999px;
  font-family: var(--sc-font-body);
  font-size: 0.69rem;
  font-weight: 600;
  margin: 0 6px 6px 0;
}

.sc-hiring-card.sc-hiring-dark .sc-tag {
  background: var(--sc-tag-blue);
  color: var(--sc-ink);
}

.sc-hiring-card.sc-hiring-light .sc-tag {
  background: var(--sc-tag-blue);
  color: var(--sc-ink);
}

.sc-hiring-card .sc-available {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--sc-font-body);
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--sc-green-bright);
  margin-top: 4px;
}

.sc-hiring-card .sc-available .fa {
  color: var(--sc-green-bright);
  font-size: 0.5rem;
}

/* Blue banner card wrapping the "Skip the hiring bottleneck" copy */
.sc-hiring-banner {
  background: var(--sc-brand-blue);
  color: #fff;
  padding: 44px 40px;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.sc-hiring-banner h2,
.sc-hiring-banner h3 {
  font-weight: 700;
  font-size: 2rem;
  line-height: 1.125;
  letter-spacing: -0.32px;
  color: #fff;
  margin-bottom: 16px;
}

.sc-hiring-banner p {
  color: rgba(255, 255, 255, 0.9);
  margin-bottom: 20px;
}

/* Stacked hiring cards, with a peeking third card for visual depth.
   Padded and centered within its column so the cards sit inset from both
   the blue banner and the outer edge, instead of touching either. */
.sc-hiring-stack {
  position: relative;
  padding: 0 40px;
}

.sc-hiring-stack .row {
  position: relative;
  z-index: 2;
}

.sc-hiring-peek {
  position: relative;
  z-index: 1;
  width: 58%;
  max-width: 320px;
  margin: -30px auto 0;
  box-shadow: var(--sc-shadow-sm);
}

@media (max-width: 991px) {
  .sc-hiring-stack {
    padding: 0 20px;
  }
}

@media (max-width: 767px) {
  .sc-hiring-stack {
    /* The blue banner sits directly above this column (zero gap by
       design on desktop) and the green process card sits directly below
       — on mobile, once everything stacks into one column, that left
       both edges of the card stack touching their neighbors with no
       breathing room. Give it some vertical padding of its own. */
    padding: 24px 0;
  }

  /* The "peek" card was a desktop-only visual trick (a third card
     partially overlapping the row above it, offset with a negative
     margin, for depth). On mobile that just hid the card entirely —
     show it as a normal full-width stacked card instead, matching the
     other two. */
  .sc-hiring-peek {
    display: block;
    position: static;
    width: 100%;
    max-width: none;
    margin: 16px 0 0;
  }
}

/* 4-step process list ("How we turn ideas into shipped software") */
.sc-step-list {
  margin: 22px 0 0;
}

.sc-step-item {
  display: flex;
  gap: 18px;
  padding: 16px 0;
  border-bottom: 1px solid rgba(28, 37, 43, 0.08);
}

.sc-step-item:last-child {
  border-bottom: none;
}

.sc-step-num {
  flex: 0 0 auto;
  font-weight: 700;
  color: var(--sc-teal);
  font-size: 0.9rem;
  min-width: 28px;
}

.sc-step-item h5 {
  font-weight: 700;
  margin-bottom: 2px;
}

.sc-step-item p {
  color: #56595c;
  margin: 0;
  font-size: 0.92rem;
}

/* Timeline variant: bordered card rows with a connecting line and a circular number badge.
   Padded so the cards sit inset from both the outer edge and the green
   process card, instead of touching either. */
.sc-step-list-timeline {
  position: relative;
  padding: 0 40px;
}

@media (max-width: 991px) {
  .sc-step-list-timeline {
    padding: 0 20px;
  }
}

@media (max-width: 767px) {
  .sc-step-list-timeline {
    padding: 0;
  }
}

.sc-step-list-timeline .sc-step-item {
  border: 1px solid rgba(28, 37, 43, 0.1);
  border-radius: 14px;
  padding: 18px 20px;
  margin-bottom: 22px;
  background: #fff;
  align-items: flex-start;
}

.sc-step-list-timeline .sc-step-item:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 33px;
  width: 1px;
  height: 22px;
  background: rgba(28, 37, 43, 0.15);
  transform: translateY(100%);
}

.sc-step-list-timeline .sc-step-num {
  width: 34px;
  height: 34px;
  min-width: 34px;
  border-radius: 50%;
  background: var(--sc-mint);
  color: var(--sc-teal);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 0.8rem;
}

.sc-step-list-timeline .sc-step-item {
  border-color: var(--sc-border);
}

.sc-step-list-timeline .sc-step-item:not(:last-child)::after {
  background: var(--sc-border);
}

.sc-step-item h5 {
  font-family: var(--sc-font-body);
  font-weight: 600;
  color: var(--sc-ink);
}

.sc-step-item p {
  font-family: var(--sc-font-body);
  color: var(--sc-text-muted);
}

/* Light CTA banner (Launch Your Next AI Project) */
.sc-cta-light {
  background: linear-gradient(135deg, #f4f4f4 0%, #eef4f2 100%);
  padding: 46px 40px;
}

.sc-cta-light h2 {
  margin-bottom: 12px;
}

.sc-cta-light p {
  color: #56595c;
  max-width: 520px;
  margin-bottom: 20px;
}

.sc-cta-light .sc-trust-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  margin-top: 22px;
}

.sc-cta-light .sc-trust-badges span {
  font-size: 0.82rem;
  color: var(--sc-dark);
  font-weight: 500;
}

.sc-cta-light .sc-trust-badges .fa {
  color: var(--sc-teal);
  margin-right: 6px;
}

/* Section heading + left/right scroll-nav buttons, shared by horizontal
   scrollers (industry cards, etc.) */
.sc-section-header-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px 24px;
  margin-bottom: 32px;
}

.sc-scroll-nav {
  gap: 10px;
  flex-shrink: 0;
  margin-left: auto;
}

.sc-scroll-btn {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  border: 1px solid rgba(27, 35, 46, 0.18);
  background: #fff;
  color: var(--sc-dark);
  align-items: center;
  justify-content: center;
  font-size: 1rem;
  cursor: pointer;
  transition: background-color 0.25s ease, color 0.25s ease, border-color 0.25s ease;
}

.sc-scroll-nav .sc-scroll-btn {
  display: flex;
}

.sc-scroll-btn:hover {
  background: var(--sc-dark);
  color: #fff;
  border-color: var(--sc-dark);
}

.sc-scroll-btn:disabled {
  opacity: 0.35;
  cursor: default;
}

/* Horizontal single-row scroller for industry cards */
.sc-industry-scroller {
  display: flex;
  gap: 28px;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  /* extra top padding so the hover lift (translateY) has room and the
     card's rounded top corners don't get clipped by the scroller */
  padding: 14px 4px 18px;
  -webkit-overflow-scrolling: touch;
  /* Hide the visible scrollbar/slider — dragging still works, and the
     left/right nav buttons cover the rest. */
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* old Edge / IE */
}

.sc-industry-scroller::-webkit-scrollbar {
  display: none; /* Chrome, Safari, new Edge */
  height: 0;
}

.sc-industry-scroller .sc-industry-card {
  flex: 0 0 320px;
  scroll-snap-align: start;
}

@media (max-width: 767px) {
  .sc-industry-scroller .sc-industry-card {
    flex-basis: 260px;
  }
}

/* Industry / domain-expertise cards */
.sc-industry-card {
  position: relative;
  border-radius: 20px;
  padding: 32px 28px;
  min-height: 340px;
  background: #f4f4f4;
  color: var(--sc-dark);
  overflow: hidden;
  text-decoration: none;
  display: flex;
  flex-direction: column;
  transition: transform 0.35s var(--sc-ease), box-shadow 0.35s var(--sc-ease),
    background-color 0.35s ease, color 0.35s ease;
  box-shadow: var(--sc-shadow-sm);
}

.sc-industry-card:hover {
  background: #000;
  color: #fff;
  transform: translateY(-6px);
  box-shadow: var(--sc-shadow-md);
  text-decoration: none;
}

.sc-industry-card .sc-eyebrow {
  display: block;
  font-family: var(--sc-font-body);
  font-size: 0.72rem;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  opacity: 0.55;
  margin-bottom: 34px;
}

.sc-industry-card h4 {
  font-weight: 600;
  font-size: 1.6rem;
  letter-spacing: -0.32px;
  /* pinned to the bottom of the card by default; hovering reveals the
     paragraph above it, which pushes the heading upward */
  margin-top: auto;
  margin-bottom: 0;
}

.sc-industry-card p {
  font-family: var(--sc-font-body);
  font-size: 0.9rem;
  line-height: 1.55;
  opacity: 0;
  max-height: 0;
  overflow: hidden;
  margin: 0;
  transition: opacity 0.3s ease, max-height 0.3s ease, margin-bottom 0.3s ease;
}

.sc-industry-card:hover p {
  opacity: 0.85;
  max-height: 140px;
  margin-bottom: 12px;
}

.sc-industry-card .fa {
  position: absolute;
  right: 22px;
  bottom: 20px;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid rgba(27, 35, 46, 0.2);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
  transition: transform 0.3s var(--sc-ease), background-color 0.3s ease, border-color 0.3s ease;
}

.sc-industry-card:hover .fa {
  background: rgba(255, 255, 255, 0.12);
  border-color: rgba(255, 255, 255, 0.3);
  transform: translate(3px, -3px);
}

/* Touch devices have no :hover, so the desktop hover-reveal above would
   leave the paragraph permanently invisible — show it by default and let
   the card grow past its min-height instead of relying on the hover
   trigger. */
@media (max-width: 991px) {
  .sc-industry-card h4 {
    margin-top: 0;
  }

  .sc-industry-card p {
    opacity: 1;
    max-height: none;
    margin-bottom: 12px;
  }
}

/* Testimonial grid (Our Clients' Success Stories) — light band contained to
   the same width as the rest of the page content (not full-bleed), 3-column
   staggered masonry, per Figma dev-mode export. */
.sc-testimonials-band {
  background: var(--sc-band-3);
  padding: 48px 40px;
}

.sc-testimonial-kicker {
  font-family: var(--sc-font-body);
  font-weight: 600;
  font-size: 0.85rem;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--sc-text-muted);
  max-width: 640px;
  margin-left: auto;
  margin-right: auto;
}

.sc-testimonials-band h2 {
  font-weight: 700;
  font-size: 3rem;
  letter-spacing: -0.4px;
}

/* "success stories" highlighted in teal, on its own line (forced with a
   <br> in the markup per the Figma layout) rather than relying on
   .main h2 b, which would also draw the swipe-in underline used
   elsewhere — this heading just needs the color, no underline. */
.sc-testimonial-highlight {
  color: var(--sc-teal);
}

/* The shared .sc-case-meta .sc-rating .fa rule colors icons teal (correct
   for the SPEDPro case study's checkmark badge) — but here .sc-rating
   wraps 5 star icons directly, which should read as gold/yellow like every
   other star rating on the page (--sc-star), not teal. Scoped to this band
   only so the SPEDPro badge is untouched. */
.sc-testimonials-band .sc-rating .fa {
  color: var(--sc-star);
}

@media (max-width: 767px) {
  .sc-testimonials-band h2 {
    font-size: 2.1rem;
  }
}

@media (max-width: 991px) {
  .sc-testimonials-band {
    padding: 34px 22px;
  }
}

.sc-testimonial-grid {
  display: flex;
  align-items: flex-start;
  gap: 28px;
  /* The three columns had no width cap, so they simply split whatever the
     band was wide: past ~1200px every card stretched into a squat, wide
     rectangle, while the mockup's cards are taller than they are wide.
     Capping the row and centring it fixes the card width from 1180px up,
     so the card keeps its proportions on any monitor. */
  max-width: 1180px;
  margin-inline: auto;
  /* The quote and the company line under the name are one tone in the
     mockup -- the client's name is the only dark text on the card. They
     live in different subtrees (.quote-sm vs the attribution .d-flex) so
     neither can inherit from the other; holding the value here keeps them
     from drifting apart the way they did when only the quote was lightened.
     #70747a is the soft grey this stylesheet already uses for muted labels
     (.sc-trustband-label) and clears WCAG AA at 4.7:1 on white. */
  --sc-testimonial-body: #70747a;
}

.sc-testimonial-col {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 28px;
}

.sc-testimonial-col-offset {
  padding-top: 56px;
}

.sc-testimonial-grid .random-quote {
  display: block !important;
  margin: 0 !important;
}

.sc-testimonial-grid .quote {
  height: auto;
  max-width: none;
  margin: 0;
  padding: 26px 24px;
  text-align: left;
  background: #fff;
}

/* The shared .random-quote .quote::before absolutely-positions the
   decorative quote mark into a top corner, so here it landed on the same
   line as the verified badge and stars and read as clutter. In the mockup
   the mark is not decoration behind the content: it sits in the flow, on
   its own line under the badge row, and pushes the message down. Remove
   the absolute one outright and rebuild it as a static block below. */
.sc-testimonial-grid .quote::before {
  content: none;
}

/* .quote-sm holds the badge row first and then the message as a bare text
   node. Making it a flex column lets ::before be a real block in the flow
   rather than an overlay; `order` on the badge row then lifts it back to
   the top, so the painted order is badge row -> quote mark -> message
   without restructuring the markup of six cards. */
.sc-testimonial-grid .quote-sm {
  display: flex;
  flex-direction: column;
  text-align: left !important;
  font-size: 0.95rem !important;
  line-height: 1.6;
  /* Was inheriting --sc-dark, the same near-black as the bold client name
     below it, so a five-line quote read as a heavy slab. */
  color: var(--sc-testimonial-body);
  padding: 0 !important;
}

.sc-testimonial-grid .quote-sm::before {
  content: "\201C";
  font-family: Georgia, "Times New Roman", serif;
  font-size: 54px;
  color: var(--sc-teal);
  opacity: 0.9;
  /* The glyph's ink sits in the top third of its em box, so a 54px line
     box would trail ~25px of dead space and push the message far further
     down than the mockup does. Pin the block to the height the ink
     actually needs and let the empty remainder overflow harmlessly -- an
     explicit height is predictable in a way that guessing at a fractional
     line-height is not. */
  display: block;
  line-height: 1;
  height: 32px;
  margin-bottom: 8px;
}

.sc-testimonial-grid .sc-quote-header {
  order: -1;
  margin-bottom: 14px;
}

.sc-testimonial-grid .quote .d-flex {
  justify-content: flex-start !important;
  /* The markup's py-4 py-lg-5 utilities are !important, and at lg they put
     48px above the attribution -- far more air than the mockup, which
     tucks the name close under the message. */
  padding: 14px 0 0 !important;
}

/* Attribution. Both lines were running at the base .text-18/.text-14
   sizes, much larger than the mockup: the name reads there as a small
   uppercase label and the company as muted support beneath it. The
   markup's inline style="font-weight: 500" was removed from index.html so
   this weight applies without needing !important to out-rank it. */
.sc-testimonial-grid .quote .text-18 {
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  color: var(--sc-dark);
  margin-top: 0 !important;
}

.sc-testimonial-grid .quote .text-14 {
  font-size: 0.75rem;
  color: var(--sc-testimonial-body);
  margin-top: 2px;
}

.sc-quote-header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}

.sc-verified-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px;
  border-radius: 999px;
  background: var(--sc-verified-bg);
  font-family: var(--sc-font-body);
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  color: var(--sc-dark);
  margin-bottom: 0;
}

.sc-verified-badge .fa {
  color: var(--sc-teal);
}

.sc-quote-stars .fa {
  color: var(--sc-star);
  font-size: 0.8rem;
  margin-right: 1px;
}

/* Dark video-testimonial placeholder cards */
.sc-video-card {
  position: relative;
  min-height: 260px;
  border-radius: 18px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: linear-gradient(150deg, #232a46 0%, #14172a 100%);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 24px 26px;
}

.sc-video-play {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--sc-teal);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 0 0 8px rgba(44, 75, 255, 0.18);
}

.sc-video-play .fa {
  color: #fff;
  font-size: 0.95rem;
  margin-left: 2px;
}

.sc-video-caption {
  position: relative;
  z-index: 1;
}

.sc-video-caption .text-18,
.sc-video-caption .text-14 {
  color: #fff;
}

/* Below lg the three columns get too narrow to hold a testimonial: at
   768px each card was only ~197px wide, so a message ran to eight or nine
   lines and the card turned into a tall ribbon. Two columns across the
   tablet range keeps the card near the ~310px width it has on a phone and
   the ~366px it has on desktop. */
@media (min-width: 768px) and (max-width: 991px) {
  .sc-testimonial-grid {
    flex-wrap: wrap;
  }

  .sc-testimonial-col {
    flex: 0 1 calc(50% - 14px);
  }

  /* Columns wrap as whole units, so with columns 1 and 2 filling the first
     row the third would drop underneath at half width and leave the right
     half of that row empty. Give it the full row instead and turn it on
     its side, so its two cards sit beside each other at the same ~310px
     as the four above them and the block reads as an even 2x3. */
  .sc-testimonial-col:nth-child(3) {
    flex-basis: 100%;
    flex-direction: row;
  }

  .sc-testimonial-col:nth-child(3) > .random-quote {
    flex: 1 1 0;
    min-width: 0;
  }

  .sc-testimonial-col-offset {
    padding-top: 0;
  }
}

@media (max-width: 767px) {
  .sc-testimonial-grid {
    flex-direction: column;
  }

  .sc-testimonial-col-offset {
    padding-top: 0;
  }
}

/* Blog section header row */
.sc-blog-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 16px;
}

.sc-blog-header p {
  margin: 0;
  max-width: 560px;
}

/* Green process card ("How we turn ideas into shipped software") */
.sc-process-card {
  background: var(--sc-teal);
  padding: 40px 34px;
  color: #fff;
  height: 100%;
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.sc-process-card h3,
.sc-process-card h2 {
  color: #fff;
  font-weight: 700;
  font-size: 2rem;
  line-height: 1.125;
  letter-spacing: -0.32px;
  position: relative;
  z-index: 1;
  margin-bottom: 16px;
}

.sc-process-card p {
  color: rgba(255, 255, 255, 0.85);
  position: relative;
  z-index: 1;
  margin-bottom: 20px;
}

.sc-process-card .btn {
  position: relative;
  z-index: 1;
}

@media (max-width: 767px) {
  .sc-cta-light,
  .sc-process-card {
    padding: 34px 22px;
  }
}

/* =========================================================================
   Button parity pass — exact Figma button treatment
   (white-fill / black-border uppercase pills, and the one filled-gray
   secondary button). Scoped to `main` so nothing outside the home page
   content area is touched.
   ========================================================================= */

/* White pill, black border, uppercase 15px/600 — the repeated secondary CTA
   used across "Explore the service", "See more/past projects",
   "Hire AI Experts", "Read our blogs". */
main .btn.btn-outline-dark {
  background: #fff;
  border: 1px solid var(--sc-ink);
  border-radius: 9px;
  color: var(--sc-ink);
  font-family: "Poppins", sans-serif;
  font-weight: 600;
  font-size: 0.9375rem;
  letter-spacing: 0.3px;
  text-transform: uppercase;
}

main .btn.btn-outline-dark:hover {
  background: var(--sc-ink);
  border-color: var(--sc-ink);
  color: #fff;
}

/* White pill on a colored/dark card background — "Get a Free Quote",
   "Talk to an AI Specialist". */
main .sc-hiring-banner .btn.btn-light,
main .sc-process-card .btn.btn-light {
  background: #fff;
  border: 1px solid #fff;
  border-radius: 9px;
  color: #000;
  font-family: "Poppins", sans-serif;
  font-weight: 600;
  font-size: 0.9375rem;
  letter-spacing: 0.3px;
  text-transform: uppercase;
}

main .sc-hiring-banner .btn.btn-light:hover,
main .sc-process-card .btn.btn-light:hover {
  background: transparent;
  color: #fff;
}

/* Filled light-gray secondary button — "Connect with our experts" is the
   one CTA that isn't an uppercase pill in the Figma spec. */
main .sc-journey-band .btn.btn-outline-dark {
  background: var(--sc-btn-fill);
  border: 1px solid #000;
  border-radius: 10px;
  color: var(--sc-ink);
  font-family: var(--sc-font-body);
  font-weight: 600;
  font-size: 0.906rem;
  text-transform: none;
  letter-spacing: normal;
}

main .sc-journey-band .btn.btn-outline-dark:hover {
  background: #000;
  color: #fff;
}

/* Primary teal CTA ("Let's talk!", "Schedule a Free Consultation").

   The colour lives in app.min-v=13.css, which the whole site shares and which
   is versioned in its filename, so every correction has to be an override
   here rather than an edit there:
     :5027   .btn-warning        background-color / border-color  #008066
     :5037   .btn-warning:focus  box-shadow rgba(222,170,12,.5)   <- yellow ring
     :12428  .btn-warning:hover  background / border-color #1c252b <- navy hover

   All fifteen of these buttons sit inside <main> on all eight pages, so the
   `main` scope below reaches every one of them and keeps the specificity
   (0,3,1) comfortably above app.min's (0,2,0) state rules.

   The gradient was already overriding the flat fill, but on a 100deg axis
   running mid-teal -> lighter -> dark, which read as a sheen across the
   middle rather than a ramp. It now uses the shared --sc-btn-gradient: a
   straight 90deg run, light on the left to dark on the right. */
main .btn.btn-warning {
  background-color: var(--sc-teal);
  background-image: var(--sc-btn-gradient);
  /* .btn carries a transparent 1.5px border. That border area still gets
     painted (background-clip defaults to border-box) but a background is
     *sized* to the padding box, so the gradient fell 1.5px short on each side
     and background-repeat tiled it into the gap: the ramp's dark end
     (#045c48) landed against the left edge and its light end against the
     right, which read as a black hairline down the left of the button.
     Sizing to the border box makes one ramp cover the whole button. */
  background-origin: border-box;
  border-color: transparent;
  border-radius: 9px;
  font-family: "Poppins", sans-serif;
  font-weight: 600;
  font-size: 0.9375rem;
  letter-spacing: 0.3px;
  text-transform: uppercase;
}

/* app.min paints the button #1c252b on both :hover and :focus. Overriding it
   with a second, reversed gradient used to put the light end on the right,
   which read as the button flipping rather than reacting -- brightness()
   dims the ramp as a whole and keeps its direction. The border is repeated
   here because app.min's rule sets border-color alongside the background.
   The translateY(-3px) lift, the shadow and the ::after shine sweep all stay
   with the rules near the top of this file. */
main .btn.btn-warning:hover,
main .btn.btn-warning:focus {
  background-color: var(--sc-teal);
  background-image: var(--sc-btn-gradient);
  /* Repeated from the base rule: app.min sets `background` (the shorthand) on
     these states, and any shorthand resets background-origin back to
     padding-box -- which would bring the tiled dark hairline back on hover. */
  background-origin: border-box;
  border-color: transparent;
}

/* Only :hover dims. app.min's navy applies to :focus as well, so :focus has
   to be in the rule above to hold the gradient -- but a button that is merely
   focused has not been pointed at, and darkening it there would leave it
   dimmed after a click until something else takes focus. */
main .btn.btn-warning:hover {
  filter: brightness(0.94);
}

/* The ring is kept and only recoloured -- it is the one thing telling a
   keyboard user where they are, and the inherited yellow is left over from
   Bootstrap's original warning palette, which this button no longer uses. */
main .btn.btn-warning:focus,
main .btn.btn-warning.focus {
  box-shadow: 0 0 0 0.2rem rgba(0, 128, 102, 0.35);
}

main .sc-explore-btn {
  padding: 8px 20px;
  font-size: 0.82rem;
}

/* =========================================================================
   Section spacing — a little vertical breathing room between every
   top-level content block on the home page. CSS-only, targets each
   section by its exact direct-child relationship to its container so
   nothing inside a section (cards, rows of columns, the footer CTA
   banner) is affected.
   ========================================================================= */
:root {
  /* Was 100px, derived from the Figma "Home page" frame (1920px wide):
     the gap between the last visible element of one section and the first
     of the next (SPEDPro tags row bottom @3307 -> hiring banner top @3422
     = 115px; process card bottom @4269 -> next section top @4369.5 =
     ~100px; testimonials band bottom @7460 -> "Latest insights" heading
     @7560 = 100px) consistently landed around 100px.

     Now 40px, because in the built page 100px read as far too much empty
     space between sections. 40px is the rhythm the trust band already had
     above and below itself, so the rest of the page is pulled down to
     match it -- which is also what makes the old .sc-trustband-flush
     override redundant (it existed purely to cancel this gap back to
     40px, and is removed below).

     This is a :root variable, so the change is deliberately global: the
     six AI service pages and services.html load this file too, and their
     section joins move from 100px to 40px with it. Those pages keep their
     own 56px .sc-svc-section rhythm for everything else.

     The hiring banner -> process card transition stays the one documented
     exception below, where Figma has them flush (0px). */
  --sc-section-gap: 40px;
}

main > .container > section.row,
main > .container > .sc-trustband,
main > .container > .row,
main > .container > .sc-journey-band,
main > .container > .sc-stats-intro,
main > .container > .sc-hiring-row,
main > .container > .sc-testimonials-band,
main > .container > .sc-blog-header,
main > .container > .container > .row,
main > .container > .container > .sc-cta-light {
  margin-top: var(--sc-section-gap);
  margin-bottom: var(--sc-section-gap);
}

/* "Real projects. Real numbers." heading + the $10M/200+/1,000,000 stat
   row + the SPEDPro case study are one visual section (per Figma), not
   three stacked sections — give them a small shared internal rhythm
   instead of the full section gap, and only push the *outer* edges
   (heading's top, case study's bottom) out to the normal section gap. */
main > .container > .sc-stats-intro {
  margin-bottom: 0;
}

main > .container > .sc-stats-row {
  /* Was 40px. That used to be the "tighter than a section break" value
     back when the section gap was 100px -- but the section gap is now 40px
     itself, so keeping 40px here would leave this group with no internal
     rhythm at all and it would read as three separate sections instead of
     one. 24px restores the distinction. */
  margin-top: 24px;
  margin-bottom: 24px;
}

/* The case-study block used to be a bare `main > .container > .zoom-img`.
   It is now three .zoom-img slides inside .sc-case-carousel, so that
   selector no longer matches anything and the section's top/bottom spacing
   would have collapsed. The carousel wrapper inherits the rule; the
   .zoom-img selector stays alongside it so the other pages, where the block
   is still a direct child, are unaffected. */
main > .container > .zoom-img,
main > .container > .sc-case-carousel {
  margin-top: 0;
  margin-bottom: var(--sc-section-gap);
}

/* The hiring row (blue banner + job cards) and the process row (steps +
   green card) sit directly on top of one another with zero gap, so the
   blue banner's bottom-right corner touches the green card's top-left
   corner — overrides the generic section-gap margin above. */
main > .container > .sc-hiring-row {
  margin-bottom: 0;
}

main > .container > .sc-process-row {
  margin-top: 0;
}

/* Below the lg breakpoint the two columns stack — DOM order puts the
   checklist (steps) above the green "From napkin sketch to app store"
   card. On mobile it should read the other way: the green summary card
   first, the supporting checklist underneath it. `.row` is already
   `display:flex` (Bootstrap), so a plain `order` swap reverses the visual
   stacking order without touching the markup. */
@media (max-width: 991px) {
  .sc-process-row > .col-lg-6:first-child {
    order: 2;
  }

  .sc-process-row > .col-lg-6:last-child {
    order: 1;
  }
}

/* Hero sits right under the nav — keep it snug up top, just add room below it. */
main > .container > section.row {
  margin-top: 0;
}

/* The blue/yellow footer CTA banner is a full-bleed block that sits directly
   under <main>, outside any .container — give it room from the section above. */
main > div[style*="linear-gradient"] {
  margin-top: var(--sc-section-gap);
}

/* ===========================================================================
   Large-screen cap — the base framework grows .container to max-width:75vw
   past 1685px viewport width, with NO upper bound. On a big monitor (or a
   normal monitor zoomed out, which is CSS-equivalent to a wider viewport)
   that lets the container keep expanding forever — 2600px viewport => a
   1950px-wide container — while text, icons, and card padding stay at their
   fixed rem/px sizes. The page doesn't get "more responsive", it just gets
   sparser: the same small type and small cards floating in far too much
   width. Capping the container's growth keeps every section's proportions
   (type size vs. whitespace) consistent from a laptop up through an
   ultra-wide/zoomed-out display, instead of only working within one range.
   =========================================================================== */
@media (min-width: 1685px) {
  .container {
    max-width: min(75vw, 1600px);
  }
}

@media (max-width: 767px) {
  :root {
    /* Figma export only covers the 1920px desktop frame, so there's no
       mobile spec to measure. The old pair was 100px/64px (a 0.64 ratio);
       at the new 40px base that same ratio would give ~26px, which is too
       tight to read as a section break at all, so mobile holds at 32px. */
    --sc-section-gap: 32px;
  }
}

/* =========================================================================
   Contact CTA — "Where there's smoke..." (blue / light-gray split)
   Shared by index.html and services.html — both link this stylesheet.
   ========================================================================= */
.sc-svc-contact {
  width: 100vw;
  position: relative;
  left: 50%;
  transform: translateX(-50%);
}

/* Root cause of a height mismatch: Bootstrap's `.row` is display:flex,
   which SHOULD stretch both columns to equal height by default — but that
   only works reliably when both columns are plain flex items with no
   competing height rules. Rather than fight flex-stretch edge cases,
   force the row onto CSS Grid instead: grid items stretch to fill their
   row's height unconditionally, so the blue column and the form column
   are guaranteed to be exactly the same height, no matter which one has
   more content. */
.sc-svc-contact .row {
  display: grid;
  grid-template-columns: 1fr 1fr;
}

/* The gap-in-the-middle-with-half-width-columns bug: the columns still
   carry Bootstrap's ".col-lg-6" class, which sets `max-width: 50%` (and a
   flex-basis) meant for a *flex* row. Percentage max-width on a grid item
   resolves against its own grid cell — which is already 50% of the row —
   so 50% of 50% left each column at just 25% of the row, with a blank gap
   where the unused space collapsed into the middle. Neutralize those
   leftover flex-column sizing properties now that the parent is a grid. */
.sc-svc-contact .row > [class*="col-"] {
  max-width: 100%;
  width: 100%;
  flex: none;
}

@media (max-width: 991px) {
  .sc-svc-contact .row {
    grid-template-columns: 1fr;
  }
}

.sc-svc-contact-left {
  background: var(--sc-brand-blue, #3aadd9);
  color: #fff;
  padding: 70px 50px;
  display: flex;
  /* Center the whole text block as a unit — both axes — while the text
     inside that block stays left-aligned (so the heading, paragraph, and
     button all share the same left edge, instead of each line centering
     independently with ragged edges). */
  align-items: center;
  justify-content: center;
}

.sc-svc-contact-inner {
  max-width: 460px;
  width: 100%;
  text-align: left;
}

.sc-svc-contact-left h2 {
  color: var(--sc-dark);
  font-weight: 700;
  font-size: 2.6rem;
  margin-bottom: 20px;
}

.sc-svc-contact-left p {
  color: rgba(14, 14, 18, 0.72);
  margin-bottom: 28px;
}

@media (max-width: 991px) {
  .sc-svc-contact-left {
    padding: 50px 26px;
  }

  .sc-svc-contact-left h2 {
    font-size: 2.1rem;
  }
}

/* -------------------------------------------------------------------------
   Sticky left column — one side stays in place while the other side
   scrolls past it. Shared by the "What you get, beyond the build" section
   on services.html and the "It's not rocket science" section on index.html.
   ------------------------------------------------------------------------- */
.sc-value-sticky {
  position: sticky;
  top: 170px;
}

@media (max-width: 991px) {
  .sc-value-sticky {
    position: static;
  }
}

/* "Why SoftCircles" / "Our Processes" button pair. Previously the second
   button used an inline `margin-left: 30px` to space it from the first —
   fine side-by-side on desktop, but once the two buttons wrap onto
   separate lines on a narrow screen, that left margin just shifted the
   second button in from the shared left edge instead of the first. A flex
   row with `gap` spaces them consistently whether they sit side-by-side or
   wrap, so both always share the same left edge. */
.sc-value-btn-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 48px;
}

/* -------------------------------------------------------------------------
   Nav "Contact" link — same text size as the other nav-links, just with a
   thin outline/pill border around it so it still reads as a CTA.
   ------------------------------------------------------------------------- */
.navbar-home .nav-link.sc-nav-contact {
  border: 1px solid rgba(28, 37, 43, 0.35);
  border-radius: 8px;
  padding-left: 16px;
  padding-right: 16px;
  transition: border-color 0.2s ease, color 0.2s ease;
}

.navbar-home .nav-link.sc-nav-contact:hover {
  border-color: #1c252b;
}


/* -------------------------------------------------------------------------
   Trust band top gap on very small screens

   The .sc-trustband-flush override used to live here: it cancelled the
   then-100px section gap back down to 40px on the home page. The section
   gap is now 40px everywhere, so that rule did nothing but restate the
   default -- it was removed, along with the class in index.html.

   It was masking one thing, though. index.html stacks five
   .negative-bottom-space-mobile spacers directly above the band, and the
   base framework gives those margin-bottom:-10px !important below 450px.
   A collapsed margin is the largest positive plus the smallest negative,
   so that -10px eats into the band's top gap: it lands at 22px while every
   other join on the page is 32px. The old rule's -24px happened to win the
   negative slot and hid this; at the smaller values it shows. So add the
   10px back and the band sits on the same rhythm as everything else.

   The adjacent-sibling selector keeps this to the one place those spacers
   actually exist -- no other page loading this file has them.
   ------------------------------------------------------------------------- */
@media (max-width: 450px) {
  main > .container > .negative-bottom-space-mobile + .sc-trustband {
    margin-top: calc(var(--sc-section-gap) + 10px);
  }
}
