/*
  Echo Digital, plain HTML/CSS/vanilla JS build.

  This file holds every component rule. Every color reference is
  var(--token), defined in theme.css. No literal color values live here,
  so the whole page reads correctly in both themes with zero changes below.

  Section order and layout family, one per section, no family repeated:
   1  Nav          floating pill nav
   2  Hero         asymmetric split, copy left / media card right
   3  Proof        stat triptych over a logo row
   4  Manifesto    full bleed editorial statement on a photographic band
   5  Services     interactive menu with a swapping detail panel
   6  Why Echo     bento grid, six cells, mixed spans
   7  Approach     wide media plate over a stepped horizontal timeline
   8  Partners     continuous marquee (the only marquee on the page)
   9  CTA band     centred full bleed brand band
  10  FAQ          disclosure accordion
  11  Footer       link columns plus an oversized cropped brand mark
*/

/* ============================== Reset ============================== */

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

* {
  margin: 0;
}

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

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

body {
  background: var(--ink);
  color: var(--fg);
  font-family: "Geist", ui-sans-serif, system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  transition: background-color 0.25s ease, color 0.25s ease;
}

h1,
h2,
h3,
p,
ul,
ol,
figure {
  padding: 0;
}

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

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

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

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

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

:focus-visible {
  outline: 2px solid var(--brand-2);
  outline-offset: 3px;
  border-radius: 4px;
}

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

/* ============================== Tokens (structural) ============================== */

:root {
  --radius-panel: 20px;
  --container: 1180px;
  --font-display: "Outfit", ui-sans-serif, system-ui, sans-serif;
}

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: 1rem;
}

@media (min-width: 640px) {
  .container {
    padding-inline: 1.5rem;
  }
}

/* ============================== Grain ============================== */

.grain {
  position: fixed;
  inset: 0;
  z-index: 60;
  pointer-events: none;
  opacity: var(--grain-opacity);
  mix-blend-mode: soft-light;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3'/></filter><rect width='160' height='160' filter='url(%23n)' opacity='0.5'/></svg>");
}

@media (prefers-reduced-transparency: reduce) {
  .grain {
    display: none;
  }
}

/* ============================== Reveal on scroll ============================== */

/*
  Progressive enhancement: without animation-timeline support, content is
  simply visible, never stuck at zero opacity. --stagger nudges where each
  item in a row finishes, so a row cascades instead of arriving as one block.
  Purpose: hierarchy, content arrives in reading order as a section appears.
*/
@keyframes rise-in {
  from {
    opacity: 0;
    transform: translate3d(0, 24px, 0);
  }
  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

@keyframes settle-in {
  from {
    opacity: 0;
    transform: translate3d(0, 40px, 0) scale(0.97);
  }
  to {
    opacity: 1;
    transform: translate3d(0, 0, 0) scale(1);
  }
}

.rise-in {
  animation: rise-in 0.75s cubic-bezier(0.16, 1, 0.3, 1) both;
  animation-delay: var(--delay, 0ms);
}

.settle-in {
  animation: settle-in 0.95s cubic-bezier(0.16, 1, 0.3, 1) both;
  animation-delay: var(--delay, 0ms);
}

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .reveal {
      animation: rise-in linear both;
      animation-timeline: view();
      animation-range: entry 0% cover calc(26% + var(--stagger, 0%));
    }
  }
}

/* ============================== Shared text / accents ============================== */

.grad-text {
  background: var(--grad-text);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.hairline {
  background: var(--grad-text);
  border-radius: 999px;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  border-radius: 999px;
  border: 1px solid var(--ghost-border);
  background: var(--ghost-bg);
  padding: 0.375rem 1rem;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

@media (min-width: 640px) {
  .eyebrow {
    font-size: 12.5px;
    letter-spacing: 0.14em;
  }
}

/* ============================== Buttons ============================== */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  flex-shrink: 0;
  white-space: nowrap;
  border-radius: 999px;
  padding: 0.875rem 1.75rem;
  font-size: 15px;
  font-weight: 600;
  transition: transform 0.2s ease, background-color 0.2s ease, border-color 0.2s ease;
}

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

.btn svg {
  width: 16px;
  height: 16px;
  transition: transform 0.2s ease;
}

.btn:hover svg {
  transform: translate(1px, -1px);
}

.btn-primary {
  background-image: var(--grad-surface);
  color: #fff;
}

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

.btn-ghost {
  border: 1px solid var(--ghost-border);
  background: var(--ghost-bg);
  color: var(--fg);
}

.btn-ghost:hover {
  border-color: var(--ghost-border-hover);
  background: var(--ghost-bg-hover);
}

.btn-white {
  background: #fff;
  color: var(--ink);
}

:root[data-theme="light"] .btn-white {
  color: #191420;
}

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

.btn-sm {
  padding: 0.625rem 1.75rem;
  font-size: 14px;
}

/* ============================== Nav ============================== */

/*
  Floating pill, detached from the viewport edge (reference:
  freerangewebsites.com.au), not flush edge to edge. Fill is --ink at full
  opacity: a solid near-black (dark theme) or near-white (light theme)
  surface, so it stays legible over the hero video behind it regardless of
  what's playing there.
*/
.nav-wrap {
  position: fixed;
  inset-inline: 0;
  top: 0;
  z-index: 50;
  padding: 1rem;
}

@media (min-width: 640px) {
  .nav-wrap {
    padding: 1.25rem 1.5rem;
  }
}

.nav {
  margin-inline: auto;
  max-width: var(--container);
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--ink);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  padding-left: 1.5rem;
  padding-right: 0.75rem;
  transition: box-shadow 0.3s ease;
}

.nav.is-scrolled {
  box-shadow: 0 16px 50px -20px rgb(0 0 0 / 0.35);
}

.nav__logo {
  display: flex;
  align-items: center;
  height: 30px;
  width: auto;
  color: var(--fg);
}

.nav__links {
  display: none;
  align-items: center;
  gap: 2.25rem;
}

@media (min-width: 1024px) {
  .nav__links {
    display: flex;
  }
}

.nav__links a {
  font-size: 16px;
  font-weight: 500;
  color: var(--fg);
  transition: color 0.2s ease;
}

.nav__links a:hover {
  color: var(--muted);
}

.nav__actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.nav__cta-desktop {
  display: none;
}

@media (min-width: 640px) {
  .nav__cta-desktop {
    display: inline-flex;
  }
}

.nav__burger {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 999px;
  border: 1px solid var(--ghost-border);
  color: var(--fg);
}

@media (min-width: 1024px) {
  .nav__burger {
    display: none;
  }
}

.nav__burger svg {
  width: 18px;
  height: 18px;
}

.nav__sheet {
  margin-inline: auto;
  max-width: var(--container);
  overflow: hidden;
  max-height: 0;
  opacity: 0;
  transition: max-height 0.28s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.28s ease;
}

@media (min-width: 1024px) {
  .nav__sheet {
    display: none;
  }
}

.nav__sheet.is-open {
  max-height: 400px;
  opacity: 1;
}

.nav__sheet-inner {
  margin-top: 0.5rem;
  border-radius: var(--radius-panel);
  border: 1px solid var(--line);
  background: var(--ink);
  backdrop-filter: blur(20px);
  padding: 0.5rem;
}

.nav__sheet a {
  display: block;
  border-radius: 999px;
  padding: 0.75rem 1.25rem;
  font-size: 16px;
  font-weight: 500;
  color: var(--fg);
}

.nav__sheet a:hover {
  background: var(--ghost-bg-hover);
}

.nav__sheet-cta {
  padding: 0.5rem;
}

@media (min-width: 640px) {
  .nav__sheet-cta {
    display: none;
  }
}

.nav__sheet-cta .btn {
  width: 100%;
  justify-content: center;
}

/* ============================== Hero ============================== */

/*
  Full bleed photograph, centered content. Like Manifesto below it, this
  section is a deliberate theme lock exception: the photo and its scrim stay
  the same dark-legible treatment in both themes (the text sitting on it is
  fixed light, not theme-driven), while the nav bar above it still follows
  the active theme. See the note on .manifesto for the same reasoning.

  Two video treatments, swapped by data-hero on this element: "original"
  (the footage untouched) and "tint" (the brand gradient blended through it
  as a duotone). Default is original. See js/main.js for the internal
  preview toggle that flips this attribute (REMOVE BEFORE SHIPPING once one
  is chosen, same as the theme toggle).
*/
.hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100dvh;
  padding-top: 6rem;
  text-align: center;
}

.hero__photo {
  position: absolute;
  inset: 0;
  z-index: -3;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
  filter: contrast(1.03) brightness(0.96);
}

/* Duotone overlay: the brand gradient blended through the video. Zero
   opacity by default (the "original" treatment), the tint variant brings it
   up, so switching treatments never needs a second video file. Blend mode
   "color" takes hue/saturation from this layer and luminosity from the
   video underneath, which is why the video itself doesn't need a separate
   desaturation step for the duotone to read cleanly. */
.hero__tint {
  position: absolute;
  inset: 0;
  z-index: -2;
  background-image: var(--grad-surface);
  mix-blend-mode: color;
  opacity: 0;
  transition: opacity 0.4s ease;
}

.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
      180deg,
      rgb(8 6 10 / 0.15) 0%,
      rgb(8 6 10 / 0.12) 32%,
      rgb(8 6 10 / 0.4) 68%,
      rgb(8 6 10 / 0.12) 100%
    ),
    radial-gradient(60% 42% at 50% 38%, rgb(8 6 10 / 0.28), transparent 72%);
}

.hero[data-hero="tint"] .hero__tint {
  opacity: 0.55;
}

.hero__inner {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  max-width: 1040px;
  margin-inline: auto;
  padding-inline: 1.5rem;
}

.hero__title {
  margin-top: 1.5rem;
  max-width: 15ch;
  font-family: var(--font-display);
  font-size: 2.75rem;
  font-weight: 700;
  line-height: 1.04;
  letter-spacing: -0.025em;
  color: #f8f6fa;
  text-shadow: 0 2px 24px rgb(0 0 0 / 0.25);
}

@media (min-width: 640px) {
  .hero__title {
    font-size: 4rem;
  }
}

@media (min-width: 1024px) {
  .hero__title {
    font-size: 4.6rem;
  }
}

/* Echo's real tagline runs long (a full sentence, not a short punchy
   phrase), so it gets its own scale rather than forcing the short-headline
   size down to fit: same weight and letter-spacing, smaller size and a
   wider measure so it settles at two to three lines instead of six. */
.hero__title--long {
  max-width: 26ch;
  font-size: 1.9rem;
}

@media (min-width: 640px) {
  .hero__title--long {
    max-width: 30ch;
    font-size: 2.6rem;
  }
}

@media (min-width: 1024px) {
  .hero__title--long {
    max-width: 34ch;
    font-size: 3.1rem;
  }
}

.hero__subtext {
  margin-top: 1.5rem;
  max-width: 48ch;
  font-size: 17px;
  line-height: 1.7;
  color: rgb(246 242 248 / 0.82);
}

.hero__subtext--long {
  max-width: 64ch;
}

.hero__ctas {
  margin-top: 2.25rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
}

.hero .btn-ghost {
  border-color: rgb(255 255 255 / 0.35);
  background: rgb(255 255 255 / 0.06);
  color: #f8f6fa;
}

.hero .btn-ghost:hover {
  border-color: rgb(255 255 255 / 0.55);
  background: rgb(255 255 255 / 0.12);
}

/* Solid white pill, independent of theme: the eyebrow sits on the video in
   both themes, so it takes a fixed treatment rather than the theme-driven
   tokens the base .eyebrow rule uses when placed on a flat page background. */
.eyebrow--solid {
  border-color: #fff;
  background: #fff;
}

/* ============================== Proof ============================== */

.proof {
  position: relative;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: var(--ink-2);
}

.proof__stats {
  display: grid;
  grid-template-columns: 1fr;
}

@media (min-width: 640px) {
  .proof__stats {
    grid-template-columns: repeat(3, 1fr);
  }
}

.proof__stat {
  padding-block: 2.5rem;
  border-bottom: 1px solid var(--line);
}

@media (min-width: 640px) {
  .proof__stat {
    border-bottom: none;
    padding-inline: 2rem;
    border-left: 1px solid var(--line);
  }
  .proof__stat:first-child {
    padding-left: 0;
    border-left: none;
  }
  .proof__stat:last-child {
    padding-right: 0;
  }
}

.proof__stat-value {
  display: block;
  font-family: var(--font-display);
  font-size: 3rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  background: var(--grad-text);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

@media (min-width: 1024px) {
  .proof__stat-value {
    font-size: 3.75rem;
  }
}

.proof__stat-label {
  display: block;
  margin-top: 0.5rem;
  font-size: 15px;
  color: var(--muted);
}

.proof__logos-row {
  border-top: 1px solid var(--line);
}

.proof__logos-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2rem;
  padding-block-start: 1rem;
  padding-block-end: 2.5rem;
}

@media (min-width: 768px) {
  .proof__logos-inner {
    flex-direction: row;
    align-items: center;
    gap: 3.5rem;
  }
}

.proof__logos-label {
  flex-shrink: 0;
  font-size: 20px;
  margin-right: 2.5rem
}

/* The label above sits in the same flex row as this and never scrolls;
   .marquee/.marquee__track below is the same mechanism the Technology
   partners section uses. flex + min-width: 0 is what lets a flex child mask
   its own overflow correctly, the usual flexbox gotcha otherwise. */
.proof__marquee {
  flex: 1;
  min-width: 0;
  width: 100%;
  margin-top: 0;
}

/* ============================== Manifesto ============================== */

/*
  This section is a deliberate exception to the page theme lock: a full bleed
  photographic band with a dark scrim, in both themes. That is not a light or
  dark mode inversion, it is a contained editorial device (a moody photo
  moment), the same device the hero card and the approach media plate use at
  smaller scale. The page background and every text token around it still
  follow the active theme.
*/
.manifesto {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}

.manifesto__img {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.62) grayscale(1);
}

.manifesto__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    100deg,
    rgb(11 7 16 / 0.88) 0%,
    rgb(11 7 16 / 0.7) 48%,
    rgb(150 30 180 / 0.5) 100%
  );
}

.manifesto__inner {
  padding-block: 7rem;
}

@media (min-width: 1024px) {
  .manifesto__inner {
    padding-block: 10rem;
  }
}

.manifesto__title {
  max-width: 16ch;
  font-family: var(--font-display);
  font-size: 2.25rem;
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: #f6f2f8;
}

@media (min-width: 640px) {
  .manifesto__title {
    font-size: 3rem;
  }
}

@media (min-width: 1024px) {
  .manifesto__title {
    font-size: 3.9rem;
  }
}

.manifesto__body {
  margin-top: 2.5rem;
  display: grid;
  gap: 2rem;
}

@media (min-width: 1024px) {
  .manifesto__body {
    grid-template-columns: 1fr 1fr;
    gap: 4rem;
  }
}

.manifesto__body p {
  font-size: 19px;
  line-height: 1.7;
  color: rgb(246 242 248 / 0.9);
}

.manifesto__body p:last-child {
  font-size: 17px;
  color: rgb(246 242 248 / 0.75);
}

/* ============================== Services ============================== */

.services {
  border-bottom: 1px solid var(--line);
  padding-block: 6rem;
}

@media (min-width: 1024px) {
  .services {
    padding-block: 8rem;
  }
}

.section-title {
  max-width: 18ch;
  font-family: var(--font-display);
  font-size: 2.25rem;
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.02em;
}

@media (min-width: 640px) {
  .section-title {
    font-size: 3rem;
  }
}

.services__layout {
  margin-top: 3.5rem;
  display: grid;
  gap: 2.5rem;
}

/* Mobile-first: hidden by default, the 1024px override below turns it back
   on. This rule must stay ABOVE the @media block, not below it: two rules of
   equal specificity resolve by source order, so a later unconditional rule
   would beat an earlier media-queried one even when the query matches. */
.services__panel-col {
  display: none;
}

@media (min-width: 1024px) {
  .services__layout {
    grid-template-columns: repeat(12, 1fr);
    gap: 4rem;
  }
  .services__list-col {
    grid-column: span 7;
  }
  .services__panel-col {
    grid-column: span 5;
    display: block;
  }
}

.services__list {
  border-top: 1px solid var(--line);
}

.services__row {
  border-bottom: 1px solid var(--line);
}

.services__row-btn {
  display: flex;
  width: 100%;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5rem;
  padding-block: 1.5rem;
  text-align: left;
}

.services__row-title {
  font-family: var(--font-display);
  font-size: 1.7rem;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--fg);
  transition: color 0.2s ease;
}

@media (min-width: 640px) {
  .services__row-title {
    font-size: 2.1rem;
  }
}

.services__row-arrow {
  display: none;
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  color: var(--muted);
  opacity: 0;
  transform: translateX(-8px);
  transition: all 0.2s ease;
}

@media (min-width: 1024px) {
  .services__row-arrow {
    display: block;
  }
  .services__row-title {
    color: var(--muted);
  }
  .services__row.is-active .services__row-title {
    color: var(--fg);
  }
  .services__row:hover .services__row-title {
    color: var(--fg);
  }
}

.services__row.is-active .services__row-arrow {
  color: var(--fg);
  opacity: 1;
  transform: translateX(0);
}

.services__row-detail {
  padding-bottom: 2rem;
}

@media (min-width: 1024px) {
  .services__row-detail {
    display: none;
  }
}

.services__row-detail p {
  max-width: 62ch;
  font-size: 16px;
  line-height: 1.7;
  color: var(--muted);
}

.services__panel {
  position: sticky;
  top: 7rem;
  overflow: hidden;
  border-radius: var(--radius-panel);
  border: 1px solid var(--line);
  background: var(--ink-2);
  padding: 2.25rem;
}

.services__panel-lead {
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.services__panel-body {
  margin-top: 1rem;
  font-size: 16px;
  line-height: 1.7;
  color: var(--muted);
}

.tags {
  margin-top: 1.5rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.tag {
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--ghost-bg);
  padding: 0.375rem 0.875rem;
  font-size: 13px;
  color: var(--muted);
}

/* ============================== Why Echo (bento) ============================== */

.why {
  border-bottom: 1px solid var(--line);
  background: var(--ink-2);
  padding-block: 6rem;
}

@media (min-width: 1024px) {
  .why {
    padding-block: 8rem;
  }
}

.why__grid {
  margin-top: 3.5rem;
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
}

@media (min-width: 768px) {
  .why__grid {
    grid-template-columns: repeat(6, 1fr);
  }
}

.why__cell {
  display: flex;
  height: 100%;
  flex-direction: column;
  overflow: hidden;
  border-radius: var(--radius-panel);
  border: 1px solid var(--line);
  padding: 2rem;
}

.why__cell--wide {
  grid-column: span 1;
  min-height: 260px;
}

@media (min-width: 768px) {
  .why__cell--wide {
    grid-column: span 3;
  }
}

.why__cell--half {
  grid-column: span 1;
  min-height: 240px;
}

@media (min-width: 768px) {
  .why__cell--half {
    grid-column: span 2;
  }
}

.why__cell--brand {
  background-image: var(--grad-surface);
  border-color: rgb(255 255 255 / 0.15);
  color: #fff;
}

.why__cell--dark {
  background: var(--ink-3);
}

.why__cell h3 {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.01em;
}

.why__cell--wide h3 {
  font-size: 1.5rem;
}

.why__cell--half h3 {
  font-size: 1.25rem;
}

.why__cell p {
  margin-top: 1rem;
  font-size: 15px;
  line-height: 1.7;
}

.why__cell--wide p {
  font-size: 16px;
  max-width: 40ch;
}

.why__cell--brand p {
  color: rgb(255 255 255 / 0.85);
}

.why__cell--dark p {
  color: var(--muted);
}

.why__cell--photo {
  position: relative;
  isolation: isolate;
  grid-column: span 1;
  min-height: 240px;
}

@media (min-width: 768px) {
  .why__cell--photo {
    grid-column: span 2;
  }
}

.why__cell--photo img {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.7) grayscale(1);
}

.why__cell--photo::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg, rgb(11 7 16 / 0.8), rgb(11 7 16 / 0.96));
}

.why__cell--photo p {
  color: rgb(246 242 248 / 0.8);
}

.why__cell--band {
  grid-column: span 1;
  gap: 1.5rem;
  border-color: rgb(150 30 180 / 0.4);
  background: linear-gradient(100deg, rgb(150 30 180 / 0.16), rgb(254 0 124 / 0.1));
}

@media (min-width: 768px) {
  .why__cell--band {
    grid-column: span 6;
    flex-direction: row;
    align-items: center;
    gap: 3.5rem;
    padding: 2.5rem;
  }
}

.why__cell--band h3 {
  font-size: 1.5rem;
}

@media (min-width: 768px) {
  .why__cell--band h3 {
    width: 34%;
    flex-shrink: 0;
  }
}

.why__cell--band p {
  font-size: 16px;
   color: var(--muted);
}

@media (min-width: 768px) {
  .why__cell--band p {
    flex: 1;
    font-size: 17px;
    margin-top: 0;
  }
}

/* ============================== Approach ============================== */

.approach {
  border-bottom: 1px solid var(--line);
  padding-block: 6rem;
}

@media (min-width: 1024px) {
  .approach {
    padding-block: 8rem;
  }
}

.approach__media {
  position: relative;
  margin-top: 3rem;
  overflow: hidden;
  border-radius: var(--radius-panel);
  border: 1px solid var(--line);
}

.approach__media img {
  width: 100%;
  height: 220px;
  object-fit: cover;
  object-position: center;
}

@media (min-width: 640px) {
  .approach__media img {
    height: 300px;
  }
}

.approach__media::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    100deg,
    rgb(11 7 16 / 0.62),
    rgb(150 30 180 / 0.42) 58%,
    rgb(254 0 124 / 0.34)
  );
}

.approach__timeline {
  margin-top: 4rem;
  border-top: 1px solid var(--line);
}

@media (min-width: 1024px) {
  .approach__timeline {
    margin-top: 5rem;
  }
}

.approach__steps {
  display: grid;
  grid-template-columns: 1fr;
  gap: 3rem 2.5rem;
  padding-top: 3rem;
}

@media (min-width: 640px) {
  .approach__steps {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1024px) {
  .approach__steps {
    grid-template-columns: repeat(4, 1fr);
  }
  .approach__step:nth-child(even) {
    margin-top: 0rem;
  }
}

.approach__step-tick {
  display: block;
  width: 40px;
  height: 3px;
}

.approach__step h3 {
  margin-top: 1.5rem;
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.approach__step p {
  margin-top: 0.75rem;
  font-size: 15.5px;
  line-height: 1.7;
  color: var(--muted);
}

/* ============================== About us ============================== */

.about {
  border-bottom: 1px solid var(--line);
  background: var(--ink-2);
  padding-block: 6rem;
}

@media (min-width: 1024px) {
  .about {
    padding-block: 8rem;
  }
}

.about__grid {
  margin-top: 3.5rem;
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem 1.5rem;
}

@media (min-width: 640px) {
  .about__grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1024px) {
  .about__grid {
    grid-template-columns: repeat(4, 1fr);
    gap: 1.75rem;
  }
}

/* Static card: photo, name, role, bio, all plainly visible, nothing hidden
   behind hover or a tap. An earlier version revealed the bio as a hover
   overlay on the photo; in practice that made it hard to read, so it's just
   normal flowed text now. */
.about-card__photo {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  border-radius: var(--radius-panel);
  border: 1px solid var(--line);
  background: var(--ink-3);
}

.about-card__photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.about-card__name {
  margin-top: 1.1rem;
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.about-card__role {
  margin-top: 0.25rem;
  font-size: 13.5px;
  color: var(--muted);
}

.about-card__bio {
  margin-top: 0.75rem;
  font-size: 14px;
  line-height: 1.65;
  color: var(--muted);
}

/* ============================== Partners marquee ============================== */

.partners {
  border-bottom: 1px solid var(--line);
  background: var(--ink-2);
  padding-block: 4rem;
}

@media (min-width: 1024px) {
  .partners {
    padding-block: 5rem;
  }
}

.partners__label {
  font-size: 15px;
  color: var(--muted);
}

.marquee {
  margin-top: 1rem;
  overflow: hidden;
  mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
}

.marquee__track {
  display: flex;
  width: max-content;
  align-items: center;
  gap: 4rem;
  padding-right: 4rem;
  animation: marquee-scroll 42s linear infinite;
  will-change: transform;
}

@media (min-width: 640px) {
  .marquee__track {
    gap: 6rem;
    padding-right: 6rem;
  }
}

@keyframes marquee-scroll {
  from {
    transform: translate3d(0, 0, 0);
  }
  to {
    transform: translate3d(-50%, 0, 0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .marquee__track {
    animation: none;
  }
}

/* These are the partners' real brand colors (unlike the monochrome client
   logos in Proof above), so no theme-driven --logo-filter here: inverting a
   colored mark would just produce the wrong colors, not a legible one. */
.marquee__track img {
  width: auto;
}

/* ============================== CTA band ============================== */

.cta-band {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background-image: var(--grad-surface);
}

.cta-band::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(60% 80% at 50% 0%, rgb(255 255 255 / 0.14), transparent 70%);
}

.cta-band__inner {
  max-width: auto;
  margin-inline: auto;
  padding-block: 6rem;
  text-align: center;
}

@media (min-width: 1024px) {
  .cta-band__inner {
    padding-block: 8rem;
  }
}

.cta-band__title {
  font-family: var(--font-display);
  font-size: 2.25rem;
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: #fff;
  width: auto;
}

@media (min-width: 640px) {
  .cta-band__title {
    font-size: 3rem;
  }
}

@media (min-width: 1024px) {
  .cta-band__title {
    font-size: 3.4rem;
  }
}

.cta-band__body {
  margin-top: 1.5rem;
  margin-inline: auto;
  max-width: 46ch;
  font-size: 17px;
  line-height: 1.7;
  color: rgb(255 255 255 / 0.85);
}

.cta-band__inner .btn {
  margin-top: 2.5rem;
}

/* ============================== Testimonials ============================== */

.testimonials {
  border-bottom: 1px solid var(--line);
  background: var(--ink-2);
  padding-block: 6rem;
}

@media (min-width: 1024px) {
  .testimonials {
    padding-block: 8rem;
  }
}

.testimonial-carousel {
  margin-top: 3.5rem;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.testimonial-carousel__track {
  width: 100%;
  max-width: 880px;
}

/* Only the active card takes layout space. Cross-fading two cards of very
   different lengths in place would either clip the long one or leave a gap
   under the short one, so the inactive card is removed from flow instead.

   Side by side rather than everything centred and stacked: a photo big
   enough to actually read as a portrait needs its own column, not a small
   circle floating above the text, and putting it beside the quote instead
   of above it stops the card's height compounding with how long the quote
   runs. Mobile still stacks (see the media query below), there just isn't
   width to spare for two columns under ~700px. */
.testimonial-card {
  display: none;
  border-radius: var(--radius-panel);
  border: 1px solid var(--line);
  background: var(--ink-3);
  padding: 2.25rem 1.75rem;
  text-align: center;
}

@media (min-width: 700px) {
  .testimonial-card {
    /* display stays none here; only .is-active sets it visible below. This
       just pre-sets the grid columns so they're ready the instant a card
       does become active, rather than needing their own breakpoint rule. */
    grid-template-columns: 200px 1fr;
    align-items: center;
    gap: 2.75rem;
    padding: 2.75rem;
    text-align: left;
  }
}

.testimonial-card.is-active {
  display: flex;
  flex-direction: column;
  align-items: center;
  animation: rise-in 0.5s cubic-bezier(0.16, 1, 0.3, 1) both;
}

@media (min-width: 700px) {
  .testimonial-card.is-active {
    display: grid;
  }
}

.testimonial-card__quote {
  width: 30px;
  height: 23px;
  color: var(--brand);
  opacity: 0.55;
}

.testimonial-card__text {
  margin-top: 1rem;
  display: grid;
  gap: 0.85rem;
}

.testimonial-card__text p {
  max-width: 56ch;
  font-size: 16px;
  line-height: 1.65;
  color: var(--fg);
}

.testimonial-card__stars {
  margin-top: 1.25rem;
  display: flex;
  justify-content: center;
  gap: 0.3rem;
  /* One warm gold, used nowhere else on the page: a star rating reads as a
     rating specifically because it's gold, the same convention every
     storefront and review widget uses. Brand purple/pink stars would just
     look like a decoration and lose that meaning. */
  color: #f5b400;
}

@media (min-width: 700px) {
  .testimonial-card__stars {
    justify-content: flex-start;
  }
}

.testimonial-card__stars svg {
  width: 16px;
  height: 16px;
}

.testimonial-card__person {
  display: flex;
  flex-direction: column;
  align-items: center;
}

@media (min-width: 700px) {
  .testimonial-card__person {
    /* Desktop reads the photo column top to bottom first, so it comes
       before .testimonial-card__main in visual order despite following it
       in the DOM (DOM order keeps the quote as the first thing a screen
       reader announces, which matters more than which column looks first). */
    order: -1;
    /* Left-aligned to match the quote column beside it: a centred photo
       next to left-aligned text read as two different alignment systems
       sharing one card. Mobile stays centred, since everything in the
       stacked layout there (photo, name, role, quote) is centred together
       and already consistent with itself. */
    align-items: flex-start;
  }
}

/*
  Portrait rectangle, not a circle: the source photos are the client's old
  circular WordPress avatars, vignetted onto a white square. Circular
  framing at this display size exposed that white padding as a ring around
  the face. Both images are now pre-cropped (see img/testimonials/) to a
  4:5 rectangle that sits entirely inside the original circle, so there is
  real photo content edge to edge and no matting or border trick needed to
  hide anything.
*/
.testimonial-card__photo {
  width: 108px;
  height: 135px;
  border-radius: var(--radius-panel);
  object-fit: cover;
  border: 1px solid var(--line);
}

@media (min-width: 700px) {
  .testimonial-card__photo {
    width: 160px;
    height: 200px;
  }
}

.testimonial-card__name {
  margin-top: 0.85rem;
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.testimonial-card__role {
  margin-top: 0.2rem;
  max-width: 40ch;
  font-size: 13.5px;
  color: var(--muted);
}

.testimonial-carousel__dots {
  margin-top: 2rem;
  display: flex;
  gap: 0.6rem;
}

.testimonial-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--line);
  transition: background-color 0.2s ease, transform 0.2s ease;
}

.testimonial-dot:hover {
  background: var(--ghost-border-hover);
}

.testimonial-dot.is-active {
  background-image: var(--grad-surface);
  transform: scale(1.25);
}

/* ============================== FAQ ============================== */

.faq {
  border-bottom: 1px solid var(--line);
  padding-block: 6rem;
}

@media (min-width: 1024px) {
  .faq {
    padding-block: 8rem;
  }
}

.faq__layout {
  display: grid;
  gap: 3rem;
}

@media (min-width: 1024px) {
  .faq__layout {
    grid-template-columns: repeat(12, 1fr);
    gap: 4rem;
  }
  .faq__heading-col {
    grid-column: span 4;
  }
  .faq__list-col {
    grid-column: span 8;
  }
}

.faq__list {
  border-top: 1px solid var(--line);
}

.faq__item {
  border-bottom: 1px solid var(--line);
}

.faq__q {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
  padding-block: 1.5rem;
  text-align: left;
}

.faq__q-text {
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}

@media (min-width: 640px) {
  .faq__q-text {
    font-size: 1.35rem;
  }
}

.faq__q-icon {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  color: var(--muted);
  transition: transform 0.3s ease, color 0.3s ease;
}

.faq__item.is-open .faq__q-icon {
  transform: rotate(45deg);
  color: var(--fg);
}

.faq__panel {
  overflow: hidden;
  max-height: 0;
  transition: max-height 0.34s cubic-bezier(0.16, 1, 0.3, 1);
}

.faq__item.is-open .faq__panel {
  max-height: 240px;
}

.faq__panel p {
  max-width: 68ch;
  padding-bottom: 1.75rem;
  font-size: 16px;
  line-height: 1.7;
  color: var(--muted);
}

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

/*
  Always dark, in both themes: rather than rewrite every child rule below
  (headings, links, the wordmark) to stop reading the theme tokens, the
  tokens themselves are redeclared here to their fixed dark-theme values.
  Custom properties inherit down the DOM, so every existing var(--fg),
  var(--muted), var(--line) etc. inside .footer picks up these fixed values
  without touching a single child rule. Same trick Manifesto and the hero
  use for their own permanent-dark treatment, just applied at a container
  level instead of per property.
*/
.footer {
  position: relative;
  overflow: hidden;
  padding-top: 5rem;
  background: #0b0710;
  --ink: #0b0710;
  --ink-2: #120c1a;
  --ink-3: #1a1024;
  --fg: #f6f2f8;
  --muted: #a396ad;
  --line: rgb(255 255 255 / 0.1);
  --line-soft: rgb(255 255 255 / 0.08);
  --ghost-border: rgb(255 255 255 / 0.2);
  --ghost-border-hover: rgb(255 255 255 / 0.4);
  --ghost-bg: rgb(255 255 255 / 0.04);
  --ghost-bg-hover: rgb(255 255 255 / 0.08);
}

.footer__top {
  display: grid;
  gap: 3.5rem;
}

@media (min-width: 1024px) {
  .footer__top {
    grid-template-columns: repeat(12, 1fr);
    gap: 2.5rem;
  }
  .footer__brand {
    grid-column: span 4;
  }
  .footer__nav {
    grid-column: span 8;
  }
}

.footer__logo {
  height: 32px;
  width: auto;
  color: var(--fg);
}

.footer__brand p {
  margin-top: 1.5rem;
  max-width: 34ch;
  font-size: 15px;
  line-height: 1.7;
  color: var(--muted);
}

.footer__nav {
  display: grid;
  gap: 2.5rem;
}

@media (min-width: 640px) {
  .footer__nav {
    grid-template-columns: repeat(3, 1fr);
  }
}

.footer__col-heading {
  font-size: 15px;
  font-weight: 600;
  color: var(--fg);
}

.footer__col ul {
  margin-top: 1rem;
  display: grid;
  gap: 0.75rem;
}

.footer__col a {
  font-size: 15px;
  color: var(--muted);
  transition: color 0.2s ease;
}

.footer__col a:hover {
  color: var(--fg);
}

.footer__bottom {
  margin-top: 4rem;
  display: grid;
  gap: 2.5rem;
  border-top: 1px solid var(--line);
  padding-block: 2.5rem;
}

@media (min-width: 640px) {
  .footer__bottom {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1024px) {
  .footer__bottom {
    grid-template-columns: repeat(3, 1fr);
  }
}

.footer__bottom h4 {
  font-size: 15px;
  font-weight: 600;
  color: var(--fg);
}

.footer__bottom address,
.footer__bottom ul {
  margin-top: 0.75rem;
  font-size: 15px;
  font-style: normal;
  line-height: 1.7;
  color: var(--muted);
}

.footer__bottom address span {
  display: block;
}

.footer__bottom ul li {
  margin-bottom: 0.5rem;
}

.footer__legal {
  font-size: 15px;
  color: var(--muted);
}

.footer__legal p + p {
  margin-top: 0.5rem;
}

.footer__credit {
  margin-top: 2.5rem;
  padding-top: 2rem;
  border-top: 1px solid var(--line);
  font-size: 14px;
  color: var(--muted);
}

.footer__credit a {
  color: var(--fg);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--line);
  transition: text-decoration-color 0.2s ease;
}

.footer__credit a:hover {
  text-decoration-color: var(--fg);
}

.footer__credit-heart {
  color: #fe4d7a;
}

/*
  Oversized wordmark, shown in full rather than cropped: the full cap height
  of every letter is visible, nothing clipped top or bottom. Sized in vw so
  it scales with the viewport the same way the cropped version used to.

  Set in the display face rather than the logo's own vector letterforms, in
  both versions of this treatment: the ring monogram is not a wordmark, and
  even at full height its own lightweight lettering goes spindly blown up
  this large. See the git history on this file for the cropped version this
  replaced, if it's ever wanted back.

  The gradient is literal white at the top fading to black at the bottom,
  which is the same near-black as the footer's own background (#0b0710 vs
  #000000, close enough that the letters read as dissolving into the footer
  rather than being cut off by a hard edge.
*/
.footer__wordmark-wrap {
  margin-top: 2.5rem;
  padding: 0 1rem 1.5rem;
}

@media (min-width: 640px) {
  .footer__wordmark-wrap {
    padding-inline: 1.5rem;
  }
}

.footer__wordmark {
  display: block;
  font-family: var(--font-display);
  font-size: 14.6vw;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.055em;
  white-space: nowrap;
  background-image: linear-gradient(180deg, #ffffff 0%, #000000 90%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

@media (min-width: 640px) {
  .footer__wordmark {
    font-size: 15.4vw;
  }
}

/* ============================== Internal theme toggle (dev tool) ============================== */

/*
  Not part of the shipped site chrome. See the REMOVE BEFORE SHIPPING comment
  in index.html and js/main.js for how to take this out once a theme is
  chosen.
*/
.theme-toggle {
  position: fixed;
  bottom: 1.25rem;
  left: 1.25rem;
  z-index: 70;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  max-width: calc(100vw - 2.5rem);
  border-radius: 999px;
  border: 1px dashed rgb(255 176 32 / 0.6);
  background: rgb(20 16 10 / 0.9);
  backdrop-filter: blur(10px);
  padding: 0.5rem 0.5rem 0.5rem 0.875rem;
  font-size: 12px;
  color: #ffd9a0;
}

.theme-toggle__sep {
  width: 1px;
  height: 16px;
  background: rgb(255 176 32 / 0.35);
}

.theme-toggle button {
  border-radius: 999px;
  padding: 0.375rem 0.75rem;
  font-size: 12px;
  font-weight: 600;
  background: rgb(255 176 32 / 0.15);
  color: #ffd9a0;
}

.theme-toggle button.is-active {
  background: #ffb020;
  color: #201406;
}
