/* ============================================================
   leonardlatescu.com — design tokens (synced with Figma)
   ============================================================ */

:root {
  /* Colors */
  --brand:              #3C4050;
  --text-primary:       #010411;
  --text-secondary:     #3C4050;
  --text-muted:         #777B8C;
  --surface-primary:    #FFFFFF;
  --surface-secondary:  #F6F7FF;

  /* Per-project brand colors */
  --brand-tinyco:       #008060;
  --brand-smartouch:    #7D27DA;
  --brand-socialgaines: #067EE7;
  --brand-travalera:      #2A3D74;
  --brand-privitas:     #151517;
  --brand-bixy:         #343841;

  /* Typography */
  --font-display: 'Poppins', system-ui, sans-serif;
  --font-body:    'Poppins', system-ui, sans-serif;

  /*
   * Two-stage fluid type scale:
   * mobile -> 1440 design frame, then 1440 -> 5K/ultrawide.
   * The upper bound is itself fluid, so typography never freezes at 1440px.
   */
  --fs-h0: clamp(32px, calc(21px + 2.7vw), min(112px, calc(39.652px + 1.41304vw))); --lh-h0: 1.10;
  --fs-h0s: clamp(32px, calc(19px + 3.68vw), min(172px, calc(32.870px + 2.71739vw))); --lh-h0s: 1.10;
  --fs-h1: clamp(32px, calc(20.732px + 3.00469vw), min(128px, calc(38.957px + 1.73913vw))); --lh-h1: 1.13;
  --fs-h1s: clamp(32px, calc(20px + 3vw), min(128px, calc(38.957px + 1.73913vw))); --lh-h1s: 1.10;
  --fs-h2: clamp(32px, calc(24.958px + 1.87793vw), min(104px, calc(31.652px + 1.41304vw))); --lh-h2: 1.15;
  --fs-h3: clamp(24px, calc(19.775px + 1.1268vw), min(72px, calc(21.913px + .97826vw))); --lh-h3: 1.22;
  --fs-h4: clamp(20px, calc(17.183px + .75117vw), min(56px, calc(17.043px + .76087vw))); --lh-h4: 1.29;
  --fs-body-xl: clamp(16px, calc(14.609px + .65217vw), 48px); --lh-body-xl: 1.35;
  --fs-body-l: clamp(16px, calc(12.174px + .54348vw), 40px); --lh-body-l: 1.40;
  --fs-body-md: clamp(15px, calc(9.739px + .43478vw), 32px); --lh-body-md: 1.50;
  --fs-body-sm: clamp(13px, calc(8.522px + .38043vw), 28px); --lh-body-sm: 1.45;
  --fs-body-xs: clamp(11px, calc(7.304px + .32609vw), 24px); --lh-body-xs: 1.35;
  --fs-eyebrow: clamp(13px, calc(8.522px + .38043vw), 28px); --lh-eyebrow: 1.45;
  --fs-testimonial: clamp(22px, calc(17.043px + .76087vw), 56px); --lh-testimonial: 1.30;
  --fs-contact: clamp(40px, calc(16px + 5.833vw), 200px); --lh-contact: 1.20;

  --ls-display: -0.02em;
  --ls-eyebrow: 0.20em;

  --fw-light: 300;
  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;

  /*
   * Resolution-aware spacing scale.
   * Every design value is exact at 1440px and grows fluidly to 2x at 5120px.
   * Below 1440px the original values remain the accessible minimum.
   */
  --sp-0: 0;
  --sp-2: clamp(2px, calc(1.217px + .05435vw), 4px);
  --sp-4: clamp(4px, calc(2.435px + .10870vw), 8px);
  --sp-8: clamp(8px, calc(4.870px + .21739vw), 16px);
  --sp-12: clamp(12px, calc(7.304px + .32609vw), 24px);
  --sp-16: clamp(16px, calc(9.739px + .43478vw), 32px);
  --sp-20: clamp(20px, calc(12.174px + .54348vw), 40px);
  --sp-24: clamp(24px, calc(14.609px + .65217vw), 48px);
  --sp-28: clamp(28px, calc(17.043px + .76087vw), 56px);
  --sp-32: clamp(32px, calc(19.478px + .86957vw), 64px);
  --sp-40: clamp(40px, calc(24.348px + 1.08696vw), 80px);
  --sp-48: clamp(48px, calc(29.217px + 1.30435vw), 96px);
  --sp-56: clamp(56px, calc(34.087px + 1.52174vw), 112px);
  --sp-60: clamp(60px, calc(36.522px + 1.63043vw), 120px);
  --sp-64: clamp(64px, calc(38.957px + 1.73913vw), 128px);
  --sp-72: clamp(72px, calc(43.826px + 1.95652vw), 144px);
  --sp-80: clamp(80px, calc(48.696px + 2.17391vw), 160px);
  --sp-96: clamp(96px, calc(58.435px + 2.60870vw), 192px);
  --sp-100: clamp(100px, calc(60.870px + 2.71739vw), 200px);
  --sp-120: clamp(120px, calc(73.043px + 3.26087vw), 240px);

  /* Confirmed layout values from Figma node 2005:5385 */
  /* 1280 / 1440 = 88.8889%; gutters remain proportional at every width. */
  --content-pad: 5.5556vw;
  --container-cap: 1920px;
  --container-max: min(calc(100% - var(--content-pad) - var(--content-pad)), var(--container-cap));
  --container-outer-space: max(var(--content-pad), calc((100vw - var(--container-cap)) / 2));
  --top-bar-height: clamp(var(--sp-32), calc(29.65px + .163vw), 34px);
  --nav-height: clamp(var(--sp-72), calc(67.30px + .326vw), 76px);
  --header-height: var(--nav-height);
  --hero-height: 804px;
  --hero-pad: var(--sp-20);
  --hero-copy-width: max(720px, calc(438.26px + 19.565vw));
  --hero-intro-width: max(644px, calc(392px + 17.5vw));
  --hero-photo-width: 583px;
  --hero-photo-right: 95px;
  --nav-logo-width: clamp(177px, calc(107.74px + 4.81vw), 354px);
  --availability-dot: clamp(5px, calc(3.826px + .08152vw), 8px);
  --availability-green: #28D969;
  --badge-width: 64px;
  --badge-height: 73.6px;
  --badge-row-step: 55.2px;
  --badge-cluster-top: 212px;
  --badge-enter-distance: clamp(10px, .83335vw, 24px);
  /* Badge inset: 40px at 1440, scaling smoothly to 80px at 5K. */
  --badge-edge: clamp(var(--sp-40), calc(24.35px + 1.087vw), var(--sp-80));

  /* Borders */
  --border-width: 1px;
  --border-color: #E4E6F0;
  --radius: 0;
  /* Corner chamfer. --cut-corner is the horizontal reach; the vertical drop is
     that reach times --cut-rise, which is the slope of a hexagon's lower-right
     edge (18.25 / 31.5 = 30.09deg). Cutting at 45deg instead made every card
     and section disagree with the honeycomb they sit on. */
  --cut-corner: var(--sp-12);
  --cut-rise: .5794;

  /* Motion */
  --dur-fast: 200ms;
  --dur-med: 400ms;
  --dur-slow: 600ms;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-gentle: cubic-bezier(0.4, 0, 0.2, 1);
  --stagger: 80ms;
}

/* ============================================================
   Base / reset
   ============================================================ */

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

html {
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  scroll-behavior: smooth;
  scroll-padding-top: var(--sp-80);
}

body {
  min-width: 320px;
  overflow-x: hidden;
  color: var(--text-primary);
  background: var(--surface-primary);
  font-family: var(--font-body);
  font-size: var(--fs-body-md);
  font-weight: var(--fw-light);
  line-height: var(--lh-body-md);
}

a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }

.ui-icon {
  display: block;
  width: var(--sp-24);
  height: var(--sp-24);
  flex: 0 0 auto;
  object-fit: contain;
}
button, a { -webkit-tap-highlight-color: transparent; }
button, input, select, textarea { font-family: inherit; }

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

.skip-link {
  position: fixed;
  z-index: 1000;
  top: var(--sp-8);
  left: var(--sp-8);
  padding: var(--sp-8) var(--sp-12);
  transform: translateY(-200%);
  color: var(--surface-primary);
  background: var(--brand);
}

.skip-link:focus { transform: none; }

/* ============================================================
   Typography helpers — map 1:1 to Figma text styles
   ============================================================ */

.h0 {
  font-family: var(--font-body);
  font-size: var(--fs-h0);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-h0);
  letter-spacing: var(--ls-display);
}

.h0-style {
  font-family: var(--font-display);
  font-size: var(--fs-h0s);
  font-style: normal;
  font-weight: var(--fw-semibold);
  line-height: var(--lh-h0s);
  letter-spacing: var(--ls-display);
}

.h1 {
  font-family: var(--font-body);
  font-size: var(--fs-h1);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-h1);
  letter-spacing: var(--ls-display);
}

.h1-style {
  font-family: var(--font-display);
  font-size: var(--fs-h1s);
  font-style: normal;
  font-weight: var(--fw-semibold);
  line-height: var(--lh-h1s);
  letter-spacing: var(--ls-display);
}

.h2 {
  font-family: var(--font-body);
  font-size: var(--fs-h2);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-h2);
  letter-spacing: var(--ls-display);
}

.h3 {
  font-family: var(--font-body);
  font-size: var(--fs-h3);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-h3);
  letter-spacing: var(--ls-display);
}

.h4 {
  font-family: var(--font-body);
  font-size: var(--fs-h4);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-h4);
  letter-spacing: var(--ls-display);
}

.body-xl { font-size: var(--fs-body-xl); line-height: var(--lh-body-xl); }
.body-l  { font-size: var(--fs-body-l);  line-height: var(--lh-body-l); }
.body-md { font-size: var(--fs-body-md); line-height: var(--lh-body-md); }
.body-sm { font-size: var(--fs-body-sm); line-height: var(--lh-body-sm); }
.body-xs { font-size: var(--fs-body-xs); line-height: var(--lh-body-xs); }

.eyebrow {
  color: var(--brand);
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-regular);
  line-height: var(--lh-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
}

.testimonial {
  font-family: var(--font-display);
  font-size: var(--fs-testimonial);
  font-style: normal;
  font-weight: var(--fw-regular);
  line-height: var(--lh-testimonial);
}

/* ============================================================
   Shared layout helpers
   ============================================================ */

.container {
  width: var(--container-max);
  max-width: none;
  margin-inline: auto;
}

.section { padding-block: clamp(var(--sp-64), 8vw, var(--sp-120)); }
.section--alt { background: var(--surface-secondary); }

/* Load reveals are enabled by JavaScript only after the initial styles exist. */
.rv {
  opacity: 1;
  translate: none;
}

@media (prefers-reduced-motion: no-preference) {
  .reveal-enabled .hero-grid__cell {
    opacity: 0;
    transform: scale(.92);
  }

  .reveal-enabled .hero.is-grid-visible .hero-grid__cell {
    opacity: .5;
    transform: none;
    transition-property: opacity, transform;
    transition-duration: var(--dur-med), var(--dur-med);
    transition-timing-function: var(--ease), var(--ease);
    transition-delay: var(--cell-delay, 0ms), var(--cell-delay, 0ms);
  }

  .reveal-enabled .rv.rv--entrance,
  .reveal-enabled .hero-reveal-line.rv--entrance {
    opacity: 0;
    translate: calc(0px - var(--sp-24)) 0;
  }

  .reveal-enabled .rv.rv--entrance.is-in,
  .reveal-enabled .hero-reveal-line.rv--entrance.is-in {
    opacity: 1;
    translate: none;
    transition-property: opacity, translate;
    transition-duration: var(--dur-slow), var(--dur-slow);
    transition-timing-function: var(--ease), var(--ease);
    transition-delay: var(--rv-delay, 0ms), var(--rv-delay, 0ms);
  }

  .reveal-enabled .badge.badge--entrance {
    opacity: 0;
    translate: var(--badge-enter-x, 0) var(--badge-enter-y, 0);
  }

  .reveal-enabled .badge.badge--entrance.is-settled {
    opacity: 1;
    translate: none;
    transition-property: opacity, translate, transform, filter;
    transition-duration: var(--dur-slow), var(--dur-slow), calc(var(--dur-slow) + var(--dur-fast)), var(--dur-slow);
    transition-timing-function: var(--ease), var(--ease), var(--ease-gentle), var(--ease-gentle);
    transition-delay: var(--badge-delay, 0ms), var(--badge-delay, 0ms), 0ms, 0ms;
  }
}

/* ============================================================
   Top bar
   ============================================================ */

/* ============================================================
   Navigation
   ============================================================ */

.site-header { min-height: var(--nav-height); }

.site-nav {
  position: relative;
  z-index: 100;
  width: 100%;
  background: transparent;
  transition: background-color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}

.site-nav.is-sticky {
  position: fixed;
  top: 0;
  left: 0;
  border-bottom: var(--border-width) solid var(--border-color);
  background: var(--surface-primary);
}

.site-nav__inner {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  padding: var(--sp-24) var(--badge-edge);
}

.site-nav__left,
.site-nav__right,
.site-nav__links,
.site-nav__actions,
.availability {
  display: flex;
  align-items: center;
}

.site-nav__left { gap: var(--sp-24); }
.site-nav__links { gap: var(--sp-40); }
.site-nav__right { gap: var(--sp-20); }
.site-nav__actions { gap: var(--sp-40); }

.availability {
  gap: var(--sp-8);
  color: var(--text-muted);
  font-size: var(--fs-body-xs);
  line-height: var(--lh-body-xs);
  letter-spacing: .08em;
  text-transform: uppercase;
  white-space: nowrap;
}

.availability__dot {
  position: relative;
  width: var(--availability-dot);
  height: var(--availability-dot);
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--availability-green);
  box-shadow: 0 0 0 1px rgb(0 128 60 / .18), 0 0 7px rgb(40 217 105 / .24);
}

.availability__dot::after {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  content: "";
  transform: scale(.2);
  opacity: 0;
  background: var(--availability-green);
  animation: availability-pulse calc(var(--dur-slow) + var(--dur-slow) + var(--dur-slow) + var(--dur-slow)) var(--ease) infinite;
}

@keyframes availability-pulse {
  0% { transform: scale(.2); opacity: 0; }
  10% { opacity: .24; }
  68% { transform: scale(3); opacity: 0; }
  100% { transform: scale(3); opacity: 0; }
}

.site-nav__separator {
  width: var(--border-width);
  height: var(--sp-20);
  flex: 0 0 auto;
  background: var(--border-color);
}

.site-logo {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-12);
  color: var(--brand);
  width: max-content;
  height: auto;
  min-height: var(--sp-32);
  flex: 0 0 auto;
}

.site-logo__tooltip {
  position: absolute;
  z-index: 20;
  top: calc(100% + var(--sp-12));
  left: 0;
  width: max-content;
  max-width: min(260px, calc(100vw - var(--sp-32)));
  padding: 14px 18px;
  border: 1px solid rgb(255 255 255 / .12);
  border-radius: 12px;
  background: var(--text-primary);
  box-shadow: 0 12px 32px rgb(1 4 17 / .16);
  color: #B1B5C2;
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: var(--fw-regular);
  line-height: 1.6;
  letter-spacing: 0;
  text-transform: none;
  white-space: normal;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transform: translateY(5px);
  transition: opacity var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease),
              visibility var(--dur-fast);
}

.site-logo__tooltip::before {
  position: absolute;
  top: -5px;
  left: 16px;
  width: 8px;
  height: 8px;
  background: var(--text-primary);
  transform: rotate(45deg);
  content: '';
}

.site-logo__tooltip strong {
  display: block;
  color: #DEE0E7;
  font-weight: var(--fw-semibold);
}

.site-logo__tooltip-status {
  display: block;
  margin-top: 2px;
}

.site-logo:is(:hover, :focus-visible) .site-logo__tooltip {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.site-logo__mark {
  display: block;
  width: calc(var(--nav-logo-width) * .2592);
  height: auto;
  flex: 0 0 auto;
  overflow: visible;
  isolation: isolate;
}

.site-logo__layer {
  fill: currentColor;
  animation: logo-first-enter 650ms var(--ease) both;
}

.site-logo__layer--first { fill: var(--text-primary); opacity: 1; }
.site-logo__layer--second {
  fill: var(--brand-smartouch);
  opacity: .8;
  animation:
    logo-second-enter 1600ms var(--ease) 900ms both,
    logo-project-colors 18s linear 2500ms infinite;
}

@keyframes logo-first-enter {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes logo-second-enter {
  from { opacity: 0; transform: translate(240px, 0); }
  to { opacity: .8; transform: translate(0, 0); }
}

@keyframes logo-project-colors {
  0%, 100% { fill: var(--brand-smartouch); }
  16.6667% { fill: var(--brand-socialgaines); }
  33.3333% { fill: var(--brand-tinyco); }
  50% { fill: var(--brand-travalera); }
  66.6667% { fill: var(--brand-privitas); }
  83.3333% { fill: var(--brand-bixy); }
}

@media (prefers-reduced-motion: reduce) {
  .site-logo .site-logo__layer {
    animation: none;
    transform: none;
  }
  .site-logo__tooltip { transition: none; }
}

.site-nav__links a,
.site-nav__actions a {
  position: relative;
  font-size: var(--fs-body-md);
  font-weight: var(--fw-light);
  line-height: var(--lh-body-md);
  white-space: nowrap;
}

.site-nav__links a::after,
.site-nav__actions a:not(.linkedin-link)::after {
  position: absolute;
  right: 0;
  bottom: -2px;
  left: 0;
  height: var(--border-width);
  content: "";
  transform: scaleX(0);
  transform-origin: left;
  background: currentColor;
  transition: transform var(--dur-fast) var(--ease);
}

.site-nav__links a:hover::after,
.site-nav__links a:focus-visible::after,
.site-nav__actions a:not(.linkedin-link):hover::after,
.site-nav__actions a:not(.linkedin-link):focus-visible::after {
  transform: scaleX(1);
  transform-origin: left;
}

/* Full word, not the two-letter mark: the square box was sized for "in" and
   would clip anything longer, so the link now flows like the text links
   beside it. */
.linkedin-link {
  display: inline-flex;
  align-items: center;
  line-height: var(--sp-20) !important;
}

.profile-menu { position: relative; }

.profile-menu summary {
  display: flex;
  align-items: center;
  gap: 6px;
  list-style: none;
  cursor: pointer;
  font-size: var(--fs-body-md);
  font-weight: var(--fw-light);
  line-height: var(--lh-body-md);
  white-space: nowrap;
}

.profile-menu summary::-webkit-details-marker { display: none; }
.profile-menu__chevron { transition: transform var(--dur-fast) var(--ease); }
.profile-menu[open] .profile-menu__chevron { transform: rotate(180deg); }

.profile-menu__panel {
  position: absolute;
  z-index: 50;
  top: calc(100% + var(--sp-16));
  right: 0;
  width: 190px;
  padding: 6px;
  border: 1px solid var(--border-color);
  border-radius: 12px;
  background: var(--surface-primary);
  box-shadow: 0 12px 32px rgb(1 4 17 / .12);
}

.profile-menu__panel a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 10px 12px;
  border-radius: 7px;
  color: var(--text-secondary);
  font-size: 14px;
  font-weight: var(--fw-regular);
  line-height: 1.5;
  transition: color var(--dur-fast), background var(--dur-fast);
}

.profile-menu__panel a::after { display: none; }
.profile-menu--up .profile-menu__panel { top: auto; bottom: calc(100% + var(--sp-16)); }
.profile-menu--up .profile-menu__chevron { transform: rotate(180deg); }
.profile-menu--up[open] .profile-menu__chevron { transform: rotate(0deg); }

.profile-menu__panel a > span:last-child { color: var(--text-muted); }
.profile-menu__panel a:is(:hover, :focus-visible) {
  color: var(--brand);
  background: var(--surface-secondary);
}

@media (max-width: 720px) {
  .profile-menu summary { font-size: var(--fs-body-sm); }
}

@media (prefers-reduced-motion: reduce) {
  .profile-menu__chevron { transition: none; }
}

/* ============================================================
   Hero — desktop frame mirrors Figma 2005:5385
   ============================================================ */

.hero {
  position: relative;
  display: grid;
  width: var(--container-max);
  min-height: calc(100svh - var(--header-height));
  min-height: calc(100dvh - var(--header-height));
  grid-template-columns: minmax(0, 1.1fr) minmax(360px, .9fr);
  align-items: center;
  overflow: visible;
  isolation: isolate;
  margin-inline: auto;
}

.hero__copy {
  position: relative;
  z-index: 3;
  display: flex;
  width: 100%;
  max-width: calc(var(--hero-copy-width) + var(--hero-pad));
  align-items: flex-start;
  align-self: center;
  flex-direction: column;
  grid-column: 1;
  grid-row: 1;
  justify-self: start;
  padding-block: clamp(var(--sp-48), 7svh, var(--sp-80));
  padding-right: var(--sp-0);
  padding-left: var(--hero-pad);
  transform: translateY(var(--sp-24));
}

.hero__meta {
  width: 100%;
  margin-bottom: clamp(var(--sp-24), 3vw, var(--sp-40));
  color: var(--text-muted);
  font-size: var(--fs-body-md);
  line-height: var(--lh-body-md);
}

.hero__introduction {
  display: block;
}

[data-hero-greeting] {
  display: inline-block;
  color: var(--text-primary);
  font-weight: 400;
  opacity: 1;
  transform: translateY(0);
  transition: opacity 180ms ease, transform 180ms ease;
}

[data-hero-greeting].is-switching {
  opacity: 0;
  transform: translateY(-3px);
}

@media (prefers-reduced-motion: reduce) {
  [data-hero-greeting] { transition: none; }
}

.hero__title {
  width: calc(100% + var(--sp-40));
  font-weight: inherit;
}

.hero__title-accent,
.hero__title-main {
  display: block;
  width: 100%;
}

.hero__title-line { display: block; }

.hero__title-accent {
  color: var(--text-primary);
  font-size: var(--fs-h0s);
  line-height: var(--lh-h0s);
  white-space: nowrap;
}

.hero__title-main {
  color: var(--brand);
  font-size: var(--fs-h0s);
  line-height: var(--lh-h0s);
  letter-spacing: var(--ls-display);
  text-wrap: balance;
}

@media (min-width: 981px) {
  .hero__title-main { width: max-content; }
  .hero__title-line { white-space: nowrap; }
}

.hero__intro {
  width: min(100%, var(--hero-intro-width));
  margin-top: clamp(var(--sp-24), 3vw, var(--sp-40));
  color: var(--text-secondary);
  font-size: var(--fs-body-xl);
  line-height: var(--lh-body-xl);
  text-wrap: pretty;
}

.hero__actions {
  display: flex;
  width: 100%;
  align-items: center;
  gap: var(--sp-20);
  margin-top: clamp(var(--sp-40), 4.5vw, var(--sp-64));
}

.button {
  /* Square corners across filled and outlined actions. */
  --button-cut: 0px;
  position: relative;
  z-index: 0;
  display: inline-flex;
  overflow: hidden;
  min-height: var(--sp-56);
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
  padding: var(--sp-16) var(--sp-28);
  clip-path: none;
  border-radius: 0;
  font-size: var(--fs-body-md);
  font-weight: var(--fw-light);
  isolation: isolate;
  line-height: var(--lh-body-md);
  white-space: nowrap;
  transition: color var(--dur-med) var(--ease),
              clip-path var(--dur-med) var(--ease),
              transform var(--dur-fast) var(--ease);
}

.button > span {
  position: relative;
  z-index: 2;
}

.button::after {
  position: absolute;
  z-index: 1;
  inset: 0;
  content: "";
  transform: scaleX(0);
  transform-origin: left center;
  background: var(--text-primary);
  transition: transform var(--dur-med) var(--ease);
}

.button:hover,
.button:focus-visible {
  color: var(--surface-primary);
}

.button:hover::after,
.button:focus-visible::after {
  transform: scaleX(1);
}

.button:active { transform: scale(.98); }

.button--filled {
  color: var(--surface-primary);
  background: var(--brand);
}

.button--filled::after {
  transform: scaleX(0);
  opacity: 1;
  background: var(--text-primary);
  transition: transform var(--dur-med) var(--ease);
}

.button--filled:hover::after,
.button--filled:focus-visible::after {
  transform: scaleX(1);
}

.button--outline {
  color: var(--brand);
  background: var(--brand);
}

.button--outline::before {
  position: absolute;
  z-index: 0;
  inset: var(--border-width);
  clip-path: none;
  content: "";
  background: var(--surface-primary);
}

.button__arrow {
  position: relative;
  top: 0;
  display: inline-grid;
  width: var(--sp-20);
  height: var(--sp-20);
  place-items: center;
  translate: 0 0;
  animation: scroll-arrow calc(var(--dur-slow) + var(--dur-med)) ease-in-out infinite;
  font-size: var(--fs-body-l);
  line-height: var(--sp-20);
  text-align: center;
  transition: translate var(--dur-fast) var(--ease);
}

@keyframes scroll-arrow {
  0%, 100% { transform: translateY(calc(0px - var(--sp-2))); }
  50% { transform: translateY(var(--sp-2)); }
}

.hero__photo {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  min-width: 0;
  min-height: 0;
  align-self: stretch;
  grid-column: 2;
  grid-row: 1;
  overflow: hidden;
  isolation: isolate;
  pointer-events: none;
}

.hero__grid {
  position: absolute;
  z-index: 0;
  top: calc(0px - var(--nav-height));
  right: calc(0px - var(--container-outer-space));
  bottom: 0;
  width: 100vw;
  overflow: visible;
  opacity: .68;
  pointer-events: none;
}

.hero__grid--focus {
  z-index: 0;
  opacity: .16;
}

.hero__grid-field {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom right, transparent 46%, #000 53%);
  mask-image: linear-gradient(to bottom right, transparent 46%, #000 53%);
}

.hero__grid-canvas {
  position: absolute;
  z-index: 1;
  inset: 0;
}

.hero-grid__fade {
  position: absolute;
  z-index: 2;
  top: var(--fade-top);
  left: var(--fade-left);
  width: 14%;
  height: var(--fade-height);
  background: linear-gradient(to right, var(--surface-primary), transparent);
  pointer-events: none;
}

.hero-grid__cell {
  position: absolute;
  top: var(--grid-y);
  left: var(--grid-x);
  width: var(--badge-width);
  height: var(--badge-height);
  background-repeat: no-repeat;
  background-position: calc(var(--badge-width) / -2) 0;
  background-size: calc(var(--badge-width) * 2.5) calc(var(--badge-height) * 2.5);
  opacity: .5;
  transform-origin: center;
}

.hero-grid__focus-cell {
  position: absolute;
  top: var(--grid-y);
  left: var(--grid-x);
  width: var(--badge-width);
  height: var(--badge-height);
  background: var(--brand);
  opacity: 0;
  -webkit-mask-image: var(--grid-mask);
  mask-image: var(--grid-mask);
  -webkit-mask-position: calc(var(--badge-width) / -2) 0;
  mask-position: calc(var(--badge-width) / -2) 0;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: calc(var(--badge-width) * 2.5) calc(var(--badge-height) * 2.5);
  mask-size: calc(var(--badge-width) * 2.5) calc(var(--badge-height) * 2.5);
  pointer-events: none;
  transition: opacity var(--dur-fast) var(--ease);
  will-change: opacity;
}

.hero__photo img {
  position: absolute;
  z-index: 1;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: right bottom;
}

@media (prefers-reduced-motion: no-preference) {
  .reveal-enabled .hero__photo--entrance img {
    opacity: 1;
    transform: translate3d(50px, 0, 0);
  }

  .reveal-enabled .hero__photo--entrance.is-photo-visible img {
    opacity: 1;
    transform: translate3d(0, 0, 0);
    transition: transform 1600ms cubic-bezier(.16, 1, .3, 1) 200ms;
  }
}

.hero__badges {
  position: absolute;
  z-index: 4;
  top: var(--badge-cluster-top);
  right: calc(var(--badge-edge) - var(--container-outer-space));
  width: calc(var(--badge-width) * 3);
  height: calc(var(--badge-height) + var(--badge-row-step) + var(--badge-row-step));
}

.badge {
  position: absolute;
  display: block;
  width: var(--badge-width);
  height: var(--badge-height);
  flex: 0 0 auto;
  transform-origin: center;
  will-change: transform, filter;
  transition: transform calc(var(--dur-slow) + var(--dur-fast)) var(--ease-gentle),
              filter var(--dur-slow) var(--ease-gentle);
}

.badge:hover,
.badge:focus-visible {
  z-index: 2;
  outline: none;
  filter: drop-shadow(0 var(--sp-8) var(--sp-16) color-mix(in srgb, var(--text-primary) 20%, transparent));
  transform: scale(1.1);
}

.tool-badge--claude {
  --tool-bg: var(--surface-secondary);
  --badge-enter-y: calc(0px - var(--badge-enter-distance));
  top: 0;
  left: calc(var(--badge-width) / 2);
}

.tool-badge--codex {
  --tool-bg: var(--surface-secondary);
  --badge-enter-y: calc(0px - var(--badge-enter-distance));
  top: 0;
  left: calc(var(--badge-width) * 1.5);
}

.tool-badge--cursor {
  --tool-bg: var(--surface-secondary);
  --badge-enter-x: var(--badge-enter-distance);
  --badge-enter-y: 0;
  top: var(--badge-row-step);
  left: calc(var(--badge-width) * 2);
}

.tool-badge--higgsfield {
  --tool-bg: var(--surface-secondary);
  --badge-enter-x: calc(0px - var(--badge-enter-distance));
  --badge-enter-y: 0;
  top: var(--badge-row-step);
  left: 0;
}

.tool-badge--n8n {
  --tool-bg: var(--surface-secondary);
  --badge-enter-x: calc(0px - var(--badge-enter-distance));
  --badge-enter-y: 0;
  top: var(--badge-row-step);
  left: var(--badge-width);
}

.tool-badge--supabase {
  --tool-bg: var(--surface-secondary);
  --badge-enter-y: var(--badge-enter-distance);
  top: calc(var(--badge-row-step) * 2);
  left: calc(var(--badge-width) / 2);
}

.tool-badge--figma {
  --tool-bg: var(--surface-secondary);
  --badge-enter-y: var(--badge-enter-distance);
  top: calc(var(--badge-row-step) + var(--badge-row-step));
  left: calc(var(--badge-width) * 1.5);
}

.tool-badge { cursor: default; }

.tool-badge__surface {
  position: absolute;
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}

.tool-badge::after {
  position: absolute;
  inset: 0;
  content: '';
  background: url('assets/images/site/tool-hex-outline.svg') center / 100% 100% no-repeat;
  pointer-events: none;
}

.tool-badge__surface {
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: calc(var(--badge-width) * .065);
  background: var(--tool-bg);
  color: #969BAA;
}

.tool-badge .tool-badge__surface img {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 34%;
  height: 34%;
  object-fit: contain;
  transform: translate(-50%, -50%);
}

.tool-badge--n8n .tool-badge__surface img {
  width: 50%;
}

.tool-badge--figma .tool-badge__surface img {
  width: 26%;
  height: 30%;
}

.tool-badge__surface > span {
  position: absolute;
  top: 83%;
  left: 72%;
  width: 52%;
  transform: translate(-50%, -50%) rotate(-30deg);
  font-size: max(9px, calc(var(--badge-width) * .115));
  font-weight: 600;
  letter-spacing: .035em;
  line-height: 1.2;
  text-transform: uppercase;
  text-align: center;
}

.badge img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* Empty section anchors must not create scrollbars before content is added. */
main > section:not(.hero):empty { min-height: 0; }

/* ============================================================
   Responsive adaptations
   ============================================================ */

@media (max-width: 1180px) {
  .hero {
    grid-template-columns: minmax(0, 58%) minmax(320px, 42%);
  }

  .hero__copy {
    max-width: none;
    padding-left: var(--sp-0);
  }

  .hero__intro { width: 100%; }

  .hero__badges {
    right: calc(var(--badge-edge) - var(--container-outer-space));
  }
}

@media (max-width: 980px) {
  :root {
    --content-pad: var(--sp-24);
    --hero-pad: var(--sp-0);
  }

  .site-nav__inner { padding-inline: var(--content-pad); }
  .site-nav__left { gap: var(--sp-24); }
  .site-nav__links,
  .site-nav__right,
  .site-nav__actions { gap: var(--sp-24); }

  .hero {
    min-height: calc(100svh - var(--header-height));
    min-height: calc(100dvh - var(--header-height));
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(520px, 72svh);
    align-items: stretch;
    overflow: visible;
  }

  .hero__copy {
    width: 100%;
    max-width: none;
    grid-column: 1;
    grid-row: 1;
    padding: clamp(var(--sp-48), 8svh, var(--sp-80)) var(--sp-0) var(--sp-0);
    transform: none;
  }

  .hero__title-main {
    max-width: var(--hero-copy-width);
  }

  .hero__title { width: 100%; }

  .hero__photo {
    position: relative;
    width: 100%;
    height: 100%;
    align-self: stretch;
    grid-column: 1;
    grid-row: 2;
    margin-top: var(--sp-32);
  }

  .hero__badges {
    position: relative;
    top: auto;
    right: auto;
    bottom: auto;
    align-self: center;
    grid-column: 1;
    grid-row: 2;
    justify-self: end;
    margin-right: var(--sp-16);
    transform: none;
  }
}

@media (max-width: 720px) {
  :root {
    --content-pad: var(--sp-16);
    --nav-height: calc(var(--sp-20) + var(--sp-20) + var(--sp-20) + var(--sp-32));
  }

  .site-nav__inner {
    align-items: stretch;
    flex-direction: column;
    gap: var(--sp-16);
    padding: var(--sp-16) var(--content-pad);
  }

  .site-nav__left {
    width: 100%;
    min-width: 0;
    justify-content: space-between;
    gap: var(--sp-16);
  }

  .site-logo {
    width: max-content;
    height: auto;
  }

  .site-logo__mark {
    width: calc(min(var(--nav-logo-width), 42vw) * .2592);
  }

  .availability {
    min-width: 0;
    flex: 1 1 auto;
    justify-content: flex-end;
    gap: var(--sp-8);
    font-size: var(--fs-body-xs);
    line-height: var(--lh-body-xs);
    text-align: right;
    white-space: normal;
  }

  .site-nav__right {
    width: 100%;
    justify-content: space-between;
    gap: var(--sp-16);
  }

  .site-nav__links { gap: var(--sp-24); flex-wrap: wrap; }
  .site-nav__actions { gap: var(--sp-16); }
  .site-nav__separator { display: none; }

  .site-nav__links a,
  .site-nav__actions a { font-size: var(--fs-body-sm); }

  .hero {
    min-height: calc(100svh - var(--header-height));
    min-height: calc(100dvh - var(--header-height));
    grid-template-rows: auto clamp(420px, 64svh, 560px);
  }

  .hero__copy {
    padding: var(--sp-48) var(--sp-0) var(--sp-0);
  }

  .hero__meta {
    margin-bottom: var(--sp-24);
    font-size: var(--fs-body-sm);
    line-height: var(--lh-body-sm);
  }

  .hero__title-accent { letter-spacing: var(--ls-display); }

  .hero__intro {
    margin-top: var(--sp-24);
  }

  .hero__actions {
    align-items: stretch;
    flex-direction: column;
    margin-top: var(--sp-48);
  }

  .button { width: 100%; }

  .hero__photo {
    width: 100%;
    height: 100%;
    grid-column: 1;
    grid-row: 2;
    margin-top: var(--sp-48);
  }

  .hero__photo img { object-position: center bottom; }

  .hero__badges {
    position: relative;
    top: auto;
    right: auto;
    bottom: auto;
    width: calc(var(--badge-width) * 3);
    height: calc(var(--badge-height) + var(--badge-row-step) + var(--badge-row-step));
    align-self: start;
    grid-column: 1;
    grid-row: 2;
    justify-self: end;
    margin: var(--sp-64) var(--sp-0) var(--sp-0);
  }
}

/* Physical 5K override: CSS viewport units can be reduced by Retina DPR or app panels. */
:root.honeycomb-xl .testimonials-section__inner {
  min-height: 1000px;
}

/* Use the physical 4K/5K screen size even when the site sits in a narrow panel. */
:root.honeycomb-xl {
  --badge-width: 112px;
  --badge-height: 128.8px;
  --badge-row-step: 96.6px;
  --badge-enter-distance: 24px;
}

/* CSS-only fallback when JavaScript is unavailable. */
@media (min-width: 4000px) {
  :root {
    --badge-width: 112px;
    --badge-height: 128.8px;
    --badge-row-step: 96.6px;
    --badge-enter-distance: 24px;
  }
}

@media (max-width: 360px) {
  .hero__title-accent { white-space: normal; }
}

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

  .hero__grid-focus-canvas { display: none; }

  *, *::before, *::after {
    scroll-behavior: auto !important;
    transition-duration: .01ms !important;
  }

  .rv {
    opacity: 1 !important;
    translate: none !important;
  }

  .availability__dot::after {
    opacity: 0;
    animation: none;
  }
  .button__arrow {
    top: 0 !important;
    animation: none;
  }

}

/* ============================================================
   Static page sections — Figma frame 2011:7864
   ============================================================ */

.section-heading,
.section-heading__copy,
.section-title {
  display: flex;
  align-items: flex-start;
  flex-direction: column;
}

.section-heading__copy { gap: var(--sp-40); }

.section-title span { display: block; }

.work-section__heading .h1-style,
.testimonials-section .section-title .h1-style {
  color: var(--brand);
}

.work-section,
.about-section { background: var(--surface-secondary); }

.testimonials-section,
.contact-footer {
  position: relative;
  overflow: hidden;
  background: var(--surface-primary);
}

/* Honeycomb rising out of the footer's bottom edge and dissolving upwards, so
   it is already faint behind the copyright line and gone above it. The tile
   carries the hero's cell geometry (80x92, 69 row step) and is sized from
   --badge-width, so it scales with the hero on 4K/5K screens. */
.contact-footer::before {
  content: "";
  position: absolute;
  z-index: 0;
  inset: 0;
  background-image: url("assets/images/site/hex-tile-hero.svg");
  background-position: left bottom;
  background-repeat: repeat;
  background-size: var(--badge-width) calc(var(--badge-width) * 138 / 80);
  -webkit-mask-image: linear-gradient(to top, #000 0%, rgba(0, 0, 0, .4) 12%, transparent 32%);
  mask-image: linear-gradient(to top, #000 0%, rgba(0, 0, 0, .4) 12%, transparent 32%);
  pointer-events: none;
}

.contact-footer__inner {
  position: relative;
  z-index: 1;
}

.work-section__inner,
.testimonials-section__inner,
.about-section__inner,
.contact-footer__inner {
  width: var(--container-max);
  margin-inline: auto;
}

/* Selected work */
.work-section {
  --active-brand: var(--surface-secondary);
  --work-grid-height: calc(var(--sp-120) + var(--sp-120));
  position: relative;
  overflow: clip;
  background-color: var(--surface-secondary);
  transition: background-color 500ms var(--ease), color 500ms var(--ease);
}

.work-grid-continuation {
  position: absolute;
  z-index: 0;
  top: 0;
  right: 0;
  width: 62vw;
  height: var(--work-grid-height);
  overflow: hidden;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, rgba(0, 0, 0, .82) 36%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0%, rgba(0, 0, 0, .82) 36%, transparent 100%);
  transition: opacity 500ms var(--ease);
}

.work-grid-continuation__canvas {
  position: absolute;
  inset: 0;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, rgba(0,0,0,.35) 30%, #000 70%);
  mask-image: linear-gradient(to right, transparent 0%, rgba(0,0,0,.35) 30%, #000 70%);
  transition: filter 500ms var(--ease);
}

.work-grid__cell {
  position: absolute;
  top: var(--grid-y);
  left: var(--grid-x);
  width: var(--badge-width);
  height: var(--badge-height);
  background-repeat: no-repeat;
  background-position: calc(var(--badge-width) / -2) 0;
  background-size: calc(var(--badge-width) * 2.5) calc(var(--badge-height) * 2.5);
  opacity: .5;
}

.work-section.is-project-active {
  color: var(--surface-primary);
  background-color: var(--active-brand);
}

.work-section.is-project-active .work-grid-continuation { opacity: 1; }
.work-section.is-project-active .work-grid-continuation__canvas { filter: brightness(0) invert(1); }

.work-section__inner {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: stretch;
  flex-direction: column;
  gap: clamp(var(--sp-64), 6vw, var(--sp-96));
  padding-block: clamp(var(--sp-80), 6.944vw, var(--sp-120));
}

.work-section__heading {
  width: 100%;
  align-items: flex-start;
  justify-content: space-between;
  flex-direction: row;
}

.view-options {
  display: flex;
  align-items: center;
  gap: var(--sp-20);
  min-height: 1lh;
  font-size: var(--fs-eyebrow);
  line-height: var(--lh-eyebrow);
}

.view-options__icon {
  appearance: none;
  display: grid;
  width: 1lh;
  height: 1lh;
  border: 0;
  padding: 0;
  place-items: center;
  opacity: .42;
  color: var(--brand);
  background: transparent;
  cursor: pointer;
  font: inherit;
  transition: opacity var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

.view-options__icon.is-active,
.view-options__icon:hover,
.view-options__icon:focus-visible { opacity: 1; }

.view-options__icon:focus-visible { outline: none; }
.view-options__icon .ui-icon {
  width: 1lh;
  height: 1lh;
  filter: invert(22%) sepia(16%) saturate(2642%) hue-rotate(198deg) brightness(83%) contrast(88%);
}

.work-section__heading,
.work-section__heading .eyebrow,
.work-section__heading .h1,
.work-section__heading .h1-style {
  transition: color 500ms var(--ease);
}

.work-section.is-project-active .work-section__heading,
.work-section.is-project-active .work-section__heading .eyebrow,
.work-section.is-project-active .work-section__heading .h1,
.work-section.is-project-active .work-section__heading .h1-style {
  color: var(--surface-primary);
}

.work-section.is-project-active .view-options__icon .ui-icon { filter: brightness(0) invert(1); }

.project-list {
  width: 100%;
  transition: border-color 500ms var(--ease);
}

.project-list.is-reveal-pending .project-row {
  opacity: 0;
  transform: translate3d(0, var(--sp-48), 0);
}

.project-list.is-project-revealing .project-row {
  animation: project-row-reveal var(--dur-slow) var(--ease) both;
  animation-delay: calc(var(--project-order) * var(--stagger));
  will-change: opacity, transform;
}

@keyframes project-row-reveal {
  from {
    opacity: 0;
    transform: translate3d(0, var(--sp-48), 0);
  }

  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

.project-row {
  width: 100%;
  border-top: .5px solid var(--text-muted);
  transition: border-color 500ms var(--ease), opacity var(--dur-med) var(--ease);
}

.project-row__link {
  display: block;
  width: 100%;
  padding-block: var(--sp-24);
  color: inherit;
  outline: none;
  transition: opacity var(--dur-med) var(--ease);
}

.project-row__link:focus-visible h3 {
  text-decoration: underline;
  text-decoration-thickness: var(--border-width);
  text-underline-offset: var(--sp-8);
}

.project-row__summary {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-40);
}

.project-row[data-project="privitas"] { --project-brand: var(--brand-privitas); }
.project-row[data-project="travalera"] { --project-brand: var(--brand-travalera); }
.project-row[data-project="bixy"] { --project-brand: var(--brand-bixy); }
.project-row[data-project="tinyco"] { --project-brand: var(--brand-tinyco); }
.project-row[data-project="smartouch"] { --project-brand: var(--brand-smartouch); }
.project-row[data-project="socialgaines"] { --project-brand: var(--brand-socialgaines); }

.project-row h3 {
  flex: 1 1 auto;
  color: var(--project-brand, var(--text-primary));
  transition: color 500ms var(--ease), opacity var(--dur-med) var(--ease);
}

.project-row__summary > p {
  flex: 0 0 auto;
  color: var(--text-muted);
  white-space: nowrap;
  transition: color 500ms var(--ease), opacity var(--dur-med) var(--ease);
}

.project-row__details {
  overflow: hidden;
  max-width: 64ch;
  max-height: 0;
  margin-top: 0;
  opacity: 0;
  translate: 0 var(--sp-12);
  transition: max-height var(--dur-slow) var(--ease),
              margin-top var(--dur-slow) var(--ease),
              opacity var(--dur-med) var(--ease),
              translate var(--dur-slow) var(--ease);
}

.project-row__details > p { color: inherit; }

.project-row__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  margin-top: var(--sp-8);
  list-style: none;
}

.project-row__tags li {
  padding: var(--sp-4) var(--sp-8);
  color: inherit;
  background: color-mix(in srgb, currentColor 18%, transparent);
  font-size: var(--fs-body-xs);
  line-height: 1;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.work-section.is-project-active .project-list,
.work-section.is-project-active .project-row {
  border-color: color-mix(in srgb, var(--surface-primary) 28%, transparent);
}

.work-section.is-project-active .project-row:not(.is-active) .project-row__link { opacity: .34; }

.work-section.is-project-active .project-row h3,
.work-section.is-project-active .project-row__summary > p { color: var(--surface-primary); }

.project-row.is-active .project-row__link { opacity: 1; }

.project-row.is-active .project-row__summary > p { opacity: 0; }

.project-row.is-active .project-row__details {
  max-height: clamp(180px, 12.5vw, 360px);
  margin-top: var(--sp-8);
  opacity: 1;
  translate: none;
}

.project-list.is-grid-view {
  display: grid;
  border-bottom: 0;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-20);
}

.project-list.is-grid-view .project-row {
  min-height: clamp(220px, 15.278vw, 440px);
  border: .5px solid var(--text-muted);
  padding-inline: var(--sp-24);
}

.work-section.is-project-active .project-list.is-grid-view .project-row {
  border-color: color-mix(in srgb, var(--surface-primary) 28%, transparent);
}

.project-list.is-grid-view .project-row__summary {
  align-items: flex-start;
  flex-direction: column;
  gap: var(--sp-8);
}

.project-list.is-grid-view .project-row__summary > p { white-space: normal; }

.project-preview {
  position: fixed;
  z-index: 40;
  right: var(--sp-40);
  bottom: 0;
  width: min(44vw, 640px);
  aspect-ratio: 16 / 10;
  opacity: 0;
  pointer-events: none;
  transform: translate3d(var(--preview-x, 0), var(--preview-y, 0), 0);
  translate: 0 var(--sp-24);
  will-change: opacity, transform, translate;
  transition: opacity var(--dur-med) var(--ease),
              translate var(--dur-slow) var(--ease),
              transform var(--dur-fast) var(--ease);
}

.work-section.is-project-active .project-preview {
  opacity: 1;
  translate: none;
}

.project-preview__frame {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: var(--surface-primary);
  box-shadow: 0 var(--sp-20) var(--sp-48) color-mix(in srgb, var(--text-primary) 18%, transparent);
}

.project-cursor {
  position: fixed;
  z-index: 60;
  top: var(--project-cursor-y, 0);
  left: var(--project-cursor-x, 0);
  display: grid;
  width: var(--sp-48);
  aspect-ratio: 1;
  place-items: center;
  color: var(--brand);
  background: var(--surface-primary);
  font-size: var(--fs-body-xl);
  line-height: 1;
  opacity: 0;
  pointer-events: none;
  translate: -50% -50%;
  transform: scale(.82);
  will-change: top, left, opacity, transform;
  transition: opacity var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease);
}

.work-section.is-project-pointer-active .project-cursor {
  opacity: 1;
  transform: scale(1);
}

@media (hover: hover) and (pointer: fine) {
  .work-section.is-project-pointer-active .project-row__link { cursor: none; }
}

.project-preview__panel {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity var(--dur-med) var(--ease);
}

.project-preview__panel.is-active { opacity: 1; }

.project-preview__panel img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.project-preview__panel--fallback {
  display: grid;
  overflow: hidden;
  place-items: center;
  color: color-mix(in srgb, var(--surface-primary) 88%, transparent);
  background: var(--active-brand);
}

.project-preview__panel--fallback::before {
  position: absolute;
  inset: 8%;
  border: .5px solid color-mix(in srgb, var(--surface-primary) 42%, transparent);
  content: "";
  background:
    linear-gradient(color-mix(in srgb, var(--surface-primary) 14%, transparent) .5px, transparent .5px),
    linear-gradient(90deg, color-mix(in srgb, var(--surface-primary) 14%, transparent) .5px, transparent .5px);
  background-size: var(--sp-40) var(--sp-40);
}

.project-preview__panel--fallback span {
  position: relative;
  z-index: 1;
  font-family: var(--font-display);
  font-size: var(--fs-h1);
  font-style: normal;
}

/* Testimonials */
.testimonials-section { position: relative; isolation: isolate; }
.testimonials-section__inner {
  position: relative;
  z-index: 1;
  display: grid;
  min-height: clamp(800px, 52.083vw, 1000px);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-40);
  padding-block: clamp(var(--sp-80), 6.944vw, var(--sp-120));
}

.testimonials-section__overview,
.testimonial-card {
  display: flex;
  min-width: 0;
  flex-direction: column;
  justify-content: space-between;
}

.testimonial-stats {
  display: grid;
  width: 80%;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-40);
  color: var(--text-primary);
}

.testimonial-stat {
  --stat-order: 0;
  display: flex;
  align-items: flex-start;
  flex-direction: column;
}

.testimonial-stat:nth-child(2) { --stat-order: 1; }
.testimonial-stat:nth-child(3) { --stat-order: 2; }

.testimonial-stats.is-counting .stat-icon__primary {
  animation: testimonial-icon-primary-in var(--dur-slow) var(--ease) both;
  animation-delay: calc(var(--stat-order) * var(--stagger));
}

.testimonial-stats.is-counting .stat-icon--users .stat-icon__secondary {
  animation: testimonial-icon-detail-in var(--dur-med) var(--ease) both;
  animation-delay: calc(var(--stat-order) * var(--stagger) + var(--dur-fast));
}

.testimonial-stats.is-counting .stat-icon__check {
  animation: testimonial-icon-check-in var(--dur-med) var(--ease) both;
  animation-delay: calc(var(--stat-order) * var(--stagger) + var(--dur-fast));
}

.testimonial-stats.is-counting .stat-icon__spin {
  animation: testimonial-icon-spin-in var(--dur-slow) var(--ease) both;
  animation-delay: calc(var(--stat-order) * var(--stagger));
}

@keyframes testimonial-icon-primary-in {
  from {
    opacity: 0;
    transform: translate3d(0, var(--sp-8), 0) scale(.9);
  }

  to {
    opacity: 1;
    transform: translate3d(0, 0, 0) scale(1);
  }
}

@keyframes testimonial-icon-detail-in {
  from {
    opacity: 0;
    transform: translate3d(calc(0px - var(--sp-4)), var(--sp-4), 0);
  }

  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

@keyframes testimonial-icon-check-in {
  from {
    opacity: 0;
    stroke-dashoffset: 10;
  }

  to {
    opacity: 1;
    stroke-dashoffset: 0;
  }
}

@keyframes testimonial-icon-spin-in {
  from {
    opacity: 0;
    transform: rotate(-360deg) scale(.9);
  }

  to {
    opacity: 1;
    transform: rotate(0) scale(1);
  }
}

.testimonial-stat > .ui-icon {
  width: var(--sp-24);
  height: var(--sp-24);
  margin-bottom: var(--sp-12);
  overflow: visible;
  color: var(--brand);
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.stat-icon__primary,
.stat-icon__secondary,
.stat-icon__spin {
  transform-box: fill-box;
  transform-origin: center;
}

.stat-icon__check {
  stroke-dasharray: 10;
  stroke-dashoffset: 0;
}

.testimonial-stat dt {
  margin-bottom: var(--sp-4);
  color: var(--text-primary);
  font-weight: var(--fw-light);
}

.testimonial-stat dd {
  color: var(--text-secondary);
  white-space: nowrap;
}

.testimonial-card { position: relative; align-items: stretch; padding-top: 120px; }

.testimonial-card__position {
  position: absolute;
  right: 0;
  top: 0;
  width: 120px;
  height: 112px;
  color: var(--text-secondary);
  font-size: var(--fs-eyebrow);
  line-height: var(--lh-eyebrow);
}

.testimonial-card__navigation-mark { position: absolute; inset: 0; width: 120px; height: 100px; pointer-events: none; }
.testimonial-card__position > [data-testimonial-position] { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
.testimonial-card__position [data-testimonial-prev] { left: 5px; }
.testimonial-card__position [data-testimonial-next] { left: 65px; }
.testimonial-number-band { position: absolute; z-index: 0; inset: 0; overflow: hidden; pointer-events: none; }
.testimonial-number-band > span { position: absolute; right: var(--container-outer-space); bottom: -.18em; color: var(--surface-secondary); font-size: clamp(400px, 36vw, 700px); font-weight: 400; line-height: 1; letter-spacing: -.07em; }

.testimonial-card__position .ui-icon {
  width: 1lh;
  height: 1lh;
}

.testimonial-card__arrow {
  position: absolute;
  top: 4px;
  appearance: none;
  display: grid;
  width: 50px;
  height: 54px;
  border: 0;
  padding: 0;
  place-items: center;
  opacity: .72;
  background: transparent;
  cursor: pointer;
  font: inherit;
  transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}

.testimonial-card__arrow:hover,
.testimonial-card__arrow:focus-visible { opacity: 1; }

.testimonial-card__arrow:active { transform: scale(.92); }

.testimonial-card__arrow:focus-visible {
  outline: .5px solid var(--brand);
  outline-offset: var(--sp-4);
}

.testimonial-stage {
  display: grid;
  min-width: 0;
  margin-top: auto;
}

.testimonial-card__quote {
  display: flex;
  align-items: flex-start;
  flex-direction: column;
  gap: var(--sp-40);
}

.testimonial-slide {
  grid-area: 1 / 1;
  opacity: 0;
  pointer-events: none;
  transform: translate3d(var(--sp-12), 0, 0);
  visibility: hidden;
  transition: opacity var(--dur-med) var(--ease), transform var(--dur-med) var(--ease);
  will-change: opacity, transform;
}

.testimonial-slide.is-active {
  opacity: 1;
  pointer-events: auto;
  transform: translate3d(0, 0, 0);
  visibility: visible;
}

.testimonial-slide.is-entering-next,
.testimonial-slide.is-leaving-prev { transform: translate3d(var(--sp-12), 0, 0); }

.testimonial-slide.is-entering-prev,
.testimonial-slide.is-leaving-next { transform: translate3d(calc(0px - var(--sp-12)), 0, 0); }

.testimonial-slide.is-entering-next,
.testimonial-slide.is-entering-prev,
.testimonial-slide.is-leaving-next,
.testimonial-slide.is-leaving-prev { visibility: visible; }

.testimonial-card__mark {
  width: var(--sp-96);
  height: var(--sp-80);
}

.testimonial-card__quote > p {
  max-width: 100%;
  color: var(--brand);
}

.testimonial-profile {
  margin-top: auto;
}

.testimonial-profile__link {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-20);
  color: inherit;
  text-decoration: none;
}

.testimonial-profile__link:hover cite { color: var(--brand); }

.testimonial-profile__link:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: var(--sp-4);
}

.testimonial-profile__photo {
  width: var(--sp-64);
  height: auto;
  aspect-ratio: 1 / 1.1547;
  flex-shrink: 0;
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  object-fit: cover;
}

.testimonial-profile cite {
  display: block;
  color: var(--text-primary);
  font-style: normal;
  font-weight: var(--fw-light);
}

.testimonial-profile__role {
  display: flex;
  align-items: center;
  gap: var(--sp-16);
  color: var(--text-secondary);
}

.testimonial-profile__role img {
  width: var(--sp-16);
  height: var(--sp-16);
}

/* About */
.about-section { overflow: clip; }

.about-section__inner {
  display: flex;
  min-height: 235svh;
  flex-direction: column;
}

.about-section__row {
  display: grid;
  flex: 1 1 auto;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: start;
  gap: var(--sp-40);
  padding-block: var(--sp-72);
}

.about-section__column {
  position: sticky;
  top: calc(var(--nav-height) + var(--sp-40));
  display: flex;
  min-height: calc(100svh - var(--nav-height) - var(--sp-80));
  align-items: flex-start;
  flex-direction: column;
  justify-content: space-between;
}

.about-section__copy {
  display: flex;
  width: 100%;
  align-items: flex-start;
  flex-direction: column;
  gap: var(--sp-32);
}

.about-title { color: var(--brand); }
.about-title span { color: var(--text-primary); }

.about-section__intro {
  max-width: clamp(600px, calc(365.217px + 16.30435vw), 1200px);
  color: var(--text-secondary);
}

.about-section__toolkit {
  max-width: clamp(600px, calc(365.217px + 16.30435vw), 1200px);
  color: var(--text-secondary);
}

.about-section__location { color: var(--text-muted); }

.about-section__cv { margin-top: var(--sp-64); }

.about-process {
  position: sticky;
  top: calc(var(--nav-height) + var(--sp-80));
  display: flex;
  width: 100%;
  min-width: 0;
  align-self: start;
  align-items: center;
  flex-direction: column;
  justify-content: center;
  isolation: isolate;
}

.about-process__honeycomb {
  position: absolute;
  z-index: -1;
  top: 50%;
  left: 50%;
  display: grid;
  width: 100%;
  min-width: 0;
  place-items: center;
  transform: translate(-50%, -50%);
  pointer-events: none;
}

.about-honeycomb__canvas {
  position: relative;
  flex: none;
  opacity: .64;
  transform: scale(var(--about-grid-scale, 1));
  transform-origin: center;
  -webkit-mask-image: radial-gradient(ellipse at center, #000 18%, rgba(0, 0, 0, .72) 54%, transparent 100%);
  mask-image: radial-gradient(ellipse at center, #000 18%, rgba(0, 0, 0, .72) 54%, transparent 100%);
}

.about-honeycomb__cell {
  position: absolute;
  top: var(--grid-y);
  left: var(--grid-x);
  width: var(--badge-width);
  height: var(--badge-height);
  background-position: calc(var(--badge-width) / -2) 0;
  background-repeat: no-repeat;
  background-size: calc(var(--badge-width) * 2.5) calc(var(--badge-height) * 2.5);
  opacity: var(--cell-opacity, 1);
}

.about-process__frame {
  position: relative;
  z-index: 1;
  width: 100%;
  overflow: hidden;
  aspect-ratio: 1440 / 1024;
}

.about-process__flow,
.about-process__wireframe,
.about-process__visual {
  position: absolute;
  inset: 0;
}

.about-process__wireframe,
.about-process__visual {
  opacity: 0;
  pointer-events: none;
}

.about-process__wireframe img,
.about-process__visual img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.about-process__screen {
  position: absolute;
  z-index: 2;
  top: var(--screen-top);
  left: var(--screen-left);
  width: var(--screen-width);
  height: var(--screen-height);
  overflow: hidden;
  opacity: 0;
  transform: translate3d(0, var(--sp-16), 0) scale(.985);
  transform-origin: center;
  will-change: top, left, width, height, opacity, transform;
}

.about-process__screen img {
  position: absolute;
  top: var(--image-top);
  left: var(--image-left);
  width: var(--image-width);
  max-width: none;
  height: auto;
}

.about-process__connectors {
  position: absolute;
  z-index: 1;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  fill: none;
  stroke: var(--text-primary);
  stroke-linecap: square;
  stroke-linejoin: miter;
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
}

.about-process__connector {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  will-change: opacity, stroke-dashoffset;
}

.about-process__arrowhead {
  fill: none;
  stroke: var(--text-primary);
  stroke-linecap: square;
  stroke-linejoin: miter;
  stroke-width: 1.5;
}

.about-process__wireframe {
  z-index: 5;
  will-change: opacity;
}

.about-process__visual {
  z-index: 6;
  clip-path: inset(0 100% 0 0);
  will-change: opacity, clip-path;
}

.about-process__caption {
  display: flex;
  z-index: 2;
  align-items: center;
  gap: var(--sp-12);
  margin-top: var(--sp-16);
  color: var(--text-muted);
}

.about-process__caption span { transition: color var(--dur-fast) var(--ease); }
.about-process[data-stage="flow"] .about-process__caption span:first-child,
.about-process[data-stage="wireframe"] .about-process__caption span:nth-child(3),
.about-process[data-stage="visual"] .about-process__caption span:last-child { color: var(--brand); }

.about-ticker {
  width: 100%;
  overflow: hidden;
  color: var(--brand);
}

.about-ticker__track {
  display: flex;
  width: max-content;
  will-change: transform;
  animation: about-ticker-scroll 30s linear infinite;
}

.about-ticker:hover .about-ticker__track { animation-play-state: paused; }

.about-capabilities {
  display: flex;
  flex: none;
  align-items: center;
  gap: var(--sp-16);
  padding-block: var(--sp-40);
  padding-right: var(--sp-16);
  color: var(--brand);
  list-style: none;
  white-space: nowrap;
}

.about-capabilities li {
  display: flex;
  align-items: center;
  gap: var(--sp-16);
}

.about-capabilities li + li::before {
  content: "·";
  color: var(--brand);
}

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

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

  .about-process__flow,
  .about-process__wireframe { display: none; }

  .about-process__visual {
    display: block;
    opacity: 1;
    clip-path: none;
  }
}

/* Contact footer */
.contact-footer { background: var(--surface-secondary); }
.contact-footer__inner {
  display: flex;
  align-items: stretch;
  flex-direction: column;
  gap: var(--sp-80);
  padding-top: clamp(var(--sp-120), 9.722vw, 320px);
  padding-bottom: clamp(var(--sp-80), 6.944vw, var(--sp-120));
}

.contact-footer__main {
  display: flex;
  align-items: flex-start;
  flex-direction: column;
  gap: var(--sp-20);
}

.contact-footer__prompt { color: var(--text-primary); }

.contact-footer__email {
  display: block;
  color: var(--brand);
  font-family: var(--font-body);
  font-size: var(--fs-contact);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-contact);
  letter-spacing: var(--ls-display);
  overflow-wrap: anywhere;
}

@media (min-width: 981px) {
  .contact-footer__email { font-size: 280px; }
}

.contact-footer__email-domain {
  display: inline-block;
  white-space: nowrap;
}

.contact-footer__bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-40);
  color: var(--text-secondary);
}

.contact-footer__links {
  display: flex;
  align-items: center;
  gap: var(--sp-40);
}

.contact-footer__links > a:not(.linkedin-link) { color: var(--brand); }

/* Section responsiveness */
@media (max-width: 980px) {
  .work-section__inner,
  .testimonials-section__inner,
  .contact-footer__inner {
    padding-block: var(--sp-80);
  }

  .testimonials-section__inner {
    min-height: 0;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--sp-80);
  }

  .testimonials-section__overview,
  .testimonial-card { gap: var(--sp-64); }

  .testimonial-stats { width: 100%; }

  .about-section__inner {
    min-height: 0;
    padding-block: var(--sp-80) var(--sp-64);
  }

  .about-section__row {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--sp-64);
    padding-block: 0;
  }

  .about-section__column {
    position: relative;
    top: auto;
    min-height: 0;
    gap: var(--sp-64);
  }

  .about-section__intro { max-width: 720px; }

  .about-process {
    position: relative;
    top: auto;
    width: 100%;
    max-width: 760px;
    margin-inline: auto;
    align-self: center;
  }

  .contact-footer__inner { padding-top: var(--sp-120); }
}

@media (max-width: 720px) {
  .section-heading__copy { gap: var(--sp-24); }

  .work-section__inner,
  .testimonials-section__inner,
  .contact-footer__inner {
    gap: var(--sp-64);
    padding-block: var(--sp-64);
  }

  .work-section__heading { align-items: flex-start; }

  .view-options { gap: var(--sp-12); }

  .project-row__link { padding-block: var(--sp-20); }

  .project-row__summary {
    align-items: flex-start;
    flex-direction: column;
    gap: var(--sp-8);
  }

  .project-row__summary > p { white-space: normal; }

  .project-list.is-grid-view { grid-template-columns: minmax(0, 1fr); }

  .project-preview {
    right: var(--sp-16);
    bottom: var(--sp-16);
    width: calc(100vw - var(--sp-32));
  }

  .project-cursor { display: none; }

  .testimonials-section__overview,
  .testimonial-card { gap: var(--sp-48); }

  .testimonial-card__quote { gap: var(--sp-32); }
  .testimonial-card__position { align-self: flex-start; }

  .testimonial-profile__photo {
    width: var(--sp-56);
    height: auto;
  }

  .about-section__inner { padding-top: var(--sp-64); }

  .about-section__row { gap: var(--sp-48); }
  .about-section__column { gap: var(--sp-48); }
  .about-process {
    width: 100%;
    margin-inline: 0;
  }

  .about-process__caption {
    gap: var(--sp-8);
    font-size: var(--fs-body-xs);
  }

  .about-capabilities {
    gap: var(--sp-8) var(--sp-12);
    padding-block: var(--sp-32);
  }

  .about-capabilities li { gap: var(--sp-12); }

  .contact-footer__inner { padding-top: var(--sp-80); }

  .contact-footer__bottom {
    align-items: flex-start;
    flex-direction: column;
  }

  .contact-footer__links {
    align-items: flex-start;
    flex-wrap: wrap;
    gap: var(--sp-16) var(--sp-24);
  }
}

/* ============================================================
   Case study pages — scaffold + tinyCo hero/snapshot
   Frame: Figma 2063:5454. Reuses the tokens, .eyebrow, .button,
   .h0/.body-*, --cut-corner and the .rv reveal system defined
   above. Shared components (nav/footer) are only tweaked under
   .case-page so the homepage is untouched.
   ============================================================ */

.case-page {
  /* Case study content column: 960px at the 1440 Figma frame (240px gutters),
     scaling up past 1440 and collapsing to the page padding on small screens. */
  --cs-col: min(clamp(960px, 66.667vw, 1440px), calc(100% - 2 * var(--content-pad)));
  /* Gap between the left/right columns — grows with the viewport. */
  /* 40px at the 1440 frame, growing to 80px at 5K like the rest of the scale. */
  --cs-col-gap: var(--sp-40);
}

.case-study__inner {
  width: var(--cs-col);
  margin-inline: auto;
}

/* Nav: sit the project list beside the logo, wrap it, mark current. */
.case-page .site-nav__left { gap: clamp(var(--sp-24), 3vw, var(--sp-56)); }
.case-page .site-nav__links { flex-wrap: wrap; row-gap: var(--sp-8); }

/* Centre the nav links on the page itself, independent of how wide the logo
   and the actions on either side happen to be. Only above 980px, where there
   is room; below that they'd collide with the logo. */
@media (min-width: 981px) {
  .site-nav__inner { position: relative; }

  .site-nav__links {
    position: absolute;
    top: 50%;
    left: 50%;
    translate: -50% -50%;
    flex-wrap: nowrap;
  }

  /* The divider sat between the links and the actions; with the links pulled
     out of the flow it has nothing left to separate. */
  .site-nav__separator { display: none; }
}
.case-page .site-nav__links a[aria-current="page"] { color: var(--brand); }
.case-page .site-nav__links a[aria-current="page"]::after {
  transform: scaleX(1);
  background: var(--brand);
}

/* --- Hero + snapshot ---------------------------------------- */
.case-hero {
  position: relative;
  /* Clip sideways (the backdrop's negative right offset would otherwise cause
     horizontal scroll) but stay visible vertically, so the honeycomb can
     extend up behind the transparent nav like the landing-page hero does. */
  overflow-x: clip;
  overflow-y: visible;
  background: var(--surface-primary);
}

.case-hero__inner {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: flex-start;
  flex-direction: column;
  padding-block: var(--sp-40) 0;
}

/* Honeycomb backdrop — homepage hero tile. Covers the right 40% of the
   viewport and runs the full height of the hero, from behind the nav down to
   the section's bottom edge, fading out towards the left. */
.case-hero__backdrop {
  position: absolute;
  z-index: 0;
  top: calc(0px - var(--nav-height));
  right: 0;
  bottom: 0;
  width: 40vw;
  overflow: hidden;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(to left, #000 0%, #000 55%, transparent 100%);
  mask-image: linear-gradient(to left, #000 0%, #000 55%, transparent 100%);
}

.case-hero__backdrop-canvas { position: absolute; inset: 0; }

.cs-honeycomb__cell {
  position: absolute;
  top: var(--grid-y);
  left: var(--grid-x);
  width: var(--badge-width);
  height: var(--badge-height);
  background-repeat: no-repeat;
  background-position: calc(var(--badge-width) / -2) 0;
  background-size: calc(var(--badge-width) * 2.5) calc(var(--badge-height) * 2.5);
  opacity: .5;
}

/* The light mesh reads much stronger against the green sections than against
   white, so it runs at half strength there, with the mask fading it further
   towards the far edge. */
.challenge .cs-honeycomb__cell,
.results .cs-honeycomb__cell { opacity: .25; }

/* Brand logos (placeholder wordmarks until real SVGs are added). */
.case-hero__logos {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-12) var(--sp-20);
  margin-bottom: var(--sp-24);
}

.case-logo {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-8);
  color: var(--text-primary);
  font-size: var(--fs-body-l);
  line-height: 1;
  letter-spacing: -0.01em;
  white-space: nowrap;
}

.case-logo__mark {
  display: grid;
  width: 1.5em;
  height: 1.5em;
  flex: 0 0 auto;
  place-items: center;
  border-radius: 50%;
  color: var(--surface-primary);
  font-size: .72em;
  font-weight: var(--fw-semibold);
}

.case-logo__mark--email { background: var(--brand-tinyco); }
.case-logo__mark--albert { background: var(--brand-smartouch); }

.case-logo__text { font-weight: var(--fw-regular); }
.case-logo__text b { font-weight: var(--fw-semibold); }
.case-logo__text sup { font-size: .5em; vertical-align: super; }
.case-logo__accent { color: var(--brand-smartouch); }

/* Real product-logo images (replace the placeholder wordmarks). */
.case-hero__logo {
  display: block;
  width: auto;
  height: calc(var(--sp-24) * .8);
  flex: 0 0 auto;
}

/* Title / subtitle — full 960 column, H1 (56/64) + body-l per Figma. */
/* The hero column is align-items: flex-start, so children are shrink-to-fit by
   default. Stretching the title and subtitle gives them the same measure as the
   divider and snapshot below, and lets each line break at the real column edge
   instead of at whatever width the text happened to need. */
/* normal, not balance: balance equalises line lengths, which on a two-line
   headline pulls words back off line one and leaves it short. Filling the
   column is what keeps the title the same measure as the hero image below. */
.case-hero__title {
  align-self: stretch;
  max-width: 100%;
  color: var(--text-primary);
  text-wrap: normal;
}

.case-hero__subtitle {
  align-self: stretch;
  max-width: 100%;
  margin-top: var(--sp-12);
  color: var(--text-secondary);
  text-wrap: pretty;
}

/* Tag row — same pill language as the homepage project tags. */
.case-hero__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  margin-top: var(--sp-24);
  list-style: none;
}

.case-hero__tags li {
  padding: var(--sp-2) var(--sp-8);
  color: var(--text-secondary);
  background: var(--surface-secondary);
  font-size: var(--fs-body-xs);
  line-height: 1;
  letter-spacing: .08em;
  text-transform: uppercase;
}

/* Divider */
.case-hero__divider {
  width: 100%;
  height: var(--border-width);
  margin-top: var(--sp-40);
  margin-bottom: calc(var(--sp-40) * .8);
  border: 0;
  background: var(--border-color);
}

/* Snapshot */
.case-snapshot {
  display: grid;
  width: 100%;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--sp-24) var(--sp-16);
  margin: 0;
}

.case-snapshot__item {
  display: flex;
  align-items: flex-start;
  flex-direction: column;
  gap: var(--sp-4);
}

.case-snapshot__item dt {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  color: var(--text-muted);
  font-size: var(--fs-body-xs);
  letter-spacing: normal;
}

.case-snapshot__icon {
  width: 1em;
  height: 1em;
  flex: 0 0 auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Product links: verifiable proof the work shipped. */
.case-snapshot__link {
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, currentColor 30%, transparent);
  text-decoration-thickness: var(--border-width);
  text-underline-offset: var(--sp-4);
  transition: color var(--dur-fast) var(--ease), text-decoration-color var(--dur-fast) var(--ease);
}

/* Outbound marker. Decorative, and outside the underline so the arrow doesn't
   pick up the link's rule. */
.case-snapshot__link::after {
  content: "\2197";
  display: inline-block;
  margin-left: .15em;
  font-size: .85em;
  line-height: 1;
  text-decoration: none;
  vertical-align: baseline;
  transition: transform var(--dur-fast) var(--ease);
}

.case-snapshot__link:hover,
.case-snapshot__link:focus-visible {
  color: var(--brand);
  text-decoration-color: currentColor;
}

.case-snapshot__link:hover::after,
.case-snapshot__link:focus-visible::after {
  transform: translate(.1em, -.1em);
}

@media (prefers-reduced-motion: reduce) {
  .case-snapshot__link::after {
    transition: none;
  }

  .case-snapshot__link:hover::after,
  .case-snapshot__link:focus-visible::after {
    transform: none;
  }
}

.case-snapshot__item dd {
  margin: 0;
  color: var(--text-primary);
  font-size: var(--fs-body-md);
  line-height: var(--lh-body-md);
}

/* Money-shot dashboard frame — cut corner echoes the brand marks. */
.case-hero__shot {
  position: relative;
  width: 100%;
  margin: 0;
  margin-top: calc(var(--sp-40) * .8);
  overflow: hidden;
  background: var(--surface-primary);
  /* Four layers rather than one: a tight contact shadow that anchors the edge,
     then progressively wider and fainter ones, so the screen reads as lifted
     off the page instead of stamped with a grey rectangle. The hero's bottom
     padding is sized to hold the widest layer, so none of it reaches the
     brand-coloured section below. */
  box-shadow:
    0 1px 2px color-mix(in srgb, var(--text-primary) 5%, transparent),
    0 4px 10px color-mix(in srgb, var(--text-primary) 5%, transparent),
    0 12px 28px color-mix(in srgb, var(--text-primary) 6%, transparent),
    0 24px 48px color-mix(in srgb, var(--text-primary) 7%, transparent);
}

/* Light/dark switch. It is sized and shaped like a honeycomb cell and then
   parked exactly on the one nearest the hero's top-right corner, which
   case-study.js works out after the mesh is built and again on resize. Until
   that runs it stays hidden, so it never flashes in the wrong place. */
.theme-toggle {
  position: absolute;
  z-index: 3;
  top: var(--toggle-y, 0);
  left: var(--toggle-x, 0);
  display: grid;
  width: var(--badge-width);
  height: var(--badge-height);
  padding: 0;
  border: 0;
  cursor: pointer;
  opacity: 0;
  place-items: center;
  background: var(--case-brand, var(--brand));
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  color: var(--surface-primary);
  transition: background var(--dur-fast) var(--ease), opacity var(--dur-med) var(--ease);
}

.theme-toggle[data-placed] { opacity: 1; }

.theme-toggle:hover { background: var(--text-primary); }

.theme-toggle:focus-visible {
  outline: var(--border-width) solid var(--text-primary);
  outline-offset: var(--sp-2);
}

.theme-toggle__icon {
  grid-area: 1 / 1;
  width: var(--sp-20);
  height: var(--sp-20);
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}

/* Show the theme currently on screen: moon while the dark shot is up, sun
   while the light one is. The aria-label still names the action. */
.theme-toggle__icon--moon { opacity: 0; transform: rotate(-90deg) scale(.6); }
.theme-toggle__icon--sun { opacity: 1; transform: none; }
.theme-toggle[aria-pressed="true"] .theme-toggle__icon--sun { opacity: 0; transform: rotate(90deg) scale(.6); }
.theme-toggle[aria-pressed="true"] .theme-toggle__icon--moon { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .theme-toggle__icon { transition: opacity var(--dur-fast) var(--ease); transform: none !important; }
}

/* Fade in while rising from below, instead of the shared side-slide fade. */
@media (prefers-reduced-motion: no-preference) {
  .reveal-enabled .case-hero__shot.rv--entrance {
    opacity: 0;
    translate: 0 var(--sp-40);
  }

  .reveal-enabled .case-hero__shot.rv--entrance.is-in {
    opacity: 1;
    translate: none;
    transition-property: opacity, translate;
    transition-duration: calc(var(--dur-slow) * 1.8), calc(var(--dur-slow) * 1.8);
    transition-timing-function: var(--ease), var(--ease);
    transition-delay: var(--rv-delay, 0ms), var(--rv-delay, 0ms);
  }
}

.case-hero__shot img {
  width: 100%;
  height: auto;
}

/* --- Placeholder sections (built out later) ---------------- */
.case-section { border-top: var(--border-width) solid var(--border-color); }
.case-section--alt { background: var(--surface-secondary); }

.case-section__inner {
  display: flex;
  width: var(--cs-col);
  min-height: clamp(320px, 40vw, 520px);
  align-items: flex-start;
  flex-direction: column;
  gap: var(--sp-16);
  margin-inline: auto;
  padding-block: clamp(var(--sp-64), 8vw, var(--sp-120));
}

.case-section__note { color: var(--text-muted); }

/* --- Responsive -------------------------------------------- */
@media (max-width: 980px) {
  .case-snapshot { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* A bit wider on narrow screens so the mesh still reads; height still comes
     from top/bottom so it runs the full hero. */
  .case-hero__backdrop { width: 60vw; }
}

@media (max-width: 720px) {
  .case-hero__title { max-width: none; }
  .case-hero__shot { margin-top: calc(var(--sp-40) * .8); }
}

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

/* On a case study the accent is the project's own brand, not the site navy.
   Declared here so the green-backed sections further down (.challenge,
   .results) still win and flip their eyebrows to white. */
/* Each case study wears its own product brand. Set once from the attribute the
   page already carries, so the section styles below stay project-agnostic. */
.case-page { --case-brand: var(--brand); }
.case-page[data-current-project="tinyco"]       { --case-brand: var(--brand-tinyco); }
.case-page[data-current-project="smartouch"]    { --case-brand: var(--brand-smartouch); }
.case-page[data-current-project="travalera"]      { --case-brand: var(--brand-travalera); }
.case-page[data-current-project="socialgaines"] { --case-brand: var(--brand-socialgaines); }
.case-page[data-current-project="privitas"]     { --case-brand: var(--brand-privitas); }
.case-page[data-current-project="bixy"]         { --case-brand: var(--brand-bixy); }

.case-page .eyebrow { color: var(--case-brand); }

/* ============================================================
   Case study — The Challenge section (Figma 2063:5668)
   960 column, 120px block padding, head/lead/cards 40px apart.
   ============================================================ */

.challenge {
  position: relative;
  /* Paints above the hero (whose inner is z-index 1) so the hero shot's shadow
     is cut off exactly at this edge instead of spilling onto the brand colour.
     The shot sits flush against this boundary, so nothing of it is covered. */
  z-index: 2;
  overflow: clip;
  border-top: 0;
  background: var(--case-brand);
}

/* On the tinyco green backdrop, every label/heading/body text flips to
   white, with reduced opacity for secondary-tier copy. */
.challenge .eyebrow { color: var(--surface-primary); }

.challenge__backdrop {
  position: absolute;
  z-index: 0;
  top: 0;
  bottom: 0;
  left: calc(0px - var(--container-outer-space));
  width: min(84vw, 1260px);
  pointer-events: none;
  -webkit-mask-image: radial-gradient(150% 130% at 0% 30%, #000 0%, rgba(0, 0, 0, .6) 30%, rgba(0, 0, 0, .25) 62%, transparent 100%);
  mask-image: radial-gradient(150% 130% at 0% 30%, #000 0%, rgba(0, 0, 0, .6) 30%, rgba(0, 0, 0, .25) 62%, transparent 100%);
}

.challenge__backdrop-canvas { position: absolute; inset: 0; }

.challenge__inner {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: flex-start;
  flex-direction: column;
  padding-block: var(--sp-120);
}

.challenge__head {
  display: flex;
  align-items: flex-start;
  flex-direction: column;
  gap: var(--sp-20);
}

.challenge__title { color: var(--surface-primary); }

.challenge__lead {
  max-width: 100%;
  margin-top: var(--sp-20);
  color: color-mix(in srgb, var(--surface-primary) 82%, transparent);
  text-wrap: pretty;
}

/* Cards — 3-up, equal height, cut-corner + soft shadow. */
.challenge__cards {
  display: grid;
  width: 100%;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-20);
  margin-top: var(--sp-40);
}

.challenge-card {
  --card-cut: calc(var(--cut-corner) * 3);
  position: relative;
  display: flex;
  aspect-ratio: 100 / 78;
  align-items: flex-start;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--sp-16);
  padding: var(--sp-20) var(--sp-24);
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - var(--card-cut) * var(--cut-rise)), calc(100% - var(--card-cut)) 100%, 0 100%);
  background: var(--surface-primary);
  /* drop-shadow rather than box-shadow so the halo follows the chamfer. */
  filter: drop-shadow(0 var(--sp-8) var(--sp-24) color-mix(in srgb, var(--text-primary) 14%, transparent));
  /* --ease, not --ease-gentle: gentle starts with an acceleration ramp, which
     on a 3px move reads as a flick. This curve leaves immediately and settles,
     which is what makes the lift feel weightless. will-change promotes the
     card so the move is composited rather than repainted each frame. */
  will-change: transform;
  transition: transform var(--dur-slow) var(--ease), filter var(--dur-slow) var(--ease);
}

/* A nudge, not a jump: 3px is enough to read as lift once the shadow deepens
   underneath it. */
.challenge-card:hover {
  transform: translateY(-3px);
  filter:
    drop-shadow(0 2px 4px color-mix(in srgb, var(--text-primary) 8%, transparent))
    drop-shadow(0 14px 32px color-mix(in srgb, var(--text-primary) 16%, transparent));
}

@media (prefers-reduced-motion: reduce) {
  .challenge-card { transition: filter var(--dur-med) var(--ease); }
  .challenge-card:hover { transform: none; }
}

/* Honeycomb detail, painted as a background image the way it always was: a
   mask over a flat colour renders the 0.5px strokes at a fraction of their
   alpha and washes them out to near-white. Two stacked layers instead, so the
   lines can change colour: grey at rest, the project's own tile on hover.
   Both are absolutely positioned to stay out of the card flex flow. */
.challenge-card::before,
.challenge-card::after {
  --mesh-reach: 100%;
  content: "";
  position: absolute;
  z-index: 0;
  inset: 0;
  /* Offset by the card padding so a cell lands on the badge hexagon; both
     scale together, so the alignment holds at every viewport. */
  background-position: var(--sp-24) var(--sp-20);
  background-repeat: repeat;
  background-size: 64px 111px;
  -webkit-mask-image: linear-gradient(135deg, #000 0%, rgba(0, 0, 0, .45) 18%, transparent 38%);
  mask-image: linear-gradient(135deg, #000 0%, rgba(0, 0, 0, .45) 18%, transparent 38%);
  -webkit-mask-size: var(--mesh-reach) var(--mesh-reach);
  mask-size: var(--mesh-reach) var(--mesh-reach);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  pointer-events: none;
  transition: opacity var(--dur-slow) var(--ease);
}

.challenge-card::before { background-image: url("assets/images/site/hex-tile.svg"); }

/* The same mesh in the project colour, cross-faded in on hover. */
.challenge-card::after {
  background-image: var(--mesh-tile-brand, url("assets/images/site/hex-tile.svg"));
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease),
              -webkit-mask-size var(--dur-slow) var(--ease),
              mask-size var(--dur-slow) var(--ease);
}

/* Hover: grey out, colour in, and both reach ~44% further across the card. */
.challenge-card:hover::before { opacity: 0; }
.challenge-card:hover::after { opacity: 1; --mesh-reach: 120%; }

/* Per-project tile, picked up from the attribute the page already carries. */
.case-page[data-current-project="tinyco"]       { --mesh-tile-brand: url("assets/images/site/hex-tile-tinyco.svg"); }
.case-page[data-current-project="smartouch"]    { --mesh-tile-brand: url("assets/images/site/hex-tile-smartouch.svg"); }
.case-page[data-current-project="travalera"]      { --mesh-tile-brand: url("assets/images/site/hex-tile-travalera.svg"); }
.case-page[data-current-project="socialgaines"] { --mesh-tile-brand: url("assets/images/site/hex-tile-socialgaines.svg"); }
.case-page[data-current-project="privitas"]     { --mesh-tile-brand: url("assets/images/site/hex-tile-privitas.svg"); }
.case-page[data-current-project="bixy"]         { --mesh-tile-brand: url("assets/images/site/hex-tile-bixy.svg"); }

@media (prefers-reduced-motion: reduce) {
  .challenge-card::before,
  .challenge-card::after { transition: opacity var(--dur-med) var(--ease); }
}

/* Card content sits above the pattern. */
.challenge-card__badge,
.challenge-card__text {
  position: relative;
  z-index: 1;
}

.challenge-card__badge {
  position: relative;
  display: grid;
  width: 64px;
  height: 74px;
  flex: 0 0 auto;
  place-items: center;
}

.challenge-card__hex {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  fill: var(--case-brand);
  stroke: none;
}

.challenge-card__icon {
  position: relative;
  width: var(--sp-24);
  height: var(--sp-24);
  color: var(--surface-primary);
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.challenge-card__text {
  display: flex;
  align-items: flex-start;
  flex-direction: column;
  gap: var(--sp-4);
}

.challenge-card__title { color: var(--text-primary); }
.challenge-card__desc { color: var(--text-secondary); }

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

/* ============================================================
   Case study — Key Decisions (Figma 2063:5855)
   Sticky-pinned scroll scrub: a 4-step stepper on the left with a
   progress bar that fills over scroll, a media panel on the right.
   ============================================================ */

/* Key Decisions carries the grey; Process above it is white. The pair reads as
   a deliberate switch into the section that does the heavy lifting. */
.decisions {
  position: relative;
  border-top: 0;
  overflow: clip;
  background: var(--surface-secondary);
}

.decisions__head {
  display: flex;
  max-width: var(--cs-col);
  align-items: flex-start;
  flex-direction: column;
  gap: var(--sp-20);
}

.decisions__title { color: var(--text-primary); }

.decisions__intro {
  /* Same measure as the other sections' body copy, so it doesn't run out to
     the media column's edge. (--cs-col resolves its 100% against the pinned
     block here, which is wider, so the column width is restated directly.) */
  max-width: min(clamp(960px, 66.667vw, 1440px), 100%);
  /* Matches the eyebrow-to-title gap, like the Challenge head. */
  margin-top: var(--sp-20);
  color: var(--text-secondary);
  text-wrap: pretty;
}

/* Scroll runway — its height drives the scrub (~50svh dwell per step). */
.decisions__scrollzone {
  position: relative;
  /* Runway = one screen (the pinned stage) + a fixed, resolution-independent
     scrub distance (~600px per step), so tall screens add no empty space.
     --scrub-steps lets a page with a different number of steps keep the same
     scrub feel instead of cramming them into a fixed distance. */
  min-height: calc(100svh + var(--scrub-steps, 3) * 600px);
}

/* Pinned stage. Height follows the content so the block keeps the same 120px
   top/bottom padding as every other section, instead of being centred in a
   full-screen box (which grew the air on tall viewports). */
.decisions__pin {
  position: sticky;
  top: var(--nav-height);
  display: flex;
  max-height: calc(100svh - var(--nav-height));
  align-items: flex-start;
  flex-direction: column;
  justify-content: center;
  /* Break out of the centred column: align left to the text gutter,
     let the media bleed right to the page edge margin (badge-edge). */
  width: 100%;
  padding-left: calc((100% - var(--cs-col)) / 2);
  padding-right: var(--badge-edge);
  padding-block: var(--sp-120);
}

.decisions__cols {
  display: grid;
  width: 100%;
  margin-top: var(--sp-40);
  grid-template-columns: minmax(0, 443fr) minmax(0, 660fr);
  /* Anchored, not centred: whichever column is shorter would otherwise float
     down half the difference, and which one that is flips with the viewport
     and the number of steps. */
  align-items: start;
  gap: var(--cs-col-gap);
}

/* ============================================================
   Process — the four steps between problem and solution
   ============================================================ */

.process__inner {
  display: flex;
  align-items: flex-start;
  flex-direction: column;
  padding-block: var(--sp-120);
}

/* Stretched, not shrink-to-fit: the column is align-items: flex-start, which
   would otherwise size the heading to its own text and let it wrap at a
   different width than the rows below it. */
.process__head {
  align-self: stretch;
  display: flex;
  align-items: flex-start;
  flex-direction: column;
  gap: var(--sp-20);
}

.process__title { align-self: stretch; }

.process__lead {
  align-self: stretch;
  max-width: 100%;
  margin-top: var(--sp-20);
  color: var(--text-secondary);
  text-wrap: pretty;
}

/* Full-width rows: a hairline rule, then a label column against the
   description. The 40px above and below each row is what gives the list its
   rhythm, so the rule reads as a divider rather than an underline. */
.process__steps {
  display: flex;
  width: 100%;
  flex-direction: column;
  gap: var(--sp-40);
  margin-top: var(--sp-40);
  padding: 0;
  list-style: none;
}

/* 25% is exactly the 240px of the design frame, but it keeps pace with the
   type as the column widens, so the nowrapped titles never outgrow it. */
.process-step {
  display: grid;
  grid-template-columns: 25% minmax(0, 1fr);
  gap: var(--sp-12);
  padding-top: var(--sp-40);
  border-top: var(--border-width) solid var(--border-color);
}

.process-step__label {
  display: flex;
  align-items: flex-start;
  flex-direction: column;
  gap: var(--sp-12);
}

/* Numbered hexagon — the badge language from the challenge cards, scaled down
   so it reads as a marker rather than an illustration. The 64x74 viewBox is
   the same path, so the proportions stay identical. */
.process-step__num {
  position: relative;
  display: grid;
  width: var(--sp-32);
  height: calc(var(--sp-32) * 74 / 64);
  flex: 0 0 auto;
  place-items: center;
}

.process-step__hex {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  fill: var(--case-brand);
  stroke: none;
}

.process-step__num b {
  position: relative;
  color: var(--surface-primary);
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-semibold);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

/* One line each: "Design System" is the only label that would otherwise wrap,
   and a two-line title breaks the row rhythm the rules establish. */
.process-step__title {
  color: var(--text-primary);
  white-space: nowrap;
}

.process-step__desc {
  color: var(--text-secondary);
  text-wrap: pretty;
}

/* Tool names lift out of the secondary copy: a recruiter scanning the section
   should catch Figma, Maze and Storybook without reading the sentences. */
.process-step__tool {
  color: var(--text-primary);
  font-weight: var(--fw-semibold);
}

/* Below the design frame the label column stops earning its width. */
@media (max-width: 860px) {
  .process-step {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--sp-16);
  }
}

/* Rise into place instead of the shared side-slide, matching the hero shot.
   The stagger already set on --rv-delay makes the rows arrive in order. */
@media (prefers-reduced-motion: no-preference) {
  .reveal-enabled .process .rv.rv--entrance {
    opacity: 0;
    translate: 0 var(--sp-40);
  }

  .reveal-enabled .process .rv.rv--entrance.is-in {
    opacity: 1;
    translate: none;
    transition-property: opacity, translate;
    transition-duration: var(--dur-slow), var(--dur-slow);
    transition-timing-function: var(--ease), var(--ease);
    transition-delay: var(--rv-delay, 0ms), var(--rv-delay, 0ms);
  }
}

/* Stepper */
.decisions__steps {
  --step-gap: var(--sp-32);
  display: flex;
  flex-direction: column;
  gap: var(--step-gap);
  list-style: none;
}

.decisions__step {
  display: flex;
  flex-direction: column;
}

.decisions__progress {
  position: relative;
  width: 100%;
  height: 1px;
  overflow: hidden;
  background: var(--border-color);
}

.decisions__progress-fill {
  position: absolute;
  inset: 0;
  transform: scaleX(0);
  transform-origin: left center;
  background: var(--case-brand);
}

.decisions__step-title {
  margin-top: var(--step-title-gap, var(--sp-32));
  color: color-mix(in srgb, var(--text-primary) 34%, var(--surface-primary));
  transition: color var(--dur-med) var(--ease);
}

/* Short viewports: tighten the step rhythm so the pinned block keeps as much
   of the section's 120px top/bottom padding as four steps allow. With the
   trade-off sentence each description runs to five lines, which no amount of
   gap tightening absorbs on its own, so the padding gives a little too. */
@media (max-height: 960px) {
  .decisions__steps {
    --step-gap: var(--sp-8);
    --step-title-gap: var(--sp-12);
  }

  .decisions__step-body-inner { gap: var(--sp-8); }

  .decisions__pin { padding-block: var(--sp-96); }
  .decisions__intro { margin-top: var(--sp-12); }
  .decisions__cols { margin-top: var(--sp-20); }
}

/* 768px-tall laptops: at 96px the content runs into the bottom padding and
   leaves it visibly smaller than the top. Declaring less keeps the two equal. */
@media (max-height: 800px) {
  .decisions__pin { padding-block: var(--sp-64); }
}

.decisions__step.is-active .decisions__step-title,
.decisions__step.is-done .decisions__step-title { color: var(--text-primary); }

/* Steps double as controls: clicking one jumps the scrub to that step, with
   its sequence fully built. */
.decisions__step { cursor: pointer; }

.decisions__step:hover .decisions__step-title,
.decisions__step:focus-visible .decisions__step-title { color: var(--text-primary); }

.decisions__step:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: var(--sp-8);
}

.decisions[data-mode="static"] .decisions__step { cursor: default; }

/* Body (tag + description) — accordion via grid-template-rows. */
.decisions__step-body {
  display: grid;
  grid-template-rows: 0fr;
  margin-top: 0;
  opacity: 0;
  transition: grid-template-rows var(--dur-slow) var(--ease),
              opacity var(--dur-med) var(--ease),
              margin-top var(--dur-slow) var(--ease);
}

.decisions__step.is-active .decisions__step-body {
  grid-template-rows: 1fr;
  margin-top: var(--sp-12);
  opacity: 1;
}

.decisions__step-body-inner {
  display: flex;
  min-height: 0;
  flex-direction: column;
  gap: var(--sp-12);
  overflow: hidden;
}

/* Tag row: the product the decision belongs to, then the decision's own
   label. Wraps rather than shrinking, so neither tag is ever truncated. */
.decisions__tags {
  display: flex;
  align-self: flex-start;
  flex-wrap: wrap;
  gap: var(--sp-8);
}

.decisions__tag {
  align-self: flex-start;
  padding: var(--sp-2) var(--sp-8);
  color: var(--text-secondary);
  /* White, because the section itself is now the grey one: a grey chip on a
     grey section has nothing to sit against. */
  background: var(--surface-primary);
  font-size: var(--fs-body-xs);
  line-height: var(--lh-body-xs);
  letter-spacing: .08em;
  text-transform: uppercase;
}

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

/* Media panel — the canvas is a fixed 1440x1024 artboard (the ratio the
   compositions were designed on), anchored to the top of the tab column.
   On short viewports its width is capped so that the whole pinned block still
   keeps the section's 120px top/bottom padding instead of eating into it.
   (--head-block ≈ eyebrow + title + intro + the gap above the columns.) */
.decisions__media {
  --head-block: 216px;
  --media-cap: calc(100svh - var(--nav-height) - 2 * var(--sp-120) - var(--head-block));
  position: relative;
  display: block;
  width: min(100%, calc(max(200px, var(--media-cap)) * 1.40625));
  height: auto;
  align-self: start;
}

.decisions__media-frame {
  position: relative;
  width: 100%;
  aspect-ratio: 1440 / 1024;
  min-height: 0;
  overflow: hidden;
  --media-cut: calc(var(--cut-corner) * 3);
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - var(--media-cut) * var(--cut-rise)), calc(100% - var(--media-cut)) 100%, 0 100%);
  /* White canvas on the section's grey, so every tab composition sits on a
     clean sheet and the chamfered edge stays visible. */
  background: var(--surface-primary);
  container-type: size;
}

/* Media blocks — an abstract, per-step composition that builds up as the
   reader scrolls through that step's dwell (see case-study.js). */
/* Each group is an "artboard" with its composition's exact aspect ratio
   (--art-ratio, set per group), centred in the padded canvas on both axes. */
.decisions__media-group {
  --media-inset: clamp(var(--sp-24), 4vw, var(--sp-48));
  position: absolute;
  inset: 0;
  width: min(calc(100cqw - 2 * var(--media-inset)), calc((100cqh - 2 * var(--media-inset)) * var(--art-ratio, 1.5)));
  margin: auto;
  aspect-ratio: var(--art-ratio, 1.5);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-fast) var(--ease);
}

.decisions__media-group.is-active {
  opacity: 1;
  pointer-events: auto;
}

.decisions__media-block {
  position: absolute;
  top: var(--block-top);
  left: var(--block-left);
  width: var(--block-width);
  height: var(--block-height);
  opacity: 0;
  transform: translate3d(0, var(--sp-12), 0) scale(calc(var(--stack-scale, 1) * .96));
  border: var(--border-width) solid var(--border-color);
  background: var(--surface-primary);
  transition: opacity var(--dur-med) var(--ease), transform var(--dur-med) var(--ease);
}

.decisions__media-block.is-visible {
  opacity: var(--stack-opacity, 1);
  transform: scale(var(--stack-scale, 1));
}

/* Real product screenshots: the exports carry their own card chrome, so the
   block adds NO container of its own — no border, no background, no shadow.
   Height is auto so the box hugs the image exactly (no letterboxing). */
.decisions__media-block--shot {
  height: auto;
  overflow: visible;
  border: 0;
  background: transparent;
}

/* Swap group (bixy tab 1): the states replace one another in place, so they
   cross-fade rather than sliding up like a normal reveal — a slide would read
   as new content arriving, not a tab switching. */
.decisions__media-group[data-media-swap] .decisions__media-block {
  transform: none;
  transition: opacity var(--dur-med) var(--ease);
}
.decisions__media-group[data-media-swap] .decisions__media-block.is-visible {
  transform: none;
}

.decisions__media-block--shot img {
  display: block;
  width: 100%;
  height: auto;
}

/* Reveal the automation first, then bring its two product cards into focus. */
[data-media-automation] .decisions__automation-flow {
  opacity: calc(1 - .58 * var(--automation-focus, 0));
  filter: blur(calc(5px * var(--automation-focus, 0)));
  transform: scale(calc(1 + .025 * var(--automation-focus, 0)));
  transition: none;
}

[data-media-automation] .decisions__automation-card {
  z-index: 1;
  opacity: var(--automation-reveal, 1);
  transform: translate3d(0, calc(32px * (1 - var(--automation-reveal, 1))), 0)
    scale(calc(.95 + .05 * var(--automation-reveal, 1)));
  filter: drop-shadow(0 8px 14px rgb(3 4 26 / .12));
  transition: none;
}

/* Wireframes carry no chrome of their own, unlike the product screenshots, so
   they get a hairline frame to sit on the canvas as artefacts rather than
   floating. overflow clips the image to the rounded corners. */
.decisions__media-block--framed {
  overflow: hidden;
  border: var(--border-width) solid var(--border-color);
  border-radius: 8px;
}

/* Stacked windows: full-size, fully opaque screens landing one on top of the
   other. The shadow alone separates the layers; corners stay square, like every
   other surface on the site. */
.decisions__media-block--stack img {
  box-shadow: 0 var(--sp-12) var(--sp-32) color-mix(in srgb, var(--text-primary) 16%, transparent);
}

/* Hexagonal loupe over the artboards.
   These compositions render at a small fraction of their native size — tab 2
   fits a 6798px canvas into roughly 430px, about 6% — so all the detail is
   present and none of it is readable. The loupe spends that headroom. It holds
   a live copy of the active group rather than a background-image, because a
   composition is not one picture: it is four panels and three connector layers,
   and only a copy magnifies all of them together. The payoff is that the drawn
   connectors stay vector-sharp inside the lens while the panels show their real
   pixels. Shape and proportion are the honeycomb cell's, 80:92, so the lens is
   the site's own hexagon rather than a new one. */
.decisions__media-frame.has-loupe { cursor: zoom-in; }

.decisions__loupe {
  --loupe-w: clamp(120px, 38cqw, 200px);
  --loupe-h: calc(var(--loupe-w) * 92 / 80);
  position: absolute;
  z-index: 4;
  top: 0;
  left: 0;
  width: var(--loupe-w);
  height: var(--loupe-h);
  padding: var(--border-width);
  opacity: 0;
  pointer-events: none;
  background: var(--case-brand, var(--brand));
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  transition: opacity var(--dur-fast) var(--ease);
  will-change: transform;
}

.decisions__loupe.is-on { opacity: 1; }

.decisions__loupe-window {
  position: relative;
  overflow: hidden;
  width: 100%;
  height: 100%;
  background: var(--surface-primary);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}

.decisions__loupe-stage {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
}

/* Inside the lens a block only fades: the reveal's slide and scale would pull
   the magnified copy out of register with the cursor. */
.decisions__loupe .decisions__media-block,
.decisions__loupe .decisions__media-block.is-visible { transform: none; }

@media (prefers-reduced-motion: reduce) {
  .decisions__loupe { transition: none; }
}

/* Loupe discoverability hint. Injected by JS only when the loupe is actually
   bound (desktop, fine pointer), so it never promises a hover that a touch
   device can't deliver. Sits bottom-left, clear of the frame's bottom-right
   chamfer, and fades out once the lens is open so it never covers what it was
   pointing at. */
.decisions__loupe-hint {
  position: absolute;
  z-index: 3;
  bottom: var(--sp-16);
  right: var(--sp-24);
  display: none;
  align-items: center;
  gap: var(--sp-8);
  margin: 0;
  padding: 0;
  /* Lighter than --text-muted, derived from it rather than hardcoded, so the
     hint recedes behind the work it points at. */
  color: color-mix(in srgb, var(--text-muted) 72%, var(--surface-primary));
  /* The smallest type in the system: a hint should sit under the content, not
     compete with it. */
  font-size: var(--fs-body-xs);
  line-height: var(--lh-body-xs);
  font-weight: var(--fw-regular);
  white-space: nowrap;
  pointer-events: none;
}

/* Present the whole time the loupe is available, bottom-right, no backdrop. */
.decisions__media-frame.has-loupe .decisions__loupe-hint { display: inline-flex; }

/* The bullet is the loupe in miniature: the same hexagon, outlined only, in the
   hint's own colour. Sized in em so it tracks the fluid type at every width. */
.decisions__loupe-hint-hex {
  width: .95em;
  height: 1.1em;
  flex: 0 0 auto;
  overflow: visible;
  fill: none;
  stroke: currentColor;
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

/* Schema connectors drawn over a composition: the flow exports carry every
   arrow that lives inside one panel and none of the ones that cross between
   panels, so those are drawn here instead and animate as the reader scrubs.
   The overlay spans the whole artboard at the composition's own viewBox, which
   is what keeps a line landing on a card edge in the raster underneath.
   Ink matches the exports' own stroke (sampled #03070a), so a drawn line and a
   baked one read as the same pen. */
.decisions__media-block--flow {
  height: auto;
  border: 0;
  background: transparent;
  pointer-events: none;
  /* No slide or scale on reveal: this block must stay in exact register with
     the panels beneath it, so the paths alone carry the animation. */
  opacity: 1;
  transform: none;
}

.decisions__media-block--flow .flow {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

/* pathLength normalises every path to 1, so one dash rule draws them all
   at the same rate regardless of how long each run actually is. */
.flow__line {
  stroke: var(--flow-ink, #03070a);
  stroke-width: 4;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset var(--dur-slow) var(--ease);
}

.is-visible .flow__line { stroke-dashoffset: 0; }

/* Heads and junctions land after their line has arrived, never before it. */
.flow__head,
.flow__node {
  fill: var(--flow-ink, #03070a);
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease) var(--dur-slow);
}

.is-visible .flow__head,
.is-visible .flow__node { opacity: 1; }

/* Static mode has no scrub to drive the draw, so the schema arrives complete. */
.decisions[data-mode="static"] .flow__line { stroke-dashoffset: 0; }
.decisions[data-mode="static"] .flow__head,
.decisions[data-mode="static"] .flow__node { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .flow__line { transition: none; }
  .flow__head,
  .flow__node { transition: none; }
}

/* Flow connectors (tab 3), drawn in code: dashed lines with arrowheads that
   grow top-down as they reveal, between the automation blocks. */
.decisions__media-connector {
  --conn-color: color-mix(in srgb, var(--text-muted) 60%, transparent);
  height: var(--conn-height, 10%);
  border: 0;
  border-left: 2px dashed var(--conn-color);
  background: transparent;
  transform: scaleY(0);
  transform-origin: top center;
}

.decisions__media-connector::after {
  position: absolute;
  bottom: 0;
  left: -6px;
  content: "";
  border: 5px solid transparent;
  border-top: 6px solid var(--conn-color);
  border-bottom: 0;
}

/* Branch connector: a stem that splits into two dashed drops with arrows. */
.decisions__media-connector--branch { border-left: 0; }
.decisions__media-connector--branch::after { content: none; }

.decisions__conn-stem,
.decisions__conn-arm,
.decisions__conn-drop {
  position: absolute;
  display: block;
}

.decisions__conn-stem {
  top: 0;
  left: 50%;
  width: 0;
  height: 50%;
  border-left: 2px dashed var(--conn-color);
}

.decisions__conn-arm {
  top: 50%;
  right: 0;
  left: 0;
  height: 0;
  border-top: 2px dashed var(--conn-color);
}

.decisions__conn-drop {
  top: 50%;
  width: 0;
  height: 50%;
  border-left: 2px dashed var(--conn-color);
}

.decisions__conn-drop--left { left: 0; }
.decisions__conn-drop--right { right: 0; }

.decisions__conn-drop::after {
  position: absolute;
  bottom: 0;
  left: -6px;
  content: "";
  border: 5px solid transparent;
  border-top: 6px solid var(--conn-color);
  border-bottom: 0;
}

/* Static mode: no scroll-driven reveal — show the first group, fully built. */
.decisions[data-mode="static"] .decisions__media-group { display: none; }
.decisions[data-mode="static"] .decisions__media-group[data-media-group="0"] { display: block; opacity: 1; }
.decisions[data-mode="static"] .decisions__media-block { opacity: 1; transform: none; }

/* Static mode (reduced motion or narrow): no pin, all steps expanded. */
.decisions[data-mode="static"] .decisions__scrollzone {
  min-height: 0;
  padding-bottom: var(--sp-80);
}

.decisions[data-mode="static"] .decisions__pin {
  position: static;
  top: auto;
  height: auto;
  max-height: none;
  justify-content: flex-start;
  padding-block: var(--sp-120) var(--sp-80);
}

.decisions[data-mode="static"] .decisions__media,
.decisions[data-mode="static"] .decisions__media-frame { height: auto; }

@media (max-width: 980px) {
  .decisions__scrollzone { min-height: 0; padding-bottom: var(--sp-80); }
  .decisions__pin {
    position: static;
    top: auto;
    height: auto;
    max-height: none;
    justify-content: flex-start;
    padding-inline: var(--content-pad);
    padding-block: var(--sp-80);
  }
  .decisions__cols {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--sp-40);
  }
  .decisions__media,
  .decisions__media-frame { height: auto; }
  .decisions__media { order: -1; }
}

/* ============================================================
   Case study — Results (Figma 2073:14859)
   Counters, a full-bleed shots ticker (slows + dims on hover),
   a reflection quote and a next-project button.
   ============================================================ */

/* The section sits on tinyCo green permanently, so its copy is white
   throughout (the stat numbers are the one deliberate exception). */
.results {
  position: relative;
  border-top: 0;
  overflow: clip;
  background: var(--case-brand);
}

.results .eyebrow,
.results__quote {
  color: var(--surface-primary);
}

.results-stat__label {
  color: color-mix(in srgb, var(--surface-primary) 78%, transparent);
}

.results__divider {
  background: color-mix(in srgb, var(--surface-primary) 30%, transparent);
}

.results__backdrop {
  position: absolute;
  z-index: 0;
  top: 0;
  bottom: 0;
  right: calc(0px - var(--container-outer-space));
  width: min(84vw, 1260px);
  pointer-events: none;
  -webkit-mask-image: radial-gradient(150% 130% at 100% 30%, #000 0%, rgba(0, 0, 0, .6) 30%, rgba(0, 0, 0, .25) 62%, transparent 100%);
  mask-image: radial-gradient(150% 130% at 100% 30%, #000 0%, rgba(0, 0, 0, .6) 30%, rgba(0, 0, 0, .25) 62%, transparent 100%);
}

.results__backdrop-canvas { position: absolute; inset: 0; }

.results__top,
.results__bottom { position: relative; z-index: 1; }

.results__top { padding-top: var(--sp-120); }

.results__head {
  display: flex;
  align-items: flex-start;
  flex-direction: column;
  gap: var(--sp-20);
}

.results__head .results__title { color: var(--surface-primary); }

.results__divider {
  width: 100%;
  height: var(--border-width);
  margin: var(--sp-60) 0 0;
  border: 0;
}

/* Attribution for the numbers above: scale, customers, and what the rating
   actually cost to earn. Same measure as the other sections' body copy. */
.results__context {
  max-width: min(clamp(960px, 66.667vw, 1440px), 100%);
  margin-top: var(--sp-60);
  color: color-mix(in srgb, var(--surface-primary) 80%, transparent);
  text-wrap: pretty;
}

/* Where each figure came from. Quieter than the copy above it: a reader who
   wants it will find it, and it is the line that survives an interview. */
.results__note {
  max-width: min(clamp(960px, 66.667vw, 1440px), 100%);
  margin-top: var(--sp-20);
  color: color-mix(in srgb, var(--surface-primary) 60%, transparent);
  text-wrap: pretty;
}

/* Stat counters */
.results__stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--sp-40);
  margin: var(--sp-60) 0 0;
}

.results-stat {
  display: flex;
  align-items: flex-start;
  flex-direction: column;
  gap: var(--sp-8);
}

.results-stat__value {
  color: var(--surface-primary);
  font-weight: var(--fw-light);
  font-variant-numeric: tabular-nums;
}

/* Shots ticker (full-bleed) */
.results-ticker {
  position: relative;
  z-index: 1;
  width: 100%;
  margin-top: var(--sp-60);
  overflow: hidden;
}

.results-ticker__track {
  display: flex;
  align-items: center;
  width: max-content;
  gap: var(--sp-16);
  will-change: transform;
}

.results-shot {
  width: auto;
  height: clamp(210px, 29.167vw, 420px);
  flex: 0 0 auto;
  margin: 0;
  overflow: hidden;
  /* Each shot declares its own ratio inline, from the file's real dimensions;
     the fallbacks are the ratios the earlier case studies were exported at.
     Without this the slot crops whatever does not fit it — privitas ships
     1440x1024 desktop captures, which a 16:10 slot would shave 12% off. */
  aspect-ratio: var(--shot-ratio, 560 / 350);
  background: var(--surface-primary);
  transition: opacity var(--dur-med) var(--ease);
}

.results-shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Mobile screen capture, paired right after its desktop sibling in the
   ticker: same height as the desktop card, width follows its own ratio. */
.results-shot--mobile {
  aspect-ratio: var(--shot-ratio, 1125 / 2700);
}

.results-ticker.is-hovering .results-shot { opacity: .6; }
.results-ticker.is-hovering .results-shot.is-hovered { opacity: 1; }

/* Ticker controls (injected by case-study.js behind TICKER_CONTROLS).
   The track auto-advances for roughly a hundred seconds a lap with hover as its
   only pause, which leaves a keyboard user stuck; these are real buttons, so
   they are reachable by tab and using one parks the auto-scroll. */
/* Centred on the ticker's bottom edge: the nav sits in normal flow right after
   it, then is pulled up by half its own height so the hexagons straddle the
   boundary, half over the screens and half on the section's brand colour. */
.results-ticker__nav {
  --arrow-w: var(--sp-40);
  --arrow-h: calc(var(--arrow-w) * 92 / 80);   /* the honeycomb cell's proportion */
  position: relative;
  z-index: 2;
  display: flex;
  justify-content: center;
  gap: var(--sp-12);
  margin-top: calc(var(--arrow-h) / -2);
  /* The shadow lives here, not on the buttons: a filter on the same element as
     a clip-path risks being clipped away with everything outside the hexagon.
     On the parent it is applied to the already-clipped shapes, so it always
     shows. Two layers, one tight for definition and one wide for lift. */
  filter:
    drop-shadow(0 1px 2px color-mix(in srgb, var(--text-primary) 38%, transparent))
    drop-shadow(0 6px 18px color-mix(in srgb, var(--text-primary) 45%, transparent));
  transition: opacity var(--dur-slow) var(--ease);
}

/* The nav is injected after the reveal system has already collected its items,
   so it cannot be an .rv itself. Tying it to the ticker's own reveal with the
   sibling combinator keeps it from appearing before the row it belongs to. */
.reveal-enabled .results-ticker.rv--entrance:not(.is-in) ~ .results-ticker__nav {
  opacity: 0;
}

/* White by default, dark grey on hover. A clip-path shape cannot carry a
   border, and the top half of each hexagon sits over light screenshots, so the
   shadow on .results-ticker__nav is what keeps the white one from dissolving
   into the images behind it. */
.results-ticker__arrow {
  display: grid;
  width: var(--arrow-w);
  height: var(--arrow-h);
  padding: 0;
  border: 0;
  cursor: pointer;
  place-items: center;
  background: var(--surface-primary);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  color: var(--text-primary);
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease),
    transform var(--dur-fast) var(--ease);
}

.results-ticker__arrow svg {
  width: 42%;
  height: 42%;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.results-ticker__arrow:hover {
  background: var(--text-secondary);
  color: var(--surface-primary);
}

/* clip-path crops an outline, so focus inverts and lifts instead. */
.results-ticker__arrow:focus-visible {
  background: var(--text-secondary);
  color: var(--surface-primary);
  outline: none;
  transform: translateY(-3px);
}

.results-ticker__arrow:active { transform: scale(.94); }

@media (prefers-reduced-motion: reduce) {
  .results-ticker__arrow:focus-visible { transform: none; }
}

/* Dragging: the row follows the pointer, so say so and stop the browser from
   selecting text or claiming the horizontal gesture. */
.results-ticker__track { touch-action: pan-y; }
.results-ticker.is-dragging { cursor: grabbing; }
.results-ticker.is-dragging .results-ticker__track { user-select: none; }
.results-ticker.is-dragging .results-shot { pointer-events: none; }

@media (prefers-reduced-motion: reduce) {
  .results-ticker__arrow { transition: none; }
}

/* Reflection + next-project button */
.results__bottom {
  display: flex;
  align-items: stretch;
  flex-direction: column;
  margin-top: var(--sp-60);
}

.results__reflection {
  display: flex;
  align-items: flex-start;
  flex-direction: column;
  gap: var(--sp-12);
}

/* The self-critique under the quote: quieter than the lesson above it, and
   held to the same measure as the rest of the section's body copy. */
.results__reflection-note {
  max-width: min(clamp(960px, 66.667vw, 1440px), 100%);
  margin-top: var(--sp-20);
  color: color-mix(in srgb, var(--surface-primary) 78%, transparent);
  text-wrap: pretty;
}

.results__quote {
  max-width: 100%;
  color: var(--surface-primary);
  text-wrap: pretty;
}

/* White on the green section; the shared .button--filled hover already wipes
   in --text-primary, so hovering turns it dark grey with white text. */
.results__next {
  align-self: flex-end;
  margin-top: var(--sp-60);
  color: var(--text-primary);
  /* Match the square corners of the other actions. */
  clip-path: none;
  background: var(--surface-primary);
}

.results__next:hover,
.results__next:focus-visible { color: var(--surface-primary); }

.results__next b { font-weight: var(--fw-semibold); }

.results__next-icon {
  position: relative;
  display: inline-grid;
  width: var(--sp-20);
  height: var(--sp-20);
  place-items: center;
  font-size: var(--fs-body-l);
  line-height: 1;
  transition: translate var(--dur-fast) var(--ease);
}

.results__next:hover .results__next-icon,
.results__next:focus-visible .results__next-icon { translate: var(--sp-4) 0; }

@media (max-width: 720px) {
  .results__stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sp-40) var(--sp-24);
  }
  .results__next { align-self: stretch; }
}
