/* Google Fonts are enqueued as their own stylesheet handle (ck-fonts) in
   functions.php. An @import here would be serial and unpreconnectable. */
/* ==========================================================================
   Codingkart — Global stylesheet
   Design tokens + shared components (navbar, buttons, footer).
   Tokens mirror the Figma variable collection 1:1; page-specific rules live
   in css/<pagename>.css and must reuse the custom properties declared here.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Design tokens
   -------------------------------------------------------------------------- */

:root {
  /* Colour — brand */
  --color-cta: #1292bc;
  --color-light-blue: #83cedc;
  --color-primary-alpha-10: #1292bc1a;

  /* Colour — background */
  --color-bg: #000000;
  --color-bg-secondary: #242424;
  --color-bg-card: #000000;
  --color-bg-card-hover: #242424;
  --color-bg-menu: #000000;
  --color-bg-accent: #1292bc;
  --color-white: #ffffff;

  /* Colour — text */
  --color-text-primary: #ffffff;
  --color-text-secondary: #e8e8e8;
  --color-text-link: #1292bc;
  --color-text-highlight: #78d2f0;
  --color-text-muted: #4f4f4f;
  --color-text-dark: #404040;
  --color-grey-93: #e0e6f8;

  /* Colour — border */
  --color-border-subtle: #494949;
  --color-border-strong: #737582;

  /* Colour — button */
  --color-button-primary: #1292bc;
  --color-button-secondary: #929292;

  /* Colour — icon */
  --color-icon-primary: #1292bc;
  --color-icon-secondary: #ffffff;

  /* Typography — families */
  --font-heading: "Plus Jakarta Sans", system-ui, -apple-system, sans-serif;
  --font-body: "Hanken Grotesk", system-ui, -apple-system, sans-serif;

  /* Typography — sizes */
  --font-size-14: 0.875rem;
  --font-size-18: 1.125rem;
  --font-size-20: 1.25rem;
  --font-size-24: 1.5rem;
  --font-size-32: 2rem;
  --font-size-64: 4rem;
  --font-size-80: 5rem;

  /* Typography — weights */
  --font-weight-regular: 400;
  --font-weight-medium: 500;
  --font-weight-semibold: 600;
  --font-weight-bold: 700;
  --font-weight-extrabold: 800;

  /* Spacing — gap scale */
  --gap-1: 8px;
  --gap-2: 16px;
  --gap-3: 24px;
  --gap-4: 32px;
  --gap-5: 40px;

  /* Spacing — section rhythm */
  --section-36: 36px;
  --section-40: 40px;
  --section-64: 64px;
  --section-80: 80px;
  --section-100: 100px;
  --section-120: 120px;

  /* Spacing — component padding */
  --padding-button-x: 24px;
  --padding-button-y: 12px;
  --padding-card: 32px;
  --padding-card-sm: 24px;
  --gap-card: 32px;
  --gap-card-sm: 24px;

  /* Radius */
  --radius-lg: 24px;
  --radius-xl: 32px;
  --radius-pill: 78px;

  /* Layout */
  --page-max-width: 1440px;
  --content-width: 1200px;

  /* Elevation */
  --shadow-button: 0 4px 7px rgba(0, 0, 0, 0.17);
  --shadow-heading: 0 4px 6px rgba(0, 0, 0, 0.16);
}

/* --------------------------------------------------------------------------
   2. Reset / base
   -------------------------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  margin: 0;
  background-color: var(--color-bg);
  color: var(--color-text-primary);
  font-family: var(--font-body);
  font-size: var(--font-size-18);
  font-weight: var(--font-weight-regular);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  margin: 0;
  font-family: var(--font-heading);
}

p {
  margin: 0;
}

ul,
ol {
  margin: 0;
  padding: 0;
  list-style: none;
}

a {
  color: inherit;
  text-decoration: none;
}

img,
svg {
  display: block;
  max-width: 100%;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

/* Components below set display explicitly, which would otherwise beat the
   UA rule for [hidden]. */
[hidden] {
  display: none !important;
}

:focus-visible {
  outline: 2px solid var(--color-cta);
  outline-offset: 3px;
}

/* --------------------------------------------------------------------------
   3. Shared typography helpers
   -------------------------------------------------------------------------- */

.h1 {
  font-family: var(--font-heading);
  font-size: var(--font-size-80);
  font-weight: var(--font-weight-extrabold);
  line-height: 1.135;
}

.h3 {
  font-family: var(--font-heading);
  font-size: var(--font-size-64);
  font-weight: var(--font-weight-semibold);
  line-height: 1.1;
}

.h5 {
  font-family: var(--font-heading);
  font-size: var(--font-size-32);
  font-weight: var(--font-weight-extrabold);
  line-height: 1;
}

.body-lg {
  font-size: var(--font-size-24);
  font-weight: var(--font-weight-regular);
  line-height: 1.4;
}

.body-md {
  font-size: var(--font-size-20);
  font-weight: var(--font-weight-regular);
  line-height: 1.4;
}

.body-sm {
  font-size: var(--font-size-18);
  font-weight: var(--font-weight-regular);
  line-height: 1.4;
}

.text-secondary {
  color: var(--color-text-secondary);
}

.text-highlight {
  color: var(--color-text-highlight);
}

/* --------------------------------------------------------------------------
   4. Layout primitives
   -------------------------------------------------------------------------- */

.section {
  padding-inline: var(--section-120);
  background-color: var(--color-bg);
}

.section__inner {
  width: 100%;
  max-width: var(--content-width);
  margin-inline: auto;
}

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

/* WordPress's own hidden-text class, used by the "Skip to content" link in
   header.php. Core styles it in the block-library stylesheet, which this
   theme dequeues on its pages, so without this rule the link sat in plain
   view above the header on every page. Hidden until a keyboard user tabs to
   it, then shown as a button in the top-left corner. */
.screen-reader-text {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.screen-reader-text:focus {
  top: var(--gap-1);
  left: var(--gap-1);
  z-index: 100;
  width: auto;
  height: auto;
  padding: 12px 20px;
  margin: 0;
  overflow: visible;
  clip: auto;
  border-radius: var(--radius-pill);
  background-color: var(--color-button-primary);
  color: var(--color-white);
  font-size: var(--font-size-18);
  line-height: 1;
}

/* --------------------------------------------------------------------------
   5. Buttons
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--gap-1);
  height: 49px;
  padding: var(--padding-button-y) var(--padding-button-x);
  border-radius: var(--radius-pill);
  font-family: var(--font-body);
  font-size: var(--font-size-18);
  font-weight: var(--font-weight-medium);
  line-height: 1;
  text-align: center;
  white-space: nowrap;
  transition: background-color 0.2s ease, border-color 0.2s ease,
    color 0.2s ease, transform 0.2s ease;
}

.btn:hover {
  transform: translateY(-1px);
}

.btn--primary {
  background-color: var(--color-button-primary);
  color: var(--color-text-primary);
  filter: drop-shadow(var(--shadow-button));
}

.btn--primary:hover {
  background-color: #0f81a7;
}

.btn--secondary {
  border: 1px solid var(--color-button-secondary);
  color: var(--color-text-secondary);
  border-radius: 88px;
}

.btn--secondary:hover {
  border-color: var(--color-text-secondary);
  color: var(--color-text-primary);
}

/* Trailing 16x16 arrow glyph inside a button */
.btn__icon {
  flex: none;
  width: 16px;
  height: 16px;
}

/* --------------------------------------------------------------------------
   6. Site header / navbar (shared across pages)
   -------------------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: var(--gap-3) var(--section-120);
  background-color: var(--color-bg-menu);
  backdrop-filter: blur(4px);
}

.navbar {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  padding-block: var(--gap-1);
  border-radius: 110px;
  backdrop-filter: blur(7px);
}

.navbar__logo {
  display: flex;
  flex: none;
  align-items: center;
  gap: 15.24px;
}

.navbar__logo-mark {
  width: 60.391px;
  height: 36px;
}

.navbar__logo-wordmark {
  width: 162.734px;
  height: 15.321px;
}

.navbar__right {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: flex-end;
}

.navbar__nav {
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  padding-inline: var(--gap-3);
}

.navbar__item {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  color: var(--color-white);
  font-family: var(--font-body);
  font-size: var(--font-size-14);
  font-weight: var(--font-weight-regular);
  line-height: 1;
  white-space: nowrap;
  transition: color 0.2s ease;
}

.navbar__item:hover {
  color: var(--color-text-highlight);
}

.navbar__chevron {
  flex: none;
  width: 16px;
  height: 16px;
  transition: transform 0.2s ease;
}

/* Submenus ------------------------------------------------------------------
   Markup comes from wp_nav_menu() — see "Primary navigation" in functions.php:

     li.navbar__entry.navbar__entry--parent
       a.navbar__item
       button.navbar__sub-toggle > img.navbar__chevron
       ul.navbar__submenu > li.navbar__entry …

   Above the nav breakpoint a submenu is a dropdown, opened by two classes that
   main.js puts on the parent <li>:

     .is-hover   while a mouse is over it
     .is-open    when its chevron button is pressed (keyboard, touch, or a
                 click that pins it open)

   Hover goes through a class rather than :hover so the script can ignore the
   fake hover a touch screen leaves behind after a tap. Plain :hover is still
   the fallback for as long as the script has not taken over (.is-enhanced).
   Below the breakpoint the same list is an accordion inside the drawer; those
   rules sit with the rest of the drawer in section 8.
   -------------------------------------------------------------------------- */

.navbar__entry {
  position: relative;
  display: flex;
  align-items: center;
  gap: 6px;
}

.navbar__sub-toggle {
  position: relative;
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  padding: 0;
}

/* The glyph keeps its 16px footprint; this only widens what can be pressed. */
.navbar__sub-toggle::after {
  content: "";
  position: absolute;
  inset: -12px -10px -12px -3px;
}

.navbar__entry.is-open > .navbar__sub-toggle .navbar__chevron {
  transform: rotate(180deg);
}

@media (min-width: 769px) {
  .navbar__submenu {
    position: absolute;
    top: 100%;
    /* border + padding + link padding, so labels line up under the parent's */
    left: -21px;
    z-index: 1;
    width: max-content;
    min-width: 220px;
    max-width: 320px;
    margin-top: 18px;
    padding: 8px;
    border: 1px solid var(--color-border-subtle);
    border-radius: 16px;
    background-color: var(--color-bg-menu);
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.55);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    /* The short delay on the way out forgives a pointer that cuts a corner. */
    transition: opacity 0.18s ease 0.1s, transform 0.18s ease 0.1s,
      visibility 0s linear 0.28s;
  }

  /* Covers the gap between the label and the panel so crossing it does not
     count as leaving. */
  .navbar__submenu::before {
    content: "";
    position: absolute;
    right: 0;
    bottom: 100%;
    left: 0;
    height: 19px;
  }

  .navbar__entry.is-open > .navbar__submenu,
  .navbar__entry.is-hover > .navbar__submenu,
  .navbar__nav:not(.is-enhanced) .navbar__entry:hover > .navbar__submenu,
  .navbar__nav:not(.is-enhanced) .navbar__entry:focus-within > .navbar__submenu {
    z-index: 2;
    opacity: 1;
    visibility: visible;
    transform: none;
    transition-delay: 0s;
  }

  /* The panel under the pointer sits above one that is still fading out. */
  .navbar__entry.is-hover > .navbar__submenu,
  .navbar__nav:not(.is-enhanced) .navbar__entry:hover > .navbar__submenu {
    z-index: 3;
  }

  .navbar__nav > .navbar__entry.is-hover > .navbar__sub-toggle .navbar__chevron {
    transform: rotate(180deg);
  }

  /* Set by main.js when the panel would run off the right-hand edge. */
  .navbar__submenu.is-flipped {
    right: -21px;
    left: auto;
  }

  /* Rows inside a panel */
  .navbar__submenu > .navbar__entry {
    gap: 0;
    border-radius: 10px;
    transition: background-color 0.2s ease;
  }

  .navbar__submenu > .navbar__entry:hover,
  .navbar__submenu > .navbar__entry.is-open {
    background-color: var(--color-bg-secondary);
  }

  .navbar__submenu .navbar__item {
    flex: 1;
    justify-content: flex-start;
    padding: 10px 12px;
    line-height: 1.35;
    white-space: normal;
  }

  .navbar__submenu .navbar__sub-toggle {
    margin-right: 10px;
  }

  /* Second level flies out sideways, so its chevron points that way and
     stays put when open. */
  .navbar__submenu .navbar__chevron,
  .navbar__submenu .navbar__entry.is-open > .navbar__sub-toggle .navbar__chevron {
    transform: rotate(-90deg);
  }

  .navbar__submenu .navbar__submenu {
    top: -9px;
    left: 100%;
    margin-top: 0;
    margin-left: 13px;
  }

  .navbar__submenu .navbar__submenu::before {
    top: 0;
    right: 100%;
    bottom: 0;
    left: auto;
    width: 14px;
    height: auto;
  }

  .navbar__submenu .navbar__submenu.is-flipped {
    right: 100%;
    left: auto;
    margin-right: 13px;
    margin-left: 0;
  }

  .navbar__submenu .navbar__submenu.is-flipped::before {
    right: auto;
    left: 100%;
  }
}

/* Hamburger — desktop hides it, the breakpoint below swaps it in. */
.navbar__toggle {
  display: none;
  width: 44px;
  height: 44px;
  flex: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  padding: 0;
  order: 2;
}

.navbar__toggle-bar {
  width: 22px;
  height: 2px;
  border-radius: 2px;
  background-color: var(--color-white);
  transition: transform 0.2s ease, opacity 0.2s ease;
}

.navbar__toggle[aria-expanded="true"] .navbar__toggle-bar:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}

.navbar__toggle[aria-expanded="true"] .navbar__toggle-bar:nth-child(2) {
  opacity: 0;
}

.navbar__toggle[aria-expanded="true"] .navbar__toggle-bar:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

/* --------------------------------------------------------------------------
   7. Site footer (shared across pages)
   -------------------------------------------------------------------------- */

.site-footer {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: var(--section-40) var(--section-120);
  background-color: var(--color-bg-secondary);
  color: var(--color-text-secondary);
}

.site-footer__inner {
  display: flex;
  width: 100%;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--section-40);
  overflow: hidden;
}

.site-footer__top {
  display: flex;
  width: 100%;
  flex-direction: column;
  align-items: flex-start;
  gap: 20px;
}

/* Three columns (Solutions, Services, Resources). Each needs at least 140px,
   so the row folds to two columns on a phone and one on the narrowest screens,
   with no breakpoint to maintain. The old fixed 208px height and hidden
   overflow are gone: a link that wraps onto a second line is now simply taller. */
.site-footer__links {
  display: grid;
  width: 100%;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 140px), 1fr));
  align-items: start;
  gap: var(--section-40) var(--gap-3);
}

.footer-widget {
  display: flex;
  min-width: 0;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
}

.footer-widget__title {
  color: var(--color-text-primary);
  font-family: var(--font-body);
  font-size: var(--font-size-18);
  font-weight: var(--font-weight-semibold);
  line-height: 1.2;
}

.footer-widget__list {
  display: flex;
  width: 100%;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--gap-1);
  color: var(--color-text-secondary);
  font-size: var(--font-size-14);
  font-weight: var(--font-weight-regular);
}

.footer-widget__list a {
  display: block;
  min-height: 18px;
  line-height: 1.4;
  overflow-wrap: break-word;
  transition: color 0.2s ease;
}

.footer-widget__list a:hover {
  color: var(--color-text-link);
}

/* Oversized gradient wordmark.
   "Crafting since 2013" is 9.24em wide, so a fixed 128px (and the old fixed
   48px on phones) only fit above about 1230px of screen and was cut off below
   it. The wordmark is a size container and its type is sized from that width:
   the whole line fits at any screen, and stops growing at the 128px design size.
   Browsers without container query units fall back to the viewport width. */
.site-footer__wordmark {
  position: relative;
  width: 100%;
  container-type: inline-size;
  overflow: hidden;
}

.site-footer__wordmark span {
  display: block;
  font-family: var(--font-heading);
  font-size: min(128px, 8.4vw);
  font-size: min(128px, 10.7cqw);
  font-weight: var(--font-weight-semibold);
  /* 173.664px at 128px, as designed, and it follows the type down. */
  line-height: 1.357;
  white-space: nowrap;
  background-image: linear-gradient(
    to top,
    rgba(255, 255, 255, 0.7),
    rgba(153, 153, 153, 0.2)
  );
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.site-footer__divider {
  width: 100%;
  height: 1px;
  margin: 0;
  border: 0;
  background-color: var(--color-border-subtle);
}

.site-footer__bottom {
  display: flex;
  width: 100%;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-3);
}

.site-footer__copyright {
  display: flex;
  align-items: center;
  padding-block: 3px;
  color: var(--color-text-secondary);
  font-size: var(--font-size-14);
  font-weight: var(--font-weight-regular);
  line-height: 1.2;
}

.site-footer__social {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 27px;
}

.site-footer__social a {
  position: relative;
  display: flex;
  height: 24px;
  align-items: center;
  justify-content: center;
  transition: opacity 0.2s ease;
}

/* The icons are about 21px, too small to tap reliably. This widens what can be
   pressed without moving anything: 44px square, clear of the neighbouring
   icon at the 27px gap. */
.site-footer__social a::after {
  content: "";
  position: absolute;
  inset: -10px -8px;
}

.site-footer__social a:hover {
  opacity: 0.7;
}

/* Each mark keeps the dimensions it was exported at. */
.social-icon--01 {
  width: 24px;
  height: 26px;
}

.social-icon--02 {
  width: 20px;
  height: 20px;
}

.social-icon--03 {
  width: 21px;
  height: 21px;
}

.social-icon--04 {
  width: 21px;
  height: 22px;
}

.social-icon--05 {
  width: 21px;
  height: 16px;
}

/* --------------------------------------------------------------------------
   8. Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 1200px) {
  :root {
    --section-120: 64px;
    --font-size-80: 3.5rem;
    --font-size-64: 3rem;
  }
}

@media (max-width: 768px) {
  :root {
    --section-120: 24px;
    --section-100: 64px;
    --section-80: 56px;
    --font-size-80: 2.5rem;
    --font-size-64: 2rem;
    --font-size-32: 1.5rem;
    --font-size-24: 1.125rem;
    --padding-card: 24px;
  }

  .navbar {
    flex-wrap: wrap;
  }

  .navbar__toggle {
    display: flex;
  }

  /* The nav collapses into a drawer that pushes down under the bar. */
  .navbar__right {
    order: 3;
    display: none;
    width: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: var(--gap-3);
    padding-block: var(--gap-3) var(--gap-2);
  }

  .navbar__right.is-open {
    display: flex;
  }

  /* With submenus open the drawer can outgrow the screen, and the page behind
     it is scroll-locked, so the drawer scrolls itself. 108px is the header
     chrome around it: 76px above (padding + the bar) and 32px below.
     flex-start replaces the desktop row's flex-end, which in a column would
     push the overflow out of the top where it cannot be scrolled to. */
  .navbar__right {
    justify-content: flex-start;
    max-height: calc(100vh - 108px);
    max-height: calc(100dvh - 108px);
    overflow-y: auto;
    overscroll-behavior: contain;
  }

  .admin-bar .navbar__right {
    max-height: calc(100vh - 154px);
    max-height: calc(100dvh - 154px);
  }

  /* Scroll rather than squash. */
  .navbar__right > * {
    flex: none;
  }

  .navbar__nav {
    flex-direction: column;
    align-items: stretch;
    gap: var(--gap-2);
    padding-inline: 0;
  }

  .navbar__item {
    justify-content: flex-start;
    padding-block: var(--gap-1);
    font-size: var(--font-size-18);
  }

  /* Submenus become an accordion: label and chevron on one row, the list
     wrapping onto the next. */
  .navbar__entry {
    flex-wrap: wrap;
    gap: 0;
  }

  .navbar__entry > .navbar__item {
    flex: 1;
    min-width: 0;
  }

  .navbar__sub-toggle {
    width: 44px;
    height: 44px;
  }

  .navbar__sub-toggle::after {
    content: none;
  }

  .navbar__submenu {
    display: none;
    flex-basis: 100%;
    margin: 4px 0 4px 4px;
    padding-left: var(--gap-2);
    border-left: 1px solid var(--color-border-subtle);
  }

  .navbar__entry.is-open > .navbar__submenu {
    display: block;
  }
.site-footer__links {

  grid-template-columns: repeat(auto-fit, minmax(min(100%, 100%), 1fr));

}
  .navbar__submenu .navbar__item {
    padding-block: 10px;
    font-size: 1rem;
    line-height: 1.35;
    white-space: normal;
  }

  .navbar__right .btn {
    justify-content: center;
  }

  body.has-nav-open {
    overflow: hidden;
  }

  /* The footer columns, wordmark and bottom bar size themselves (section 7),
     so nothing is overridden here. On a phone the bottom bar stacks. */
  .site-footer__bottom {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* ==========================================================================
   9. Subscription landing-page components

   Shared by every /<vertical>-subscription.html page (coffee, kombucha, …).
   These were originally written inline in css/coffee-subscription.css; they
   live here so a second vertical does not carry a second copy. Page files
   keep only what genuinely differs: hero slab/aside metrics, the pill states
   a given page uses, and case-study blocks that are not common.
   ========================================================================== */

:root {
  /* Type step the landing pages add below the global 80/64 pair. */
  --cs-font-16: 1rem;
  --cs-font-56: 3.5rem;

  /* Surfaces — landing-page cards sit on #1d1d1d, not the global #242424. */
  --cs-surface: #1d1d1d;
  --cs-surface-inset: #0a0d14;

  /* Body copy on these pages is white at 70%, not the global secondary grey. */
  --cs-text-body: rgba(255, 255, 255, 0.7);

  /* Borders — #404040 is --color-text-dark; the hairline has no global peer. */
  --cs-border: var(--color-text-dark);
  --cs-border-mid: var(--color-text-muted);
  --cs-hairline: rgba(255, 255, 255, 0.07);

  /* Comparison-table pills. Pages opt into the states they actually use. */
  --cs-negative: rgba(239, 68, 68, 0.6);
  --cs-negative-fill: linear-gradient(
    170.68deg,
    rgba(239, 68, 68, 0.15) 0%,
    rgba(0, 0, 0, 0.1) 100%
  );
  --cs-positive-fill: linear-gradient(
    113.72deg,
    rgba(18, 146, 188, 0.4) 3.53%,
    rgba(15, 23, 42, 0.4) 71.27%
  );
  /* "Partial support" — amber sits well away from both the red negative
     (~0deg) and the green tick (~145deg) so it reads as partial rather than
     as a weak fail. Figma draws these rows in the red pill with a warning
     glyph; the amber state is a deliberate departure from that. */
  --cs-partial: rgba(245, 158, 11, 0.6);
  --cs-partial-fill: linear-gradient(
    170.68deg,
    rgba(245, 158, 11, 0.15) 0%,
    rgba(0, 0, 0, 0.1) 100%
  );

  /* Accent glow shared by every "active/hover" card in the designs. */
  --cs-glow: 0 7px 30px rgba(18, 146, 188, 0.4);
  --cs-avatar-fill: rgba(0, 174, 239, 0.12);
  --cs-avatar-border: rgba(0, 174, 239, 0.3);
  --cs-avatar-text: #00aeef;

  /* Hero metrics each page overrides — the card and its tilted slabs are
     the same component at different heights per vertical. */
  --cs-hero-aside-h: 657px;
  --cs-slab-bottom-top: 415.51px;

  /* Trust band — the stat count is the same but each design sets its own
     gutter and side padding, so both are overridable. */
  --cs-trust-pad-x: 110px;
  --cs-trust-gap: 42px;
}

/* --- Section shell -------------------------------------------------------- */

/* Every section below the hero uses the same 100px block rhythm and the
   1200px content column the designs are built on. */
.cs-section {
  position: relative;
  padding: var(--section-100) var(--section-120);
  background-color: var(--color-bg);
  overflow: hidden;
}

.cs-section__inner {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: var(--content-width);
  margin-inline: auto;
}

/* The wide curved stroke that bleeds past both page edges. */
.cs-section__curve {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 2721px;
  max-width: none;
  transform: translate(-50%, -50%);
  pointer-events: none;
}

.cs-section__curve--faq {
  top: 30%;
}

/* --- Eyebrow pill --------------------------------------------------------- */

.eyebrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--gap-1);
  padding: 9px 20px;
  border: 1px solid var(--color-light-blue);
  border-radius: 100px;
  font-family: var(--font-heading);
  font-size: var(--font-size-14);
  font-weight: 300;
  line-height: 19.5px;
  text-transform: capitalize;
  white-space: nowrap;
}

/* The final CTA uses the same dot + label without the pill outline. */
.eyebrow--bare {
  padding: 0;
  border: 0;
}

/* --- Section heading block ------------------------------------------------ */

.cs-heading {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 20px;
  padding-bottom: var(--section-40);
}

.cs-heading .eyebrow {
  /* The pill is inline-flex inside a column flex parent, so it needs to be
     told not to stretch to the column width. */
  align-self: flex-start;
}

.cs-heading__title {
  font-size: var(--font-size-64);
  font-weight: var(--font-weight-semibold);
  line-height: 1.0625;
  text-transform: capitalize;
}

.cs-heading__sub {
  font-size: var(--font-size-24);
  line-height: 1.4;
}

/* --- Check glyph and checklists ------------------------------------------- */

/* The exported leaf is wider than its 24px frame and is clipped by it in the
   design, so the box and the leaf are sized separately. */
.cs-check {
  position: relative;
  display: block;
  flex: none;
  width: 24px;
  height: 24px;
  overflow: hidden;
}

.cs-check img {
  position: absolute;
  top: 0.72px;
  left: -3.4px;
  width: 30.8px;
  height: 24.56px;
  max-width: none;
}

.cs-checklist {
  display: flex;
  width: 524px;
  max-width: 100%;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}

.cs-checklist__item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  color: var(--cs-text-body);
  font-size: var(--font-size-18);
  line-height: 1.4;
}

/* --- Highlight list ------------------------------------------------------- */

/* The arrow-led one-liners inside a hero card. Lighter than .cs-checklist:
   a 14px glyph and 16px text rather than a 24px check box and 18px text.
   Promoted here from the pet-food page when the Shopify app development page
   needed the same block. */
.cs-highlights {
  display: flex;
  width: 100%;
  flex-direction: column;
  gap: 12px;
}

.cs-highlights__item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}

.cs-highlights__arrow {
  flex: none;
  width: 14px;
  color: var(--color-light-blue);
  font-size: var(--font-size-14);
  font-weight: 700;
  line-height: 1.6;
}

.cs-highlights__text {
  color: var(--cs-text-body);
  font-size: var(--cs-font-16);
  line-height: 1.4;
}

/* --- Section icons -------------------------------------------------------- */

/* A fixed box with a per-glyph leaf inside it. The box is a custom property
   because not every exported icon frame is 36px square. */
.cs-icon {
  --cs-icon-box: 36px;
  display: flex;
  flex: none;
  width: var(--cs-icon-box);
  height: var(--cs-icon-box);
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.cs-icon img {
  width: 36px;
  height: 36px;
  max-width: none;
}

/* Box-size exceptions. */
.cs-icon--box-33 {
  --cs-icon-box: 33px;
}

.cs-icon--why-tall {
  height: 41.569px;
}

/* Leaf sizes — each keeps the aspect ratio it was exported at. */
.cs-icon--grind img {
  width: 30.292px;
}

.cs-icon--box img {
  width: 32.625px;
  height: 32.628px;
}

.cs-icon--billing img {
  width: 35.007px;
}

.cs-icon--portal img {
  width: 35.438px;
  height: 30.938px;
}

.cs-icon--browser img {
  height: 30.132px;
}

.cs-icon--why-tall img {
  height: 41.569px;
}

.cs-icon--swap img {
  width: 29.25px;
  height: 29.221px;
}

.cs-icon--delivery img {
  width: 35.999px;
  height: 19.487px;
}

.cs-icon--bottles img {
  height: 22.43px;
}

.cs-icon--window img {
  width: 30.938px;
  height: 30.938px;
}

.cs-icon--cycle img {
  width: 34.125px;
  height: 34.125px;
}

.cs-icon--wine img {
  width: 23.273px;
}

.cs-icon--noselect img {
  width: 32.047px;
}

.cs-icon--discount img {
  width: 35.154px;
  height: 18.821px;
}

.cs-icon--store img {
  width: 30.003px;
  height: 29.274px;
}

.cs-icon--quantity img {
  width: 25.502px;
  height: 25.502px;
}

.cs-icon--crosssell img {
  width: 34.322px;
  height: 34.87px;
}

.cs-icon--wizard img {
  width: 29.29px;
  height: 35.147px;
}

.cs-icon--addon img {
  width: 26.129px;
  height: 34.877px;
}

/* Shared by both service pages (app development + Plus). */
.cs-icon--storefront img {
  width: 27.252px;
  height: 27.252px;
}

.cs-icon--webhooks img {
  width: 33.97px;
  height: 34.596px;
}

.cs-icon--checkout-ext img {
  width: 30.002px;
  height: 30.002px;
}

/* Shared with the subscription development page. */
/* The problem-grid glyphs, shared by the Shopify app development and
   WooCommerce migration pages. */
.cs-icon--sad-manual img {
  width: 33.13px;
  height: 36px;
}

.cs-icon--sad-admin img {
  width: 36.094px;
  height: 36px;
}

.cs-icon--sad-events img {
  width: 36.085px;
  height: 36px;
}

.cs-icon--dashboard img {
  width: 31.5px;
  height: 31.5px;
}

.cs-icon--3pl img {
  width: 33.851px;
  height: 22.864px;
}

/* --- Stat block ----------------------------------------------------------- */

.cs-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--gap-1);
  text-align: center;
}

.cs-stat__value {
  font-family: var(--font-heading);
  font-size: var(--font-size-32);
  font-weight: var(--font-weight-extrabold);
  line-height: 42px;
  letter-spacing: -0.36px;
  color: var(--color-light-blue);
  text-transform: capitalize;
}

.cs-stat__label {
  color: var(--color-text-secondary);
  font-size: var(--font-size-18);
  line-height: 1.4;
}

/* --- Hero ----------------------------------------------------------------- */

.cs-hero {
  position: relative;
  padding: var(--gap-3) var(--section-120) var(--section-80);
  background-color: var(--color-bg);
  overflow: hidden;
}

.cs-hero__glow {
  position: absolute;
  top: 118px;
  left: -172px;
  width: 303px;
  max-width: none;
  pointer-events: none;
}

/* Four concentric filled circles anchored off the right edge, behind the
   card. They are stacked smallest-last so the overlaps read as rings, and
   the whole stack carries the layer blur that makes it a glow rather than
   four hard bands. */
.cs-hero__rings {
  position: absolute;
  top: 706px;
  right: -455px;
  filter: blur(150px);
  pointer-events: none;
}

.cs-hero__rings img {
  position: absolute;
  max-width: none;
}

.cs-hero__rings img:nth-child(1) {
  top: 0;
  right: 0;
  width: 992px;
  height: 992px;
}

.cs-hero__rings img:nth-child(2) {
  top: 89px;
  right: 89px;
  width: 814px;
  height: 814px;
}

.cs-hero__rings img:nth-child(3) {
  top: 141px;
  right: 141px;
  width: 710px;
  height: 710px;
}

.cs-hero__rings img:nth-child(4) {
  top: 239px;
  right: 239px;
  width: 514px;
  height: 514px;
}

.cs-hero__inner {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 76px;
  width: 100%;
  max-width: var(--content-width);
  margin-inline: auto;
}

.cs-hero__text {
  display: flex;
  flex: none;
  width: 587px;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: var(--section-36);
}

.cs-hero__badge {
  width: 172.582px;
  height: 56px;
  object-fit: cover;
}

.cs-hero__copy {
  display: flex;
  width: 100%;
  flex-direction: column;
  align-items: flex-start;
  gap: 20px;
}

.cs-hero__lead {
  display: flex;
  width: 100%;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
}

.cs-hero__heading {
  font-size: var(--cs-font-56);
  font-weight: var(--font-weight-semibold);
  line-height: 62px;
  text-transform: capitalize;
}

/* Boxed definition paragraph with the accent rule down its left edge. */
.cs-hero__definition {
  width: 100%;
  padding: 20px 20px 20px 21.204px;
  border-left: 1.204px solid var(--color-cta);
  border-radius: var(--radius-lg);
  background-color: rgba(18, 146, 188, 0.3);
  color: var(--cs-text-body);
  font-size: var(--font-size-18);
  line-height: 1.4;
}

.cs-hero__sub {
  font-size: var(--font-size-24);
  line-height: 1.4;
}

.cs-hero__actions {
  display: flex;
  align-items: flex-start;
  gap: 20px;
}

.cs-hero__actions .btn {
  height: 48px;
  padding-inline: 18px;
  font-family: var(--font-heading);
}

.cs-hero__rule {
  width: 594px;
  max-width: 100%;
  height: 1px;
  margin: 0;
  border: 0;
  background-image: linear-gradient(
    to right,
    var(--color-border-subtle),
    rgba(73, 73, 73, 0)
  );
}

.cs-hero__aside {
  position: relative;
  flex: none;
  width: 538px;
  align-self: stretch;
  min-height: var(--cs-hero-aside-h);
}

/* Two tilted slabs peeking out above and below the card. */
.cs-hero__slab {
  position: absolute;
  left: 26.83px;
  width: 474.674px;
  height: 202.463px;
  border-radius: var(--radius-lg);
  background-color: var(--color-light-blue);
  transform: rotate(4.26deg) skewX(1.57deg);
}

.cs-hero__slab--top {
  top: 17.51px;
}

.cs-hero__slab--bottom {
  top: var(--cs-slab-bottom-top);
}

.cs-hero-card {
  position: absolute;
  top: 34.38px;
  left: 0;
  display: flex;
  width: 538px;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  border: 1px solid var(--color-text-dark);
  border-radius: var(--radius-xl);
  background-color: var(--cs-surface);
  box-shadow: 10px 14px 24px rgba(0, 0, 0, 0.25);
  overflow: hidden;
}

.cs-hero-card__body {
  display: flex;
  width: 100%;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--gap-3);
  padding: var(--padding-card);
}

.cs-hero-card__kicker {
  color: var(--color-cta);
  font-size: var(--font-size-20);
  font-weight: var(--font-weight-medium);
  line-height: 1.4;
  letter-spacing: -0.32px;
  text-transform: uppercase;
}

.cs-hero-card__copy {
  display: flex;
  width: 100%;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--gap-2);
}

/* No text-transform: the designs set these titles in sentence-and-proper
   case, and every page writes the title that way in the markup. Capitalising
   here only broke the small words ("Migrated From WooCommerce To Shopify"). */
.cs-hero-card__title {
  font-size: var(--font-size-24);
  font-weight: var(--font-weight-extrabold);
  /* 42px at the 24px desktop size, as designed. Unitless so it follows the
     type down on phones, where a fixed 42px was over twice the 18px text. */
  line-height: 1.75;
  letter-spacing: -0.36px;
}

.cs-hero-card__text {
  color: var(--cs-text-body);
  font-size: var(--font-size-18);
  line-height: 1.4;
  letter-spacing: -0.32px;
}

/* The screenshot sits under a bottom-weighted scrim. */
.cs-hero-card__shot {
  position: relative;
  width: 100%;
  height: 321px;
  overflow: hidden;
}

.cs-hero-card__shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
}

.cs-hero-card__shot::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.8));
  pointer-events: none;
}

/* --- Trust band ----------------------------------------------------------- */

.cs-trust {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-5);
  padding: 50px var(--cs-trust-pad-x);
  border-top: 1px solid var(--cs-border);
  border-bottom: 1px solid var(--cs-border);
  background-color: var(--color-bg);
}

.cs-trust__label {
  color: var(--color-text-secondary);
  font-size: var(--font-size-24);
  line-height: 1.4;
  white-space: nowrap;
}

.cs-trust__stats {
  display: flex;
  align-items: flex-start;
  gap: var(--cs-trust-gap);
}

/* --- Problem grid (2x2, one bordered block with hairline dividers) -------- */

/* The 1px grid gap lets the shared background show through as the divider,
   so this is one block rather than four gapped cards. */
.cs-problem-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  border: 1px solid var(--cs-border);
  border-radius: var(--radius-xl);
  background-color: var(--cs-border);
  overflow: hidden;
}

.cs-problem {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--gap-3);
  padding: var(--padding-card);
  background-color: var(--color-bg-card);
  transition: background-color 0.2s ease;
}

.cs-problem:hover {
  background-color: var(--cs-surface);
}

.cs-problem__title {
  font-size: var(--font-size-24);
  font-weight: var(--font-weight-extrabold);
  line-height: 1.4;
  letter-spacing: -0.36px;
  text-transform: capitalize;
}

.cs-problem__text {
  font-size: var(--font-size-18);
  line-height: 1.4;
  letter-spacing: -0.32px;
}

/* --- Comparison table ----------------------------------------------------- */

/* The table is the one block that cannot reflow, so it scrolls in its own
   container instead of forcing the page body sideways. */
.cs-table__scroll {
  border: 1px solid var(--cs-border);
  border-radius: var(--radius-lg);
  overflow-x: auto;
}

.cs-table {
  width: 100%;
  min-width: 900px;
  border-collapse: collapse;
  text-align: left;
}

.cs-table th,
.cs-table td {
  padding-block: 15px;
  padding-inline: 0;
  font-size: var(--font-size-18);
  font-weight: var(--font-weight-regular);
  vertical-align: middle;
}

.cs-table thead th {
  padding: 16px 0;
  border-bottom: 1px solid var(--cs-hairline);
  color: var(--color-text-primary);
  font-weight: var(--font-weight-semibold);
  white-space: nowrap;
}

.cs-table tbody th {
  width: 510px;
  color: var(--cs-text-body);
  font-weight: var(--font-weight-medium);
}

.cs-table tbody tr + tr th,
.cs-table tbody tr + tr td {
  border-top: 1px solid var(--cs-hairline);
}

/* 24px of the 32px design gap comes from the cell padding either side. */
.cs-table th + th,
.cs-table th + td,
.cs-table td + td {
  padding-left: var(--gap-4);
}

.cs-table thead th:first-child,
.cs-table tbody th:first-child {
  padding-left: var(--padding-card-sm);
}

.cs-table thead th:last-child,
.cs-table tbody td:last-child {
  padding-right: var(--padding-card-sm);
}

.cs-pill {
  display: flex;
  align-items: center;
  gap: var(--gap-1);
  min-height: 47.408px;
  padding: 13px;
  border-radius: 12px;
  color: var(--cs-text-body);
  font-size: var(--font-size-18);
  line-height: 1.4;
}

.cs-pill--no {
  border: 1px solid var(--cs-negative);
  background-image: var(--cs-negative-fill);
}

.cs-pill--yes {
  border: 1px solid var(--color-cta);
  background-image: var(--cs-positive-fill);
}

.cs-pill--partial {
  border: 1px solid var(--cs-partial);
  background-image: var(--cs-partial-fill);
}

.cs-pill__icon {
  flex: none;
  width: 24px;
  height: 24px;
}

/* --- Client proof stack --------------------------------------------------- */

/* Named-client rows for a hero aside: name, detail, optional tag chip, and a
   metric on the right. The first row is the lead proof point and gets a solid
   surface + full outline; the rest are translucent with a left rule.
   Promoted here from the F&B hub when the subscription development page
   needed the same stack. */
.cs-proof {
  display: flex;
  width: 538px;
  flex: none;
  flex-direction: column;
  gap: var(--gap-3);
}

.cs-proof__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-2);
  padding: var(--padding-card-sm);
  border: 1.4px solid transparent;
  border-left: 2px solid var(--color-light-blue);
  border-radius: 16px;
  background-color: rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(57px);
  overflow: hidden;
}

.cs-proof__item--lead {
  border: 1.4px solid var(--color-light-blue);
  background-color: var(--cs-surface);
  backdrop-filter: none;
  box-shadow: 0 14px 24px rgba(0, 0, 0, 0.35);
}

.cs-proof__client {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 7px;
}

.cs-proof__name {
  font-size: var(--font-size-18);
  font-weight: var(--font-weight-semibold);
  line-height: 1.4;
}

.cs-proof__detail {
  color: var(--cs-text-body);
  font-size: var(--cs-font-16);
  font-weight: 300;
  line-height: 1.4;
}

.cs-proof__tag {
  align-self: flex-start;
  padding: 4px 8px;
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-lg);
  color: var(--cs-text-body);
  font-size: var(--cs-font-16);
  line-height: 1.4;
  letter-spacing: -0.32px;
}

.cs-proof__metric {
  display: flex;
  flex: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  text-align: center;
}

.cs-proof__value {
  color: var(--color-text-highlight);
  font-size: var(--font-size-18);
  font-weight: var(--font-weight-semibold);
  line-height: 1.4;
}

.cs-proof__unit {
  color: var(--cs-text-body);
  font-size: var(--cs-font-16);
  font-weight: 300;
  line-height: 1.4;
}

.cs-proof__rule {
  width: 100%;
  height: 0;
  margin: 0;
  border: 0;
  border-top: 2px solid var(--cs-border);
}

.cs-proof__note {
  padding: var(--padding-card-sm);
  border-radius: 16px;
  background-color: rgba(131, 206, 220, 0.1);
  font-size: var(--cs-font-16);
  line-height: 1.4;
  letter-spacing: -0.32px;
}

/* --- Hero-card stat row --------------------------------------------------- */

/* Headline numbers inside .cs-hero-card, under a hairline rule. Distinct from
   .cs-case-stats, which is centred and spread across the case-study card: this
   one is left-aligned, sits on the link blue rather than the highlight blue,
   and packs three metrics into the 538px card. Promoted here from the Shopify
   Plus page when the WooCommerce migration page needed the same row. */
.cs-cardrule {
  width: 100%;
  height: 0;
  margin: 0;
  border: 0;
  border-top: 1px solid var(--cs-border);
}

.cs-cardstats {
  display: flex;
  width: 100%;
  gap: var(--gap-4);
}

.cs-cardstat {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--gap-1);
}

.cs-cardstat__value {
  color: var(--color-text-link);
  font-family: var(--font-heading);
  font-size: var(--font-size-32);
  font-weight: var(--font-weight-bold);
  line-height: 1.4;
  text-transform: capitalize;
}

.cs-cardstat__label {
  color: var(--color-text-secondary);
  font-size: var(--font-size-18);
  font-weight: var(--font-weight-medium);
  line-height: 1.4;
}

/* --- Feature card grid ---------------------------------------------------- */

/* A compact card: icon, 18px name, 16px body. Smaller and denser than
   .cs-build-card, which is a two-up card with 24px titles and 18px body.
   Promoted here from the Shopify app development page when the Shopify Plus
   page needed the same card. Pages set their own column count; three-up is
   the default. --center is the app-development page's centred variant; the
   badge is the Plus page's "Plus only" tag. */
.cs-feature-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--gap-3);
}

.cs-feature-grid > li {
  display: flex;
}

.cs-feature-card {
  display: flex;
  width: 100%;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--gap-2);
  padding: var(--padding-card-sm);
  border: 1px solid var(--cs-border-mid);
  border-radius: var(--radius-lg);
  background-color: var(--color-bg);
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.cs-feature-card:hover {
  border-color: var(--color-text-highlight);
  box-shadow: 0 7px 15px rgba(18, 146, 188, 0.4);
}

.cs-feature-card--center {
  align-items: center;
  text-align: center;
}

.cs-feature-card__name {
  font-size: var(--font-size-18);
  font-weight: var(--font-weight-semibold);
  line-height: 1.4;
}

.cs-feature-card__text {
  color: var(--color-text-secondary);
  font-size: var(--cs-font-16);
  font-weight: var(--font-weight-medium);
  line-height: 1.4;
  opacity: 0.8;
}

/* Pushed to the bottom so badges line up across a row of uneven cards. */
.cs-feature-card__badge {
  margin-top: auto;
  padding: 4px 12px;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-lg);
  background-color: var(--color-primary-alpha-10);
  color: var(--color-text-highlight);
  font-size: var(--font-size-14);
  font-weight: var(--font-weight-semibold);
  line-height: 1.4;
}

/* --- Qualifier grid ------------------------------------------------------- */

/* The "is this right for you?" 2x2: four bordered panels that read as one
   block, sharing their inner borders so every divider is one line thick, with
   only the four outer corners rounded. Icon, 24px extrabold title, 18px body.
   Promoted here from the developer listing page when the full-stack specialty
   page needed the same block; the remaining specialty pages use it too. The
   section wrapper stays page-local — only the grid is shared. */
.cs-qualifier__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0;
}

.cs-qualifier__card {
  display: flex;
  min-height: 280px;
  flex-direction: column;
  justify-content: center;
  gap: var(--gap-3);
  padding: var(--padding-card);
  border: 1px solid var(--color-border-subtle);
  background-color: var(--color-bg);
}

/* Collapse the doubled inner borders. */
.cs-qualifier__card:nth-child(2n) {
  border-left: 0;
}

.cs-qualifier__card:nth-child(n + 3) {
  border-top: 0;
}

.cs-qualifier__card:nth-child(1) {
  border-top-left-radius: var(--radius-xl);
}

.cs-qualifier__card:nth-child(2) {
  border-top-right-radius: var(--radius-xl);
}

.cs-qualifier__card:nth-child(3) {
  border-bottom-left-radius: var(--radius-xl);
}

.cs-qualifier__card:nth-child(4) {
  border-bottom-right-radius: var(--radius-xl);
}

.cs-qualifier__icon {
  flex: none;
}

.cs-qualifier__title {
  font-family: var(--font-heading);
  font-size: var(--font-size-24);
  font-weight: var(--font-weight-extrabold);
  line-height: 1.4;
}

.cs-qualifier__text {
  color: var(--color-text-secondary);
  font-size: var(--font-size-18);
  line-height: 1.4;
}

/* Single column below 768: the shared-border bookkeeping above no longer
   applies, so each cell owns all four borders and only the first and last
   corners round. */
@media (max-width: 768px) {
  .cs-qualifier__grid {
    grid-template-columns: 1fr;
  }

  .cs-qualifier__card {
    min-height: 0;
    border: 1px solid var(--color-border-subtle);
    border-radius: 0;
  }

  .cs-qualifier__card + .cs-qualifier__card {
    border-top: 0;
  }

  .cs-qualifier__card:first-child {
    border-top-left-radius: var(--radius-xl);
    border-top-right-radius: var(--radius-xl);
  }

  .cs-qualifier__card:last-child {
    border-bottom-left-radius: var(--radius-xl);
    border-bottom-right-radius: var(--radius-xl);
  }
}

/* --- Build-card grid ------------------------------------------------------ */

.cs-build-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--gap-3);
}

.cs-build-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--gap-3);
  padding: var(--padding-card-sm);
  border: 1px solid var(--cs-border);
  border-radius: var(--radius-xl);
  background-color: var(--color-bg-card);
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.cs-build-card:hover {
  border-color: var(--color-light-blue);
  box-shadow: var(--cs-glow);
}

.cs-build-card__title {
  font-size: var(--font-size-24);
  font-weight: var(--font-weight-extrabold);
  line-height: 1.4;
  letter-spacing: -0.36px;
  text-transform: capitalize;
}

.cs-build-card__text {
  font-size: var(--font-size-18);
  line-height: 1.4;
  letter-spacing: -0.32px;
}

/* --- Case-study card ------------------------------------------------------ */

.cs-case .eyebrow {
  margin-bottom: var(--gap-3);
}

.cs-case-card {
  border: 1px solid var(--cs-border-mid);
  border-radius: var(--radius-xl);
  background-color: var(--cs-surface);
  overflow: hidden;
}

.cs-case-card__head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--gap-2);
  padding: var(--section-40) 48px 33px;
  border-bottom: 1px solid var(--cs-border-mid);
  background-image: linear-gradient(
    168.86deg,
    rgba(0, 174, 239, 0.05) 0%,
    rgba(0, 174, 239, 0) 60%
  );
}

.cs-case-card__kicker {
  color: var(--color-cta);
  font-size: var(--font-size-20);
  font-weight: var(--font-weight-medium);
  line-height: 1.4;
  letter-spacing: -0.32px;
  text-transform: uppercase;
}

.cs-case-card__title {
  font-size: var(--font-size-32);
  font-weight: var(--font-weight-extrabold);
  /* 42px at the 32px desktop size; unitless for the same reason as above. */
  line-height: 1.3125;
  letter-spacing: -0.36px;
  text-transform: capitalize;
}

.cs-case-card__lede {
  font-size: var(--font-size-24);
  line-height: 1.4;
  letter-spacing: -0.32px;
}

.cs-case-card__body {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
}

.cs-case-card__col {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--gap-3);
  padding: var(--section-40) 48px;
}

/* The divider follows the shorter column, so it is drawn on the cell rather
   than as a full-height rule. */
.cs-case-card__col:first-child {
  border-right: 1px solid var(--cs-border-mid);
}

.cs-case-block__label {
  color: var(--color-cta);
  font-family: var(--font-body);
  font-size: var(--font-size-20);
  font-weight: var(--font-weight-medium);
  line-height: 1.4;
  letter-spacing: -0.32px;
  text-transform: uppercase;
}

.cs-case-block__text {
  padding-top: 10px;
  color: var(--cs-text-body);
  font-size: var(--font-size-18);
  line-height: 1.4;
}

/* Some cards list what was built instead of running it as prose; the list
   needs the same label-to-content offset the prose blocks get. */
.cs-case-block .cs-checklist {
  padding-top: 10px;
}

.cs-case-card__rule {
  width: 100%;
  height: 1px;
  margin: 0;
  border: 0;
  background-color: var(--cs-border-mid);
}

/* Headline numbers under a rule inside the case-study card. Not every
   vertical's card carries them — kombucha's does not. */
.cs-case-stats {
  display: flex;
  width: 100%;
  align-items: flex-start;
  justify-content: space-between;
}

.cs-case-stats .cs-stat__label {
  max-width: 121px;
  color: var(--color-text-primary);
  letter-spacing: -0.32px;
}

.cs-case-shot {
  width: 100%;
  border: 1px solid var(--cs-hairline);
  border-radius: var(--radius-lg);
  background-color: var(--cs-surface-inset);
  overflow: hidden;
}

.cs-case-shot img {
  width: 100%;
  height: 344.25px;
  object-fit: cover;
}

.cs-case-card__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-3);
  padding: 25px 48px 24px;
  border-top: 1px solid var(--cs-border-mid);
}

.cs-case-card__note {
  font-size: var(--font-size-18);
  line-height: 1.4;
  letter-spacing: -0.32px;
}

.cs-case-card__foot .btn {
  height: 48px;
  padding-inline: 18px;
  font-family: var(--font-heading);
}

/* --- Why-choose rows ------------------------------------------------------ */

.cs-why {
  border-bottom: 1px solid var(--cs-border);
}

.cs-why__pattern {
  position: absolute;
  top: 6px;
  left: 0;
  width: 100%;
  height: 1144px;
  object-fit: cover;
  opacity: 0.1;
  pointer-events: none;
}

.cs-why-list {
  display: flex;
  flex-direction: column;
  gap: var(--gap-3);
}

/* Icon | title | body — three columns on one row, per the design. */
.cs-why-row {
  display: grid;
  grid-template-columns: 36px 434px 1fr;
  align-items: center;
  gap: var(--gap-3);
  padding: var(--padding-card-sm);
  border: 1px solid var(--cs-border);
  border-radius: var(--radius-lg);
  transition: border-color 0.2s ease, box-shadow 0.2s ease,
    background-color 0.2s ease;
}

.cs-why-row:hover {
  border-color: var(--color-light-blue);
  background-color: var(--cs-surface);
  box-shadow: var(--cs-glow);
}

.cs-why-row__title {
  font-size: var(--font-size-24);
  font-weight: var(--font-weight-semibold);
  line-height: 1.4;
  letter-spacing: -0.36px;
  text-transform: capitalize;
}

.cs-why-row__text {
  font-size: var(--font-size-18);
  line-height: 1.4;
  letter-spacing: -0.32px;
}

.cs-author {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: var(--gap-3);
  padding: 17px 19px 16px;
  border-top: 1px solid var(--cs-hairline);
}

.cs-author__avatar {
  display: flex;
  flex: none;
  width: 50px;
  height: 50px;
  align-items: center;
  justify-content: center;
  border: 1.25px solid var(--cs-avatar-border);
  border-radius: 25px;
  background-color: var(--cs-avatar-fill);
  color: var(--cs-avatar-text);
  font-family: var(--font-heading);
  font-size: var(--font-size-20);
  font-weight: var(--font-weight-extrabold);
  line-height: 32px;
}

.cs-author__name {
  font-family: var(--font-heading);
  font-size: var(--font-size-18);
  font-weight: var(--font-weight-semibold);
  line-height: 1.4;
  letter-spacing: -0.36px;
  text-transform: capitalize;
}

.cs-author__role {
  font-size: var(--cs-font-16);
  line-height: 1.4;
  letter-spacing: -0.32px;
}

/* --- Step timeline -------------------------------------------------------- */

.cs-steps {
  position: relative;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
}

/* The connector runs between the centres of the first and last markers,
   which sit one half-column in from each edge. */
.cs-steps::before {
  content: "";
  position: absolute;
  top: 27px;
  left: 10%;
  right: 10%;
  height: 1px;
  background-color: var(--cs-border-mid);
}

.cs-step {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--gap-2);
  padding-inline: 12px;
  text-align: center;
}

.cs-step__marker {
  display: flex;
  width: 54px;
  height: 54px;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--color-light-blue);
  border-radius: 27px;
  background-color: var(--cs-surface);
  color: var(--color-cta);
  font-family: var(--font-heading);
  font-size: var(--font-size-18);
  font-weight: var(--font-weight-extrabold);
  letter-spacing: -0.36px;
}

.cs-step__title {
  max-width: 199px;
  font-family: var(--font-body);
  font-size: var(--font-size-18);
  font-weight: var(--font-weight-semibold);
  line-height: 1.4;
}

.cs-step__text {
  max-width: 199px;
  color: var(--color-text-secondary);
  font-size: var(--cs-font-16);
  font-weight: var(--font-weight-medium);
  line-height: 1.4;
  opacity: 0.8;
}

/* --- FAQ accordion -------------------------------------------------------- */

.cs-accordion {
  display: flex;
  flex-direction: column;
  gap: var(--gap-3);
}

.cs-accordion__item {
  border: 1px solid var(--cs-border);
  border-radius: 12px;
  overflow: hidden;
  transition: background-color 0.2s ease;
}

.cs-accordion__item.is-open {
  background-color: var(--cs-surface);
}

.cs-accordion__heading {
  margin: 0;
  font-size: inherit;
  font-weight: inherit;
}

.cs-accordion__trigger {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-3);
  padding: var(--gap-2);
  text-align: left;
}

.cs-accordion__question {
  font-family: var(--font-body);
  font-size: var(--font-size-18);
  font-weight: var(--font-weight-semibold);
  line-height: 1.4;
}

.cs-accordion__icon {
  position: relative;
  display: block;
  flex: none;
  width: 36px;
  height: 36px;
}

.cs-accordion__icon img {
  position: absolute;
  inset: 0;
  width: 36px;
  height: 36px;
  transition: opacity 0.2s ease;
}

.cs-accordion__icon-open {
  opacity: 0;
}

.is-open .cs-accordion__icon-closed {
  opacity: 0;
}

.is-open .cs-accordion__icon-open {
  opacity: 1;
}

/* Collapsing via grid rows keeps the panel in normal flow and animates
   cleanly without measuring heights in JS. */
.cs-accordion__panel {
  display: grid;
  grid-template-rows: 0fr;
  visibility: hidden;
  /* Visibility flips instantly on open but waits for the collapse to finish
     on close, so the answer is never hidden while it is still on screen. */
  transition: grid-template-rows 0.25s ease, visibility 0s 0.25s;
}

.cs-accordion__item.is-open .cs-accordion__panel {
  grid-template-rows: 1fr;
  visibility: visible;
  transition: grid-template-rows 0.25s ease, visibility 0s;
}

.cs-accordion__answer {
  overflow: hidden;
  padding: 0 12px 10px;
  font-size: var(--font-size-18);
  line-height: 1.4;
  letter-spacing: -0.32px;
}

/* --- Related-services grid ------------------------------------------------ */

.cs-related-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--gap-3);
}

.cs-related-grid > li {
  display: flex;
}

/* A single related card on a row of its own, full width, below a three-card
   grid (the service link under the industry pages' other verticals). */
.cs-related-grid--single {
  grid-template-columns: 1fr;
  margin-top: var(--gap-3);
}

.cs-related-card {
  display: flex;
  width: 100%;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: var(--gap-2);
  padding: var(--padding-card-sm);
  border: 1px solid var(--cs-border);
  border-radius: var(--radius-lg);
  transition: border-color 0.2s ease, box-shadow 0.2s ease,
    background-color 0.2s ease;
}

.cs-related-card:hover {
  border-color: var(--color-light-blue);
  background-color: var(--cs-surface);
  box-shadow: 0 7px 15px rgba(18, 146, 188, 0.4);
}

.cs-related-card__kicker {
  color: var(--color-cta);
  font-size: var(--font-size-20);
  font-weight: var(--font-weight-medium);
  line-height: 1.4;
  letter-spacing: -0.32px;
  text-transform: uppercase;
}

.cs-related-card__copy {
  display: flex;
  width: 100%;
  flex: 1;
  flex-direction: column;
  gap: var(--gap-2);
}

.cs-related-card__title {
  font-size: var(--font-size-24);
  font-weight: var(--font-weight-semibold);
  line-height: 1.4;
  letter-spacing: -0.36px;
  text-transform: capitalize;
}

.cs-related-card__text {
  color: var(--cs-text-body);
  font-size: var(--font-size-18);
  line-height: 1.4;
  letter-spacing: -0.32px;
}

.cs-related-card__proof {
  font-size: var(--font-size-18);
  line-height: 1.4;
}

.cs-related-card__proof strong {
  font-weight: var(--font-weight-bold);
}

.cs-related-card__more {
  width: 100%;
  padding-top: var(--gap-2);
  border-top: 1px solid var(--cs-border);
  color: var(--color-cta);
  font-size: var(--font-size-18);
  line-height: 1.4;
  letter-spacing: -0.32px;
}

/* --- Final CTA ------------------------------------------------------------ */

.cs-final-cta {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 160px var(--section-120);
  background-color: var(--color-bg);
  overflow: hidden;
}

.cs-final-cta__glow {
  position: absolute;
  bottom: 0;
  left: 50%;
  width: 899px;
  max-width: none;
  transform: translateX(-50%);
  pointer-events: none;
}

.cs-final-cta__inner {
  position: relative;
  z-index: 1;
  display: flex;
  width: 100%;
  max-width: 1204px;
  flex-direction: column;
  align-items: center;
  gap: var(--gap-3);
  text-align: center;
}

.cs-final-cta__copy {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--gap-2);
}

.cs-final-cta__heading {
  max-width: 900px;
  font-size: var(--font-size-64);
  font-weight: var(--font-weight-extrabold);
  line-height: 1.0625;
  text-transform: capitalize;
}

.cs-final-cta__sub {
  max-width: 900px;
  font-size: var(--font-size-20);
  line-height: 1.4;
}

.cs-final-cta .btn {
  height: 48px;
  margin-top: var(--gap-2);
  padding-inline: 18px;
  font-family: var(--font-heading);
}

/* The case-study designs set this headline at the 80px step and keep it in
   sentence case, where the subscription pages use the 64px capitalised step.
   Promoted here when a second case-study page needed it. */
.cs-final-cta__heading--xl {
  max-width: 1204px;
  font-size: var(--font-size-80);
  font-weight: var(--font-weight-bold);
  line-height: 80.8px;
  text-transform: none;
  text-shadow: 0 4px 6px rgba(0, 0, 0, 0.25);
}

/* --------------------------------------------------------------------------
   Case-study detail pages

   Shared by every case-study-<client>.html page. The .cs-hero shell above is
   reused as-is; only the aside's payload differs — these designs mount a bare
   screenshot between the two tilted slabs where the vertical pages mount a
   .cs-hero-card with body copy. Every offset is a ratio of the design's
   538px-wide group, so the slabs stay pinned to the screenshot as it scales
   with the column. Each page sets the six metrics.
   -------------------------------------------------------------------------- */

.cs-hero__aside--shot {
  display: flex;
  align-items: center;
}

.cs-hero-stack {
  position: relative;
  width: 100%;
  padding-block: var(--cs-shot-top) var(--cs-shot-bottom);
}

.cs-hero-stack .cs-hero__slab {
  left: 4.99%;
  width: 88.23%;
  height: var(--cs-slab-height);
}

.cs-hero-stack .cs-hero__slab--top {
  top: var(--cs-slab-top-top);
}

.cs-hero-shot {
  position: relative;
  z-index: 1;
  width: 100%;
  margin: 0;
  aspect-ratio: var(--cs-shot-ratio);
  border-radius: var(--radius-xl);
  overflow: hidden;
  filter: drop-shadow(10px 14px 12px rgba(0, 0, 0, 0.25));
}

.cs-hero-shot img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* --- Project meta band ---------------------------------------------------- */

/* The designs' TrustSignals frame, repurposed as the case-study fact strip:
   fixed 243px columns centred in the page, hairlined top and bottom in
   #404040 rather than the usual subtle border. */
.cs-meta {
  padding: 50px var(--section-120);
  border-top: 1px solid var(--color-text-dark);
  border-bottom: 1px solid var(--color-text-dark);
  background-color: var(--color-bg);
}

.cs-meta__list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--gap-3);
  max-width: var(--content-width);
  margin-inline: auto;
}

.cs-meta__item {
  display: flex;
  width: 243px;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--gap-1);
  text-align: center;
}

/* A value longer than the 243px column — a full URL, say — sizes to its
   content instead of wrapping. The ChiDog design drops the fixed width on
   exactly that one column for this reason. */
.cs-meta__item--wide {
  width: auto;
}

.cs-meta__label {
  font-family: var(--font-heading);
  color: var(--color-text-highlight);
  font-size: var(--font-size-24);
  font-weight: var(--font-weight-bold);
  line-height: 1;
  white-space: nowrap;
}

.cs-meta__value {
  max-width: 211px;
  margin: 0;
  color: var(--color-text-secondary);
  font-size: var(--font-size-18);
  line-height: 1.3;
}

.cs-meta__item--wide .cs-meta__value {
  max-width: none;
}

.cs-meta__value a {
  color: inherit;
  text-decoration: underline;
}

.cs-meta__value a:hover {
  color: var(--color-text-link);
}

/* --- Narrative blocks ----------------------------------------------------- */

/* Challenge / Solution / Outcome / Conclusion share one shell: the .cs-section
   rhythm, a 64px label, then a stack of bordered cards. Each block closes on
   the design's Line 5 — a 2px rule fading up to the CTA blue and back. */
.cs-block__title {
  padding-bottom: var(--section-40);
  color: var(--color-text-primary);
  font-size: var(--font-size-64);
  font-weight: var(--font-weight-semibold);
  line-height: 70.4px;
  text-transform: capitalize;
}

.cs-items {
  display: flex;
  flex-direction: column;
  gap: var(--gap-card-sm);
}

.cs-item {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: var(--padding-card-sm);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-lg);
}

.cs-item__title {
  color: var(--color-text-primary);
  font-family: var(--font-heading);
  font-size: var(--font-size-24);
  font-weight: var(--font-weight-semibold);
  line-height: 1.2;
}

.cs-item__text {
  color: var(--color-text-secondary);
  font-size: var(--font-size-18);
  line-height: 1.45;
}

.cs-item__list {
  margin: 0;
  padding-left: 27px;
  list-style: disc;
  color: var(--color-text-secondary);
  font-size: var(--font-size-18);
  line-height: 1.45;
}

/* Second-level bullets sit at the design's 54px indent. */
.cs-item__list .cs-item__list {
  margin-top: 4px;
}

.cs-item__text a,
.cs-item__list a {
  color: inherit;
  text-decoration: underline;
}

.cs-item__text a:hover,
.cs-item__list a:hover {
  color: var(--color-text-link);
}

.cs-rule {
  width: 100%;
  height: 2px;
  margin: var(--section-40) 0 0;
  border: 0;
  /* Line 5: black → #1292BC at 45% → black, drawn right-to-left in Figma on
     a layer that is then rotated 180°, which lands the peak here. */
  background-image: linear-gradient(
    to right,
    rgba(0, 0, 0, 0),
    var(--color-cta) 45%,
    rgba(0, 0, 0, 0)
  );
}

/* The conclusion leads with 24px paragraphs rather than titled cards. */
.cs-conclusion__copy {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.cs-conclusion__text {
  color: var(--color-text-secondary);
  font-size: var(--font-size-24);
  line-height: 1.4;
}

/* --------------------------------------------------------------------------
   Forms

   First used by contact.html. Shared rather than page-local because the
   treatment is a reusable input language, not one design's layout: a
   translucent CTA-blue plate over a 50px backdrop blur, pill radius, glow
   shadow, and an accent focus ring. Any future quote or booking page wants
   the same set — every .cs-final-cta on the site already points at #contact.
   -------------------------------------------------------------------------- */

.form {
  display: flex;
  width: 100%;
  flex-direction: column;
  align-items: center;
  gap: var(--gap-4);
}

.form__row {
  display: flex;
  width: 100%;
  gap: var(--gap-3);
}

.form__field {
  display: flex;
  flex: 1 0 0;
  min-width: 0;
  width: 100%;
  flex-direction: column;
}

/* The visible label is the placeholder, as drawn. .form__label carries the
   same text for assistive tech and is clipped visually — a placeholder alone
   is not an accessible name. */
.form__label {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.form__input,
.form__textarea {
  width: 100%;
  padding: 17px 25px;
  border: 1px solid var(--color-border-subtle);
  border-radius: 54px;
  background-color: rgba(18, 146, 188, 0.15);
  backdrop-filter: blur(50px);
  box-shadow: 0 8px 27px rgba(0, 0, 0, 0.5);
  color: var(--color-text-primary);
  font-family: var(--font-body);
  font-size: var(--cs-font-16);
  font-weight: var(--font-weight-medium);
  line-height: 1.3;
}

.form__input::placeholder,
.form__textarea::placeholder {
  color: var(--color-border-strong);
  opacity: 1;
}

/* The design demos this state on the first field. */
.form__input:focus-visible,
.form__textarea:focus-visible {
  outline: none;
  border-color: var(--color-text-highlight);
  box-shadow: 0 8px 17px rgba(0, 0, 0, 0.5);
}

.form__textarea {
  min-height: 170px;
  border-radius: var(--radius-xl);
  box-shadow: 0 8px 57px rgba(0, 0, 0, 0.5);
  resize: vertical;
}

/* :invalid matches before the field is ever touched, so the red edge is held
   back until a submit attempt adds .is-validated. */
.form.is-validated .form__input:invalid,
.form.is-validated .form__textarea:invalid {
  border-color: #ef4444;
}

.form__status {
  margin: 0;
  font-size: var(--font-size-18);
  line-height: 1.4;
  text-align: center;
}

.form__status:empty {
  display: none;
}

.form__status--ok {
  color: var(--color-text-highlight);
}

.form__status--error {
  color: #ef4444;
}

.form .btn {
  height: 49px;
  padding-inline: var(--gap-4);
  font-family: var(--font-body);
}

/* --------------------------------------------------------------------------
   Client trust strip

   Promoted out of css/home.css when the About page needed the same marquee.
   Pure CSS — no JS — so it works anywhere the markup is dropped in.
   -------------------------------------------------------------------------- */

.trust {
  /* Component-scoped knobs — the marquee is the only consumer, so these stay
     here rather than in the global token block. */
  --trust-marquee-gap: var(--gap-5);
  --trust-marquee-duration: 32s;
  --trust-marquee-scale: 1;

  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--gap-4);
  padding-block: var(--section-64);
  background-color: var(--color-bg-menu);
  border-bottom: 1px solid var(--color-bg-secondary);
}

.trust__claim {
  color: var(--color-cta);
  font-size: var(--font-size-24);
  font-weight: var(--font-weight-medium);
  line-height: 1;
  text-align: center;
}

/* Marquee viewport — clips the strip that scrolls behind it. */
.trust__list {
  position: relative;
  width: 100%;
  overflow: hidden;
}

/* Each logo is drawn at its own designed size, so the strip scales as a whole
   rather than per-image — that keeps their relative weights intact. zoom (not
   transform) because this has to shrink the laid-out width too, or the loop
   maths below would still be running on desktop dimensions. */
.trust__marquee {
  display: flex;
  width: max-content;
  zoom: var(--trust-marquee-scale);
}

/* The markup repeats the logo set four times. Every group is identical and
   they sit flush end to end, so sliding each one left by exactly its own
   width lands the next group in its place — the loop has no seam. Four
   groups (~1096px each) keep the strip filled up to a ~3288px viewport. */
.trust__track {
  display: flex;
  height: 40px;
  flex: none;
  align-items: center;
  gap: var(--trust-marquee-gap);
  /* Trailing gap so the join between two groups matches the inner spacing. */
  padding-inline-end: var(--trust-marquee-gap);
  animation: trust-marquee-scroll var(--trust-marquee-duration) linear infinite;
}

.trust__list:hover .trust__track,
.trust__list:focus-within .trust__track {
  animation-play-state: paused;
}

@keyframes trust-marquee-scroll {
  from {
    transform: translateX(0);
  }

  to {
    transform: translateX(-100%);
  }
}

/* Stopped outright rather than run at a near-zero duration. The repeated
   groups still overflow the viewport, so the strip stays full. */
@media (prefers-reduced-motion: reduce) {
  .trust__track {
    animation: none;
  }
}

.trust__item {
  display: flex;
  height: 40px;
  flex: none;
  align-items: center;
  justify-content: center;
  mix-blend-mode: luminosity;
}

.trust__item--pair {
  gap: 0;
}

.trust__item--plain {
  mix-blend-mode: normal;
}

.trust__item--wide {
  width: 157px;
}

.trust__logo-kysu {
  width: 109.878px;
  height: 38.423px;
}

.trust__logo-wide {
  width: 157px;
  height: 45px;
  object-fit: contain;
  object-position: bottom;
}

/* Edge mask over the entering/leaving logos. The width tracks the container
   so it stays an edge treatment on small screens — at a fixed 153px the two
   masks together covered 82% of a 375px viewport. The 153px ceiling keeps the
   desktop frame identical to the Figma spec. */
.trust__fade {
  position: absolute;
  top: -10px;
  width: clamp(40px, 12%, 153px);
  height: calc(100% + 20px);
  background-color: rgba(0, 0, 0, 0.2);
  backdrop-filter: blur(7px);
  pointer-events: none;
}

.trust__fade--start {
  left: 0;
}

.trust__fade--end {
  right: 0;
}

@media (max-width: 768px) {
  /* The claim wraps to two lines here, and at line-height 1 they touch. */
  .trust__claim {
    line-height: 1.3;
  }

  .trust {
    --trust-marquee-duration: 24s;
    --trust-marquee-scale: 0.78;
  }
}

@media (max-width: 480px) {
  .trust {
    --trust-marquee-scale: 0.62;
  }
}

/* --------------------------------------------------------------------------
   Capabilities bento
   Heading in the left half of the first row, lead card top-right, then full
   rows of two beneath it, joined by collapsed hairline borders.

   Promoted out of css/home.css when the Solutions page needed the same grid
   for its industries listing. Markup and class names are unchanged, so the
   homepage consumes it exactly as before.

   Heights are min-height, not height. The original fixed 340px plus
   `overflow: hidden` on the card did not fix the lead card overlapping the
   row below it — it hid the symptom, and silently clipped any copy that did
   not fit. Because .cap-card centres its content, that clipping was
   symmetric: the icon lost its top and the last body line disappeared, with
   no scrollbar or ellipsis to show it had happened. The Solutions cards
   carry longer copy than the homepage one-liners, so the boxes have to grow.
   -------------------------------------------------------------------------- */

.capabilities {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: var(--section-100) var(--section-120);
  background-color: var(--color-bg);
  border-bottom: 1px solid var(--color-border-subtle);
  overflow: hidden;
}

.capabilities__bg {
  position: absolute;
  top: 22.95%;
  right: -58.75%;
  bottom: 26.2%;
  left: -30.21%;
  width: auto;
  pointer-events: none;
}

.capabilities__grid {
  position: relative;
  z-index: 1;
  display: flex;
  width: 100%;
  flex-direction: column;
  align-items: flex-start;
}

/* min-height, not height: the rows are column-flex siblings, so a fixed box
   lets a tall child spill out and land on top of the next row. */
.capabilities__row {
  display: flex;
  width: 100%;
  min-height: 340px;
  align-items: stretch;
}

/* The heading is capped at its 457px text width, so it cannot grow into the
   499px slot Figma gives it. space-between hands that leftover to the gap
   instead of parking it after the card, which would leave the lead card
   short of the right edge and out of line with the column beneath it. */
.capabilities__row--lead {
  align-items: center;
  justify-content: space-between;
  gap: var(--section-100);
}

/* Unitless line-height: the old hardcoded 70.4px did not scale with the
   --font-size-64 downshift at 1200px and 768px, so a long heading reached
   five lines inside a 340px row and overlapped the cards below. */
.capabilities__heading {
  flex: 1 0 0;
  min-width: 0;
  max-width: 457px;
  color: var(--color-text-primary);
  font-size: var(--font-size-64);
  font-weight: var(--font-weight-semibold);
  line-height: 1.1;
  text-transform: capitalize;
}

.cap-card {
  display: flex;
  flex: 1 0 0;
  min-width: 0;
  flex-direction: column;
  justify-content: center;
  gap: var(--gap-3);
  padding: var(--padding-card);
  background-color: var(--color-bg-card);
  border: 1px solid var(--color-border-subtle);
  border-bottom: 0;
}

/* Half the grid plus the 1px the collapsed border eats, so the card stays
   aligned with the right-hand column below it at any width. Resolves to
   Figma's 601px on the 1200px desktop grid. */
.cap-card--lead {
  flex: none;
  width: calc(50% + 1px);
  min-height: 340px;
  border-radius: var(--radius-xl) var(--radius-xl) 0 0;
}

.cap-card--round-tl {
  border-radius: var(--radius-xl) 0 0 0;
}

.cap-card--no-left {
  border-left: 0;
}

.cap-card--bottom {
  border-bottom: 1px solid var(--color-border-subtle);
}

.cap-card--round-bl {
  border-radius: 0 0 0 var(--radius-xl);
}

.cap-card--round-br {
  border-radius: 0 0 var(--radius-xl) 0;
}

.cap-card__icon {
  display: flex;
  flex: none;
  width: 36px;
  height: 36px;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

/* Each glyph keeps its designed leaf size inside the shared 36px box. */
.cap-icon--coffee {
  width: 34.86px;
  height: 34.87px;
}

.cap-icon--petfood {
  width: 24.67px;
  height: 35px;
}

.cap-icon--kombucha {
  width: 21.08px;
  height: 33.75px;
}

.cap-icon--wine {
  width: 23.27px;
  height: 36px;
}

.cap-icon--clothing {
  width: 27.93px;
  height: 31.27px;
}

.cap-card__text {
  display: flex;
  width: 100%;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--gap-2);
}

.cap-card__title {
  color: var(--color-text-primary);
  font-size: var(--font-size-32);
  font-weight: var(--font-weight-extrabold);
  line-height: 1.2;
  text-transform: capitalize;
}

.cap-card__body {
  color: var(--color-text-secondary);
  font-size: var(--font-size-24);
  font-weight: var(--font-weight-regular);
  line-height: 1.35;
}

@media (max-width: 1200px) {
  /* Width is handled by the base calc() — only the gap tightens here. */
  .capabilities__row--lead {
    gap: var(--section-40);
  }
}

@media (max-width: 900px) {
  .capabilities__row,
  .capabilities__row--lead {
    min-height: 0;
    flex-direction: column;
    gap: 0;
  }

  .capabilities__heading {
    max-width: none;
    margin-bottom: var(--section-40);
  }

  /* The lead card has to be released explicitly. It is the one card that
     carries its own width and min-height, so without this it stays pinned
     to the desktop box while every other card goes fluid. */
  .cap-card,
  .cap-card--lead {
    width: 100%;
    min-height: 260px;
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-lg);
    margin-bottom: var(--gap-2);
  }
}

/* --------------------------------------------------------------------------
   Carousel chrome
   Arrows, counter and dots for any [data-carousel-scope]. Driven by the
   Carousel prototype in js/main.js, which renders the dots and writes the
   counter from the real slide count — the markup ships an empty <ul> and a
   placeholder count.
   Promoted out of css/home.css when the developer listing page needed the
   same controls. The track itself stays page-local: every page sizes its
   own slides.
   -------------------------------------------------------------------------- */

.carousel-controls {
  display: flex;
  flex: none;
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  gap: 6px;
}

.carousel-controls__arrows {
  display: flex;
  align-items: center;
  gap: var(--gap-2);
}

.carousel-arrow {
  display: flex;
  width: 48px;
  height: 48px;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: opacity 0.2s ease;
}

.carousel-arrow:hover {
  opacity: 0.75;
}

.carousel-arrow:disabled {
  opacity: 0.35;
  cursor: default;
}

.carousel-arrow img {
  width: 48px;
  height: 48px;
}

.carousel-arrow--prev img {
  transform: rotate(-90deg);
}

.carousel-arrow--next img {
  transform: rotate(-90deg) scaleY(-1);
}

.carousel-controls__status {
  display: flex;
  align-items: center;
  gap: var(--gap-2);
}

.carousel-counter {
  display: flex;
  align-items: center;
  gap: 2px;
  color: var(--color-text-secondary);
  font-size: var(--font-size-20);
  font-weight: var(--font-weight-regular);
  line-height: 1;
  white-space: nowrap;
}

.carousel-dots {
  display: flex;
  align-items: center;
  gap: var(--gap-1);
}

/* Rendered by js/main.js as a <button>, one per page of the track. */
.carousel-dot {
  display: block;
  width: 16px;
  height: 8px;
  padding: 0;
  border-radius: 50px;
  background-color: var(--color-bg-secondary);
  transition: background-color 0.2s ease;
}

.carousel-dot.is-active {
  background-color: var(--color-bg-accent);
}

/* --dark inverts the resting dot for use on a lifted surface, where the
   default #242424 would disappear into the panel behind it. */
.carousel-dots--dark .carousel-dot {
  background-color: var(--color-bg);
}

.carousel-dots--dark .carousel-dot.is-active {
  background-color: var(--color-bg-accent);
}

/* ==========================================================================
   10. Subscription landing-page components — responsive
   ========================================================================== */

@media (max-width: 1200px) {
  .cs-hero__inner {
    gap: var(--gap-5);
  }

  .cs-hero__text {
    flex: 1;
    width: auto;
    min-width: 0;
  }

  .cs-hero__aside {
    width: 460px;
  }

  .cs-hero-card,
  .cs-hero__slab {
    width: 100%;
  }

  .cs-hero__slab {
    left: 5%;
    width: 88%;
  }

  .cs-hero__rings,
  .cs-section__curve {
    display: none;
  }

  /* The fixed stat widths plus the label no longer fit on one line, so the
     band wraps and the stats share the row instead. */
  .cs-trust {
    flex-wrap: wrap;
    padding-inline: var(--section-120);
  }

  .cs-trust__stats {
    flex: 1 1 100%;
    flex-wrap: wrap;
    gap: var(--gap-4);
  }

  .cs-trust__stats .cs-stat {
    width: auto;
    flex: 1 1 180px;
  }

  .cs-why-row {
    grid-template-columns: 36px minmax(0, 300px) 1fr;
  }

  .cs-case-card__head,
  .cs-case-card__col,
  .cs-case-card__foot {
    padding-inline: var(--padding-card);
  }

  .cs-final-cta {
    padding-block: 120px;
  }

  .cs-final-cta__heading--xl {
    font-size: var(--font-size-64);
    line-height: 1.0625;
  }

  .cs-block__title {
    font-size: 48px;
    line-height: 1.1;
  }
}

@media (max-width: 1024px) {
  .cs-proof {
    width: 100%;
  }

  .cs-feature-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  /* The hero card stops sitting beside the copy and moves under it. */
  .cs-hero__inner {
    flex-direction: column;
    align-items: stretch;
  }

  .cs-hero__text {
    width: 100%;
  }

  .cs-hero__aside {
    width: 100%;
    min-height: 0;
  }

  .cs-hero-card {
    position: static;
    width: 100%;
  }

  .cs-hero__slab {
    display: none;
  }

  /* The hero is one column here, so the shot group stops holding the aside's
     height and just caps at the design width. */
  .cs-hero-stack {
    max-width: 538px;
  }

  /* Four meta columns leave a lone orphan on a second row at this width. */
  .cs-meta__list {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--section-40) var(--gap-3);
    max-width: 560px;
  }

  .cs-meta__item,
  .cs-meta__item--wide {
    width: 100%;
  }

  /* A URL has no spaces to wrap at. Left alone in a half-width column it
     pushes the whole page wider than the screen (ChiDog's website link did). */
  .cs-meta__value,
  .cs-meta__item--wide .cs-meta__value {
    max-width: 100%;
    overflow-wrap: anywhere;
  }

  .cs-problem-grid,
  .cs-build-grid,
  .cs-related-grid {
    grid-template-columns: 1fr;
  }

  .cs-case-card__body {
    grid-template-columns: 1fr;
  }

  .cs-case-card__col:first-child {
    border-right: 0;
    border-bottom: 1px solid var(--cs-border-mid);
  }

  .cs-why-row {
    grid-template-columns: 36px 1fr;
    align-items: start;
  }

  .cs-why-row__text {
    grid-column: 2;
  }

  .cs-steps {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--section-40) var(--gap-3);
  }

  .cs-steps::before {
    display: none;
  }
}

@media (max-width: 768px) {
  .cs-proof__item {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--gap-2);
  }

  .cs-proof__metric {
    align-items: flex-start;
    text-align: left;
  }

  .cs-cardstats {
    flex-wrap: wrap;
    gap: var(--gap-3);
  }

  .cs-feature-grid {
    grid-template-columns: 1fr;
  }

  .cs-hero {
    padding-block: var(--gap-3) var(--section-80);
  }

  .cs-hero__heading {
    font-size: 2.25rem;
    line-height: 1.15;
  }

  .cs-hero__glow {
    display: none;
  }

  .cs-hero__actions {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
  }

  .cs-hero__actions .btn {
    justify-content: center;
  }

  .cs-checklist,
  .cs-hero__rule {
    width: 100%;
  }

  /* The trust band turns into a stacked list. */
  .cs-trust {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--gap-4);
    padding: var(--section-40) var(--section-120);
  }

  .cs-trust__stats {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--gap-4);
    width: 100%;
  }

  /* flex: none undoes the 1 1 180px these get in the tablet block above.
     There 180px is a column width; once the list turns into a column here,
     the same basis became a 180px height for every stat, leaving a hundred
     pixels of nothing between each one. */
  .cs-trust__stats .cs-stat {
    width: 100%;
    flex: none;
    align-items: flex-start;
    text-align: left;
  }

  .cs-heading {
    gap: var(--gap-2);
  }

  .cs-case-card__title {
    font-size: var(--font-size-24);
    line-height: 1.3;
  }

  .cs-case-shot img {
    height: auto;
  }

  .cs-case-card__foot {
    flex-direction: column;
    align-items: flex-start;
  }

  .cs-case-stats {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--gap-3);
  }

  .cs-case-stats .cs-stat {
    align-items: flex-start;
    text-align: left;
  }

  .cs-case-stats .cs-stat__label {
    max-width: none;
  }

  .cs-why-row {
    grid-template-columns: 1fr;
  }

  .cs-why-row__text {
    grid-column: 1;
  }

  .cs-steps {
    grid-template-columns: 1fr;
  }

  .cs-step {
    align-items: flex-start;
    padding-inline: 0;
    text-align: left;
  }

  .cs-step__title,
  .cs-step__text {
    max-width: none;
  }

  .cs-accordion__trigger {
    gap: var(--gap-2);
  }

  .cs-final-cta {
    padding-block: var(--section-100);
  }

  .cs-final-cta__heading--xl {
    font-size: var(--font-size-32);
    line-height: 1.2;
  }

  /* The 2×2 meta grid set at 1024 carries down unchanged. */
  .cs-meta {
    padding-block: var(--section-40);
  }

  /* Paired fields stack rather than squeeze below the nav breakpoint. */
  .form__row {
    flex-direction: column;
    gap: var(--gap-4);
  }

  .cs-block__title {
    font-size: var(--font-size-32);
    line-height: 1.15;
  }

  .cs-conclusion__text {
    font-size: var(--font-size-20);
  }
}

/* ==========================================================================
   11. Hire-a-developer page components

   Shared by /hire-dedicated-developer/ and its four specialty children
   (full-stack, Shopify, Node.js, React). Written per-page first; a rule-level
   diff of the five stylesheets found the four specialty pages to be ~95%
   identical, so everything used by two or more of them lives here. Two of the
   five now ship no page stylesheet at all.

   Placed after section 10 on purpose. In the static build these rules sat in
   css/<page>.css, which loads after this file, and several of them exist only
   to beat a responsive rule in section 10 — the 4-up grids restate their own
   1200/768 steps for exactly that reason. Moving them above section 10 would
   silently hand those breakpoints back.

   Deliberately NOT promoted onto the existing marker classes: .cs-process and
   .cs-faq are unstyled hooks on the other 10 landing pages, so the tint and
   the rule are modifiers (--tinted, --ruled) rather than additions to the bare
   class. .cs-why needed nothing at all — its existing border-bottom already
   resolves to the same colour, since --cs-border is var(--color-text-dark).
   ========================================================================== */

/* --- Hero: the two-up specialty variant ----------------------------------- */

/* The four specialty heroes are one shot on two rotated slabs, at identical
   geometry — the same five stack measurements css/case-study-chidog.css sets,
   plus the slab pair. All six custom properties are required together: inside
   .cs-hero-stack the slab is declared as `height: var(--cs-slab-height)` and
   `top: var(--cs-slab-top-top)`, so omitting either makes the declaration
   invalid at computed-value time — the height falls back to `auto`, which on
   an empty absolutely-positioned element is zero, and the slabs vanish.
   Expressed as shares of the 448.98px group so the pair keeps framing the shot
   as it scales. */
.cs-hero--specialty {
  /* Bottom slab's lower edge: 229 + 17.51 + 202.463. */
  --cs-hero-aside-h: 448.98px;
  --cs-shot-top: 34.74px;
  --cs-shot-bottom: 17.24px;
  --cs-shot-ratio: 538 / 397;
  --cs-slab-height: 45.09%; /* 202.463 / 448.98 */
  --cs-slab-top-top: 3.9%; /* 17.51 / 448.98 */
  --cs-slab-bottom-top: 54.91%; /* 246.51 / 448.98 */

  padding-block: 177px var(--section-80);
}

/* Figma rotates this glow 87deg and parks it off the left edge. */
.cs-hero--specialty .cs-hero__glow {
  top: 118px;
  left: -172px;
  width: 303px;
}

/* Anchored to the card's centre rather than the shared default, which is tuned
   for the taller case-study heroes. Section 10 already hides the ring stack at
   1200, so only the resting position is set here. */
.cs-hero--specialty .cs-hero__rings {
  top: 300px;
  right: -370px;
}

/* Opt out of the shared heading's capitalize, which would render the designs'
   "for" and "and" as "For" and "And". 60.6/56 as a ratio rather than the raw
   px so it still tracks when section 10 steps the heading down at 768. Same
   pair of overrides as css/about.css:53. Used by all five pages. */
.cs-hero--sentence .cs-hero__heading {
  line-height: 1.082;
  text-transform: none;
}

/* --- Section rules -------------------------------------------------------- */

/* The qualifier section closes on the subtle border; .cs-qualifier__grid above
   is the 2x2 itself. */
.cs-qualifier {
  border-bottom: 1px solid var(--color-border-subtle);
}

.cs-services {
  border-bottom: 1px solid var(--color-text-dark);
}

/* .cs-faq is a bare hook on the subscription pages. Only the hire pages close
   the section on a rule, so it is a modifier. */
.cs-faq--ruled {
  border-bottom: 1px solid var(--color-text-dark);
}

/* Placeholder answers are dimmed and italic so an unfilled panel is obvious in
   the page, not only in the markup. Pairs with data-placeholder-copy. */
.cs-faq__todo {
  color: var(--color-text-muted);
  font-style: italic;
}

/* --- Feature grid: four up ------------------------------------------------ */

/* .cs-feature-grid defaults to three. These designs are four, and the card
   carries a short bullet list instead of a paragraph. */
.cs-feature-grid--4up {
  grid-template-columns: repeat(4, 1fr);
}

.cs-feature-card__list {
  padding-left: 24px;
  color: var(--color-text-secondary);
  font-size: var(--cs-font-16);
  font-weight: var(--font-weight-medium);
  line-height: 1.4;
  list-style: disc;
  opacity: 0.8;
}

/* --- Why rows: the brighter hover ---------------------------------------- */

/* .cs-why-row's 36px / 434px / 1fr grid is already these designs' geometry, so
   the rows are a straight reuse. Its hover resolves to --color-light-blue on
   --cs-surface; these nodes draw the highlight blue on the card-hover grey.
   The shared glow is left alone. */
.cs-why--bright .cs-why-row:hover {
  border-color: var(--color-text-highlight);
  background-color: var(--color-bg-card-hover);
}

/* --- Engagement models --------------------------------------------------- */

/* Three fixed 380px cards, centred. All three carry the highlight border in
   Figma, so here it is a resting style rather than a hover. */
.cs-engagement {
  border-bottom: 1px solid var(--color-text-dark);
}

.cs-engagement__grid {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-3);
}

.cs-engagement__card {
  display: flex;
  width: 380px;
  max-width: 100%;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--gap-2);
  padding: var(--padding-card-sm);
  border: 1.4px solid var(--color-text-highlight);
  border-radius: var(--radius-lg);
  background-color: var(--color-bg);
  box-shadow: 0 7px 5px rgba(18, 146, 188, 0.3);
  text-align: center;
}

.cs-engagement__badge {
  display: flex;
  width: 56px;
  height: 56px;
  flex: none;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background-color: rgba(18, 146, 188, 0.3);
}

.cs-engagement__title {
  font-size: var(--font-size-18);
  font-weight: var(--font-weight-bold);
  line-height: 1.4;
}

.cs-engagement__text {
  color: var(--color-text-secondary);
  font-size: var(--cs-font-16);
  font-weight: var(--font-weight-medium);
  line-height: 1.4;
  opacity: 0.8;
}

/* --- Process: four steps on a tinted band -------------------------------- */

.cs-process--tinted {
  background-color: var(--color-bg-secondary);
}

/* .cs-steps defaults to five. */
.cs-steps--4up {
  grid-template-columns: repeat(4, 1fr);
}

/* The connector runs between the first and last marker centres, which sit one
   half-column in from each edge — an eighth of the row at four up. */
.cs-steps--4up::before {
  left: 12.5%;
  right: 12.5%;
}

/* Figma parks this mark past the right edge, rotated. Decorative, so it is
   allowed to clip against the section's overflow. */
.cs-process__mark {
  position: absolute;
  top: -30px;
  right: -40px;
  z-index: 0;
  transform: rotate(-5.57deg);
  pointer-events: none;
}

/* --- Case-study carousel ------------------------------------------------- */

/* The chrome is the shared .carousel-* set in section 9; the track and the card
   are sized here. .cs-card itself carries no shared rules, so every card rule
   below is scoped to .cs-cases and cannot reach the case-studies page.
   min-height rather than a fixed 700px so a stat row that wraps at narrow
   widths grows the card instead of being clipped by the overflow that rounds
   the corners. */
.cs-cases {
  background-color: var(--color-bg-menu);
  border-bottom: 1px solid var(--color-border-subtle);
}

.cs-cases__header {
  display: flex;
  width: 100%;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--gap-5);
  padding-bottom: var(--section-40);
}

/* 70.4/64 as a ratio so the heading keeps its proportions when --font-size-64
   steps down at 1200 and 768. */
.cs-cases__heading {
  max-width: 711px;
  font-size: var(--font-size-64);
  font-weight: var(--font-weight-semibold);
  line-height: 1.1;
  text-transform: capitalize;
}

.cs-cases__list {
  display: flex;
  width: 100%;
  align-items: stretch;
  gap: var(--gap-3);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}

.cs-cases__list::-webkit-scrollbar {
  display: none;
}

.cs-cases .cs-card {
  display: flex;
  min-height: 700px;
  flex: 0 0 calc((100% - var(--gap-3)) / 2);
  flex-direction: column;
  justify-content: flex-end;
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-xl);
  background-color: var(--color-bg);
  overflow: hidden;
  scroll-snap-align: start;
}

/* The media panel stacks the exported layers in paint order, each filling the
   panel, exactly as the design composites them. */
.cs-cases .cs-card__media {
  position: relative;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

.cs-cases .cs-card__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.cs-cases .cs-card__scrim {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 362px;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.8) 100%);
}

.cs-cases .cs-card__body {
  display: flex;
  flex: none;
  flex-direction: column;
  gap: var(--gap-3);
  padding: var(--padding-card);
  background-color: var(--color-bg);
}

.cs-cases .cs-card__body--raised {
  background-color: var(--color-bg-card-hover);
}

.cs-cases .cs-card__eyebrow {
  color: var(--color-text-link);
  font-family: var(--font-heading);
  font-size: var(--font-size-20);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
}

.cs-cases .cs-card__text {
  display: flex;
  flex-direction: column;
  gap: var(--gap-2);
}

.cs-cases .cs-card__title {
  font-family: var(--font-heading);
  font-size: var(--font-size-32);
  font-weight: var(--font-weight-extrabold);
  line-height: 1.4;
  text-transform: capitalize;
}

.cs-cases .cs-card__desc {
  color: var(--color-text-secondary);
  font-size: var(--font-size-20);
  line-height: 1.4;
}

.cs-cases .cs-card__desc--medium {
  font-weight: var(--font-weight-medium);
}

/* The stat trio uses .cs-cardstats, the in-card row above — not .cs-stats,
   which is defined only in css/home.css. These designs sit the value on the
   highlight blue rather than the component's link blue. */
.cs-cases .cs-cardstats {
  white-space: nowrap;
}

.cs-cases .cs-cardstat__value {
  color: var(--color-text-highlight);
}

/* --- Decorative backdrop ------------------------------------------------- */

/* Figma lays a faint technical-grid image behind two blocks on each specialty
   page at 10%. The file is the same still frame template-parts/why-pattern.php
   ships — the source GIFs are byte-identical — so it is reused rather than
   re-exported. */
.cs-backdrop {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.1;
  pointer-events: none;
}

/* --- Responsive ---------------------------------------------------------- */

/* The headings are not restated at any breakpoint: they are sized in
   --font-size-64, which section 8 already steps to 3rem at 1200 and 2rem
   at 768. */

@media (max-width: 1200px) {
  .cs-feature-grid--4up {
    grid-template-columns: repeat(2, 1fr);
  }

  .cs-hero--specialty {
    padding-block: var(--section-80);
  }
}

@media (max-width: 1024px) {
  .cs-steps--4up {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--gap-5) 0;
  }

  /* The connector only reads across a single row, so it is dropped once the
     steps wrap. */
  .cs-steps--4up::before {
    content: none;
  }

  .cs-process__mark {
    display: none;
  }

  .cs-cases .cs-card {
    flex-basis: 78%;
  }

  .cs-cases__header {
    align-items: flex-start;
    flex-direction: column;
    gap: var(--gap-3);
  }
}

@media (max-width: 768px) {
  .cs-feature-grid--4up {
    grid-template-columns: 1fr;
  }

  .cs-engagement__card {
    width: 100%;
  }

  .cs-cases .cs-card {
    flex-basis: 88%;
    min-height: 0;
  }
}

@media (max-width: 480px) {
  .cs-cases .cs-card {
    flex-basis: 100%;
  }
}