/* ==========================================================================
   Ewan Lumsden — Design portfolio
   Foundations: fonts, design tokens, reset, base typography
   ========================================================================== */

/* --- Self-hosted Poppins ------------------------------------------------- */

@font-face {
  font-family: "Poppins";
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url("/fonts/poppins/poppins-300.woff2") format("woff2");
}

@font-face {
  font-family: "Poppins";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/poppins/poppins-400.woff2") format("woff2");
}

@font-face {
  font-family: "Poppins";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/fonts/poppins/poppins-500.woff2") format("woff2");
}

@font-face {
  font-family: "Poppins";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/fonts/poppins/poppins-600.woff2") format("woff2");
}

@font-face {
  font-family: "Poppins";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/fonts/poppins/poppins-700.woff2") format("woff2");
}

/* --- Design tokens --------------------------------------------------------
   Breakpoints (referenced in media queries, cannot live in custom props):
   sm: 480px   md: 768px   lg: 1024px   xl: 1280px
   ------------------------------------------------------------------------ */

:root {
  /* Brand colours */
  --color-turquoise: #3dceb2;
  --color-turquoise-dark: #2fa98f;
  --color-turquoise-button: #3ac1ab;
  --color-turquoise-button-dark: #2e9a89;
  --color-blue: #2d5a7a;
  --color-blue-dark: #234459;
  --color-deep: #10202c;

  /* Neutrals (cool-tinted to sit with the brand blue) */
  --color-ink: #101820;
  --color-muted: #5c7182;
  --color-paper: #f7f9fa;
  --color-white: #ffffff;
  --color-border: #e2e8ec;

  /* Text/background pairings are contrast-checked — see notes below.
     Turquoise fails as text on light backgrounds (1.97:1) and is for
     accents, buttons (with ink text) and decorative use only. */

  /* Typography */
  --font-base: "Poppins", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --text-xs: 0.75rem;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.375rem;
  --text-2xl: 1.75rem;
  --text-3xl: 2.25rem;
  --text-4xl: 2.75rem;
  --text-5xl: 3.5rem;
  --leading-tight: 1.15;
  --leading-base: 1.6;

  /* Spacing scale (8px baseline) */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;
  --space-9: 6rem;
  --space-10: 8rem;

  /* Layout */
  --container-max: 75rem; /* 1200px */
  --container-padding: var(--space-4);

  /* Surface */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 16px;
  --shadow-sm: 0 1px 2px rgba(16, 24, 32, 0.06);
  --shadow-md: 0 8px 24px rgba(16, 24, 32, 0.08);

  /* Motion */
  --transition-fast: 150ms ease;
  --transition-base: 250ms ease;

  /* Reveal footer (kept in sync with the footer's real height by JS;
     this is just a reasonable fallback before that runs) */
  --footer-height: 420px;
}

@media (min-width: 768px) {
  :root {
    --container-padding: var(--space-6);
  }
}

/* --- Reset ---------------------------------------------------------------- */

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

* {
  margin: 0;
}

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

body {
  min-height: 100vh;
  line-height: var(--leading-base);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: none;
  cursor: pointer;
}

p,
h1,
h2,
h3,
h4 {
  overflow-wrap: break-word;
}

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

/* --- Base typography -------------------------------------------------------- */

body {
  font-family: var(--font-base);
  font-weight: 400;
  font-size: var(--text-base);
  color: var(--color-ink);
  background-color: var(--color-paper);
}

h1,
h2,
h3,
h4 {
  font-weight: 600;
  line-height: var(--leading-tight);
}

h1 {
  font-size: var(--text-4xl);
}

h2 {
  font-size: var(--text-3xl);
}

h3 {
  font-size: var(--text-2xl);
}

h4 {
  font-size: var(--text-lg);
}

@media (min-width: 768px) {
  h1 {
    font-size: var(--text-5xl);
  }

  h2 {
    font-size: var(--text-4xl);
  }
}

/* --- Layout helpers ------------------------------------------------------- */

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

/* --- Accessibility ---------------------------------------------------------- */

.skip-link {
  position: absolute;
  left: var(--space-3);
  top: -3rem;
  z-index: 100;
  padding: var(--space-3) var(--space-4);
  background-color: var(--color-blue);
  color: var(--color-white);
  border-radius: var(--radius-sm);
  transition: top var(--transition-fast);
}

.skip-link:focus {
  top: var(--space-3);
}

.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;
}

:focus-visible {
  outline: 2px solid var(--color-blue);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

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

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

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

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-md);
  font-weight: 600;
  font-size: var(--text-sm);
  line-height: var(--leading-tight);
  text-align: center;
  transition: background-color var(--transition-fast), color var(--transition-fast),
    border-color var(--transition-fast), transform var(--transition-fast);
}

.button--primary {
  background-color: var(--color-turquoise-button);
  color: var(--color-white);
}

.button--primary:hover {
  background-color: var(--color-turquoise-button-dark);
}

.button--secondary {
  background-color: transparent;
  color: var(--color-blue);
  border: 2px solid var(--color-blue);
  padding-block: calc(var(--space-3) - 2px);
}

.button--secondary:hover {
  background-color: var(--color-blue);
  color: var(--color-white);
}

@media (prefers-reduced-motion: no-preference) {
  .button:active {
    transform: scale(0.97);
  }
}

/* ==========================================================================
   Site header / primary navigation
   ========================================================================== */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background-color: var(--color-white);
  border-bottom: 1px solid var(--color-border);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-block: var(--space-4);
}

.site-logo {
  display: flex;
  align-items: center;
}

.site-logo img {
  height: 36px;
  width: auto;
}

.site-nav {
  display: flex;
  align-items: center;
}

.site-nav__list {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  list-style: none;
  padding: 0;
}

.site-nav__list a:not(.button) {
  font-weight: 500;
  color: var(--color-ink);
  padding-block: var(--space-2);
  border-bottom: 2px solid transparent;
  transition: border-color var(--transition-fast), color var(--transition-fast);
}

.site-nav__list a:not(.button):hover {
  color: var(--color-blue);
  border-bottom-color: var(--color-turquoise);
}

.nav-toggle {
  display: none;
  position: relative;
  width: 2.75rem;
  height: 2.75rem;
}

.nav-toggle__bar,
.nav-toggle__bar::before,
.nav-toggle__bar::after {
  position: absolute;
  left: 50%;
  width: 1.5rem;
  height: 2px;
  background-color: var(--color-ink);
  transform: translateX(-50%);
  transition: transform var(--transition-fast), opacity var(--transition-fast);
}

.nav-toggle__bar {
  top: 50%;
  margin-top: -1px;
}

.nav-toggle__bar::before {
  content: "";
  top: -0.5rem;
  left: 0;
  transform: none;
}

.nav-toggle__bar::after {
  content: "";
  top: 0.5rem;
  left: 0;
  transform: none;
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bar {
  background-color: transparent;
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bar::before {
  top: 0;
  transform: rotate(45deg);
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bar::after {
  top: 0;
  transform: rotate(-45deg);
}

@media (max-width: 767px) {
  .nav-toggle {
    display: block;
  }

  .site-nav__list {
    position: absolute;
    inset-inline: 0;
    top: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background-color: var(--color-white);
    border-bottom: 1px solid var(--color-border);
    box-shadow: var(--shadow-md);
    padding: var(--space-4) var(--container-padding) var(--space-6);
    transform: translateY(-8px);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: transform var(--transition-base), opacity var(--transition-base),
      visibility var(--transition-base);
  }

  .site-nav__list.is-open {
    transform: translateY(0);
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
  }

  .site-nav__list li {
    border-bottom: 1px solid var(--color-border);
  }

  .site-nav__list li:last-child {
    border-bottom: none;
    padding-top: var(--space-4);
  }

  .site-nav__list a:not(.button) {
    display: block;
    padding-block: var(--space-4);
  }
}

/* ==========================================================================
   Site wrapper + reveal footer
   The footer is fixed to the bottom of the viewport (removed from normal
   flow), sitting behind .site-wrapper (opaque, higher z-index). A spacer
   the same height as the footer sits at the end of .site-wrapper to
   reserve scroll room for it. As the wrapper's own tail scrolls past,
   there's nothing left to cover the footer's fixed position, so it's
   gradually uncovered — it appears to slide up from behind the page.
   The footer's real height is kept in sync with --footer-height by JS.
   ========================================================================== */

.site-wrapper {
  position: relative;
  z-index: 1;
  background-color: var(--color-paper);
}

.footer-spacer {
  height: var(--footer-height);
}

/* ==========================================================================
   Site footer
   ========================================================================== */

.site-footer {
  position: fixed;
  bottom: 0;
  left: 0;
  z-index: 0;
  width: 100%;
  background-color: var(--color-deep);
  color: var(--color-white);
  padding-block: var(--space-8) var(--space-5);
}

.site-footer__inner {
  display: grid;
  gap: var(--space-7);
}

@media (min-width: 640px) {
  .site-footer__inner {
    grid-template-columns: 1fr 1fr;
  }
}

@media (min-width: 1024px) {
  .site-footer__inner {
    grid-template-columns: 1.4fr 1fr 1fr 1fr;
  }
}

.site-footer__brand p {
  margin-top: var(--space-4);
  max-width: 18rem;
  color: #c9d6dd;
  font-size: var(--text-sm);
}

.site-footer__col h3 {
  margin-bottom: var(--space-4);
  font-size: var(--text-lg);
}

.site-footer__col ul {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  list-style: none;
  padding: 0;
}

.site-footer__links li {
  position: relative;
  padding-left: var(--space-4);
}

.site-footer__links li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background-color: var(--color-turquoise);
}

.site-footer__col a {
  color: #c9d6dd;
  font-size: var(--text-sm);
  transition: color var(--transition-fast);
}

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

.site-footer__icon-list li a {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.site-footer__icon-list svg {
  flex-shrink: 0;
  color: var(--color-turquoise);
}

.site-footer__email {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  color: #c9d6dd;
  font-size: var(--text-sm);
  transition: color var(--transition-fast);
}

.site-footer__email:hover {
  color: var(--color-turquoise);
}

.site-footer__email svg {
  flex-shrink: 0;
  color: var(--color-turquoise);
}

.site-footer__legal {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  margin-top: var(--space-7);
  padding-top: var(--space-5);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  text-align: center;
}

.site-footer__legal p,
.site-footer__legal a {
  color: #8ca0af;
  font-size: var(--text-xs);
  transition: color var(--transition-fast);
}

.site-footer__legal a:hover {
  color: var(--color-turquoise);
}

/* ==========================================================================
   Sections, cards, placeholder media
   ========================================================================== */

.section {
  padding-block: var(--space-9);
}

.section--muted {
  background-color: var(--color-white);
}

.section-heading {
  max-width: 40rem;
  margin-bottom: var(--space-7);
}

.section-heading p {
  margin-top: var(--space-3);
  color: var(--color-muted);
}

/* ==========================================================================
   Trust section
   Left-aligned statement on a plain white background; the dotted
   world map is confined to the right-hand side and bleeds to the
   true edge of the viewport, with a white fade on its inner edge so
   it blends into the text side rather than reading as a hard crop.
   ========================================================================== */

.trust-section {
  position: relative;
  overflow: hidden;
  background-color: var(--color-white);
  padding-block: var(--space-9);
  text-align: left;
}

.trust-section__map-wrap {
  position: absolute;
  top: 50%;
  right: 0;
  z-index: 0;
  display: none;
  width: 50%;
  aspect-ratio: 720 / 607;
  transform: translateY(-50%);
}

@media (min-width: 1024px) {
  /* A fixed min-height so the (fixed-width) text column always has
     room, independent of the map. The map-wrap's own aspect-ratio
     (above) is what keeps object-fit: cover showing the same slice
     of the image at every viewport width — previously its height
     came from inset:0 against the section, and since the section's
     text-driven height didn't scale with the map's viewport-relative
     width, the crop (and the pings pinned to it) drifted at
     different widths/zoom levels. */
  .trust-section {
    min-height: 38rem;
  }

  .trust-section__map-wrap {
    display: block;
  }
}

.trust-section__map-wrap::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(to right, var(--color-white) 0%, rgba(255, 255, 255, 0) 35%);
}

.trust-section__map {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: right center;
  opacity: 0.4;
}

.trust-section__content {
  position: relative;
  z-index: 2;
  max-width: 28rem;
}

.trust-section__content p {
  margin-top: var(--space-4);
  color: var(--color-muted);
}

.trust-section__ping {
  position: absolute;
  z-index: 2;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: var(--color-turquoise-dark);
}

.trust-section__ping::before {
  content: "";
  position: absolute;
  inset: -8px;
  border-radius: 50%;
  background-color: var(--color-turquoise);
  opacity: 0.55;
  animation: trust-ping 2.6s cubic-bezier(0, 0, 0.2, 1) infinite;
}

/* Positioned within the map area (which now only occupies the section's
   right half) and matched to actual dot clusters in globe.jpg as
   rendered, since object-fit: cover crops the source image and raw
   file coordinates wouldn't line up with what's on screen. */

.trust-section__ping--1 {
  left: 29%;
  top: 42%;
}
.trust-section__ping--1::before {
  animation-delay: 0s;
}

.trust-section__ping--2 {
  left: 45%;
  top: 39%;
}
.trust-section__ping--2::before {
  animation-delay: -0.5s;
}

.trust-section__ping--3 {
  left: 50%;
  top: 40%;
}
.trust-section__ping--3::before {
  animation-delay: -1s;
}

.trust-section__ping--5 {
  left: 10%;
  top: 68%;
}
.trust-section__ping--5::before {
  animation-delay: -2s;
}

.trust-section__ping--6 {
  left: 82%;
  top: 68%;
}
.trust-section__ping--6::before {
  animation-delay: -2.4s;
}

@keyframes trust-ping {
  0% {
    transform: scale(0.6);
    opacity: 0.6;
  }
  75%,
  100% {
    transform: scale(2.4);
    opacity: 0;
  }
}

.card {
  background-color: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  box-shadow: var(--shadow-sm);
  transition: transform var(--transition-base), box-shadow var(--transition-base);
}

a.card:hover,
a.card:focus-visible {
  transform: translateY(-4px);
  box-shadow: var(--shadow-md);
}

.card h3 {
  margin-top: var(--space-4);
}

.card p {
  margin-top: var(--space-2);
  color: var(--color-muted);
  font-size: var(--text-sm);
}

.card-grid {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: repeat(auto-fit, minmax(15.5rem, 1fr));
}

/* ==========================================================================
   Service cards
   Default: full-bleed image/gradient with a scrimmed label. On hover/focus,
   an inset panel scales and fades in over it with an icon, heading, short
   copy and a decorative "learn more" affordance. The whole card is a single
   link — the reveal panel duplicates content for sighted hover users only
   and is hidden from assistive tech.
   ========================================================================== */

.service-grid {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
}

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

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

.service-grid--quad {
  grid-template-columns: 1fr;
}

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

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

/* Quad cards are narrower than the 3-up homepage grid, so the reveal
   panel needs a taller box and tighter chrome to fit its content
   without clipping. */
.service-grid--quad .service-card {
  aspect-ratio: 4 / 5;
}

.service-grid--quad .service-card__label {
  font-size: var(--text-lg);
}

.service-grid--quad .service-card__reveal {
  inset: var(--space-4);
  padding: var(--space-5);
  gap: var(--space-2);
}

.service-grid--quad .service-card__reveal > svg {
  width: 32px;
  height: 32px;
}

.service-grid--quad .service-card__reveal-heading {
  font-size: var(--text-base);
}

.service-grid--quad .service-card__reveal-cta {
  width: 2.25rem;
  height: 2.25rem;
  margin-top: 0;
}

.service-card {
  position: relative;
  display: block;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  border-radius: var(--radius-lg);
  color: var(--color-white);
  isolation: isolate;
}

.service-card__image {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 600ms cubic-bezier(0.22, 1, 0.36, 1);
}

.service-card:hover .service-card__image,
.service-card:focus-visible .service-card__image {
  transform: scale(1.07);
}

.service-card__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(to top, rgba(16, 24, 32, 0.8) 0%, rgba(16, 24, 32, 0.15) 55%, transparent 75%);
}

.service-card__label {
  position: absolute;
  z-index: 2;
  inset-inline: 0;
  bottom: var(--space-6);
  margin: 0;
  text-align: center;
  font-size: var(--text-xl);
  transition: opacity 250ms ease, transform 250ms ease;
}

.service-card:hover .service-card__label,
.service-card:focus-visible .service-card__label {
  opacity: 0;
  transform: translateY(10px);
}

.service-card__reveal {
  position: absolute;
  z-index: 3;
  inset: var(--space-5);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-6);
  border-radius: var(--radius-lg);
  background-color: var(--color-turquoise);
  color: var(--color-ink);
  text-align: center;
  box-shadow: var(--shadow-md);
  opacity: 0;
  transform: scale(0.9) translateY(14px);
  transition: opacity 400ms cubic-bezier(0.22, 1, 0.36, 1), transform 400ms cubic-bezier(0.22, 1, 0.36, 1);
}

.service-card__reveal > svg {
  flex-shrink: 0;
}

.service-card:hover .service-card__reveal,
.service-card:focus-visible .service-card__reveal {
  opacity: 1;
  transform: scale(1) translateY(0);
}

.service-card__reveal-heading {
  margin: 0;
  font-size: var(--text-lg);
}

.service-card__reveal-text {
  font-size: var(--text-sm);
  color: var(--color-blue-dark);
}

.service-card__reveal-cta {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  margin-top: var(--space-2);
  border-radius: 50%;
  background-color: var(--color-ink);
  color: var(--color-white);
  transition: transform 250ms ease;
}

.service-card:hover .service-card__reveal-cta,
.service-card:focus-visible .service-card__reveal-cta {
  transform: scale(1.08);
}

/* ==========================================================================
   Point cards
   A grid of cards, each carrying a large decorative index numeral
   behind an icon/heading/sentence — a lighter-weight cousin of the
   service cards, reused for page-level "reasons/features" lists
   (homepage-agnostic: used on both the graphic and web design pages).
   ========================================================================== */

.point-grid {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
}

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

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

.point-card {
  position: relative;
  overflow: hidden;
  padding: var(--space-6);
  background-color: var(--color-white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  transition: transform 250ms ease, box-shadow 250ms ease;
}

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

.point-card__index {
  position: absolute;
  top: var(--space-2);
  right: var(--space-5);
  z-index: 0;
  font-size: 4.5rem;
  font-weight: 700;
  line-height: 1;
  color: var(--color-border);
  user-select: none;
}

.point-card__icon {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3.5rem;
  height: 3.5rem;
  margin-bottom: var(--space-4);
  border-radius: 50%;
  background-color: var(--color-turquoise);
  color: var(--color-ink);
}

.point-card__title {
  position: relative;
  z-index: 1;
  margin: 0 0 var(--space-2);
  font-size: var(--text-lg);
}

.point-card__text {
  position: relative;
  z-index: 1;
  margin: 0;
  color: var(--color-muted);
  font-size: var(--text-sm);
}

/* ==========================================================================
   Featured projects
   A row of image tiles; the image itself is the resting state, and
   hovering zooms the image in while a dark overlay scales/fades in a
   project name and a "View Website" link over the top.
   ========================================================================== */

.portfolio-grid {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
}

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

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

  .portfolio-grid--triple {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* Carousel variant: a horizontally scrolling, snap-aligned track with
   arrow buttons instead of a static grid — lets a section show more
   items than fit on screen at once. */

.portfolio-carousel {
  position: relative;
  padding-inline: 3.25rem;
}

.portfolio-carousel__track {
  display: flex;
  gap: var(--space-6);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.portfolio-carousel__track::-webkit-scrollbar {
  display: none;
}

.portfolio-carousel__track .portfolio-card {
  flex: 0 0 100%;
  scroll-snap-align: start;
}

@media (min-width: 640px) {
  .portfolio-carousel__track .portfolio-card {
    flex-basis: calc((100% - var(--space-6)) / 2);
  }
}

@media (min-width: 1024px) {
  .portfolio-carousel__track .portfolio-card {
    flex-basis: calc((100% - 2 * var(--space-6)) / 3);
  }
}

.portfolio-carousel__arrow,
.testimonial-carousel__arrow {
  position: absolute;
  top: 50%;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border: none;
  border-radius: 50%;
  background-color: var(--color-turquoise);
  color: var(--color-white);
  box-shadow: var(--shadow-md);
  cursor: pointer;
  transform: translateY(-50%);
  transition: transform 200ms ease, opacity 200ms ease, background-color 200ms ease;
}

.portfolio-carousel__arrow:hover:not(:disabled),
.testimonial-carousel__arrow:hover:not(:disabled) {
  background-color: var(--color-turquoise-dark);
  transform: translateY(-50%) scale(1.08);
}

.portfolio-carousel__arrow:disabled,
.testimonial-carousel__arrow:disabled {
  opacity: 0.35;
  cursor: default;
}

.portfolio-carousel__arrow--prev,
.testimonial-carousel__arrow--prev {
  left: 0;
}

.portfolio-carousel__arrow--next,
.testimonial-carousel__arrow--next {
  right: 0;
}

.portfolio-card {
  position: relative;
  overflow: hidden;
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-lg);
  isolation: isolate;
  box-shadow: var(--shadow-sm);
}

/* Featured Projects carousel images are square (site mockups), unlike
   the 4:3 photos used elsewhere with .portfolio-card — match the box
   to their ratio so nothing gets cropped top/bottom. */
.portfolio-carousel .portfolio-card {
  aspect-ratio: 1 / 1;
}

.portfolio-card__image {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 500ms cubic-bezier(0.22, 1, 0.36, 1);
}

.portfolio-card:hover .portfolio-card__image,
.portfolio-card:focus-within .portfolio-card__image {
  transform: scale(1.1);
}

.portfolio-card__overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  padding: var(--space-5);
  text-align: center;
  background-color: rgba(16, 24, 32, 0.78);
  opacity: 0;
  transition: opacity 350ms ease;
}

.portfolio-card:hover .portfolio-card__overlay,
.portfolio-card:focus-within .portfolio-card__overlay {
  opacity: 1;
}

.portfolio-card__name {
  margin: 0;
  color: var(--color-white);
  font-size: var(--text-lg);
  transform: scale(0.85);
  transition: transform 350ms cubic-bezier(0.22, 1, 0.36, 1);
}

.portfolio-card__link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-5);
  border-radius: 999px;
  background-color: var(--color-white);
  color: var(--color-ink);
  font-size: var(--text-xs);
  font-weight: 600;
  transform: scale(0.85);
  transition: transform 350ms cubic-bezier(0.22, 1, 0.36, 1);
}

.portfolio-card:hover .portfolio-card__name,
.portfolio-card:hover .portfolio-card__link,
.portfolio-card:focus-within .portfolio-card__name,
.portfolio-card:focus-within .portfolio-card__link {
  transform: scale(1);
}

/* ==========================================================================
   Process timeline
   4 numbered steps on a connecting line (desktop); stacks to a plain
   list on mobile since the horizontal line doesn't translate well
   to a single column.
   ========================================================================== */

.process-timeline {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-7);
}

@media (min-width: 768px) {
  .process-timeline {
    grid-template-columns: repeat(4, 1fr);
    gap: var(--space-6);
  }

  .process-timeline::before {
    content: "";
    position: absolute;
    top: 28px;
    left: 0;
    right: 0;
    height: 2px;
    background-color: var(--color-border);
  }
}

.process-step {
  position: relative;
  z-index: 1;
  text-align: center;
}

.process-step__number {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  margin-inline: auto;
  margin-bottom: var(--space-4);
  border-radius: 50%;
  background-color: var(--color-turquoise);
  color: var(--color-ink);
  font-weight: 700;
  font-size: var(--text-lg);
}

.process-step__title {
  margin: 0 0 var(--space-2);
  font-size: var(--text-lg);
}

.process-step__text {
  margin: 0;
  color: var(--color-muted);
  font-size: var(--text-sm);
}

/* ==========================================================================
   Industry marquee
   Two rows of pill chips drifting in opposite directions, full-bleed
   within their section — a looser, more fluid alternative to a static
   grid for a long list of industries. Each track renders its chip set
   twice back-to-back and animates to -50% for a seamless loop; the
   second copy is aria-hidden and untabbable so assistive tech and
   keyboard users only ever see one real set of links.
   ========================================================================== */

.industry-marquee {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  margin-top: var(--space-5);
  padding-block: var(--space-5);
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, black 6%, black 94%, transparent);
  mask-image: linear-gradient(90deg, transparent, black 6%, black 94%, transparent);
}

.industry-marquee__track {
  display: flex;
  gap: var(--space-4);
  width: max-content;
  animation: marquee-left 46s linear infinite;
}

.industry-marquee__set {
  display: flex;
  flex-shrink: 0;
  gap: var(--space-4);
}

.industry-marquee__row--reverse .industry-marquee__track {
  animation-name: marquee-right;
  animation-duration: 40s;
}

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

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

.industry-chip {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-5);
  border-radius: 999px;
  background-color: var(--color-white);
  border: 1px solid var(--color-border);
  box-shadow: var(--shadow-sm);
  color: var(--color-ink);
  font-weight: 600;
  font-size: var(--text-sm);
  white-space: nowrap;
  transition: transform 250ms ease, box-shadow 250ms ease, border-color 250ms ease;
}

.industry-chip:hover,
.industry-chip:focus-visible {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
  border-color: var(--color-turquoise);
}

.industry-chip svg {
  flex-shrink: 0;
  color: var(--color-blue);
}

@media (prefers-reduced-motion: reduce) {
  .industry-marquee {
    overflow: visible;
    -webkit-mask-image: none;
    mask-image: none;
  }

  .industry-marquee__track {
    animation: none;
    width: auto;
    transform: none;
    flex-wrap: wrap;
  }

  .industry-marquee__set[aria-hidden="true"] {
    display: none;
  }

  .industry-marquee__set {
    /* Unwraps the set so its chips become direct flex children of
       .industry-marquee__track and wrap against the track's actual
       width, instead of the set's own (much wider) intrinsic width. */
    display: contents;
  }
}

.placeholder-media {
  aspect-ratio: 4 / 3;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-md);
  background-color: var(--color-white);
  background-image: repeating-linear-gradient(
    45deg,
    var(--color-border),
    var(--color-border) 1px,
    transparent 1px,
    transparent 12px
  );
  border: 1px dashed var(--color-border);
  color: var(--color-muted);
  font-size: var(--text-xs);
  text-align: center;
  padding: var(--space-3);
}

/* ==========================================================================
   Hero
   Dark, full-bleed hero with a scattered collage of work "screens" set
   behind a centered heading/CTA. A radial scrim keeps the centre legible
   over the busier edges; a faint grid adds texture without an image.
   ========================================================================== */

.hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background-color: var(--color-deep);
  background-image: linear-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.04) 1px, transparent 1px);
  background-size: 40px 40px;
  padding-block: var(--space-9);
  text-align: center;
  /* Mouse-parallax offset for .hero__bg-item, updated by script.js;
     falls back to 0 so nothing moves before JS runs or without JS. */
  --mx: 0px;
  --my: 0px;
}

.hero__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.hero__bg-item {
  display: none;
  position: absolute;
  width: 15rem;
  height: auto;
  aspect-ratio: 578 / 659;
  object-fit: cover;
  border-radius: var(--radius-md);
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.45);
  animation: hero-float 7s ease-in-out infinite;
  --depth: 1;
}

/* For collage images whose source aspect ratio differs from the
   578/659 default — lets them size to their own natural ratio
   instead of being cropped by object-fit: cover. */
.hero__bg-item--natural-ratio {
  aspect-ratio: auto;
}

.hero__bg-item--top-left {
  top: -1.5rem;
  left: 3%;
  width: 14rem;
  --rot: -5deg;
  --depth: 1.1;
  animation-delay: -1.2s;
}

.hero__bg-item--top-right {
  top: -2rem;
  right: 4%;
  --rot: 7deg;
  --depth: 1;
  animation-delay: 0s;
}

.hero__bg-item--bottom-left {
  bottom: -3rem;
  left: 2%;
  width: 17rem;
  --rot: -6deg;
  --depth: 1.2;
  animation-delay: -2.3s;
}

.hero__bg-item--bottom-right {
  bottom: -4rem;
  right: 8%;
  width: 12rem;
  --rot: 5deg;
  --depth: 0.8;
  animation-delay: -4.6s;
}

.hero__bg-item--left {
  top: 40%;
  left: -1%;
  width: 10rem;
  --rot: -8deg;
  --depth: 1.5;
  animation-delay: -3.5s;
}

.hero__bg-item--right {
  top: 44%;
  right: -1%;
  width: 10rem;
  --rot: 6deg;
  --depth: 1.4;
  animation-delay: -5.8s;
}

/* Below 1024px the full 6-image collage is dropped — too busy and too
   large for the available space — but a couple of images can opt in
   here to stay as a corner accent instead of the hero going flat.
   Smaller and lower opacity than the desktop treatment. */
@media (max-width: 1023px) {
  .hero__bg-item--mobile-visible {
    display: block;
    width: 11rem;
    opacity: 0.45;
  }
}

@keyframes hero-float {
  0%,
  100% {
    transform: rotate(var(--rot)) translate(calc(var(--mx) * var(--depth)), calc(var(--my) * var(--depth)))
      translateY(0);
  }
  50% {
    transform: rotate(var(--rot)) translate(calc(var(--mx) * var(--depth)), calc(var(--my) * var(--depth)))
      translateY(-14px);
  }
}

.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: radial-gradient(
    ellipse at center,
    var(--color-deep) 0%,
    rgba(16, 32, 44, 0.85) 45%,
    rgba(16, 32, 44, 0.55) 100%
  );
}

.hero__content {
  position: relative;
  z-index: 2;
  max-width: 40rem;
  margin-inline: auto;
}

.hero h1 {
  color: var(--color-white);
}

.hero__content p {
  margin-top: var(--space-4);
  font-size: var(--text-lg);
  color: #c9d6dd;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-4);
  margin-top: var(--space-6);
}

.hero .button--secondary {
  color: var(--color-white);
  border-color: var(--color-white);
}

.hero .button--secondary:hover {
  background-color: var(--color-white);
  color: var(--color-blue);
}

@media (min-width: 1024px) {
  .hero {
    padding-block: var(--space-10);
    min-height: 36rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
  }

  .hero__bg-item {
    display: block;
  }
}

/* Placeholder collage item: same floating-card treatment as the real
   .hero__bg-item screenshots, for pages that don't have real imagery
   yet. Combine with a .hero__bg-item--<corner> modifier for
   positioning, e.g. class="hero__visual-item hero__bg-item--top-left". */

.hero__visual-item {
  position: absolute;
  width: 13rem;
  aspect-ratio: 4 / 5;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-3);
  border: 4px solid rgba(255, 255, 255, 0.18);
  border-radius: var(--radius-lg);
  background-color: rgba(255, 255, 255, 0.06);
  background-image: repeating-linear-gradient(
    45deg,
    rgba(255, 255, 255, 0.14),
    rgba(255, 255, 255, 0.14) 1px,
    transparent 1px,
    transparent 10px
  );
  color: #c9d6dd;
  font-size: var(--text-xs);
  text-align: center;
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.45);
  animation: hero-float 7s ease-in-out infinite;
  --depth: 1;
}

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

.testimonials {
  display: grid;
  gap: var(--space-7);
  align-items: center;
}

.testimonials__cards {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-7);
}

/* Extra inset so the quote badge (which straddles the card's top-left
   corner) has room to sit clear of the viewport edge — container
   padding alone isn't enough for it at narrow widths. Desktop's grid
   layout doesn't need this since the stagger offset below already
   clears the badge. */
@media (max-width: 767px) {
  .testimonials__cards {
    padding-inline: var(--space-5);
  }
}

.testimonial-card {
  position: relative;
  display: flex;
  gap: var(--space-4);
  max-width: 26rem;
  padding: calc(var(--space-5) + 20px) var(--space-6) var(--space-5);
  background-color: var(--color-white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}

.testimonial-card:last-child {
  margin-inline-start: 0;
}

.testimonial-card__quote {
  position: absolute;
  top: 0;
  left: 0;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  background-color: var(--color-blue);
  color: var(--color-white);
  box-shadow: var(--shadow-sm);
}

.testimonial-card__avatar {
  flex-shrink: 0;
  width: 3.5rem;
  height: 3.5rem;
  border-radius: 50%;
  background-color: var(--color-white);
  background-image: repeating-linear-gradient(
    45deg,
    var(--color-border),
    var(--color-border) 1px,
    transparent 1px,
    transparent 6px
  );
  border: 1px dashed var(--color-border);
}

.testimonial-card blockquote p {
  font-size: var(--text-sm);
  color: var(--color-ink);
}

.testimonial-card footer {
  margin-top: var(--space-2);
}

.testimonial-card__author {
  display: block;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-ink);
}

.testimonial-card__company {
  display: block;
  font-size: var(--text-xs);
  font-weight: 400;
  color: var(--color-muted);
}

.testimonial-card__logo {
  display: block;
  margin-top: var(--space-3);
  height: 2rem;
  width: auto;
  max-width: 9rem;
  object-fit: contain;
  object-position: left center;
}

.testimonial-card__logo--round {
  width: 2.4rem;
  height: 2.4rem;
  max-width: none;
  border-radius: 50%;
  object-fit: cover;
}

/* Homepage-only single-card carousel variant (other pages keep the
   static 2-card .testimonials__cards layout). Reuses .testimonial-card
   styling as-is — only the container/track differs. */
.testimonial-carousel {
  position: relative;
  min-width: 0;
  padding-inline: 3.25rem;
}

.testimonial-carousel__track {
  display: flex;
  overflow-x: auto;
  /* Explicit, not just "not needed": leaving this unset lets the UA
     compute it as auto too (an overflow-x/y coupling in the spec), and
     since off-screen slides can be taller than the active slide the
     JS height sync pins the track to, that made the track a genuine
     vertical scroll container — hovering it while wheel-scrolling the
     page let it eat part of the scroll first, yanking the visible
     card's top out of view before the rest reached the page. */
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.testimonial-carousel__track::-webkit-scrollbar {
  display: none;
}

/* One "page" per slide, margin-free by design: Chrome's scroll-snap
   resting position ignores an element's margin when computing where
   scroll-snap-align: start lands it — confirmed on every card, not
   just the first — so a card relying on margin-inline for its shadow
   clearance would settle flush-left with no visible gap on that side.
   Padding is part of the border box and isn't affected, so the gap
   lives here instead, on the thing that actually gets snapped to. */
.testimonial-carousel__slide {
  flex: 0 0 100%;
  box-sizing: border-box;
  padding: 1.5rem 2rem 2rem;
  scroll-snap-align: start;
}

.testimonial-carousel__track .testimonial-card {
  max-width: none;
  width: 100%;
}

/* Every card here is the sole child of its own .testimonial-carousel__slide
   wrapper, so it trivially matches the global .testimonial-card:last-child
   rule (the 2-card stagger offset meant for the static layout elsewhere) —
   neutralise it here. */
.testimonial-carousel__slide .testimonial-card:last-child {
  margin-inline-start: 0;
}

/* The next/prev arrow's own box-shadow read as a hazy band toward the
   card at a glance. Scoped to this carousel only — the Featured
   Projects arrows keep --shadow-md. */
.testimonial-carousel__arrow {
  box-shadow: none;
}

/* Badge sits inset within the card instead of overhanging its left
   edge, so it can't be clipped by the track's horizontal scrolling. */
.testimonial-carousel .testimonial-card__quote {
  left: 1.25rem;
  transform: translateY(-50%);
}

/* Below 768px the side-mounted arrows eat into the card's width badly
   enough to feel cramped, so the arrows drop below the card instead —
   .testimonial-carousel switches from side padding reserved for
   absolutely-positioned arrows to a two-row grid (track, then arrows). */
@media (max-width: 767px) {
  .testimonial-carousel {
    display: grid;
    grid-template-areas:
      "track track"
      "prev next";
    grid-template-columns: 1fr 1fr;
    row-gap: var(--space-4);
    padding-inline: 0;
  }

  .testimonial-carousel__track {
    grid-area: track;
  }

  .testimonial-carousel__slide {
    padding: 1.5rem var(--space-4) 1.5rem;
  }

  /* Wider mobile card makes the default bottom padding read as too
     tight under the client logo — give it more room to breathe. */
  .testimonial-carousel .testimonial-card {
    padding-bottom: calc(var(--space-6) + 20px);
  }

  .testimonial-carousel .testimonial-carousel__arrow {
    position: static;
    transform: none;
  }

  .testimonial-carousel .testimonial-carousel__arrow:hover:not(:disabled) {
    transform: scale(1.08);
  }

  .testimonial-carousel__arrow--prev {
    grid-area: prev;
    justify-self: end;
    margin-right: var(--space-2);
  }

  .testimonial-carousel__arrow--next {
    grid-area: next;
    justify-self: start;
    margin-left: var(--space-2);
  }
}

.testimonials__content p {
  margin-top: var(--space-4);
  color: var(--color-muted);
  max-width: 30rem;
}

.testimonials__content .button {
  margin-top: var(--space-6);
}

.text-heavy {
  font-weight: 700;
}

@media (min-width: 768px) {
  .testimonials {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-9);
  }

  /* Homepage-only carousel variant gets more room than the static
     2-card layout, so the shadow has genuine breathing space instead
     of being squeezed into a narrow leftover column. */
  .testimonials--carousel {
    grid-template-columns: 1.4fr 1fr;
    /* JS resizes the track to match whichever card is active, so this
       column's height changes slide to slide. With the default
       align-items: center from .testimonials, that row-height change
       recentred both columns — the text column visibly bobbed up and
       down even though only the card was meant to grow/shrink. Anchor
       both columns to the top instead so the text column never moves. */
    align-items: start;
  }

  .testimonial-card:last-child {
    margin-inline-start: var(--space-8);
  }
}

/* ==========================================================================
   Legal content (privacy notice, etc.)
   ========================================================================== */

.legal-content {
  max-width: 42rem;
}

.legal-meta {
  margin-top: var(--space-2);
  color: var(--color-muted);
  font-size: var(--text-sm);
}

.legal-content h2 {
  margin-top: var(--space-8);
  font-size: var(--text-2xl);
}

.legal-content p {
  margin-top: var(--space-4);
  color: var(--color-muted);
}

.legal-content ul {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-4);
  padding: 0;
  list-style: none;
}

.legal-content li {
  position: relative;
  padding-left: var(--space-5);
  color: var(--color-muted);
}

.legal-content li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.6em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background-color: var(--color-turquoise);
}

.legal-content a {
  color: var(--color-blue);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.legal-content a:hover {
  color: var(--color-blue-dark);
}

/* ==========================================================================
   About teaser
   ========================================================================== */

.about-teaser {
  display: grid;
  gap: var(--space-7);
  align-items: center;
}

.about-teaser p {
  margin-top: var(--space-4);
  color: var(--color-muted);
}

.about-teaser .button {
  margin-top: var(--space-6);
}

@media (min-width: 768px) {
  .about-teaser {
    grid-template-columns: 1fr 1fr;
  }
}

.about-photos {
  position: relative;
  width: 100%;
  max-width: 25rem;
  aspect-ratio: 4 / 4.4;
  margin-inline: auto;
}

@media (min-width: 768px) {
  .about-photos {
    margin-inline: 0;
  }
}

/* Three photos fan out above the headshot, slightly behind and
   overlapping it. The middle one sits straight; the outer two tilt
   away from it. */

.about-photos__accent {
  position: absolute;
  top: 0;
  z-index: 1;
  width: 44%;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  padding: var(--space-2);
  border: 4px solid var(--color-white);
  border-radius: var(--radius-lg);
  background-color: var(--color-paper);
  box-shadow: var(--shadow-md);
  animation: about-photo-float 6s ease-in-out infinite;
}

.about-photos__accent img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--radius-sm);
}

.about-photos__accent--1 {
  left: 0;
  z-index: 1;
  --rot: -4deg;
  animation-delay: 0s;
}

.about-photos__accent--2 {
  right: 0;
  z-index: 1;
  --rot: 4deg;
  animation-delay: -3s;
}

.about-photos__accent--3 {
  left: 28%;
  z-index: 2;
  --rot: 0deg;
  animation-delay: -1.5s;
}

@keyframes about-photo-float {
  0%,
  100% {
    transform: rotate(var(--rot)) translateY(0);
  }
  50% {
    transform: rotate(var(--rot)) translateY(-10px);
  }
}

.about-photos__main {
  position: absolute;
  z-index: 3;
  bottom: 0;
  left: 50%;
  width: 58%;
  aspect-ratio: 1 / 1;
  transform: translateX(-50%);
  overflow: hidden;
  border-radius: 50%;
  border: 6px solid var(--color-white);
  box-shadow: var(--shadow-md);
}

.about-photos__main img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ==========================================================================
   Final CTA
   White section with a centred heading/CTA and a scatter of floating
   icon badges standing in for the "faces" in the reference design.
   ========================================================================== */

.final-cta {
  position: relative;
  overflow: hidden;
  background-color: var(--color-white);
  padding-block: var(--space-9);
  text-align: center;
}

.final-cta__content {
  position: relative;
  z-index: 2;
  max-width: 38rem;
  margin-inline: auto;
}

.final-cta__eyebrow {
  margin: 0;
  color: var(--color-blue);
  font-weight: 600;
  font-size: var(--text-sm);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.final-cta__content h2 {
  margin-top: var(--space-3);
}

.final-cta__content p:not(.final-cta__eyebrow) {
  margin-top: var(--space-4);
  color: var(--color-muted);
}

.final-cta__content .button {
  margin-top: var(--space-6);
}

.final-cta__icon {
  position: absolute;
  z-index: 1;
  display: none;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background-color: var(--color-white);
  border: 1px solid var(--color-border);
  color: var(--color-blue);
  box-shadow: var(--shadow-md);
  animation: final-cta-float 6s ease-in-out infinite;
}

.final-cta__icon--1 {
  top: 8%;
  left: 8%;
  width: 4.5rem;
  height: 4.5rem;
  animation-delay: 0s;
}

.final-cta__icon--2 {
  top: 12%;
  right: 10%;
  width: 3.5rem;
  height: 3.5rem;
  animation-delay: -1s;
}

.final-cta__icon--3 {
  top: 46%;
  left: 3%;
  width: 3rem;
  height: 3rem;
  animation-delay: -2s;
}

.final-cta__icon--4 {
  top: 42%;
  right: 4%;
  width: 4rem;
  height: 4rem;
  animation-delay: -3s;
}

.final-cta__icon--5 {
  bottom: 8%;
  left: 14%;
  width: 3.5rem;
  height: 3.5rem;
  animation-delay: -4s;
}

.final-cta__icon--6 {
  bottom: 10%;
  right: 12%;
  width: 4rem;
  height: 4rem;
  animation-delay: -5s;
}

@keyframes final-cta-float {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-10px);
  }
}

@media (min-width: 1280px) {
  .final-cta__icon {
    display: flex;
  }
}

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

.contact-hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background-color: var(--color-deep);
  background-image: linear-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.04) 1px, transparent 1px);
  background-size: 40px 40px;
  padding-block: var(--space-9) var(--space-10);
  text-align: center;
}

.contact-hero h1 {
  position: relative;
  z-index: 2;
  color: var(--color-white);
}

.contact-hero__icon {
  position: absolute;
  z-index: 1;
  display: none;
  align-items: center;
  justify-content: center;
  width: 3.25rem;
  height: 3.25rem;
  border-radius: 50%;
  background-color: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.16);
  color: var(--color-turquoise);
  animation: contact-hero-float 6s ease-in-out infinite;
}

.contact-hero__icon--1 {
  left: 6%;
  top: 32%;
  --rot: -8deg;
  animation-delay: 0s;
}

.contact-hero__icon--2 {
  left: 21%;
  top: 43%;
  --rot: 6deg;
  animation-delay: -1.8s;
}

.contact-hero__icon--3 {
  right: 6%;
  top: 32%;
  --rot: 7deg;
  animation-delay: -3.2s;
}

.contact-hero__icon--4 {
  right: 21%;
  top: 43%;
  --rot: -5deg;
  animation-delay: -4.6s;
}

@keyframes contact-hero-float {
  0%,
  100% {
    transform: rotate(var(--rot)) translateY(0);
  }
  50% {
    transform: rotate(var(--rot)) translateY(-10px);
  }
}

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

.contact-form-section {
  padding-bottom: var(--space-9);
}

.contact-form-card {
  position: relative;
  margin: calc(var(--space-7) * -1) auto 0;
  max-width: 50rem;
  padding: var(--space-6);
  background-color: var(--color-white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}

@media (min-width: 768px) {
  .contact-form-card {
    margin-top: calc(var(--space-9) * -1);
    padding: var(--space-8);
  }
}

.contact-form-card__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-7);
}

.contact-form-card__header h2 {
  margin: 0;
  font-size: var(--text-2xl);
}

.contact-form-card__icon {
  flex-shrink: 0;
  color: var(--color-blue);
  animation: icon-pulse 2.4s ease-in-out infinite;
}

@keyframes icon-pulse {
  0%,
  100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.12);
  }
}

.contact-form__row {
  display: grid;
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}

@media (min-width: 640px) {
  .contact-form__row {
    grid-template-columns: 1fr 1fr;
  }
}

.form-field {
  margin-bottom: var(--space-4);
}

.form-field input,
.form-field textarea {
  width: 100%;
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font-family: inherit;
  font-size: var(--text-sm);
  color: var(--color-ink);
  background-color: var(--color-white);
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.form-field input::placeholder,
.form-field textarea::placeholder {
  color: var(--color-muted);
}

.form-field input:focus,
.form-field textarea:focus {
  border-color: var(--color-blue);
  box-shadow: 0 0 0 3px rgba(45, 90, 122, 0.15);
}

.form-field textarea {
  resize: vertical;
  min-height: 9rem;
}

.contact-form__status {
  margin: 0 0 var(--space-4);
  font-size: var(--text-sm);
  min-height: 0;
}

.contact-form__status:empty {
  display: none;
}

.contact-form__status.is-pending {
  color: var(--color-muted);
}

.contact-form__status.is-success {
  color: #1e8449;
}

.contact-form__status.is-error {
  color: #c0392b;
}

.contact-form__footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  margin-top: var(--space-6);
}

.contact-form__privacy {
  max-width: 26rem;
  color: var(--color-muted);
  font-size: var(--text-xs);
}

.contact-form__privacy a {
  color: var(--color-blue);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.contact-form__privacy a:hover {
  color: var(--color-blue-dark);
}

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

.not-found {
  padding-block: var(--space-10);
  text-align: center;
}

.not-found__content {
  max-width: 32rem;
  margin-inline: auto;
}

.not-found__code {
  margin: 0;
  font-size: var(--text-5xl);
  font-weight: 700;
  line-height: 1;
  color: var(--color-turquoise);
}

.not-found__content h1 {
  margin-top: var(--space-3);
}

.not-found__content p {
  margin-top: var(--space-3);
  color: var(--color-muted);
}

.not-found__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  margin-top: var(--space-6);
}
